[英]Filling hundreds SVG paths with an image causes serious performance issues
I'm creating hexagonal tiles using SVG like that: 我正在使用SVG创建六角形瓷砖,如下所示:
<style>
.tile:hover {
fill: red;
}
</style>
<svg width="1000" height="1000">
<g>
<path
d="M-17.32050807568877,-10L0,-20L17.32050807568877,-10L17.32050807568877,10.000000000000002L0,20.000000000000004L-17.32050807568877,10.000000000000002"
class="tile"></path>
...
</g>
</svg>
I have about 400 tiles on the screen. 我的屏幕上有大约400个磁贴。 You can check how it looks here: https://337706.playcode.io/ Try to hover over some tiles.
您可以在此处查看外观: https : //337706.playcode.io/尝试将鼠标悬停在某些图块上。 Hovered tiles should become red, and there is no performance issues.
悬停的图块应变为红色,并且没有性能问题。 There is also no issue if I fill all of the tiles with color:
如果我用颜色填充所有图块,也没有问题:
<style>
.tile {
fill: green;
}
</style>
I'd like to fill the tiles with an image, so I have created a pattern: 我想用图像填充图块,所以我创建了一个模式:
<defs>
<pattern patternUnits="objectBoundingBox" id="grass" width="70" height="80">
<image href="https://i.ibb.co/9ZZgDhy/tiles.png"></image>
</pattern>
</defs>
And then, fill tiles with it: 然后,用它填充瓷砖:
<style>
.tile {
fill: url(#grass);
}
.tile:hover {
fill: red;
}
</style>
After that, the performance drops dramatically. 之后,性能会急剧下降。 (you can check it here, but bear in mind it may even crash your browser: https://337697.playcode.io/ )
(您可以在此处进行检查,但请记住,它甚至可能使您的浏览器崩溃: https : //337697.playcode.io/ )
I have checked the profiler on Chrome, it says 98% of the time is spent on "Composite Layers". 我已经在Chrome上检查了探查器,它说98%的时间都花在了“复合层”上。
I have noticed that the problem is not about the image itself but about the <pattern>
because even if I remove the image and place just green rectangle instead, the performance is the same bad. 我注意到问题不在于图像本身,而是与
<pattern>
有关,因为即使我删除图像并仅放置绿色矩形,其性能也一样差。 If I remove the pattern and just fill the tile with color, there is no issue... 如果我删除图案并仅用颜色填充瓷砖,则没有问题...
How can I fill the tiles with image and fix this performance issue? 如何用图像填充图块并解决此性能问题? Is there a better way of setting the background image?
有设置背景图片的更好方法吗?
It should be quicker using clipped images. 使用裁剪的图像应该更快。
I've created the map using a nested loop to create a bunch of <use>
elements. 我使用嵌套循环创建了地图,以创建一堆
<use>
元素。 The downside to this method is that you can't do a simple CSS colour change on hover. 这种方法的缺点是您无法在悬停时进行简单的CSS颜色更改。
var map = document.getElementById("map"); var SVG_NS = map.namespaceURI; var XLINK_NS = "http://www.w3.org/1999/xlink"; var H_STEP = 34.64; var V_STEP = 30; var y = 0; for (let j=0; j<20; j++) { var xStart = (j % 2) ? (H_STEP / 2) : 0; for (let i=0; i<20; i++) { addUse("grass", xStart + i * H_STEP, j * V_STEP); } } function addUse(defId, x, y) { var use = document.createElementNS(map.namespaceURI, "use"); use.setAttributeNS(XLINK_NS, "xlink:href", "#"+defId); use.setAttribute("x", x); use.setAttribute("y", y); map.appendChild(use); }
<svg width="1000" height="1000"> <defs> <clipPath id="hexagon"> <path d="M0,10 L17.32,0 L34.64,10 L34.64,30 L17.32,40 L0,30 Z"/> </clipPath> <image id="grass" href="https://i.ibb.co/9ZZgDhy/tiles.png" width="105" height="80" clip-path="url(#hexagon)"/> </defs> <g id="map"> </g> </svg>
I think the composite process with that many SVG's filled with a pattern is just asking too much. 我认为,包含许多SVG且填充有模式的复合过程的要求太多。 I'm basing that thought on this write-up .
我在此基础上这个想法写了 。 I'm not sure if there is a good way to improve that, but there are other ways to accomplish what you want.
我不确定是否有改善它的好方法,但是还有其他方法可以实现您想要的。
css clip-path
in place of an SVG. css clip-path
代替SVG的示例。 Note you need to do a bit more work in CSS to correctly position everything. 请注意,您需要在CSS中做更多的工作才能正确放置所有内容。
Each hexagon is a square and all corners land on a quarter or half. 每个六边形都是一个正方形,所有角点占四分之一或一半。 That makes the math a bit easier.
这使数学变得容易一些。 I'm absolutely positioning each tile and then providing
height
, width
, X ( left:offset
) and Y ( top:offset
) via the Javascript when they're appended. 我绝对定位每个图块,然后在附加它们时通过Javascript提供
height
, width
,X( left:offset
)和Y( top:offset
)。
Here's a Codepen if you want to play with it. 如果您想使用Codepen ,可以使用它。
It seems quite performant even with 2500 elements... 即使有2500个元素,它的表现也似乎不错 。
var container = document.getElementById("wrapper"); var totalCols = 10; var totalRows = 15; var stepX = (1/totalCols) * 100; var stepY = stepX * 0.75; for (let r=0; r<totalRows; r++ ){ for(let c=0; c<totalCols; c++){ var offset = (r % 2) ? (stepX * 0.5) : 0; addHexagon(offset + c * stepX, r * stepY); } } function addHexagon (x,y) { var newPos = 'top: ' + y + '%;' + 'left: ' + x + '%;' + 'width: ' + stepX +'%;' + 'height: ' + stepX + '%;' var el = document.createElement('div') el.setAttribute('class', 'el') el.setAttribute('style', newPos); container.appendChild(el); }
#wrapper { width:1000px; height: 1000px; background: #333; position: relative; overflow:hidden; } .el { position: absolute; /* set height & width using js */ /* make the hexagon and mask the content */ clip-path: polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%); /* asethetic only */ background-image: url(https://images.unsplash.com/photo-1560146491-308b0f69a52a?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=200&q=80); background-size: cover; background-position: center center; background-repeat: no-repeat; } .el:hover { background-color: blue; background-image: none; }
<div id="wrapper"></div>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.