【问题标题】:SVG <g> element dragging causes flickering issue using d3使用 d3 拖动 SVG <g> 元素会导致闪烁问题
【发布时间】:2018-04-24 06:02:00
【问题描述】:

我一直在尝试使用 d3 库通过使用 transform translate 来拖放 dvg 元素。我可以拖动一个元素,但拖动时它会闪烁。

到目前为止,我一直在从下面的链接中搜索并进行反复试验,但这对我没有帮助。

"Stuttering" drag when using d3.behavior.drag() and transform

D3.js: Dragging everything in group ('g') by element contained in the group using origin() function

How to drag an svg group using d3.js drag behavior?

对于最后一个链接,我想我无法理解导致此问题的此要求的 svg 结构的必要性。有人可以帮我吗?

【问题讨论】:

  • 我不熟悉 d3 库,但我注意到您拖动的函数参数有时会收到 undefined 作为参数,这会导致它闪烁。您可以首先检查 .on("drag", dragged) 是否从正确的位置调用,并将正确的参数数据传递给回调。
  • 但是,我是 D3 的新手,对此我不确定,但该参数尚未在函数中使用。我尝试将其删除,但没有成功
  • 我已经发布了这个问题的原因和解决方案here
  • @roland:出于我的好奇,如果不将任何内容附加到拖动对象或仅更改我的 svg 的结构,难道不可能吗?这个要求的原因是我正在处理大型 svg,如果可能的话,我不想从 javascript 添加任何内容
  • @DipeshRaichana:你尝试过第二种方法吗?

标签: javascript d3.js svg drag-and-drop


【解决方案1】:

为此,使用d3.event 而不是d3.mouse 更容易。这是带有.data()的d3风格方法:

  1. 读出源 svg 中 &lt;g&gt;translate 属性。
  2. translate 的x 和y 值添加到d3 对象的data
  3. 在拖动事件期间调整&lt;g&gt;datatranslate

function bindDragging() {

    // Define d3 object
    var g = d3.select("#group");

    // Get translate (from: https://stackoverflow.com/a/38230545/3620572)
    var elem = document.createElementNS("http://www.w3.org/2000/svg", "g");
    elem.setAttributeNS(null, "transform", g.attr("transform"));
    var matrix = elem.transform.baseVal.consolidate().matrix;
    var x = matrix.e;
    var y = matrix.f;

    g.data([{
        // Position of the group
        x: x,
        y: y
        }])
        .call(d3.drag()
            .on("start", dragstarted)
            .on("drag", dragged)
            .on("end", dragend)
        );

    function dragstarted(d) {
        g.selectAll("rect").classed("active", true);
    }

    function dragged(d) {
        // Set the new position
        d.x += d3.event.dx;
        d.y += d3.event.dy;
        d3.select(this).attr("transform", function (d) {
            return "translate(" + [d.x, d.y] + ")"
        });

    }

    function dragend(d) {
        g.selectAll("rect").classed("active", false);
    }
}
bindDragging();
#group {
    stroke-width: 3;
    stroke: #808080;
    cursor: -webkit-grab;
    cursor: grab;
}

.active {
    stroke: #ff0000;
    cursor: -webkit-grabbing;
    cursor: grabbing;
}
<div class="svgContainer">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 776.63 680.09">
    <g id="group" transform="translate(0, 0)">
        <rect width="100" height="50" style="fill:rgb(40, 40, 109);" />
        <rect width="100" height="50" y="50" style="fill:rgb(63, 149, 75);" />
    </g>
</svg>
</div>
<script src="https://d3js.org/d3.v4.min.js"></script>

【讨论】:

  • 非常感谢。我想请你分享它背后的思考过程。我的意思是,我的代码中存在什么问题,您是如何解决的(如果您能回答,将不胜感激)?
  • @DipeshRaichana:不客气。这正是 D3.js 的用途。你对 x 和 y 变量做了一些奇怪的事情。最好将数据绑定到 D3 对象(D3 = 数据驱动文档)。首先,您必须从给定的 svg 中读取数据(在本例中为变换的 x 和 y)。然后将此数据绑定到 D3 对象(&lt;g&gt;)。现在您可以使用这些数据进行易位。顺便说一句,JavaScript 可能会更短。
  • 感谢您的解释。我使用 D3 是因为它的功能不仅仅是使用 SVG 进行拖放(我搜索并知道 svg 动画不能与 jquery 一起使用)。
猜你喜欢
  • 1970-01-01
  • 2021-06-24
  • 1970-01-01
  • 2023-03-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多