在做可视化的很多时候,我们需要在主图的一角设置一个缩略图来掌握全局情况。本次将使用力导向图作为例子,完成缩略图的实现。
绘制的原理就是依靠主图的数据再画一个图出来,无需再次计算,只改变图形形态。
最终效果
主图节点拖动,缩略图跟着变化。
http://en.jsrun.net/UyiKp/show
代码解析
数据
依然使用之前例子的力导向图绘制数据及方法
var nodes = [
{value:"66666666",type:"home",index:"0"},
{value:"11111111111",type:"phone",index:"1"},
{value:"22222222222",type:"phone",index:"2"},
{value:"33333333333",type:"phone",index:"3"},
{value:"44444444444",type:"phone",index:"4"},
{value:"55555555555",type:"phone",index:"5"},
{value:"aaa",type:"weixin",index:"6"},
{value:"bbb",type:"weixin",index:"7"},
{value:"ccc",type:"weixin",index:"8"},
{value:"ddd",type:"weixin",index:"9"},
{value:"eee",type:"weixin",index:"10"},
{value:"fff",type:"weixin",index:"11"},
];
var links = [
{source:0,target:1},
{source:0,target:2},
{source:0,target:3},
{source:0,target:4},
{source:0,target:5},
{source:2,target:6},
{source:2,target:7},
{source:2,target:8},
{source:3,target:9},
{source:3,target:10},
{source:3,target:11},
]
力导向图绘制
var height = 500;
var width = 500;
var svg = d3.select("#forceMap").append("svg")
.attr("width",width)
.attr("height",height)
.attr("id","forceSvg");
var mapG = svg.append("g")
.attr("id","forceGroup");
var force = d3.layout.force()
.nodes(nodes)
.links(links)
.size([width,height])
.linkDistance(100)
.charge([-1250])
.gravity(0.5)
.friction(0.5);
force.start();
var linkG = mapG.selectAll(".link")
.data(links)
.enter()
.append("line")
.attr("class","link")
.attr("stroke","#ccc");
var nodeG = mapG.selectAll(".node")
.data(nodes)
.enter()
.append("circle")
.attr("class","node")
.attr("r",8)
.attr("fill",function(d){
switch(d.type){
case "home": return "red";break;
case"phone": return "blue";break;
case "weixin": return "green";break;
}
})
.call(force.drag); //这个例子为节点添加了可拖动的功能
force.on("tick", function () {
linkG.attr("x1", function (d) {
return d.source.x;
})
.attr("y1", function (d) {
return d.source.y;
})
.attr("x2", function (d) {
return d.target.x;
})
.attr("y2", function (d) {
return d.target.y;
});
nodeG.attr("cx", function (d) {
return d.x
})
.attr("cy", function(d){
return d.y
});
drawThumb(); //在tick最后,执行绘制缩略图
});
这次代码中添加了drag方法,为了使节点可拖动。
绘制缩略图
function drawThumb(){
//每次绘制前删除之前的图形(这是一种简单有效的动画理论,但是比较消耗资源,之后会介绍如何节省资源完成需求)
d3.select("#thumbSvg").remove();
var thumbSvg = d3.select("#thumbMap").append("svg")
.attr("width",100)
.attr("height",100)
.attr("id","thumbSvg");
var thumbG = thumbSvg.append("g")
.attr("id","thumbGroup");
var thumbLink = thumbG.selectAll(".tlink")
.data(links)
.enter()
.append("line")
.attr("class","tlink")
.attr("stroke","#ccc")
//缩略图绘制和主图的差异在这,不需要tick,只需要把节点的坐标直接赋予即可
.attr("x1", function (d) {
return d.source.x/5;//这里的除5是缩略图和主图的比例,thumbWidth/forceWidth
})
.attr("y1", function (d) {
return d.source.y/5;
})
.attr("x2", function (d) {
return d.target.x/5;
})
.attr("y2", function (d) {
return d.target.y/5;
});
var thumbNode = thumbG.selectAll(".tnode")
.data(nodes)
.enter()
.append("circle")
.attr("class","tnode")
.attr("r",1.2)//图形尺寸都要缩小
.attr("fill",function(d){
switch(d.type){
case "home": return "red";break;
case"phone": return "blue";break;
case "weixin": return "green";break;
}
})
.attr("cx", function (d) {
return d.x/5
})
.attr("cy", function(d){
return d.y/5
});
}
在绘制缩略图时,我在最前面有一个remove方法,就是用新的图形代替旧的图形,完成缩略图的动画效果,模拟了tick。
但在实际使用中,数据量很大时,如此删了画画了删,非常耗资源。
所以更好的方法是判断是否有thumbSvg,有的话就只改变node和link的x,y,没有的话就按上面代码一样绘制。
ok,缩略图的绘制完成,很简单的例子,按照这个思路可以完成大部分可视化的缩略图绘制。除了拖动外,还可以添加缩放和平移功能,但注意缩放时所有尺寸的比例都会跟着变化,会复杂很多。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。