【问题标题】:svg.js svg.draggable.js and manipulation of appearancesvg.js svg.draggable.js 和外观操作
【发布时间】:2017-05-16 17:56:09
【问题描述】:

我想使用svg.js in 来实现拖放,并操纵图形元素的外观。它主要是有效的,但我不完全明白为什么。

我已经从我的应用程序中提取了基本部分来说明我的应用程序的情况。可以在那里玩,看看效果。

https://jsfiddle.net/bwl21/ex8dcxtm/12/

SVG 由我的应用程序生成为字符串。我通过将 SVG 添加到 jsfiddle 中的 HTML 窗格来模拟这一点。

我有一个函数“set_draggable(id)”,它获取 svg 元素的 id 并附加一个拖动处理程序。

function set_draggable(svg_element) {

  var xx = SVG.get(svg_element);
  xx.addClass("zn_draggable");

  xx.draggable(function(x, y) {
    return {
      x:  Math.floor(x),
      y:  Math.floor(y)
    }
  });

  var sx = 0,
    sy = 0;
  xx.on('dragstart', function(e) {
    sx = e.detail.p.x;
    sy = e.detail.p.y;
    this.fill("red");
  });

  // todo: don't know why 'this' is the only way to change the filling ...
  xx.on('dragend', function(e) {
    this.fill("green");
    var result = {
      delta: [ e.detail.p.x - sx, e.detail.p.y - sy],
      element: svg_element
    };
    alert(JSON.stringify(result));
  })
}


set_draggable("ZN_18");
set_draggable("ZN_19");
set_draggable("ZN_20");
set_draggable("ZN_21");

我的问题:

  1. 在可拖动事件处理程序中,我想更改对象的颜色。 为什么“this”指的是拖动的对象?这是我发现应用 fill() 效果的唯一方法。我尝试使用xx,这是我附加可拖动的dom节点。还尝试使用e.target.fill("red")

  2. 当拖动 Fermata - Character(这是一条路径)时,颜色不会改变。它在拖动文本时起作用。 可能是什么原因?

    bwl21的回答:同时我发现组的属性并没有覆盖孩子的属性。所以我不得不从路径中删除描边和填充。

    尽管如此,我没有设法导航到孩子并更改那里的属性。

  3. 当拖动 ZN_19 时,它可以仅垂直移动,因为我将其设为可拖动。如果我将它包装在一个组中(如 ZN_20)并在其上调用 draggable(),我可以随意移动它。

  4. 有没有更好的方法来获得作为拖动结果的增量?我将 x 和 y 存储在 'dragstart' 处理程序中,并在 'dragend' 处理程序中计算增量。我希望增量是整数,因为我通过传递给 draggable() 的函数对其进行舍入。

  5. 如果我有很多对象(我的应用程序大约有 300 个),我会因为创建很多处理程序而面临性能问题吗?有没有更好的方法来做到这一点。

欢迎任何帮助。

【问题讨论】:

    标签: javascript svg svg.js


    【解决方案1】:

    哇,这是一堆问题。我会努力解决的。

    1。为什么'this'指的是拖动的对象?

    这是 svg.js 通常所做的事情。所有事件处理程序都在元素的上下文中执行。 所以点击元素时会打印true

    el.on('click', function() { console.log(this == el) })
    

    所以是的,您可以改用xx,它在您的示例中工作得很好。只需将this 替换为xx

    但是,this 是一种保存方式,因为在使用可能在其他地方重新清除的外部变量时,您可能会遇到变量范围问题(典型示例:在循环中附加事件处理程序)

    2。为什么fermata的填充不改变

    这已经被正确回答了。作为一个一般提示,我可以说:如果组仅具有一种形状,则不要使用它们。没有必要这样做。

    关于在 dom 中导航的后续问题:svg.js 有一个精彩的文档。只需在http://svgjs.dev/ 的搜索中输入children

    您有多种可能性:

    el.children() // array
    el.get(index) // element at index
    el.first() // first element
    el.last() // last element
    

    3。为什么拖动文本只能垂直工作

    您的 svg 不是使用 svg.js 生成的。 svg.js 将每个第一级 tspan 视为一个新行 IF 它是用 svg.js 创建的。如果不是,它没有什么特别的。在您的情况下,这意味着:文本 IS 移动了(查看 dom - 您可以看到它)。但是,在您的 svg 代码中,您在 tspan 中将 x 坐标重置为 80,以便它永远留在那里。如果您不希望这样,请不要使用x,而是使用dx 或在tspan 上调用newLine(),这将启用对行的特殊处理,其中还包括在文本x 坐标更改时对x 坐标的更改。

    对此的说明:我在您的示例小提琴中这样做了,这使文本消失了。那是因为文本本身有一个 189 的 x 不在屏幕上,所以你需要先将它调整为 80

    4。有没有更好的方法来获得作为阻力结果的增量?

    没有。

    在将坐标设置在元素上之前,会对坐标应用舍入。但是:在事件对象中给出了原始点,因为它是事实的来源

    5。使用许多元素时是否存在性能问题

    大量元素会减慢 dom 操作。所以不要将数百个元素一起移动。仅仅对它们应用处理程序应该不是问题。

    但是,性能还取决于浏览器。尝试编写高性能代码。通过定义它们(el.draggable(nameOfFunc))重用draggable-constraint函数,尽量避免在处理程序中访问外部变量(如xx),因此不需要生成闭包,不要在拖动上做繁重的工作,使用dragend代替繁重的工作。

    希望我能帮上忙

    【讨论】:

    • 非常感谢您的详细回答。它真的很有帮助。我为细节添加了单独的 cmets,
    • WRT 2. 我没有设法使路径与光标一起移动而不将其包装在一个组中。路径数据不在最终坐标中,所以我必须对其进行转换。我看到了导航方法,但没有设法更改属性。我会再试一次。同时,通过从路径中删除属性,我有一个可行的解决方案。我现在在组中还有一个手柄,以便更容易用鼠标捕捉它。
    • WRT 3:svg 是在 svg.js 之外生成的,因为我没有足够早地找到库。而且我计划将 SVG 生成器移至无法访问 DOM 的网络工作者。将 SVG 生成为字符串非常容易。我也有问题,SVG 必须与我使用 jspdf 创建的 PDF 看起来相同。所以我需要控制每一行文本。我试过usig;但它没有用。 dx 添加到上一行的末尾。使其工作的唯一方法是将其包装在一个组中并拖动该组。
    • WRT4:你的意思是在拖动的事件对象中我应该找到原始(拖动开始的位置)位置吗?我找不到它。
    • WRT 5:到目前为止我没有性能问题。我不会拖动 300 个元素。但是感谢您的提示,为了安全起见,我将相应地修改代码。但由于我将起始坐标作为外部变量,恐怕我会继续使用正在生成的闭包。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-31
    • 2011-03-01
    相关资源
    最近更新 更多