D3.js学习笔记四:画一个折线图

2015年02月11日 javascript 暂无评论 阅读 4,417 views 次

作图思路

参照上图,折线图有几个元素需要绘制,背景、标题栏、副标题、横纵坐标轴及标签、图例和折线(包括上面的圆点标记),我们分别将它们画出来,随数据更新还要将旧的数据删除。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>画一个折线图</title>
<script type="text/javascript" src="js/d3.js"></script>
</head>
<style type="text/css">
body{
height: 100%;
}
.axis path,
.axis line {
fill: none;
stroke: black;
shape-rendering: crispEdges;
}
.axis text {
font-family: sans-serif;
font-size: 11px;
}
</style>
<body>
<script type="text/javascript">
var dataset=[];
var xMarks=[];
var w=600;
var h=400;
var padding=40;
//模拟数据
getData();
//定义画布
var svg=d3.select("body")
.append("svg")
.attr("width",w)
.attr("height",h);
//添加背景
svg.append("g")
.append("rect")
.attr("x",0)
.attr("y",0)
.attr("width",w)
.attr("height",h)
.style("fill","#FFF")
.style("stroke-width",2)
.style("stroke","#E7E7E7");
//横坐标轴比例尺
var xScale = d3.scale.linear()
.domain([0,dataset.length-1])
.range([padding,w-padding]);
//纵坐标轴比例尺
var yScale = d3.scale.linear()
.domain([0,d3.max(dataset)])
.range([h-padding,padding]);
//定义横轴
var xAxis = d3.svg.axis()
.scale(xScale)
.orient("bottom").ticks(dataset.length);
//添加横坐标轴并通过编号获取对应的横轴标签
var xBar=svg.append("g")
.attr("class", "axis")
.attr("transform", "translate(0," + (h - padding) + ")")
.call(xAxis)
.selectAll("text")
.text(function(d){return xMarks[d];});
//定义纵轴
var yAxis = d3.svg.axis()
.scale(yScale)
.orient("left").ticks(10);
//添加纵轴
var yBar=svg.append("g")
.attr("class", "axis")
.attr("transform", "translate("+padding+",0)")
.call(yAxis);
//添加折线
var line = d3.svg.line()
.interpolate("step-after")
.x(function(d,i){return xScale(i);})
.y(function(d){return yScale(d);});
var path=svg.append("path")
.attr("d", line(dataset))
.style("fill","#F00")
.style("fill","none")
.style("stroke-width",1)
.style("stroke","#F00")
.style("stroke-opacity",0.9);
//添加系列的小圆点
svg.selectAll("circle")
.data(dataset)
.enter()
.append("circle")
.attr("cx", function(d,i) {
return xScale(i);
})
.attr("cy", function(d) {
return yScale(d);
})
.attr("r",5)
.attr("fill", function(d) {
return "rgb( " + (d%255) + ",0, 0)";
});
//重新作图
function drawChart()
{
getData();
yBar.transition().duration(1000).call(yAxis);
//纵轴数据更新
yScale = d3.scale.linear()
.domain([0,d3.max(dataset)])
.range([h-padding,padding]);
//重绘路径
path.transition().duration(1000).attr("d", line(dataset));
//重绘4圆点
svg.selectAll("circle")
.data(dataset)
.transition()
.duration(1000)
.attr("cx", function(d,i) {
return xScale(i);
})
.attr("cy", function(d) {
return yScale(d);
})
.attr("fill", function(d) {
return "rgb( " + (d%255) + ",0, 0)";
});
}
//产生随机数据
function getData()
{
var dataNum=15;
dataset=[];
xMarks=[];
for(i=1;i<dataNum;i++)
{
dataset.push(Math.round(Math.random()*h));
xMarks.push("标签"+i);
}
}
</script>
<p align="left">
<button onClick="javascript:drawChart();">刷新数据</button>
</p>
</body>
</html>

步骤很清楚,首先模拟一个数据,然后添加SVG和背景图像,加入两个线性的坐标轴,纵轴就是数字,不必管它,横轴需要根据编号取得对应的标签。将坐标轴设置好方向和位置,用call()方法添加到图形中。 产生一个线段点位坐标组line,根据横纵轴的比例尺信息产生点位坐标,然后用这个坐标组画路径,路径的形状由line对象的interpolate属性决定,它的可选值有:

•linear - piecewise linear segments, as in a polyline.

•linear-closed - close the linear segments to form a polygon.

•step - alternate between horizontal and vertical segments, as in a step function.

•step-before - alternate between vertical and horizontal segments, as in a step function.

•step-after - alternate between horizontal and vertical segments, as in a step function.

•basis - a B-spline, with control point duplication on the ends.

•basis-open - an open B-spline; may not intersect the start or end.

•basis-closed - a closed B-spline, as in a loop.

•bundle - equivalent to basis, except the tension parameter is used to straighten the spline.

•cardinal - a Cardinal spline, with control point duplication on the ends.

•cardinal-open - an open Cardinal spline; may not intersect the start or end, but will intersect other control points.

•cardinal-closed - a closed Cardinal spline, as in a loop.

•monotone - cubic interpolation that preserves monotonicity in y.

具体样式可以替换一下代码中的值查看效果。

然后我们为折线顶点加了小圆点,这个是为了以后响应鼠标行为加的,而且将顶点作为单独的元件,也方便美化。

添加了一个按钮,点击更新数据并重新作图,重新作图部分我们用transition()指定了动画效果,并制定了效果延续时间。现在,我们完成了一部分工作,图形已经有了点模样:

给我留言

您必须 登录 才能发表留言!

Copyright © 大一网 保留所有权利.  

用户登录

分享到: