【数据可视化】可放缩可拖拽画布的力导向图
2016-07-26 12:47
609 查看
以力导向图为蓝本合并力导向图和放缩图,实现了可放缩可拖拽画布的力导向图
Mike Bostock给出的两个例子(http://bl.ocks.org/mbostock)
力导向图(Force Dragging III http://bl.ocks.org/mbostock/ad70335eeef6d167bc36fd3c04378048)
放缩图(Pan & Zoom http://bl.ocks.org/mbostock/2b534b091d80a8de39219dd076b316cd)
效果:
拖拽并缩小后:
1、确认主次
2、增加缩放控制变量
3、响应放缩事件
4、拖拽事件的碰撞检测和坐标转换
4、图元渲染过程画布的放缩和移动
5、模块化代码(force_zoom_canvas.js)
6、force_zoom_canvas.js调用方式
Mike Bostock给出的两个例子(http://bl.ocks.org/mbostock)
力导向图(Force Dragging III http://bl.ocks.org/mbostock/ad70335eeef6d167bc36fd3c04378048)
放缩图(Pan & Zoom http://bl.ocks.org/mbostock/2b534b091d80a8de39219dd076b316cd)
效果:
拖拽并缩小后:
1、确认主次
以力导向图为蓝本
2、增加缩放控制变量
var transform = d3.zoomIdentity;
3、响应放缩事件
d3.select(canvas) .call( d3.zoom() .scaleExtent([1/10, 10]) .on("zoom", function(){ transform = d3.event.transform; render(); } ) )
4、拖拽事件的碰撞检测和坐标转换
// 合并两个dragsubject()函数 function subject_from_event() { //1、查找对象时,事件对象的坐标是屏幕坐标,需要转换成实际坐标 var ex = transform.invertX(d3.event.x), ey = transform.invertY(d3.event.y); var node = simulation.find(ex,ey); //2、计算鼠标是否落在图形内部,如果落在图形外返回空以实现画布的拖拽 var dx = ex - node.x, dy = ey - node.y; if(dx*dx+dy*dy <radius*radius){ //3、力导向图拖拽事件需要节点的屏幕坐标,使用[rx,ry]保存实际坐标,把[x,y]替换成屏幕坐标 node.rx = node.x; node.ry = node.y; node.x = transform.applyX(node.rx); node.y = transform.applyY(node.ry); return node; } return null; } function drag_started(){ if (!d3.event.active) simulation.alphaTarget(0.3).restart(); // 力学坐标应为实际坐标 d3.event.subject.fx = d3.event.subject.rx; d3.event.subject.fy = d3.event.subject.ry; } function dragged(){ // 力学坐标应为实际坐标 d3.event.subject.fx = transform.invertX(d3.event.x); d3.event.subject.fy = transform.invertY(d3.event.y); } function drag_ended(){ if (!d3.event.active) simulation.alphaTarget(0); // 还原[x,y]为实际坐标 d3.event.subject.x = d3.event.subject.rx; d3.event.subject.y = d3.event.subject.ry; d3.event.subject.fx = null; d3.event.subject.fy = null; }
4、图元渲染过程画布的放缩和移动
// 更换ticked()为render(),渲染前进行画布的放缩和移动 context.translate(transform.x, transform.y); context.scale(transform.k, transform.k);
5、模块化代码(force_zoom_canvas.js)
function force_zoom_canvas(canvas_id){ // TODO 内部变量 var graph={}, canvas = document.getElementById (canvas_id), context = canvas.getContext("2d"), width = canvas.width, height = canvas.height, transform = d3.zoomIdentity, distance = 47, radius = 13, simulation = d3.forceSimulation(); // TODO 配置D3 function initialize(nodes,links){ graph.nodes = nodes; graph.links = links; simulation .force("link", d3.forceLink().distance(distance).strength(1).id(function(n) { return n.id; })) .force("charge", d3.forceManyBody()) .force("center", d3.forceCenter(width / 2, height / 2)) .nodes(graph.nodes) .on("tick",render); simulation.force("link") .links(graph.links); d3.select(canvas) .call(d3.drag().container(canvas).subject(subject_from_event).on("start", drag_started).on("drag", dragged).on("end", drag_ended)) .call(d3.zoom().scaleExtent([1/10, 10]).on("zoom", function(){transform = d3.event.transform;render();})) .call(render); //TODO 图元发现 function subject_from_event() { var ex = transform.invertX(d3.event.x), ey = transform.invertY(d3.event.y); var node = simulation.find(ex,ey); var dx = ex - node.x, dy = ey - node.y; if(dx*dx+dy*dy <radius*radius){ node.rx = node.x; node.ry = node.y; node.x = transform.applyX(node.rx); node.y = transform.applyY(node.ry); return node; } return null; } //TODO 图元拖拽 function drag_started(){ if (!d3.event.active) simulation.alphaTarget(0.3).restart(); d3.event.subject.fx = d3.event.subject.rx; d3.event.subject.fy = d3.event.subject.ry; } function dragged(){ d3.event.subject.fx = transform.invertX(d3.event.x); d3.event.subject.fy = transform.invertY(d3.event.y); } function drag_ended(){ if (!d3.event.active) simulation.alphaTarget(0); d3.event.subject.x = d3.event.subject.rx; d3.event.subject.y = d3.event.subject.ry; d3.event.subject.fx = null; d3.event.subject.fy = null; } } // TODO 图元渲染 function render(){ context.save(); context.clearRect(0, 0, width, height); context.translate(transform.x, transform.y); context.scale(transform.k, transform.k); graph.links.forEach(function(l){ context.beginPath(); context.moveTo(l.source.x, l.source.y); context.lineTo(l.target.x, l.target.y); context.strokeStyle = "#aaa"; context.stroke(); }); graph.nodes.forEach(function(n){ context.fillStyle= "#777"; context.beginPath(); context.moveTo(n.x+radius, n.y); context.arc(n.x, n.y,radius,0,Math.PI*2); context.fill(); context.fillStyle= "#fff"; context.stroke(); var w = context.measureText(n.id).width; var h = context.measureText(n.id.substr(0,1)).width; context.fillText(n.id, n.x-w/2, n.y+h/2); }); context.restore(); } // TODO 接口 graph = { "Run":initialize }; return graph; }
6、force_zoom_canvas.js调用方式
<!DOCTYPE html> <html> <head> <title></title> <script src="d3.v4.js"></script> <script src="force_zoom_canvas.js"></script> <canvas width="1280" height="720" id="force_zoom"></canvas><p/> </head> <body> <script> var fzc = force_zoom_canvas("force_zoom"); fzc.Run([ {"id": "2"},{"id": "3"},{"id": "5"},{"id": "7"},{"id": "11"},{"id": "13"},{"id": "17"},{"id": "19"},{"id": "23"},{"id": "29"},{"id": "31"},{"id": "37"},{"id": "41"},{"id": "43"},{"id": "47"},{"id": "51"},{"id": "53"},{"id": "1"},{"id": "8"},{"id": "21"},{"id": "34"},{"id": "55"} ],[ {"source": "55", "target": "1"},{"source": "55", "target": "8"},{"source": "55", "target": "21"},{"source": "55", "target": "34"},{"source": "1", "target": "2"},{"source": "1", "target": "3"},{"source": "1", "target": "5"},{"source": "1", "target": "7"},{"source": "8", "target": "11"},{"source": "8", "target": "13"},{"source": "8", "target": "17"},{"source": "8", "target": "19"},{"source": "21", "target": "23"},{"source": "21", "target": "29"},{"source": "21", "target": "31"},{"source": "34", "target": "37"},{"source": "34", "target": "41"},{"source": "34", "target": "43"},{"source": "34", "target": "47"},{"source": "34", "target": "51"},{"source": "34", "target": "53"} ]); </script> </body> </html>
相关文章推荐
- 学习prefuse
- ios、android 数据可视化图表赏析
- 数据可视化解读阿里、腾讯帝国2015年扩张概况
- 奇虎360-数据可视化
- 搞懂5种数据可视化方法,胜任90%热门信息图设计
- 软件即服务和云计算之间有什么区别
- (转)智能+可视化 看商业智能的发展方向
- 《Nevron NET Vision Enterprise 2007 v7.2.Q1》For VS2003 & For VS2005 FTP下载 技术共享
- 学习R网址
- 利用VTK对数据进行可视化的实例
- MATLAB-数据可视化笔记
- 计算机图形实现建模技术的3种方法
- 【斯坦福大学】计算机图形学实验室的概况
- MATLAB与外部程序的数据交互三板斧
- 如何正确理解商业智能(BI)?--上
- 基于内容的信息存取与MPEG-7
- web设计趋势与潮流
- 22个免费的数据可视化和分析工具推荐
- MapInfo简介