可以推迟SVG的渲染,直到我完成操作它为止?

时间:2012-09-08 15:50:56

标签: javascript svg

我正在构建一个使用SVG在浏览器中运行的复杂GUI。 SVG有许多可以操作的对象。

只要我同时操纵一个或几个物体,一切都顺利进行,但是当我开始移动大群物体时,事情开始变得非常缓慢。

我通过更改每个属性来移动SVG元素。我认为这很慢,因为浏览器每次更改DOM时都会渲染SVG,因此要移动一组元素,SVG会被渲染多次,因为要移动的元素。这是对的吗?

我做了一个实验,我认为证明了我的观点。如果我将要移动的所有元素分组到SVG组中,然后通过更改其transform属性来移动该组。此举非常顺利。在这种情况下,我只更改SVG DOM一次,SVG只重新渲染一次。

问题是我不能使用这种技术,因为元素不是一直以相同的方式分组。每次重新组合元素似乎都会增加许多不必要的复杂性。

我想知道是否有办法推迟SVG的渲染,直到我移动所有对象?

3 个答案:

答案 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)

因此,在这种情况下,事件仅在两次时触发,一次按下鼠标按钮,第二次在释放时触发。