梦入琼楼寒有月,行过石树冻无烟

D3 behavior

behavior,即“行为”,他主要包含了d3.behavior.drag以及d3.behavior.zoom来分别实现和处理拖拽和缩放的交互形式。

click


在先介绍 behavior前,我们需要了解到基本的鼠标事件,鼠标事件主要分为6种,主要是辨别鼠标的按下、触点等两种:

ID DA
click 鼠标单击某元素时(被 mousedown(鼠标按下) and mouseup(鼠标松开)组合在一起)
mouseover 当接收到光标触点时 ……
mouseout 当光标从 …… 移出时
mousemove 当鼠标移动时 ……
mousedown 当鼠标 按下 时 ……
mouseup 当鼠标按下松开时 ……

在下述的 code 中我们组要实现了鼠标的按下(mousedown \ click)、鼠标松开(mouseup)、光标接触(mouseover)、光标移出(mouseout)的例子,并配合过渡效果来分别的进行显示,需要值得注意的是click与 mousedown不是完全一样的,可以从下述 code 看出差别。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
var padding = {
width: 800,
height: 800
}

var svg = d3.select("body")
.append("svg")
.attr("width",padding.width)
.attr("height",padding.height)

svg.append("rect")
.attr("fill","blue")
.attr("x",200)
.attr("y",20)
.attr("width",100)
.attr("height",100)
/*
|- mouseover 收到光标时
|- mouseout 当光标移出时
|- mousedown 当鼠标按下时 / click 当鼠标按下时
|- mouseup 当鼠标松下时
*/
.on("mouseover", function () {
d3.select("rect")
.transition()
.duration(2000)
.attr("fill","red")
})
.on("mouseout", function () {
d3.select("rect")
.transition()
.duration(2000)
.attr("fill","blue")
.attr("width",100)
})
.on("click", function () {
d3.select("rect")
.transition()
.duration(2000)
.attr("width",200)
})
.on("mouseup", function () {
d3.select("rect")
.transition()
.duration(2000)
.attr("width",100)
})

drag


拖拽 (drag) 主要通过使用d3.behavior.drag来进行实现,是指通过鼠标将元素从一个位置到另一位置,通常主要分为按下鼠标、鼠标移动、鼠标松开等三个步骤,D3 为此提供了一种更为简单方法 :

ID DA FA
d3.behavior.drag() 创建一个拖拽
drag.on(type[,listener]) 设置时间监听器,主要支持三种类型,分别为:“dragstart(拖拽开始)、drag(拖拽中)、dragend(拖拽结束)“,而listener是监听函数,默认返回当前指定事件监听器
drag.origin() 设置拖拽起点,可以使得鼠标与被平移元素以相对不变的偏移量进行移动 ,如果设置了起点,那么将会在鼠标按下(mousedown)事件发生时进行调用
on.dragstart 监听 drag 拖动是否开始
on.dragend 监听 dran 拖动是否结束

在下述的 code 中,我们主要通过使用drag来进行移动,当移动的时候将数据cy\cx数据赋值到当前svg图像的x\y轴中,并通过使用dragstartdragend来进行监听drag是否被拖动,从而添加过渡属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
/* 基本 svg 样式 */
var padding = {
width: 800,
height: 800
}

var svg = d3.select("body")
.append("svg")
.attr("width",padding.width)
.attr("height",padding.height)

/* 圆数据与位置 */
var circles = [
{cx: 50, cy: 50, r:20}
]

/*
|_ 起点坐标 origin
|_ 将拖拽时的坐标赋值给 event.x \ event.y
|_ 当拖拽开始时将颜色设置为 red 并将圆弧半径设置为 50 dragstart
|_ 拖拽结束后将颜色与半径设置原来的样子 dragend
*/
var drag = d3.behavior.drag()
.origin(function (d,i) {
return {x: d.cx, y: d.cy}
})
.on("drag", function (d) {
d3.select(this)
.attr("cx", d.cx = d3.event.x)
.attr("cy", d.cy = d3.event.y)
})
.on("dragstart", function (d) {
d3.select("circle")
.transition()
.duration(2000)
.attr("fill","red")
.attr("r",50)
})
.on("dragend", function (d) {
d3.select("circle")
.transition()
.duration(2000)
.attr("fill","blue")
.attr("r",20)
})

/* 绘制圆 */
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","blue")
.call(drag)

zoom

缩放(zoom)是在数据可视化中较为常用的小细节之一,因此 d3 为我们提供了d3.behavior.zoom方法来用于构建缩放行为。

ID DA FA
d3.behavior.zoom 构建一个缩放行为
zoom(selection) 将此行为应用到选择集中
zoom.translate() 设置缩放的平移量,默认为0,并返回当前的平移向量
zoom.scale() 设置初始放大、缩小量的最大值,默认为0~∞
zoom.center() 设置缩放的中心点,默认为鼠标的位置
zoom.x() 设置一个 x方向比例尺,比例尺会随着放大、缩小改变定义域
zoom.y() 设置一个 y方向比例尺,比例尺会随着放大、缩小改变定义域
zoom.on 设置事件类型,主要分为:”zoomstart(缩放开始)、zoom(正在缩放)、zoomend(缩放结束)“三种


通过on.zoom来计算出缩放的开始并因此得到圆的大小和坐标信息,之后绑定数据进行绘制,在这其中主要通过使用scaleExtent来设置缩放的倍数,其方法主要分为最小值、最大值,下述code中的缩放最大为2倍,最小为1倍,并设置基础的比例尺,通过缩放来观察比例尺的缩放变化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
/* 基本 svg 结构 */
var padding = {
width: 800,
height: 800
}

var svg = d3.select("body")
.append("svg")
.attr("width",padding.width)
.attr("height",padding.height)

var circles = [
{cx: 150, cy: 200, r:30}
]

/* 比例尺 */
var x = d3.scale.linear()
.domain([0, padding.width])
.range([0, padding.width])


var y = d3.scale.linear()
.domain([0, padding.height])
.range([0, padding.height])

/* 计算出基本缩放后大小与位置 */
var zoom = d3.behavior.zoom()
.x(x)
.y(y)
.scaleExtent([1,2])
/*
|_ 缩放开始进行颜色过渡 zoomstart
|_ 缩放中计算出位置与大小 zoom
|_ 缩放结束进行控制台输出 zoomend
*/
.on("zoomstart", function () {
d3.select("circle")
.transition()
.duration(2000)
.attr("fill","red")
})
.on("zoom", function (d) {
d3.select(this)
.attr("transform","translate(" + d3.event.translate + ")" + /* 平移位置 */
"scale(" + d3.event.scale + ")") /* 缩放大小 */
console.log("x 的定义域" + x.domain())
console.log("y 的值域" + y.domain())
})
.on("zoomend", function () {
d3.select("circle")
console.log("缩放结束")
})

/* 绑定位置数据到 元素 <g> */
var g = svg.append("g")
.call(zoom)

/* 绘制圆 */
g.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", "blue")
⬅️ Go back