這次要再增強一點互動性
有時候就是會想要把東西拉來拉去啦!
在d3中,如果想要拖拉物件可以使用drag來達成
drag分為三個事件(階段)
start
在drag中,一樣可以透過匿名函式跟動畫等等,來製作豐富的效果
function dragstarted(d) {
d3.select(this).select("text")
.transition()
.duration(60)
.attr("x", d.x = d3.event.x)
.attr("y", d.y = d3.event.y-linear(d)/2);
d3.select(this).select("rect")
.transition()
.duration(60)
.attr("x", d.x = d3.event.x-22)
.attr("y", d.y = d3.event.y-linear(d)/2+5);
}
drag
function dragged(d) {
d3.select(this).select("text")
.attr("x", d.x = d3.event.x)
.attr("y", d.y = d3.event.y-linear(d)/2);
d3.select(this).select("rect")
.attr("x", d.x = d3.event.x-22)
.attr("y", d.y = d3.event.y-linear(d)/2+5);
}
end
之所以會用index來記錄i是因為,select(this)的物件只有一個,所以裡面的i都會是0,而不是原本取得的i值,所以先記錄到index來在後面可以使用,讓長條圖在拖拉結束後可以回到原本的位置
function dragended(d,i) {
var index = i
d3.select(this).select("text")
.transition()
.duration(600)
.attr("y",function(d){
return 500-linear(d)-5;
})
.attr("x",function(d,i){ //因為這邊的部分是在select(this)之下,所以資料量只有1,所以i=0
return xlinear(index)+27; //因此要在前面將正確的i記在index之中
})
d3.select(this).select("rect")
.transition()
.duration(600)
.attr("x",function(d){
return xlinear(index)+5;
})
.attr("y",function(d){
return 500-linear(d);
})
}
最後在使用的時候要利用call來呼叫,on來監聽事件,並且要先利用d3.drag()來開啟拖拉的功能
var bar = chart.selectAll("g")
.data(dataset)
.enter().append("g")
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended))
Demo & code : https://codepen.io/FanWay/pen/PEaXWb