Javascript 有没有办法得到标签';绘图前的宽度和高度?

Javascript 有没有办法得到标签';绘图前的宽度和高度?,javascript,leaflet,leaflet-label,Javascript,Leaflet,Leaflet Label,我正在使用带有传单标签的传单。有时标记重叠,这对UX不利,因此我实现了以下蜘蛛侠功能: /*Geometry*/ //Abstract Shape function capable to check intersection function Shape(params) { Initializable.call(this, params); this.initialize("Type", "Default"); //Let's know whether intersect

我正在使用带有传单标签的传单。有时标记重叠,这对UX不利,因此我实现了以下蜘蛛侠功能:

/*Geometry*/
//Abstract Shape function capable to check intersection
function Shape(params) {
    Initializable.call(this, params);
    this.initialize("Type", "Default");
    //Let's know whether intersection is symmetric
    this.initialize("Symmetric", true);
    this.initialize("Intersects", function (shape) {
        return false;
    });
}
//These rectangles have two horizontal and two vertical sides
function HorizontalVerticalRectangle(params) {
    params.Type = "HorizontalVerticalRectangle";
    var self = this;
    if (typeof params.Intersects !== "function") {
        //Default Intersects function
        params.Intersects = function (shape) {
            //If the two shapes have the same types and self is not to the right, left, bottom or top compared to shape then they intersect each-other
            if (shape.Type === self.Type) {
                return !((self.TopLeft.x > shape.BottomRight.x) ||
                         (self.BottomRight.x < shape.TopLeft.x) ||
                         (self.TopLeft.y > shape.BottomRight.y) ||
                         (self.BottomRight.y < shape.TopLeft.y));
                //In case of top half circles, we need to make sure that the horizontal square collides the circle and in the top half
            } else if (shape.Type === "TopHalfCircle") {
                return (self.TopLeft.y <= shape.Center.y) && HorizontalVerticalRectangle.prototype.CollidesCircle(self, shape.Center.x, shape.Center.y, shape.Diameter / 2);
            }
            //Not implemented
            return false;
        };
    }
    Shape.call(this, params);
    this.initialize("TopLeft", { x: 0, y: 0 });
    this.initialize("BottomRight", { x: 0, y: 0 });
    //Make sure the x and y coordinates are kept as floats
    this.TopLeft.x = parseFloat(this.TopLeft.x);
    this.TopLeft.y = parseFloat(this.TopLeft.y);
    this.BottomRight.x = parseFloat(this.BottomRight.x);
    this.BottomRight.y = parseFloat(this.BottomRight.y);
    //Coordinate setters
    this.setTopLeftX = function (x) {
        self.TopLeft.x = parseFloat(x);
    };
    this.setTopLeftY = function (y) {
        self.TopLeft.y = parseFloat(y);
    };
    this.setBottomRightX = function (x) {
        self.BottomRight.x = parseFloat(x);
    };
    this.setBottomRightY = function (y) {
        self.BottomRight.y = parseFloat(y);
    };
}
HorizontalVerticalRectangle.prototype.CollidesCircle = function (horizontalRectangle, centerX, centerY, radius) {
    var deltaX = centerX - Math.max(horizontalRectangle.TopLeft.x, Math.min(centerX, horizontalRectangle.BottomRight.x));
    var deltaY = centerY - Math.max(horizontalRectangle.TopLeft.y, Math.min(centerY, horizontalRectangle.BottomRight.y));
    return Math.pow(deltaX, 2) + Math.pow(deltaY, 2) <= Math.pow(radius, 2);
};
//These are circles where the center has the maximum y and the shape is upwards on screens
function TopHalfCircle(params) {
    params.Type = "TopHalfCircle";
    var self = this;
    if (typeof params.Intersects !== "function") {
        //Default Intersects function
        params.Intersects = function (shape) {
            //If the two shapes have identical type, none of them is above (below in coordinates) the other by more than the other's radius and the full circles intersect, 
            //then the half circles intersect each-other
            if (shape.Type === self.Type) {
                return ((self.Center.y - shape.Center.y) < (self.Diameter / 2)) &&
                       ((shape.Center.y - self.Center.y) < (shape.Diameter / 2)) &&
                       (Math.pow(self.Center.x - shape.Center.x, 2) + Math.pow(self.Center.y - shape.Center.y, 2) < Math.pow(((self.Diameter + shape.Diameter) / 2), 2));
                //In case of top horizontal vertical rectangle, we need to make sure that the horizontal square collides the circle and in the top half
            } else if (shape.Type === "HorizontalVerticalRectangle") {
                return (shape.TopLeft.y <= self.Center.y) && HorizontalVerticalRectangle.prototype.CollidesCircle(shape, self.Center.x, self.Center.y, self.Diameter / 2);
            }
            //Not Implemented
            return false;
        };
    }
    Shape.call(this, params);
    this.initialize("Center", { x: 0, y: 0 });
    this.initialize("Diameter", 0);
    //Make sure the coordinates and diameter are kept as floats
    this.Center.x = parseFloat(this.Center.x);
    this.Center.y = parseFloat(this.Center.y);
    this.Diameter = parseFloat(this.Diameter);
    //Setters
    this.setCenterX = function (x) {
        self.Center.x = parseFloat(x);
    };
    this.setCenterY = function (y) {
        self.Center.y = parseFloat(y);
    };
    this.setDiameter = function (d) {
        self.Diameter = parseFloat(d);
    };
}
//Placement strategies for markers, but they can be used for different purposes as well
var PlacementStrategies = {
    //This function finds groups of shapes seeing which shape intersects which other shape
    Group: function (shapes, comparator) {
        if (typeof comparator !== "function") {
            comparator = function () {
                return true;
            };
        }
        //This variable is empty at start, but at the end will hold the shape groups
        var groups = [];
        //Traverse the shapes to build the groups
        for (var shapeIndex in shapes) {
            //This variable will hold false if the shape does not fit into any existing group and the group index otherwise
            var foundGroup = false;
            //Traverse the groups to find whether a group where the shape fits in already exists
            for (var groupIndex = 0; groupIndex < groups.length; groupIndex++) {
                //Traverse the shapes of the current group to see whether any of them intersects the shape
                for (var innerShapeIndex = 0; (groupIndex < groups.length) && (innerShapeIndex < groups[groupIndex].length) ; innerShapeIndex++) {
                    //If shape intersects with the current group's current shape, then set foundGroup and exit two for cycles
                    if (Shape.prototype.intersects(shapes[shapeIndex], shapes[groups[groupIndex][innerShapeIndex]])) {
                        foundGroup = groupIndex;
                        innerShapeIndex = groups[groupIndex].length;
                        groupIndex = groups.length;
                    }
                }
            }
            //If the shape does not fit into any groups, then we create its own group
            if (foundGroup === false) {
                groups.push([shapeIndex]);
                //Otherwise we search for the location where the shape fits best
            } else {
                //Desired location. If it results in false, then the shape will be pushed to the end, otherwise it will be inserted at insertIndex
                var insertIndex = false;
                //Traverse the shapes of the found group to find the desired location to insert
                for (var innerShapeIndex = 0; innerShapeIndex < groups[foundGroup].length; innerShapeIndex++) {
                    //If the shape to be inserted is "smaller" than the found group's current shape, then store the index and quit the cycle
                    if (!comparator(shapes[groups[foundGroup][innerShapeIndex]], shapes[shapeIndex])) {
                        insertIndex = innerShapeIndex;
                        innerShapeIndex = groups[foundGroup].length;
                    }
                }
                //Insert the shape into the desired location or to the end if there was no desired middle location
                if (insertIndex === false) {
                    groups[foundGroup].push(shapeIndex);
                } else {
                    groups[foundGroup].splice(insertIndex, 0, shapeIndex);
                }
            }
        }
        return groups;
    },
    //This function merges shape groups if they intersect each-other
    MergeGroup: function (shapes, groups, merged, comparator) {
        if (typeof comparator !== "function") {
            comparator = function () {
                return true;
            };
        }
        //This time we merge the contents of the groups into the first index
        mergeIssued = true;
        while (mergeIssued) {
            //There was no merge issued yet
            mergeIssued = false;
            //Traverse the main groups
            for (var mergeIndex in merged) {
                //Traverse the groups to merge with
                for (var innerMergeIndex in merged[mergeIndex]) {
                    //If the group to merge with is empty, then it was already parsed
                    if ((merged[merged[mergeIndex][innerMergeIndex]]) && (merged[merged[mergeIndex][innerMergeIndex]].length > 0)) {
                        //Traverse the inner groups of the inner group
                        for (var toMove in merged[merged[mergeIndex][innerMergeIndex]]) {
                            //Move them if they are not yet present in the main merge group
                            if (merged[mergeIndex].indexOf(merged[merged[mergeIndex][innerMergeIndex]][toMove]) === -1) {
                                merged[mergeIndex].push(merged[merged[mergeIndex][innerMergeIndex]][toMove]);
                                mergeIssued = true;
                            }
                            //Remove the content of the inner group to avoid duplicates
                            merged[merged[mergeIndex][innerMergeIndex]] = [];
                        }
                    }
                }
            }
        }

        //Traverse the merge groups to move the shapes
        for (var mergeIndex in merged) {
            //Traverse the inner groups where we read the shapes from
            for (var innerMergeIndex in merged[mergeIndex]) {
                //Traverse the shapes of the inner group
                for (var shapeIndex in groups[merged[mergeIndex][innerMergeIndex]]) {
                    //If the shape is not yet present in the target group, we move it
                    if (groups[mergeIndex].indexOf(groups[merged[mergeIndex][innerMergeIndex]][shapeIndex]) === -1) {
                        //A variable which will hold the index of insertion or false, if the element should be the lasts
                        var insertLocation = false;
                        //Traverse the shapes of the target group to find the correct location
                        for (var targetIndex = 0; (insertLocation === false) && (targetIndex < groups[mergeIndex].length) ; targetIndex++) {
                            //If the shape located at the current index is not "smaller" than the shape to be inserted, then we found the target location
                            if (!comparator(shapes[groups[mergeIndex][targetIndex]], shapes[groups[merged[mergeIndex][innerMergeIndex]][shapeIndex]])) {
                                insertLocation = targetIndex;
                            }
                        }
                        //If there was no "bigger" element, then push at the end of the array
                        if (insertLocation === false) {
                            groups[mergeIndex].push(groups[merged[mergeIndex][innerMergeIndex]][shapeIndex]);
                            //Otherwise insert it to the correct location
                        } else {
                            groups[mergeIndex].splice(insertLocation, 0, groups[merged[mergeIndex][innerMergeIndex]][shapeIndex]);
                        }
                    }
                }
                //Clear the group where we moved the shapes from
                groups[merged[mergeIndex][innerMergeIndex]] = [];
            }
        }

        //We copy the non-empty groups into another container
        var finalGroups = [];
        for (var groupIndex in groups) {
            if (groups[groupIndex].length > 0) {
                finalGroups.push(groups[groupIndex]);
            }
        }
        //And return it
        return finalGroups;
    },
    //This strategy moves rectangles inside a group into a semi circle upwards on the screen
    SemiCircleHorizontalRectangles: function (shapes, groups) {
        //If groups is falsy, then this is the first try
        if (!groups) {
            //Which means that we need to create it by calling PlacementStrategies.Group with the comparator desired here
            groups = PlacementStrategies.Group(shapes, function (shape1, shape2) {
                //The shapes to the left are "smaller" to minimize line collisions
                return shape1.TopLeft.x < shape2.TopLeft.x;
            });
        }
        //This will hold top circles of the groups of shapes
        var groupTopCircles = [];
        //Traverse the raw groups
        for (var groupIndex in groups) {
            //We need to know the center of the circle, which will be the middle point of the horizontal coordinates and the lowest point in the circle
            var maxY = false;
            var minX = false;
            var maxX = false;
            //We need to know the half periphery to calculate the diameter
            var halfPeriphery = 0;
            //Traverse the shapes in the group
            for (var innerShapeIndex in groups[groupIndex]) {
                //Calculate the values where we calculate the center coordinates from
                if ((minX === false) || (minX > shapes[groups[groupIndex][innerShapeIndex]].TopLeft.x)) {
                    minX = shapes[groups[groupIndex][innerShapeIndex]].TopLeft.x;
                }
                if ((maxX === false) || (maxX < shapes[groups[groupIndex][innerShapeIndex]].BottomRight.x)) {
                    maxX = shapes[groups[groupIndex][innerShapeIndex]].BottomRight.x;
                }
                if ((maxY === false) || (maxY < shapes[groups[groupIndex][innerShapeIndex]].BottomRight.y)) {
                    maxY = shapes[groups[groupIndex][innerShapeIndex]].BottomRight.y;
                }
                //Add the length of the diagonal of the shape to halfPeriphery
                halfPeriphery += Math.sqrt(Math.pow(shapes[groups[groupIndex][innerShapeIndex]].BottomRight.x - shapes[groups[groupIndex][innerShapeIndex]].TopLeft.x, 2) + Math.pow(shapes[groups[groupIndex][innerShapeIndex]].BottomRight.y - shapes[groups[groupIndex][innerShapeIndex]].TopLeft.y, 2));
            }
            //Add the half circle to the container
            groupTopCircles[groupIndex] = new TopHalfCircle({ Center: { x: (minX + maxX) / 2, y: maxY }, Diameter: 2 * halfPeriphery / Math.PI });
        }
        //Container for groups to be merged
        var merged;
        //Traverse all the shapes
        for (var halfCircleIndex = 0; halfCircleIndex < groupTopCircles.length; halfCircleIndex++) {
            var s1 = (groups[halfCircleIndex].length === 1) ? shapes[groups[halfCircleIndex][0]] : groupTopCircles[halfCircleIndex];
        //Traverse the "later" shapes
            for (var secondHalfCircleIndex = halfCircleIndex + 1; secondHalfCircleIndex < groupTopCircles.length; secondHalfCircleIndex++) {
                var s2 = (groups[secondHalfCircleIndex].length === 1) ? shapes[groups[secondHalfCircleIndex][0]] : groupTopCircles[secondHalfCircleIndex];
                //If the two half circles intersect each-other, then merge them
                if (Shape.prototype.intersects(s1, s2)) {
                    if (!merged) {
                        merged = {};
                    }
                    if (!merged[halfCircleIndex]) {
                        merged[halfCircleIndex] = [];
                    }
                    //We always merge into the first group
                    merged[halfCircleIndex].push(secondHalfCircleIndex);
                }
            }
        }
        //If there was a merge then we do the effective merging and repeat this strategy for the resulting half-circles
        if (merged) {
            return PlacementStrategies.SemiCircleHorizontalRectangles(shapes, PlacementStrategies.MergeGroup(shapes, groups, merged, function (shape1, shape2) {
                //We will order horizontal-verticle rectangles here, we might refactor this function to get a comparator instead later
                return shape1.TopLeft.x < shape2.TopLeft.x;
            }));
        }
        //Angle iterator for the half circle
        var angle;
        //The amount of step with the angle iterator
        var angleStep;
        //Traverse the groups to change the coordinates
        for (var groupIndex in groups) {
            //If the group has a single element, then we jump over it
            if (groups[groupIndex].length > 1) {
                //Initialize the angle iterator and calculate its step size
                angle = Math.PI;
                angleStep = angle / (groups[groupIndex].length - 1);
                //Traverse the shapes
                for (var shapeIndex in groups[groupIndex]) {
                    //The translation is calculated based on circle coordinates
                    var translation = {
                        x: groupTopCircles[groupIndex].Center.x + (groupTopCircles[groupIndex].Diameter * Math.cos(angle) / 2),
                        y: groupTopCircles[groupIndex].Center.y + (groupTopCircles[groupIndex].Diameter * Math.sin(angle) / 2)
                    };
                    //The middle of the rectangles will place at the desired point and we need the middle coordinates for that
                    var halfDiffX = (shapes[groups[groupIndex][shapeIndex]].BottomRight.x - shapes[groups[groupIndex][shapeIndex]].TopLeft.x) / 2;
                    var halfDiffY = (shapes[groups[groupIndex][shapeIndex]].BottomRight.y - shapes[groups[groupIndex][shapeIndex]].TopLeft.y) / 2;
                    //Calculate the new bounds of the rectangle and step the iterator
                    shapes[groups[groupIndex][shapeIndex]].setTopLeftX(translation.x - halfDiffX);
                    shapes[groups[groupIndex][shapeIndex]].setTopLeftY(translation.y - halfDiffY);
                    shapes[groups[groupIndex][shapeIndex]].setBottomRightX(translation.x + halfDiffX);
                    shapes[groups[groupIndex][shapeIndex]].setBottomRightY(translation.y + halfDiffY);
                    angle += angleStep;
                }
            }
        }
        return shapes;
    }
};
//General intersects function for shapes, which gets two shapes and checks whether they intersect each-other
Shape.prototype.intersects = function (shape1, shape2) {
    //If the first shape is symmetric and the types of shapes match, it is enough to check a single direction of intersection
    //Otherwise we need to check both directions
    return ((shape1.Symmetric) && (shape1.Type === shape2.Type)) ? (shape1.Intersects(shape2)) : (shape1.Intersects(shape2) || shape2.Intersects(shape1));
};
/*Geometry*/
/*Spiderfier*/
function Spiderfier(params) {
    Initializable.call(this, params);
    var self = this;
    var isSpiderfied = false;
    this.defaultFunction = function () { };
    //Custom Spiderfy Events
    this.initialize("OnSpiderfy", this.defaultFunction, true);
    this.initialize("OnUnspiderfy", this.defaultFunction, true);
    this.initialize("rows", [], true);
    this.initialize("cm", function () {
        return cachedMarkers;
    }, true);
    this.initialize("options", {});
    this.SpiderLines = {};
    this.isCurrentlySpiderfied = function () {
        return isSpiderfied;
    };
    this.refreshRows = function (r, stopRefresh) {
        rows = r;
        if (isSpiderfied && (!stopRefresh)) {
            self.spiderfy();
        }
    };
    this.spiderfy = function (r) {
        if (r) {
            self.refreshRows(r, true);
        }
        params.OnSpiderfy(rows, self);
        isSpiderfied = true;
    };
    this.unspiderfy = function (r) {
        if (r) {
            self.refreshRows(r, true);
        }
        params.OnUnspiderfy(rows, self);
        isSpiderfied = false;
    };
    //Handles marker draw and spiderfying
    this.drawAndSpiderfy = function (r, o) {
        //First handle the spiderfy thing
        if (o) {
            self.options = o;
        }
        if (self.isCurrentlySpiderfied()) {
            self.spiderfy(r, params.cm());
            drawSpiderMarkers(r, params.cm(), self);
        } else {
            self.unspiderfy(r, params.cm());
        }
        //And then draw the markers
        drawMarkers(rows, options);
    };
}
//Gets the rectangles of the markers
function markersToRectangles(rows) {
    var shapes = [];
    var lowPoint;
    for (var rowIndex in rows) {
        //Convert the geographical point of the marker into graphical point
        lowPoint = map.latLngToLayerPoint(L.latLng(rows[rowIndex].RealLat, rows[rowIndex].RealLon));
        shapes.push(new HorizontalVerticalRectangle({
            TopLeft: { x: lowPoint.x - 18, y: lowPoint.y - 44 },
            BottomRight: { x: lowPoint.x + 18 + 0, y: lowPoint.y }
        }));
    }
    return shapes;
}
//Spiderfies rectangles with half circle strategy
function RectangleHalfCircleSpiderfy(rows, spdfr) {
    //Initialize real latitude and longitude if not already done so
    for (var rowIndex in rows) {
        if (!rows[rowIndex].RealLat) {
            rows[rowIndex].RealLat = rows[rowIndex].Lat;
            rows[rowIndex].RealLon = rows[rowIndex].Lon;
        }
    }
    //Gather the desired rectangles
    var rectangles = PlacementStrategies.SemiCircleHorizontalRectangles(markersToRectangles(rows));
    //Store the geographic coordinates
    for (var rowIndex in rectangles) {
        //Convert graphical coordinates into geographic coordinates
        var location = map.layerPointToLatLng(L.point(rectangles[rowIndex].TopLeft.x + 14, rectangles[rowIndex].BottomRight.y));
        rows[rowIndex].Lat = location.lat;
        rows[rowIndex].Lon = location.lng;
    }
}
function normalUnspiderfy(rows, spiderfier) {
    for (var rowIndex in rows) {
        if (rows[rowIndex].RealLat !== undefined) {
            rows[rowIndex].Lat = rows[rowIndex].RealLat;
            rows[rowIndex].Lon = rows[rowIndex].RealLon;
            delete rows[rowIndex].RealLat;
            delete rows[rowIndex].RealLon;
        }
    }
    for (var lineIndex in spiderfier.SpiderLines) {
        map.removeLayer(spiderfier.SpiderLines[lineIndex].polyLine);
    }
    spiderfier.SpiderLines = {};
}
//Draws spider markers
function drawSpiderMarkers(rows, cachedMarkers, spiderfier) {
    //For each row...
    for (var i = 0; i < rows.length; i++) {
        //If real location exists and differs from the display location and there is either no spider line yet or points to a different location than the expected one
        if (rows[i].RealLat && rows[i].RealLon &&
            ((rows[i].Lat != rows[i].RealLat) || (rows[i].Lon != rows[i].RealLon)) &&
            ((!spiderfier.SpiderLines[i]) || (spiderfier.SpiderLines[i].location.Lat != rows[i].Lat) || (spiderfier.SpiderLines[i].location.Lon != rows[i].Lon))
           ) {
            //Then check whether the spider line exists and remove it if so
            if (spiderfier.SpiderLines[i]) {
                map.removeLayer(spiderfier.SpiderLines[i].polyLine);
            }
            //And generate a new spider line
            spiderfier.SpiderLines[i] = { location: new L.LatLng(rows[i].Lat, rows[i].Lon), realLocation: new L.LatLng(rows[i].RealLat, rows[i].RealLon) };
            spiderfier.SpiderLines[i].polyLine = L.polyline([spiderfier.SpiderLines[i].location, spiderfier.SpiderLines[i].realLocation]);
            spiderfier.SpiderLines[i].polyLine.options.weight = 2;
            spiderfier.SpiderLines[i].polyLine.options.color = "#5f0df1";
            spiderfier.SpiderLines[i].polyLine.addTo(map);
        }
    }
}
var spiderfier;
/*Spiderfier*/

