一直想写写D3,觉得D3真心比较强大,基本上你能想出来的图表都能绘制出来,只不过使用起来比前几个要稍麻烦一点。

正好最近读完了《数据可视化实战》,将关于D3的知识梳理了一遍,写这篇博客记录一下。

D3 是一个缩写,它的全称叫Data-Driven Documents(数据驱动的文档)。D3是基于数据操作文档的JavaScript库。D3帮助你使用HTML,SVG和CSS生动的展现数据。D3不需要将你使用某个特定的框架,D3重点在于对主流浏览器的全兼容,同时结合了强大的虚拟化组件,以数据驱动的方式去操作DOM。

D3支持所谓的主流浏览器除了IE8及以前的版本。D3测试了火狐,Chrome、Safari、Opera和IE9。D3的大部分组件可以在旧的浏览器运行,D3核心库的最低运行要求:支持JavaScript和W3C DOM API.对于IE8,建议使用兼容性库Aight库.D3采用的是Selectors API的第一级标准,你要是考虑兼容性可以预加载Sizzle库。你得使用主流的浏览器以便可以支持SVG和CSS3的转场特效。

官网地址:http://d3js.org/

下载官方包 d3.v3.zip 或者添加如下代码:

<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>

数据

var dataset = [1,2,3,4,5];
d3.select("body").selectAll("p")
.data(dataset)
.enter()
.append("p")
.text("New paragraph!");

结果如下图

详细的解释

d3.select("body")
  选择DOM 中的body 元素,把它交给连缀方法中的下一个方法。
.selectAll("p")
  选择DOM 中的所有段落。因为还没有段落,所以返回空元素。可以认为这个空元素代表马上就会创建的段落。
.data(dataset)
  解析并数出数据值。dataset 数组中有5 个值,因而此后的所有方法都将执行五遍,每次针对一个值。
.enter()
  要创建新的绑定数据的元素,必须使用enter()。这个方法会分析当前选择的DOM 元素和传给它的数据,如果数据值比对应的DOM 元素多,就创建一个新的占位元素。然后把这个新占位元素的引用交给链中的下一个方法。
.append("p")
  取得由enter() 创建的空占位元素,并把一个p 元素追加到相应的DOM 中。然后它再把自己刚创建的元素交给链中的下一个方法。
.text("New paragraph!")
  取得新创建的p 元素,插入文本值。

将最后一行修改为

.text(function(d) { return d; });

结果如下

我们用数据填充了每个段落,机关都在data() 方法里。在连缀方法中,只要调用data() 了,就可以随时创建一个接收d 为输入的匿名函数。与当前元素对应,方法data() 确保了每个d 都会被赋予原始数据集中的一个值。随着D3 遍历每个元素,“当前元素”的这个值也会跟着变化。比如,循环到第三次时,代码会创建第三个p 元素,而d 就会被赋予数据集中的第三个值(即dataset[2])。于是,第三个段落的文本就是“15”。

SVG绘制

首先要创建一个SVG 元素,以便在其中保存所有图形,先找到文档的body 元素,然后在结束的</body> 标签前添加一个新的svg 元素,并设置长宽,代码如下

var svg = d3.select("body")
.append("svg")
.attr("width", 500)
.attr("height", 50);

添加一些数据

var dataset = [ 5, 10, 15, 20, 25 ];

使用data() 迭代每个数据点,为它们分别创建一个圆形

var circles = svg.selectAll("circle")
.data(dataset)
.enter()
.append("circle");

最后设置图形的样式

circles.attr("cx", function(d, i) {
return (i * 50) + 25;
})//设置x的位置
.attr("cy", 50 / 2)//设置y的位置
.attr("r", function(d) {
return d;
})//设置圆的半径
.attr("fill", "yellow")//设置填充颜色
.attr("stroke", "orange")//设置圆的边缘线颜色
.attr("stroke-width", function(d) {
return d / 2;
});//设置圆的边缘线的宽度

结果如下图

比例尺

“比例尺是一组把输入域映射为输出范围的函数。”

先创建比例尺,设定值域为100~500和实际范围10~350,代码如下

var scale = d3.scale.linear()
.domain([100, 500])
.range([10, 350]);

可以测试一下scale

scale(100); // 返回10
scale(300); // 返回180
scale(500); // 返回350

添加数据集

var dataset = [
          [5, 20], [480, 90], [250, 50], [100, 33], [330, 95],
          [410, 12], [475, 44], [25, 67], [85, 21], [220, 88]
        ];

可以根据d3的max()和min()方法创建一个动态映射轴值的比例尺函数,max() 函数只是简单地循环数组中的每个值,然后找出其中最大的那个。min()则是找出其中最小的那个。

定义比例尺函数,其中w是svg宽,h是svg高。

var w = 500;
var h = 100; var xScale = d3.scale.linear()
.domain([0, d3.max(dataset, function(d) { return d[0]; })])
.range([0, w]);
var yScale = d3.scale.linear()
.domain([0, d3.max(dataset, function(d) { return d[1]; })])
.range([0, h]);

