我正在构建一个使用SVG在浏览器中运行的复杂GUI。 SVG有许多可以操作的对象。
只要我同时操纵一个或几个物体,一切都顺利进行,但是当我开始移动大群物体时,事情开始变得非常缓慢。
我通过更改每个属性来移动SVG元素。我认为这很慢,因为浏览器每次更改DOM时都会渲染SVG,因此要移动一组元素,SVG会被渲染多次,因为要移动的元素。这是对的吗?
我做了一个实验,我认为证明了我的观点。如果我将要移动的所有元素分组到SVG组中,然后通过更改其transform属性来移动该组。此举非常顺利。在这种情况下,我只更改SVG DOM一次,SVG只重新渲染一次。
问题是我不能使用这种技术,因为元素不是一直以相同的方式分组。每次重新组合元素似乎都会增加许多不必要的复杂性。
我想知道是否有办法推迟SVG的渲染,直到我移动所有对象?
答案 0 :(得分:1)
也许您可以尝试从dom树中删除它,然后在更改后将其添加回来,例如:
<!DOCTYPE html>
<html>
<script type="text/javascript">
function change () {
var mySVG = document.getElementById('mySVG'),
circle = document.getElementById('myCircle'),
body = document.body;
body.removeChild(mySVG);
circle.setAttribute('cx', '150');
circle.setAttribute('cy', '100');
circle.setAttribute('r', '80');
body.appendChild(mySVG);
}
</script>
<body>
<button onclick="change();">change</button>
<svg id="mySVG" xmlns="http://www.w3.org/2000/svg" version="1.1">
<circle id="myCircle" cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red" />
</svg>
</body>
</html>
此致
本
答案 1 :(得分:1)
浏览器检测到对DOM的更改,但是每次更改都不会重新呈现整个svg,它们都会对渲染操作进行排队(批处理)(通常在脚本片段执行修改后的某个时间进行渲染)已完成执行)。如果每个更改都触发了某种布局/重排操作(基本上是树遍历),我不会感到惊讶,以确定绘制的内容和位置。
答案 2 :(得分:0)
从你的问题描述中,它听起来像一个拖放界面,你可以选择多个元素并移动它们。它可能不是拖放,但原则以同样的方式解决。你有三个事件,开始,移动和结束,拖放它看起来像这样:
start = function(e) {
//capture the initial position
}
move = function(e) {
//change the x and y attributes or transform attr
}
end = function(e) {
//finish up
}
svg.addEventListener("mousedown", start)
svg.addEventListener("mousemove", move)
svg.addEventListener("mouseup", end)
现在,如果您只想在操作结束时更改属性,则可以执行以下操作:
start = function(e) {
//capture the initial position
}
end = function(e) {
//change the x and y attributes or transform attr
//finish up
}
svg.addEventListener("mousedown", start)
svg.addEventListener("mouseup", end)
因此,在这种情况下,事件仅在两次时触发,一次按下鼠标按钮,第二次在释放时触发。