function getStrategyName(code) {
    switch (code) {
        case 2: return "Grouped";
        case 3: return "RectangleHalfCircleSpiderfy";
        default: return "Unspecified";
    }
}

function drawStrategicMarkers(rows, drawOpt) {
    if (drawOpt.strategy < 3) {
        if (drawOpt.strategy === 2) {
            drawOpt.grouped = true;
        }
        return drawMarkers(rows, drawOpt);
    } else {
        if (!spiderfier) {
            window["spiderfier"] = new Spiderfier({
                OnSpiderfy: window[getStrategyName(drawOpt.strategy)],
                OnUnspiderfy: normalUnspiderfy,
            });
        }
        spiderfier.drawAndSpiderfy(rows);
    }
}
要绘制标记,请测量标签,然后重新绘制标记,以获得标签大小。这种方法非常粗糙,我宁愿允许标签与标记或其他标签相交,这是一个令人悲哀的决定。因此,我想知道:有没有一种方法可以根据标签未来的内容获得尚未绘制的标签的宽度和高度

内容如下所示:

<div class="leaflet-label  leaflet-zoom-animated leaflet-label-right" style="z-index: 540; transform: translate3d(912px, 500px, 0px); opacity: 1;">
    <p class="orange">34534</p>
    <p>3343453</p>
