1

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

只要我同时操作一个或几个对象,一切都会顺利进行,但是当我开始移动大组对象时,事情开始变得非常缓慢。

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

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

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

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

4

3 回答 3

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>

问候,

于 2012-09-08T19:07:25.640 回答
1

浏览器肯定会检测到对 DOM 的更改,但它们不会在每次更改时重新渲染整个 svg,它们都会排队(批处理)渲染操作(通常渲染发生在执行修改的脚本片段完成执行后的某个时间)。如果每次更改都触发了某种布局/重排操作(基本上是树遍历),我不会感到惊讶,以确定要绘制的内容和位置。

于 2012-09-09T09:42:05.303 回答
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)

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

于 2012-09-08T19:24:39.307 回答