代码如下(详细注释)
<!DOCTYPE>
<html>
<meta charset="utf-8">
<style>
text{
font: 10px sans-serif;
}
.axis path,
.axis line{
fill: none;
stroke: black;
shape-rendering: crispEdges;
}
</style>
<body>
<h1>The columns diagram </h1>
<script src="d3/d3.v3.js"></script>
<script>
//设置svg图的属性
var dataset=[50,43,120,87,99,167,142];//数据集
var width = 400;//svg的宽度
var height = 400;//svg的高度
var svg = d3.select("body")
.append ("svg")//在body中新建一个svg图
.attr("width",width)//设置svg图的宽度
.attr("height",height);//设置svg图的高度
var padding = { //设置外边距
top:20,
right:20,
bottom:20,
left:25
};
</script>
<script>
//绘制条形图
function draw(){
//设置比例尺的属性
var xAxisWidth = 300;//坐标横轴的长度
var yAxisWidth = 300;//坐标纵轴的长度
var xScale = d3.scale.ordinal()//创建序数比例尺
//获得一个等差数列作为定义域
.domain(d3.range(dataset.length))
//获得一个range区间,内部间隔为0.2倍的step
.rangeRoundBands([0,xAxisWidth],0.2);
console.log(xScale.rangeBand());
var yScale = d3.scale.linear()//创建线性比例尺
//利用0-最大高度作为高度的定义域
.domain([0,d3.max(dataset)])
.range([0,yAxisWidth]);
svg.selectAll("text").remove();
//向svg图中添加矩形和文本
var updateRect = svg.selectAll("rect")
.data(dataset);//获得需要更新的部分
var enterRect = updateRect.enter();//获得数据多余的部分
var exitRect = updateRect.exit();//获得标签多余的部分
var updateText = svg.selectAll("text")
.data(dataset);//获得需要更新的部分
var enterText = updateText.enter();//获得数据多余的部分
var exitText = updateText.exit();//获得标签多余的部分
updateRect.attr("fill","red")//设置矩形的颜色
//设置矩形的左上角的坐标
.attr("x",function(d,i){
return padding.left+xScale(i);
})
.attr("y",function(d,i){
return height - padding.bottom-yScale(d);
})
//设置矩形的尺寸,由比例尺得到(间隔)
.attr("width",xScale.rangeBand())
.attr("height",function(d){
return yScale(d);
})
.on("mouseover",function(d,i){
d3.select(this)
.attr("fill","yellow");
})
.on("mouseout",function(d,i){
d3.select(this)
.transition()
.duration(500)
.attr("fill","red");
});
enterRect.append("rect")//利用多出的数据添加新的元素,然后同上设置
.attr("fill","steelblue")
.attr("x",function(d,i){
return padding.left+xScale(i);
})
.attr("y",function(d,i){
return height - padding.bottom-yScale(d);
})
.attr("width",xScale.rangeBand())
.attr("height",function(d){
return yScale(d);
})
.on("mouseover",function(d,i){
d3.select(this)
.attr("fill","yellow");
})
.on("mouseout",function(d,i){
d3.select(this)
.transition()
.duration(500)
.attr("fill","red");
})
.transition()
.delay(500)
.duration(1000)
.attr("fill","red");
exitRect.remove();//数据不够的情况下,将多余的没有数据初始化的元素删除
updateText.attr("fill","white")//设置字体的颜色
.attr("font-size","14px")//设置字体的大小
.attr("text-anchor","middle")//设置文本的中心位于起始位置上
//设置起始位置的相对的原点坐标
.attr("x",function(d,i){
return padding.left + xScale(i);
})
.attr("y",function(d){
return height- padding.bottom - yScale(d);
})
//设置起始位置相对于设置的原点的坐标(rangeBand自带padding)
.attr("dx",xScale.rangeBand()/2)
.attr("dy","1em")
.text(function(d){
return d;
});
enterText.append("text")//利用多出的数据添加新的元素,然后同上设置
.attr("fill","white")
.attr("font-size","14px")
.attr("text-anchor","middle")
.attr("x",function(d,i){
return padding.left + xScale(i);
})
.attr("y",function(d){
return height- padding.bottom - yScale(d);
})
.attr("dx",xScale.rangeBand()/2)
.attr("dy","1em")
.text(function(d){
return d;
});
exitText.remove();//数据不够的情况下, 将多余的没有数据初始化的元素删除
//创建x轴
var xAxis = d3.svg.axis()//创建一个坐标轴
.scale(xScale)//设置比例尺为xScale
.orient("bottom");//放置在下侧
//重新设置y轴比例尺的值域,与原来相反
yScale.range([yAxisWidth,0]);
//创建y轴
var yAxis = d3.svg.axis()//创建一个坐标轴
.scale(yScale)//设置比例尺为yScale
.orient("left");//放置在左侧
svg.selectAll("g").remove();
svg.append("g")//追加一个存放元素的group容器
.attr("class","axis")//设置css类名
.attr("transform", "translate(" + padding.left +","+(height-padding.bottom) + ")" )
.call(xAxis);
svg.append("g")//同上
.attr("class","axis")
.attr("transform","translate(" + padding.left+","+(height-yAxisWidth-padding.top)+ ")" )
.call(yAxis);
}
</script>
<script>
console.log(dataset);
draw();
</script>
<script>
function add()
{
dataset.push( Math.floor(Math.random()*100) );
console.log(dataset);
draw();
}
</script>
<br>
<button type="button" onclick = "add()">添加一个数据</button>
</body>
</html>
效果图如下:
- 呈现出一个柱状图,可以通过点击按钮通过随机数添加一个新的矩形条,颜色从最初的铁蓝色转变为红色
- 当鼠标经过矩形条时,矩形条变为黄色,离开的时候矩形条缓慢变回红色