</div>

34534

3343453

当然,这个div有填充和边框,但是如果我能够以某种方式读取内部的宽度和高度,我将能够添加所需的值

如果我知道标签将包含什么,是否有可靠的公式可以用来收集标签容器的边界和限制

没有

在HTML中,在将块元素添加到DOM之前,您无法知道该块元素的名称。原因是多方面的,;主要的事实是,当添加块元素时,可能会有许多不同的(非显式的)CSS选择器应用于该块元素。加上用户代理样式表、GPU字体呈现、DPI字体大小等

我在工作的时候研究过这个

这是我收集标签大小信息的一种非常简单的方法

请不要。将元素添加到DOM后使用


您可以在同一渲染帧内自由地从DOM中移除该元素(或移除传单层,因为它将具有相同的效果)。您可以将元素添加到DOM中,获取其计算尺寸,将该元素删除到DOM中,并快速执行此操作,以使浏览器不会在这两者之间点击帧渲染(除其他外,因为执行此操作时浏览器UI线程被阻塞)


这就是传单.LayerGroup.Collision的工作原理:将所有内容添加到DOM(将所有传单层添加到地图),获取所有内容的计算样式,将边界框添加到
rbush
结构,计算碰撞,在一帧内从DOM中移除元素(地图中的层)

如果我知道标签将包含什么,是否有可靠的公式可以用来收集标签容器的边界和限制

