我正在像这样使用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>
我在屏幕上有大约400个磁贴。您可以在此处查看外观:https://337706.playcode.io/ 尝试将鼠标悬停在某些图块上。悬停的图块应变为红色,并且没有性能问题。 如果我用颜色填充所有图块,也没有问题:
<style>
.tile {
fill: green;
}
</style>
我想用图像填充瓷砖,所以我创建了一个图案:
<defs>
<pattern patternUnits="objectBoundingBox" id="grass" width="70" height="80">
<image href="https://i.ibb.co/9ZZgDhy/tiles.png"></image>
</pattern>
</defs>
然后,用它填充瓷砖:
<style>
.tile {
fill: url(#grass);
}
.tile:hover {
fill: red;
}
</style>
之后,性能急剧下降。 (您可以在此处进行检查,但请记住,它甚至可能使您的浏览器崩溃:https://337697.playcode.io/)
我已经在Chrome上检查了分析器,它说98%的时间都花在了“复合层”上。
我已经注意到问题不是关于图像本身,而是关于<pattern>
,因为即使我删除图像并仅放置绿色矩形,性能也一样差。如果我删除图案并仅用颜色填充瓷砖,就没有问题...
如何用图像填充图块并解决此性能问题?有没有更好的设置背景图片的方法?
答案 0 :(得分:0)
使用裁剪后的图像应该更快。
我已经使用嵌套循环创建了地图,以创建一堆<use>
元素。这种方法的缺点是您无法在悬停时进行简单的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>
答案 1 :(得分:0)
我认为,用这么多SVG填充模式的复合过程要求太多。我基于这个write-up来思考。我不确定是否有改善的方法,但是还有其他方法可以实现您想要的目标。
css clip-path
代替SVG的示例。请注意,您需要在CSS中做更多的工作才能正确放置所有内容。
每个六边形是一个正方形,并且所有角都落在四分之一或一半上。这使数学变得容易一些。我绝对定位每个图块,然后在附加JavaScript时通过Javascript提供height
,width
,X(left:offset
)和Y(top:offset
)。>
如果您想玩的话,这里是Codepen。
即使有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>