D3中,选择元素的函数有两个select
和selectAll
,两种方法都很常用,select返回匹配选择器的第一个元素,而selectAll返回匹配选择器的所有元素。
选择所需元素的方法:
d3.select("body"); //选择body元素
d3.select("#tp1"); //选择id为tp1的元素
d3.select(".tp2"); //选择类为tp2的元素
当然,也可以对选择集中的元素再进行选择:
d3.select("body")
.selectAll("p");
d3.select
和 d3.selectAll
所返回的对象称为选择集 selection。
利用 selection.attr(name,[]) 来设置或获取选择集的属性。
利用 selection.text([]) 设定或获取选择集的文本内容。
添加元素的方法为 selection.append(name) ,在选择集的末尾添加一个元素,name为元素的名称。
插入元素的方法为 selection.insert(name, [before]) ,name是插入元素的名称,before为CSS选择器的名称,将元素插入到指定元素之前。
删除选择集中的元素 selection.remove() 。
对于d3.select
和 d3.selectAll
返回的选择集是没有数据的。数据绑定的过程就是让这些被选择的元素中 “含有” 数据。
selection.datum(value)
选择集中的每个元素都绑定相同的数据value。
selection.data(values, [key])
选择集中的每一个元素分别绑定数组values中的每一项,key为键值函数,用于指定绑定时的对应规则。
在data绑定之后,有三种情况,分别按驻足长度和元素数量的关系如下:
d3.selectAll("p")
.data(d)
.enter()
.append("p")
键函数key:
只有在选择集原来已经有数据的情况下,使用键函数才有效果!
比如有如下内容:
<body>
<p></p>
<p></p>
<p></p>
<script src="https://d3js.org/d3.v5.js"></script>
<script>
let Data = [{name: "p1", data: 12}, {name: "p2", data: 17}, {name: "p3", data: 14}];
let p = d3.select("body").selectAll("p")
.data(Data)
.text(function (d) {
return d.name + ':' + d.data;
});
</script>
</body>
let DataEntry = [{name: "p5", data: 17}, {name: "p4", data: 14}, {name: "p6", data: 12}];
p.data(DataEntry, d => d.data)
.text(function (d) {
return d.name + ':' + d.data;
});
可以看到此时p中的元素变为:
可以看到data作为键值,并没有按照DataEntry中的顺序进行依次绑定,而是保持原本顺序不变,使键值对应的数据作出更新。可以利用这一性质在制作动态图时更新数据。
d3.transition()
创建一个过渡效果。对于每个选择集都可以使用**transition()**方法创建过渡。
transition.delay([value])
设定延迟时间。过渡经过一段时间后才发生,单位是毫秒。
transition.duration([value])
设定过渡的持续时间。单位为毫秒。
默认情况下,如果不设置时间的话delay为0ms,duration为250ms。
transition.ease(value,[])
设定过渡样式、在目标处弹跳几次等方式。
过渡前后的状态不同,因此需要指定过渡前后元素的不同属性。
transition.attr(name,value)
属性name过渡到目标值value,value可以是一个函数。
例如如下代码:
.attr("r", function (d) {
//...
})
.attr("cx", function (d) {
//...
})
.attr("cy", function (d) {
//...
})
.transition()
.delay(3000)
.duration(2000)
.attr("r", function (d) {
//...
})
.attr("fill", function (d) {
//...
});
transition.attrTween(name, tween())
将属性 name 使用差值函数 tween() 。
例如:
svg.transition()
.duration(2000)
.attrTween("width", function (d,i,a) {
return function (t) {
return parseInt(a + t * 300);
}
})
d是被绑定的数据,i是索引号,a是width的属性初始值。
setInterval(code, millisec)
以指定的周期来执行代码,直到 clearInterval()
被调用或者窗口被关闭。
例如:
// 调用更新函数,每0.7s更新一次
setInterval(function () {
update((++idx) % 12);
}, 700);
删除方法:
let id = setInterval(function () {
update((++idx) % 12);
}, 700);
//...
clearInterval(id);
效果图(含实时更新的情况):
let circles = svg.selectAll("circle")
.data(DataLine)
.enter()
.append("circle")
.attr("r", function (d) {
return 1;
})
.attr("cx", function (d) {
return w - inner.right - (d.longitude * (-1) - 60) / 70 * W;
})
.attr("cy", function (d) {
return h - inner.bottom - (d.latitude - 25) / 30 * H;
});
circles.transition()
.delay(3000)
.duration(2000)
.attr("r", function (d) {
return d.PRCP * 5;
})
.attr("fill", function (d) {
return 'rgba(0,' + Math.max(0, (175 - parseInt(d.WSF5))) + ',' + (255) + ',0.8)';
});
setInterval(function () {
add1day(); //更新idx的函数
update(idx);
}, 2000);
function update(t) {
comment.text(idx);
updateElement();
}
function updateElement() {
svg.selectAll("circle")
.data(DataEntry[sce], d => d.station)
.transition()
.duration(2000)
.attr("r", function (d) {
return d.PRCP * 5;
})
.attr("fill", function (d) {
return 'rgba(0,' + Math.max(0, (175 - parseInt(d.WSF5))) + ',' + (255) + ',0.8)';
});
}
动态条形图代码:
let rects = groups.data(DataEntry)
.enter().append("rect")
.attr("x", inner.left)
.attr("height", H * 0.65)
.attr("fill", function (d, i) {
return Color[i];
})
.attr("width", function (d) {
return xScale(d.sunshine);
});
// 设定更新函数
function UpdateElement() {
rects.data(DataEntry, d => d.city)
.transition()
.duration(600)
.attr("y", function (d, i) {
return i * H + inner.bottom;
})
.attr("width", function (d) {
return xScale(d.sunshine);
});
}
UpdateElement();
// 更新函数
function update(t) {
//...
comment.text(DataEntry[0].month);
UpdateElement();
}
// 调用更新函数,每0.7s更新一次
setInterval(function () {
update((++idx) % 12);
}, 700);