d3-drag
Drag-and-drop
是一种易学流行的交互手势:将指针指向目标对象,按下并且拖动它到一个新的位置,然后释放。D3 的 drag 提供了方便灵活并且抽象的拖拽交互。
例子 🌰:
◎ d3.drag()
创建一个新的拖拽行为并返回自身。drag
既是一个对象,也是一个函数,通常通过 selection.call
被应用在选中的元素上。
var drag = d3.drag();
◎ drag(selection)
将拖拽应用到指定的 selection
。通常不用这个方法来应用拖拽,而是通过 selection.call
。例如,将拖拽实例应用到一个选择集上:
d3.selectAll(".node").call(d3.drag().on("start", started));
在内部拖拽行为使用 selection.on
将拖拽必需的事件绑定到元素上,事件名称都带有 .drag
,因此可以使用这个特殊的事件名来解绑拖拽事件:
selection.on(".drag", null);
◎ drag.container([container])
如果指定了 container
,则将拖拽行为的容器访问器设置为指定的对象或方法。如果没有指定 container
,则返回当前的容器访问器,默认为:
function container() {
return this.parentNode;
}
拖拽手势的 container
定义了随后 drag events 的座标系统,影响 event.x
和 event.y
。容器访问器返回的元素随后被传递给 d3.mouse
或 d3.touch
,因此需要的时候要定义好容器访问器。
默认的容器访问器返回接收到初始事件的元素的父节点,在拖动 SVG 或者 HTML 元素时,通常是合理的,因为这些元素通常通过父元素定位。但是拖动 Canvas 中的元素时,你可能需要将容器访问器设置为 Canvas
自身:
function container() {
return this;
}
此外,设置容器访问器时,还可以直接将元素设置为参数:
drag.container(canvas)
◎ drag.subject([subject])
subject
译为主体,如果 subject
指定,则为拖拽行为指定主体访问器。如果没有指定,则返回当前的主体访问器。默认为:
function subject(d) {
return d == null ? {x: d3.event.x, y: d3.event.y} : d;
}
主体代表的是 the thing being dragged (当前被拖拽) 的东西。当接收到启动输入事件时被计算,比如 mousedown
或 touchstart
, 在拖拽启动时立即被计算。
默认情况下,主体为接收原始事件元素上的 datum
。 如果 datum 没有定义,则主体为输入事件的座标。当在 SVG 中拖拽时,默认的主体为当前元素绑定的数据;但在 Canvas 中默认的主体为 Canvas 本身绑定的数据,此时自定义的主体访问器就显得有用了,比如,可以将自定义主体访问器设置为鼠标事件座标周围一定半径范围内的圆。
◎ drag.on(typenames, [listener])
此方法用于设置用于拖动的指定类型名的事件侦听器。如果 listener
指定,则将其设置为对应的 typenames
的回调。
如果对应 typenames
已经存在事件监听器则将其替换掉;如果 listener
为 null
则表示移除对应的 typenames
上的事件监听器。如果没有指定 listener
,则返回第一个对应 typenames
的事件监听器。
typenames
是一个或者由空格分割的多个 typename。type
必须为以下几种:
start
- 拖拽开始 (mousedown or touchstart)drag
- 拖拽中 (mousemove or touchmove)end
- 拖拽结束 (mouseup, touchend or touchcancel)
在拖拽过程中通过 drag.on
改变事件监听器不会影响当前的拖拽手势,相反,必须使用 event.on
。
◎ event.on(typenames, [listener])
与 drag.on
等价, 但是仅仅应用在当前的拖拽手势。在拖拽手势开始时会创建一个当前拖拽 event listeners 的 copy,这个副本会被绑定到当前拖拽手势并且可以被 event.on
修改,这对于仅接收当前手势的临时监听器很有用。
🌰:
//定义拖拽函数
var drag = d3.behavior.drag()
.on("drag", dragmove)
function dragmove(d) {
d3.select(this)
.attr("cx", d.cx = d3.event.x)
.attr("cy", d.cy = d3.event.y)
}
//绘制圆形
var circles = [{
cx: 150,
cy: 200,
r: 30
},
{
cx: 250,
cy: 200,
r: 30
}
]
svg.selectAll("circle")
.data(circles)
.enter()
.append("circle")
.attr("cx", function (d) {
return d.cx
})
.attr("cy", function (d) {
return d.cy
})
.attr("r", function (d) {
return d.r
})
.attr("fill", color)
.call(drag)
d3-zoom
◎ d3.behavior.zoom()
该行为会自动在容器元素中创建事件监听器来处理元素的缩放和平移动作,可支持鼠标事件和触摸事件。
d3.behavior.zoom()
构造一个新的缩放行为。构造之后,可以通过 selection.call()
将此行为应用于选择器:
var zoom = d3.behavior.zoom();
selection.call(zoom);
所有注册的监听器都使用 “zoom” 命名空间, 故如下可以移除缩放行为:
selection.on(".zoom", null);
◎ zoom(selection)
应用缩放行为到指定的选择器 selection
,注册所需的事件监听器,支持缩放和拖拽行为。
◎ zoom.translate([translate])
指定当前的缩放平移向量为 translate
;如果未指定 translate
,返回当前平移向量,默认:[0, 0]
。
◎ zoom.scale([scale])
指定当前的缩放比例,如果未指定 scale
,则返回当前的缩放比例,默认为1
。
Drag Events
当 drag event listener 被调用时, d3.event
会被设置为当前的拖拽事件,event
对象暴露以下属性:
- target - 相关联的 drag behavior。
- type - 字符串 “start”, “drag” 或 “end”。
- subject - 通过 drag.subject 定义的 subject。
- x - subject 的 x 座标。
- y - subject 的 y 座标。
- dx - 与上一次拖拽相比 x 座标的变化。
- dy - 与上一次拖拽相比 y 座标的变化。
- identifier - 字符串 “mouse”, 或者表示 touch identifier 的数字。
- active - 当前活动的拖拽手势的数量。
- sourceEvent - 底层原始事件比如 mousemove 或 touchmove。
event
对象也暴露了 event.on
方法。
🔗 参考文章: