制作柱状图的技巧
有一些基本规则:
- 避免使用 3D 效果;
- 直观地排序数据点 - 按字母顺序或按数字排序;
- 柱条之间保持一定距离;
- y 轴从 0 开始,而不是从最小值开始;
- 使用统一的颜色;
- 添加轴标签、标题、导引线。
D3.js 网格系统
在背景中添加 栅格线
突出那些值。
垂直
和水平
的线都可以添加,但是建议是只添加一种。过多的线会分散注意力。以下代码片段演示了如何添加水平和垂直的栅格。
-
axis.tickSize([inner,outer])
设定或获取坐标轴的内外刻度的长度。默认都为6
-
axis.innerTickSize([size])
设定或获取坐标轴的内刻度的长度。内刻度指不是两端的刻度。
-
axis.outerTickSize([size])
设定或获取坐标轴的外刻度的长度。外刻度指两端的刻度。
-
asix.tickFormat([format])
设定或获取刻度的格式。
// 添加垂直的栅格
chart.append('g')
.attr('class', 'grid')
.attr('transform', `translate(0, ${height})`)
.call(d3.axisBottom()
.scale(xScale)
.tickSize(-height, 0, 0)
.tickFormat(''))
// 添加水平的栅格
chart.append('g')
.attr('class', 'grid')
.call(d3.axisLeft()
.scale(yScale)
.tickSize(-width, 0, 0)
.tickFormat(''))
D3.js 中的标签
文字指导,为坐标轴添加标签。
- 它们可以使用 x 和 y 坐标定位,文本对齐是通过
text-anchor
属性实现的。 - 添加标签文字,只需
调用文本元素上的 text 方法
。
// 添加百分比
barGroups
.append("text")
.attr("class", "value")
.attr("fill", "#fff")
.attr("x", a => xScale(a.language) + xScale.bandwidth() / 2)
.attr("y", a => yScale(a.value) + 30)
.attr("text-anchor", "middle")
.text(a => `${a.value}%`);
// 为坐标轴添加标签
svg
.append("text")
.attr("class", "label")
.attr("x", -(height / 2) - margin)
.attr("y", margin / 2.4)
.attr("transform", "rotate(-90)")
.attr("text-anchor", "middle")
.text("Love meter (%)");
svg
.append("text")
.attr("class", "label")
.attr("x", width / 2 + margin)
.attr("y", height + margin * 1.7)
.attr("text-anchor", "middle")
.text("Languages");
与 D3.js 交互
给 SVG 元素添加事件监听。
svgElement
.on('mouseenter', function (actual, i) {
d3.select(this).attr(‘opacity’, 0.5)
})
.on('mouseleave’, function (actual, i) {
d3.select(this).attr(‘opacity’, 1)
})
-
当悬停在特定的列时,该栏的顶部就会画一条水平线。
虚线,是通过
stroke-width
和stroke-dasharray
属性实现的。(使用 stroke-dasharray,可以定义虚线的图案和间距,从而改变形状的轮廓。)
.attr("stroke-width", 3) .attr("stroke-dasharray", 6)
-
增加了透明度,加大了柱条的宽度。
.attr("opacity", 0.6) .attr("width", xScale.bandwidth() + 10);
-
写mouseenter 事件 的同时记得要写mouseout 事件恢复或删除更改
.
什么是矩形树图 ?
矩形树图的本名为:矩形式树状结构图(Treemap)
,实现层次结构可视化的图表结构 .
矩形树图
用于表示层级、上下级、包含与被包含关系。
实现效果需要一下几步:
- 数据的转化
- 用叶子节点数组绘图
- 添加矩阵
需要先了解的一些API
-
d3.treemap()
定义一个矩形树图布局函数
-
d3.treemap().size()
指定矩形树图的布局范围
-
节点.leaves()
将生成的树形结构转化成叶子节点数组 (叶子是没有子节点的节点)。
-
d3.hierarchy()
可视化分层数据的布局算法,通过它可以返回根以及节点
-
节点.sum(value)
返回所有的节点
-
scaleOrdinal()
颜色比例尺
eg: D3提供了一些颜色比例尺,10就是10种颜色,20就是20种:
const color = d3.scaleOrdinal(d3.schemeCategory10);
const color = d3.scaleOrdinal(d3.schemeCategory20);
具体实现步骤
-
初始化数据
const treeData = { name: "中国", children: [ { name: "浙江", children: [ { name: "杭州", gdp: 1234 }, { name: "宁波", gdp: 3334 }, { name: "温州", gdp: 2000 }, { name: "绍兴", gdp: 1002 } ] }, ... ] };
-
通过布局函数 treemap() 定义一个矩形树图 并且通过.size 指定布局范围
const treemap = d3.treemap().size([width, height]);
-
创建一个层级布局
const root = d3.hierarchy(treeData).sum(d => d.gdp);
-
获取treemap结构树
const tree = treemap(root);
-
将生成的树形结构转化成叶子节点数组
const leaves = tree.leaves();
-
通过颜色比例尺提供颜色
const color = d3.scaleOrdinal(d3.schemeCategory10);
-
用叶子节点数组绘图
const svg = d3 .select("#treemap") .append("svg") .attr("width", width) .attr("height", height); const g = svg .selectAll(".rects") .data(leaves) .enter() .append("g") .attr("class", "rects");
-
添加矩阵
g.append("rect") .attr("x", function(d){ return d.x0 }) .attr("y", function(d){ return d.y0 }) .attr("width", function(d){ return d.x1 - d.x0 }) .attr("height", function(d){ return d.y1 - d.y0 }) .style("fill", d => color(d.parent.data.name)) .style("stroke", "#cccccc");
-
添加描述
g.append("text") .attr("x", d => (d.x1 - d.x0) / 2 + d.x0) .attr("y", d => (d.y1 - d.y0) / 2 + d.y0) .attr("dx", d => { return -d.data.name.length / 2 + "em"; }) .attr("dy", d => { return "-0.5em"; }) .text(d => { return d.data.name; }) .attr("font-size", d => { return 14 - d.depth + "px"; }) .attr("fill", "#f0f0f0"); g.append("text") .attr("x", d => (d.x1 - d.x0) / 2 + d.x0) .attr("y", d => (d.y1 - d.y0) / 2 + d.y0) .attr("dx", d => { return -(d.value.toString().length + 2) / 4 + "em"; }) .attr("dy", d => { return "1em"; }) .text(d => { return "(" + d.value + ")"; }) .attr("font-size", d => { return 14 - d.depth + "px"; }) .attr("fill", "#ffffff");