使用比例尺函数处理数据,并到svg中显示

svg.selectAll("circle")
.data(dataset)
.enter()
.append("circle")
.attr("cx", function(d) {
return d[0];
})
.attr("cy", function(d) {
return d[1];
})
.attr("r", function(d) {
return Math.sqrt(h - d[1]);
});

效果如下

d3.scale.linear() 还有几个非常方便的方法。
nice()
告诉比例尺取得为range() 设置的任何值域,把两端的值扩展到最接近的整数。根据D3 的维基:“比如,值域[0.20147987687960267, 0.996679553296417]的优化值域为[0.2, 1]。”这个方法对正常人都有用,因为人不是计算机,看到0.20147987687960267 这样的数你一定会头大。
rangeRound()
用rangeRound() 代替range() 后,则比例尺输出的所有值都会舍入到最接近的整数值。对输出值取整有利于图形对应精确的像素值,避免边缘出现模糊不清的锯齿。
clamp()
默认情况下,线性比例尺可以返回指定范围之外的值。例如,假如给定的值位于输入值域之外,那么比例尺也会返回一个位于输出范围之外的值。不过,在比例尺上调用clamp(true) 后,就可以强制所有输出值都位于指定的范围内。这意味着超出范围的值,会被取整到范围的最低值或最高值(总之是最接近的那个值)。

除了线性(linear)比例尺,D3 还内置了另外几个比例尺方法。
sqrt
平方根比例尺。
pow
幂比例尺,适合值以指数级变化的数据集。
log
对数比例尺。

quantize
输出范围为独立的值的线性比例尺,适合想把数据分类的情形。
quantile
与quantize 类似,但输入值域是独立的值,适合已经对数据分类的情形。
ordinal
使用非定量值(如类名)作为输出的序数比例尺,非常适合比较苹果和桔子。
d3.scale.category10()、d3.scale.category20()、d3.scale.category20b() 和d3.scale.category20c()
能够输出10 到20 种类别颜色的预设序数比例尺,非常方便。
d3.time.scale()
针对日期和时间值的一个比例尺方法,可以对日期刻度作特殊处理。

数轴

接着上面的例子进行,创建数轴

var xAxis = d3.svg.axis()//创建通用的数轴函数
.scale(xScale)//基于xScale比例尺工作
.orient("bottom");//设置标签相对数轴显示在什么地方。默认位置是底部。

在SVG 中生成数轴,放在脚本底部,以便在SVG 中的其他元素都生成之后再生成数轴,这样数轴就可以出现在“上面”了。

svg.append("g")
  .attr("class", "axis") // 指定"axis" 类
  .call(xAxis);

效果如下

略难看,而且x轴的位置也不对。

修整一下数轴,在<head> 中的<style> 标签里写两条CSS 样式规则。

.axis path, .axis line {
fill: none;
stroke: black;
shape-rendering: crispEdges;
}
.axis text {
font-family: sans-serif;
font-size: 11px;
}

用到SVG 变换(transform)了。添加一行代码,把整个数轴分组平移到图表下方,详细如下

svg.append("g")
.attr("class", "axis")
.attr("transform", "translate(0," + (h - 20) + ")")
.call(xAxis);

效果如下

然后添加Y轴,做一些调整,最后JS文件如下

var margin = {top: 20, right: 20, bottom: 30, left: 40},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var dataset = [
[ 5, 20 ],
[ 480, 90 ],
[ 250, 50 ],
[ 100, 33 ],
[ 330, 95 ],
[ 410, 12 ],
[ 475, 44 ],
[ 25, 67 ],
[ 85, 21 ],
[ 220, 88 ]
];
var x = d3.scale.linear()
.domain([0, d3.max(dataset, function(d) { return d[0]; })])
.range([0, width]); var y = d3.scale.linear()
.domain([0, d3.max(dataset, function(d) { return d[1]; })])
.range([height, 0]); var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom"); var yAxis = d3.svg.axis()
.scale(y)
.orient("left"); var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")"); svg.selectAll("circle")
.data(dataset)
.enter()
.append("circle")
.attr("cx", function(d) {
return x(d[0]);
})
.attr("cy", function(d) {
return y(d[1]);
})
.attr("r", function(d) {
return 10;
});
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.append("text")
.attr("class", "label")
.attr("x", width)
.attr("y", -6)
.style("text-anchor", "end")
.text("X轴"); svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("class", "label")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Y轴");

最终效果如下

D3的基础今天就到这里~~

有时间的话,推荐读一下《数据可视化实战》~~