没有

在HTML中,在将块元素添加到DOM之前,您无法知道该块元素的名称。原因是多方面的,;主要的事实是,当添加块元素时,可能会有许多不同的(非显式的)CSS选择器应用于该块元素。加上用户代理样式表、GPU字体呈现、DPI字体大小等

我在工作的时候研究过这个

这是我收集标签大小信息的一种非常简单的方法

请不要。将元素添加到DOM后使用


您可以在同一渲染帧内自由地从DOM中移除该元素(或移除传单层,因为它将具有相同的效果)。您可以将元素添加到DOM中,获取其计算尺寸,将该元素删除到DOM中,并快速执行此操作,以使浏览器不会在这两者之间点击帧渲染(除其他外,因为执行此操作时浏览器UI线程被阻塞)


这就是传单.LayerGroup.Collision的工作原理:将所有内容添加到DOM(将所有传单层添加到地图),获取所有内容的计算样式,将边界框添加到
rbush
结构,计算碰撞,在一帧内从DOM中移除元素(地图中的层)

“将元素添加到DOM后,请使用window.getComputedStyle。“别无选择。正如我在问题中已经描述的,我需要在绘制标签之前获得标签的大小。你建议我画它们,然后读它们的尺寸。但是我需要它们的维度来知道在哪里绘制它们,所以如果它们已经绘制好了,那么我就不再对它们的维度感兴趣了。“您可以自由地从DOM中删除该元素”不是一个选项。如果它已经存在了,那么我对确定它的位置不感兴趣,我有很好的理由不去做那些我不会深入研究以保持事情简单的事情。长话短说:我想知道在画传单标签之前,是否有办法得到它的尺寸。你的意见是没有办法做到这一点。如果没有更好的选择,我可以测量标签并查看标签的宽度,如果一个paragraph包含n个字母,那么我可以重复使用这些尺寸,因此实际上有一种方法,但需要进行大量的研究。“这就是传单.LayerGroup.Collision的工作原理”我不用从DOM中读取数据就用数学方法计算,当我知道在哪里放置东西时,我就画出标记。如果我们忽略标签的问题,这将非常有效。我可以在不同的情况下、不同的浏览器和不同的样式中预先测量标签,但这需要一段时间。有一个解决办法,但它是痛苦的。我知道你的意见是没有别的办法了。你可能是对的,但让我们等待其他答案,看看是否还有其他信息。我明白你的意思,你想做“正确”的事情,但无论你喜欢与否,你都会受到DOM的限制。您可能希望尝试实现这一点的任何技术(例如)最终将比添加度量值删除方法花费更多的时间(并且迟早您会遇到边缘情况)。您可能希望尝试基于的方法,但迟早您会遇到边缘情况,CSS样式未应用于您正在度量的文本,你会注意到这些小故障。你不会节省任何时间,因为→测量NVAS→addToDom将花费比addToDom更多的时间→测量→removeDom:前者渲染文本两次,后者渲染文本一次
<div class="leaflet-label  leaflet-zoom-animated leaflet-label-right" style="z-index: 540; transform: translate3d(912px, 500px, 0px); opacity: 1;">
    <p class="orange">34534</p>
    <p>3343453</p>
</div>