Bir html editörü geliştirdiğimde satır numarasını hesaplamanın bir yolunu buldum. Birincil yöntem şudur:
IE'de getBoundingClientRects'i çağırabilirsiniz, her satırı bir dikdörtgen olarak döndürür
Webkit veya yeni standart html motorunda, her bir öğenin veya düğümün istemci dikdörtgenlerini döndürür, bu durumda her bir dikdörtgeni karşılaştırabilirsiniz, yani her biri bir dikdörtgen olmalıdır, böylece yüksekliği daha küçük olan dikdörtgenleri göz ardı edebilirsiniz (eğer Bir dikdörtgenin üstü ondan daha küçük ve altı ondan daha büyükse, koşul doğrudur.
öyleyse test sonucunu görelim:
Yeşil dikdörtgen, her satırdaki en büyük dikdörtgendir
Kırmızı dikdörtgen, seçim sınırıdır
Mavi dikdörtgen, genişledikten sonra başlangıçtan seçime kadar olan sınırdır, kırmızı dikdörtgenden daha büyük olabileceğini görüyoruz, bu nedenle her dikdörtgenin altını kontrol ederek sınırlandırmak için kırmızı dikdörtgenin altından daha küçük olması gerekir.
var lineCount = "?";
var rects;
if (window.getSelection) {
//Get all client rectangles from body start to selection, count those rectangles that has the max bottom and min top
var bounding = {};
var range = window.getSelection().getRangeAt(0);//As this is the demo code, I dont check the range count
bounding = range.getBoundingClientRect();//!!!GET BOUNDING BEFORE SET START!!!
//Get bounding and fix it , when the cursor is in the last character of lineCount, it may expand to the next lineCount.
var boundingTop = bounding.top;
var boundingBottom = bounding.bottom;
var node = range.startContainer;
if (node.nodeType !== 1) {
node = node.parentNode;
}
var style = window.getComputedStyle(node);
var lineHeight = parseInt(style.lineHeight);
if (!isNaN(lineHeight)) {
boundingBottom = boundingTop + lineHeight;
}
else {
var fontSize = parseInt(style.fontSize);
if (!isNaN(fontSize)) {
boundingBottom = boundingTop + fontSize;
}
}
range = range.cloneRange();
//Now we have enougn datas to compare
range.setStart(body, 0);
rects = range.getClientRects();
lineCount = 0;
var flags = {};//Mark a flags to avoid of check some repeat lines again
for (var i = 0; i < rects.length; i++) {
var rect = rects[i];
if (rect.width === 0 && rect.height === 0) {//Ignore zero rectangles
continue;
}
if (rect.bottom > boundingBottom) {//Check if current rectangle out of the real bounding of selection
break;
}
var top = rect.top;
var bottom = rect.bottom;
if (flags[top]) {
continue;
}
flags[top] = 1;
//Check if there is no rectangle contains this rectangle in vertical direction.
var succ = true;
for (var j = 0; j < rects.length; j++) {
var rect2 = rects[j];
if (j !== i && rect2.top < top && rect2.bottom > bottom) {
succ = false;
break;
}
}
//If succ, add lineCount 1
if (succ) {
lineCount++;
}
}
}
else if (editor.document.selection) {//IN IE8 getClientRects returns each single lineCount as a rectangle
var range = body.createTextRange();
range.setEndPoint("EndToEnd", range);
rects = range.getClientRects();
lineCount = rects.length;
}
//Now we get lineCount here