数据可视化(7)--D3基础的更多相关文章

  1. 数据可视化-svg入门基础(二)

    接上一篇:数据可视化-svg入门基础(一),基础一主要是介绍了svg概念,元素样式设置等. svg是(scalable vector graphic)伸缩矢量图像. 一.目录 (1)图形元素 (2)文 ...

  2. 交互式数据可视化-D3.js(四)形状生成器

    使用JavaScript和D3.js实现数据可视化 形状生成器 线段生成器 var linePath = d3.line() - 使用默认的设置构造一个 line 生成器. linePath.x() ...

  3. 数据可视化之powerBI基础(十二)PowerBI导入Excel数据有哪几种方式?

    https://zhuanlan.zhihu.com/p/64999937 Excel作为使用最频繁.应用最广泛.用户最庞大的数据处理工具,当然也应该是PowerBI最常用的数据获取方式,本文介绍一下 ...

  4. 数据可视化之powerBI基础(九)Power BI中的“新表”,你会用吗?

    https://zhuanlan.zhihu.com/p/64413703 通常情况下,在PowerBI进行分析的各种数据表都是从外部的各种数据源导入进来的,但并不总是如此,某些情况下在PowerBI ...

  5. 数据可视化(8)--D3数据的更新及动画

    最近项目组加班比较严重,D3的博客就一拖再拖,今天终于不用加班了,赶紧抽点时间写完~~ 今天就将D3数据的更新及动画写一写~~ 接着之前的博客写~~ 之前写了一个散点图的例子,下面可以自己写一个柱状图 ...

  6. 交互式数据可视化-D3.js(三)比例尺

    线性比例尺 线性比例尺是常用比例尺常用方法有: var linear = d3.scaleLinear() - 创建一个定量的线性比例尺. linear.domain([numbers]) - 定义或 ...

  7. 交互式数据可视化-D3.js(二)选择集和数据

    选择集 select和selectAll类似jquery: d3.select('body') d3.select('.body') d3.select('#body') d3.selectAll(' ...

  8. 数据可视化之powerBI基础(十一)Power BI中的数据如何导出到Excel中?

    https://zhuanlan.zhihu.com/p/64415543 把Excel中数据加载到PowerBI中我们都已经熟悉了,但是怎么把在PowerBI中处理好的数据导出到Excel中呢?毕竟 ...

  9. 数据可视化之powerBI基础(十)快速度量值,帮你更快的进行数据分析

    https://zhuanlan.zhihu.com/p/64414831 刚开始学习PowerBI,最头疼的可能就是度量值了,毕竟用了Excel这么多年,只相信自己眼睛看到的,对于这个"虚 ...

随机推荐

  1. solr&lucene3.6.0源码解析(四)

    本文要描述的是solr的查询插件,该查询插件目的用于生成Lucene的查询Query,类似于查询条件表达式,与solr查询插件相关UML类图如下: 如果我们强行将上面的类图纳入某种设计模式语言的话,本 ...

  2. day14---html基础

    本节内容: 一.HTML 二.CSS 三.JS HTML 1.一套规则,浏览器认识的规则. 2.开发者: 学习Html规则 开发后台程序: - 写Html文件(充当模板的作用) ****** - 数据 ...

  3. 【转】VC中的字符串处理

    http://hi.baidu.com/nmn714/item/ab8d2a96d0f2d6f228164727 貌似不少人刚开始做windows程序时都会纠结在字符串处理上,所以我把关于字符串处理的 ...

  4. 蛙蛙推荐:WEB安全入门

    信息安全基础 信息安全目标 真实性:对信息的来源进行判断,能对伪造来源的信息予以鉴别, 就是身份认证. 保密性:保证机密信息不被窃听,盗取,或窃听者不能了解信息的真实含义. 完整性:保证数据的一致性, ...

  5. MySql学习(MariaDb)

    资料 http://www.cnblogs.com/lyhabc/p/3691555.html http://www.cnblogs.com/lyhabc/p/3691555.html MariaDb ...

  6. JDBC学习2:为什么要写Class.forName("XXX")?

    Class.forName(String name) 接上一篇JDBC.本来这个内容是放在前面的一篇里面的一起的,后来发现越写越多,想想看就算了,还是单独开一篇文章好了,这样也能写得更加详细点. 上一 ...

  7. Cassandra中的数据一致性

       Cassandra中数据一致性指的是数据行在各个复制节点(replicas)上的更新和同步程度.通过提供tunable consistency,Cassandra扩展了eventual cons ...

  8. [Unity3D]再次点击以退出程序

    [Unity3D]再次点击以退出程序 本文介绍为Android应用编写点击返回按键时的"再次点击以退出程序"的方法. +BIT祝威+悄悄在此留下版了个权的信息说: 下面是一个测试用 ...

  9. 国外社交网站获取分享数量APIs

    之前有一篇文章详细介绍了如何获取网页在Facebook,Twitter和LinkedIn社交平台上分享的数量,点击这里查看.这里再扩充一下! Twitter GET URL: http://cdn.a ...

  10. hibernate HQL和Criteria

    package com.test; import java.util.Date; import java.util.List; import org.hibernate.Query; import o ...