【 D3.js 进阶系列 — 6.0 】 拖拽的应用(Drag)

拖拽(Drag)是交互式中很重要的一种,本文将讲解拖拽的使用方法。

1. drag 的定义

D3中可用 d3.behavior.drag() 来定义 drag 行为。

第 2 行表示当 drag 事件发生后即调用 dragmove 函数。除了 drag 事件之外,还有 dragstart 和 dragend 事件,这一点在【进阶 – 第 2.1 章】中有过类似的叙述。

dragmove()里,出现了 d3.event.x 和 d3.event.y 两个变量,这是当前鼠标的位置。我们后面将绘制圆,这里的意思是把圆重新绘制到当前鼠标所在处。

2. 绘制圆

绘制圆的方法相信大家都很熟悉了。最后在圆的选择集中使用 call 函数,调用刚才定义的 drag 行为即可。call函数我们前面说过,即将选择集自身作为参数,传递给 drag 函数。

3. 结果

结果如下,拖拽试试:

源代码单击以下链接后查看:

http://www.ourd3js.com/demo/J-6.0/drag.html

谢谢阅读。

文档信息

【 D3.js 进阶系列 — 6.0 】 拖拽的应用(Drag)》上有21条评论

  1. 请问drag可以作用在画布上,让画布上的所有元素一起拖动吗?
    var svg = d3.select(“#body1″).append(“svg”).attr(“width”,
    width).attr(“height”,
    height).attr(“style”,
    “float:left;”)
    .call(d3.behavior.drag().on(“drag”, dragmove));

    请问这个dragmove 要怎么写?

  2. 请教楼主:
    有3条path,有可能重叠,想要在mouseover时把当前path放在最上层,mouseout时恢复原状。
    Svg中没有类似z-index的属性,尝试用了this.parentNode.appendChild(this);但是在IE下会有兼容问题,mouseout事件捕获不到。
    请问LZ遇到过类似问题,并有什么好的解决方案吗?

    • 您好,我想您一定调查过这个问题了。正如您所知道的,SVG没有z-index属性,其元素的渲染是完全按照元素的先后顺序决定的。

      解决这类问题的办法,可以通过对元素进行重新排序来解决。
      d3 的 selection.sort() 可以通过传入一个比较器,将选择集中的元素重新排序。 解释起来不好说,我写了一个例子,实现了此功能,希望能给你作为参考。粘贴之后可直接运行。

      主要思路是:对于三个图形元素,分别绑定三个数据,并且按照其初始先后顺序赋一个z_index值。以后,当mouseover触发时,将被触发元素的z_index设置为比其他元素都大的值,然后排序,这样它就位于最前端了。mouseout触发后,再恢复原值。

      谢谢。

  3. 不知道博主用过jquery ui的drag and drop模块,看你说D3的drag功能,那么应该不会没有与之对应的drop功能吧

    • 我没有用过 jquery 的 drop 模块,刚在网上查了下才知道那是什么样的功能。

      很遗憾,D3中没有实现这一项功能,你有两个方法解决此问题:

      1. JQuery 和 D3 并用即可,没有规定一个网页中只用其中一个。其实它们两者的功能目标是不同的,D3 主要是封装了很多可视化图表的算法,让用户不必自己去学习了,不是要代替 JQuery 的意思。

      2. 可以在 D3 的基础上实现以下 Drop 的功能,并不会太困难的。

      希望能够帮到你,谢谢。

  4. 你好博主,我是新手,想请教下您几个问题:
    1.就比如说您的这个例子,您怎么知道D3里面有这个d3.behavior.drag()来定义拖拽行为呢?
    2.加入我写好了一个html,发给朋友,如何才能让朋友点开也能看到我的动画呢?需要怎么设置?
    3.http://www.drbunsen.org/kmeans-pp-silhouettes/,我是学习机器学习的,假如我有一个聚类算法,如网站,他的这个算法能借助D3.js来实现吗?

    • 1. 当然是看API学习的,可以参考 d3js.org
      2. 可能这位兄台没怎么接触过网络编程,建议在百度上搜索 “Web开发入门” 之类的关键词。这个一时半会解释不清。
      3. 对于 Kmeans算法,我只听过其名,不太熟悉具体内容,不知道它到底是做什么的。不过D3中已经封装了很多算法,大多数情况下不需要自己写算法的,除非你仅仅使用D3的“绘制”功能。

      希望能够帮到你,谢谢。

      • 您好,我是网络编程新手,对数据可视化感兴趣所以就想来研究研究d3.js,问一下博主就如同你说的d3封装了很多算法,那像(3)中网站中的,我是觉得他是先将kmeans++算写进网页,然后在调用什么来绘制可视化效果的,我就不知道有没有用d3.js来实现数据挖掘分类聚类等可视化效果的案例?

        • 1. 他使用了不少 d3 中的函数,但是都是诸如求和、求平均值、求等差数列等简单的数学函数,d3的核心功能他并没有使用。算法是他自己写的。
          至于得到了计算的结果,他怎么显示图形的,那个网页中没有告诉我们。

          2. 我对于“数据挖掘分类聚类”不太熟悉,不知道是怎样的功能。

          欢迎进入数据可视化的研究,希望能够多多交流。

          谢谢。O(∩_∩)O

  5. 请问如何能使用d3的方法对div进行拖拽呢?

    • //定义一个拖拽对象
      var drag = d3.behavior.drag()
      .on(“drag”, dragmove);

      //定义拖拽事件触发时的函数
      function dragmove(d) {
      d3.select(this)
      .style(“left”, d3.event.x )
      .style(“top”, d3.event.y );
      }

      //在body里插入一个div元素
      var div = d3.select(“body”).append(“div”);

      //设置样式属性,将position属性改成绝对定位(主要是这个)
      div.style({
      “position”: “absolute”,
      “width”: “200px”,
      “height”: “200px”,
      “background-color”: “red”
      });

      //调用拖拽对象
      div.call(drag);

      你把上面的代码复制运行下吧,可以直接用的。但是,在拖拽时鼠标位置总会处于矩形的左上角,在这里为了使代码简短且容易理解,不添加多余代码来解决此问题。

      如果有问题欢迎随时留言,谢谢。

      • 先感谢一下~为什么在我这还是拖不动呢……

        • function dragmove(d) {
          d3.select(this)
          .style(“left”, d3.event.x + “px”)
          .style(“top”, d3.event.y + “px”);
          }
          改成这样就可以了,谢谢啦!

          • 这可能是浏览器的问题,我用的是Chrome,估计谷歌浏览器自动添加了px。

            总之解决了就好。O(∩_∩)O~

  6. Drag

    //创建一个SVG容器
    var svgContainer = d3.select(“body”).append(“svg”)
    .attr(“width”,1200)
    .attr(“height”,1200);
    var drag = d3.behavior.drag()
    .on(“drag”, dragmove);
    //画长方形
    var rectangle = svgContainer.append(“rect”)
    .attr(“x”,10)
    .attr(“y”,10)
    .attr(“width”,250)
    .attr(“height”,100)
    .attr(“fill”,”black”)
    .call(drag);
    function dragmove(d) {
    d3.select(this)
    .attr(“x1″, d.x1 = d3.event.x )
    .attr(“y1″, d.y1 = d3.event.y )
    .attr(“width”, d.width = d3.event.x )
    .attr(“height”, d.height = d3.event.y );
    }

  7. 楼主 在fragmove中的代码:
    .attr(“cx”, d.cx = d3.event.x )
    .attr(“cy”, d.cy = d3.event.y );
    属性值这么写我这为什么跑不起来啊,改成如下就行了
    .attr(“cx”, d3.event.x )
    .attr(“cy”, d3.event.y );
    有啥区别啊

    • d.cx = d3.event.x 的意思是先将 d3.event的值赋值给 d.cx,d.cx是原数据。修改了原数据后,再通过attr来修改圆的位置。

      如果只是写成 .attr(“cx”, d3.event.x ) 则不会修改源数据,而只是改变位置。

      两种都行,看你有没有要修改原数据的需求。

      至于为什么跑不起来,可能是你的数据不是像我这么定义的吧,我不看全部代码的话判断不了。

评论已关闭。