现在,市面上各种操作图形的,例如hightchart、echarts等,虽然能做很多效果,但是局限性就是很难去定制。
D3.js不是通过json配置的方式来制作图表,而是通过提供一些简化操作的api来操作svg,canvas等。可以把D3形象理解为:SVG中的jQuery。
select:选择符合条件的第一个元素
selectAll:选择符合条件的全部元素集
data():用来绑定数据
d3.select("body").style("background-color", "black"); // 直接选择 ->并设置属性
d3.selectAll("p").style("color", function() { // 选择 -> 动态设置属性
return "hsl(" + Math.random() * 360 + ", 100%, 50%)";
});
d3.selectAll("p") // 选择 -> 绑定数据 -> 动态设置属性
.data([4, 8, 15, 16, 23, 42])
.style("font-size", function(d) { return d + "px"; }); // function(d)为遍历data的数据
上面的例子,通过data()绑定数据后,就可以通过function(d) { return ...}来遍历data中的数据,使数据表现到样式上
操作svg:
// 把所有圆圈改变半径
d3.selectAll(".circle").transition() // 定义动画
.duration(750) // 动画持续时间
.delay(function(d, i) { return i * 10; }) // 元素动画要延时多少时间开始
.attr("r", "6"}); // 设置半径
上面的例子,通过attr给圆形加半径,通过 transition加动画效果
一个简单的图像生成器: 引入d3.js,选择
情况一(data=dom): 当dom上的
<html>
<head>
<script src="https://d3js.org/d3.v3.min.js"></script>
<link rel="stylesheet" href="index.css">
</head>
<body>
<div id="dashboard">
<p>Earnings</p>
<div class="chart">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
</div>
<script>
var data = [30, 86, 168, 281, 303, 565];
var chartData = d3.select(".chart")
.selectAll("div")
.data(data) // 可以抽出一个变量chartData
chartData
.style("width", function(d) { return d + 'px' })
.text(function(d) { return '$ ' + d; });
</script>
</body>
</html>
情况二(data>dom): 如果data数据是异步的,我们就没办法事先知道data数组的具体个数,这时我们需要enter(),enter特指 数据已经存在但是当前DOM元素中还不存在的每个数据元素的占位符节点。文字描述不好理解,可以看下面例子来结合理解
<html>
<head>
<script src="https://d3js.org/d3.v3.min.js"></script>
<link rel="stylesheet" href="index.css">
</head>
<body>
<div id="dashboard">
<p>Earnings</p>
<div class="chart">
<!-- <div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div> -->
</div>
</div>
<script>
var data = [30, 86, 168, 281, 303, 565];
var chartData = d3.select(".chart")
.selectAll("div")
.data(data) // 可以抽出一个变量chartData
chartData
.enter()
.append("div")
.style("width", function(d) { return d + 'px' })
.text(function(d) { return '$ ' + d; });
</script>
</body>
</html>
<div class="chart">下已经没有div标签,这时我们用了enter(),就可以指代data存在但是dom上不存在的数据,所以页面能达到相同的效果。需要注意的是,如果<div class="chart">下已经有6个div了,那enter()就会不起效果,所以这个例子chart下6个div必须注销掉,enter()才能执行
情况三(data<dom):
如果<div class="chart">下的div太多了,这时需要exit来选中多余的dom,并通过remove去除掉。
<html>
<head>
<script src="https://d3js.org/d3.v3.min.js"></script>
<link rel="stylesheet" href="index.css">
</head>
<body>
<div id="dashboard">
<p>Earnings</p>
<div class="chart">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
</div>
<script>
var data = [30, 86, 168, 281, 303, 565];
var chartData = d3.select(".chart")
.selectAll("div")
.data(data) // 可以抽出一个变量chartData
chartData
.style("width", function(d) { return d + 'px' })
.text(function(d) { return '$ ' + d; });
chartData.exit().remove() //去除多余的div
</script>
</body>
</html>
以下就是这个图形生成器的基本行为,如果data>dom,就要用enter来增加dom元素;如果data<dom,就要用exit来减少多余元素,最终保持每次更新视图都保证data和dom的同步。
var data = [30, 86, 168, 281, 303, 565];
var chartData = d3.select(".chart")
.selectAll("div")
.data(data)
// 图形生成器
function update(){
chartData // 随着data数据变化更新视图元素
.style("width", function(d) { return scale(d) + 'px' })
.text(function(d) { return '$ ' + d; });
chartData
.enter() // 当data数据增加后添加视图元素
.append("div")
.style("width", function(d) { return scale(d) + 'px' })
.text(function(d) { return '$ ' + d; });
chartData.exit().remove() // 当data数据减少后移除视图元素
}
update()
图形生成器完成后,接下来我们只要更新数据,再执行生成器,页面上的视图就会跟着变化。