D3.js绘制实时映射的缩略图

镇三山
• 阅读 5285

在做可视化的很多时候,我们需要在主图的一角设置一个缩略图来掌握全局情况。本次将使用力导向图作为例子,完成缩略图的实现。

绘制的原理就是依靠主图的数据再画一个图出来,无需再次计算,只改变图形形态。

最终效果

主图节点拖动,缩略图跟着变化。
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,缩略图的绘制完成,很简单的例子,按照这个思路可以完成大部分可视化的缩略图绘制。除了拖动外,还可以添加缩放和平移功能,但注意缩放时所有尺寸的比例都会跟着变化,会复杂很多。

点赞
收藏
评论区
推荐文章
blmius blmius
4年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
美凌格栋栋酱 美凌格栋栋酱
7个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Easter79 Easter79
3年前
Vue 仿钉钉流程图(流程节点绘制 vue+Ant【如果用其他UI库需要替换几个组件】 附 demo)
Vue仿钉钉流程图(流程节点绘制vueAntDesignofVue)仿钉钉流程图Api包括:一维数组传参,获取单节点数据,返回所有节点组成的一位数组生成每个节点的父节点Id集合很多公司后台管理系统都需要画流程图,功能大同小异,所以,仿照钉钉管理
Jacquelyn38 Jacquelyn38
4年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Karen110 Karen110
4年前
5行代码搞定14种常见图的python可视化库,还自带16种优美主题,真是太喜欢了
有时候我们做数据可视化并不需要特别复杂的功能,仅仅是想把简单的数据用图形展示出来今天就给大家介绍一种非常适合新手的python可视化库pygalpygal比较小众,专注于SVG图,擅长交互,最主要的是它能用非常少的代码就可画出非常漂亮的图形pygal能绘制Line(折线图)、Bar(柱状图)、Histogram(直方图)、Pie(饼图)、Radar(雷达
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Stella981 Stella981
3年前
Python使用Plotly绘图工具,绘制柱状图
使用Plotly绘制基本的柱状图,需要用到的函数是graph\_objs中Bar函数通过参数,可以设置柱状图的样式。通过barmod进行设置可以绘制出不同类型的柱状图出来。我们先来实现一个简单的柱状图:coding:utf8importplotlyaspyimportplotly
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Python进阶者 Python进阶者
1年前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这