码字不易—口水少来–有用请好评-打赏也行喔
为了初学者,本文尽量细致再细致,觉得太啰嗦的大牛绕过----我膜拜您
需求:完整柱状图
备注:前奏选择器、比例尺、坐标轴等基础知识不在赘叙,下面会有相关链接;
推荐链接:别个的教程 https://blog.csdn.net/qq_34414916/article/details/80029352
正文开始:
本文旨在封装一个基于d3 多端适配的柱状图组件 所以大家看到的会是一个方法;
方法外壳:
MendegBar = (DataObject) => {
//移动端适配 预计padding以及width、height会通过一个胶着方法,以此判断是否进行适配
let { dom = "", height, width, padding = { top: 20, left: 20, bottom: 20, right: 20 } } = DataObject;
if (dom === "") {
console.log("dom不存在 !");
}
//padding:图表分组位置参数
//没有传入height时便获取dom的宽高
height ? null : height = d3.select(dom).node().getBoundingClientRect().height;
width ? null : width = d3.select(dom).node().getBoundingClientRect().width;
}
首先需要画布,也就是即将展现数据的地方(区域),推荐使用svg
//新建画布
let svg = d3
.select(dom)
.append("svg")
.attr("height", height)
.attr("width", width)
.style("background", "#fff");
有了画布,我们得为以后的操作流出余地,也就是可能会出现一个画布好几个图表的情况发生,所以需要一个组,用来将我们的一个个图表装起来;
//定义一个装图表的分组并且确定他的位置
svg.append("g").attr("transform", "translate(" + padding.top + "," + padding.left + ")").attr("background", "skyblue");
数据,为方便学习,此处数据并未提出方法外
// 数据集
let data = [100,200,50,20,400,80];
接下来就要考虑比例尺和坐标轴了 首先要明确一个概念 在d3中,比例尺有很多种,具体表现都是通过方法的 推荐一个常用比例尺的网站 https://segmentfault.com/a/1190000011006780
//为x轴 y轴添加坐标轴 该方法考虑抽出作为独立api d3.scaleBand() 序数比例尺 .domain()输入域 range() 输出域
// d3.range(0, 10, 1) 返回一个算数级数组 例如 [0,1,2,3.......9] (开始,结束,分度)
//此处为省略了 开始(0) 分度(1) 采取他们的默认值 (0,data.length,1) d3.range(data.length) data.length为终止数 注意 生成序列并不包括 data.length
// .rangeRound()设置比例尺的输出范围并四舍五入
// d3.scaleBand().domain(d3.range(data.length)).rangeRound([0,width-padding.left-padding.right])
// d3.scaleBand()比例尺的输入域是 [0,1,2,...,data,length-1] 输出域是 [0,500-20-20];
// scaleBand()序数比例尺 scaleLinear()线性比例尺
let xScale = d3.scaleBand()
.domain(d3.range(data.length)).rangeRound([0, width - padding.left - padding.right]);
// y轴输入域 [0,400] 输出域 [500-20-20,0]
let yScale = d3.scaleLinear()
.domain([0, d3.max(data)])
.range([height - padding.top - padding.bottom, 0]);
// 坐标轴
// .axisBottom(canshu) 创建向下的坐标轴 参数是比例尺 axisLeft向左的坐标轴
let xAxis = d3.axisBottom(xScale);
let yAxis = d3.axisLeft(yScale);
// 到这一步 柱状图的基本架子已经搭起来了,下面需要做的便是怎么把数据呈现了
//将坐标轴组件加入当前图表分组
g.append("g")
.attr("transform", "translate(" + 0 + "," + (height - padding.top - padding.bottom) + ")")
.call(xAxis);
g.append("g")
.attr("transform", "translate(0,0)")
.call(yAxis);
下面一步便是将数据呈现,那么我们就需要svg里的各种标签组件上手了。
//首先 为每一个数据(一个矩形)创建一个分组组g 这里出现一个概念 enter() 这里的意思是根据数据补全g
//本来g.selectAll(".rect") 是获取不到东西的 但是 .data(data).enter().append("g")以后 data有多少数据,我就给他补全多少g
// 题外话:data()将数据绑定到选择集上
let g_s = g.selectAll(".rect")
.data(data)
.enter()
.append("g");
// console.log("神奇的enter",g_s);// 为了效果更明显 [g, g, g, g, g, g]
// 现在正主来了 为数据画出一片天地 嘎嘎,就是矩形来着
//科普一下 svg的基础哈
/*
svg 预定义形状元素
矩形 <rect>
圆形 <circle>
椭圆 <ellipse>
线 <line>
折线 <polyline>
多边形 <polygon>
路径 <path> 高大上 ,就是条线而已 可以设置开始和结束哟
<text> 元素用于定义文本。
rect 的属性:
rect 元素的 width 和 height 属性可定义矩形的高度和宽度
style 属性用来定义 CSS 属性
CSS 的 fill 属性定义矩形的填充颜色(rgb 值、颜色名或者十六进制值)
CSS 的 stroke-width 属性定义矩形边框的宽度
CSS 的 stroke 属性定义矩形边框的颜色
x 属性定义矩形的左侧位置(例如,x="0" 定义矩形到浏览器窗口左侧的距离是 0px) 在这里呢就是坐标轴的位置 咱自己的坐标轴
y 属性定义矩形的顶端位置(例如,y="0" 定义矩形到浏览器窗口顶端的距离是 0px)
CSS 的 fill-opacity 属性定义填充颜色透明度(合法的范围是:0 - 1)
CSS 的 stroke-opacity 属性定义笔触颜色的透明度(合法的范围是:0 - 1)
CSS 的 opacity 属性定义整个元素的透明值(合法的范围是:0 - 1)
*/
//这是每个矩形之间的距离
let rectPadding = 30;
g_s.append("rect")
.attr("x", function (d, i) {
// d 数据 单项数据 i 索引
return xScale(i) + rectPadding / 2;
// 这个意思还用我解释吗?还是解释一下吧,嘎嘎,我一定是个好老师
// 每一个rect "x" 属性的值 都等于 处于x轴的刻度的值(等差数列喔)加上 每个矩形之间的距离的一半喔
// xScale(i) 2 78 154 .. 然后第一个的x轴位置是多少呢 那当然是2啦 不过咱们得有间距 所以得加上间距 然后呢还得砍掉一半
// 别问我为什么,揍你
})
.attr("y", function (d) {
return yScale(d);
// 参照上面 强调依据 x y 相对于我们自己的坐标轴来的哈
})
.attr("width", function () {
//科普一下哈 xScale.step() 这个得到的是每一个等差刻度的宽喔 这里是 76
//所以下面为什么会这么return 不用我再多说了吧
return xScale.step() - rectPadding;
})
.attr("height", function (d) {
console.log(d, yScale(400));
//这个呢,能看明白不 设置高 算了 为防止一些yt看不明白 小说一下
//总高度 - 上下空白 - yScale(d)(数据d时,y轴的输出是多少)
//回顾y轴比例尺 [height - padding.top - padding.bottom, 0] 倒着来的喔
// 所以d越大,对应在y轴的值就越小 400 时 yScale(400)//0
//明白不,再不明白趴着让我打屁屁就明白了 嘿嘿
return height - padding.top - padding.bottom - yScale(d);
})
.attr("fill", "skyblue");//这个呢就是矩形颜色的干活 (最近看个抗日剧、那剧情......)
//最后 给每个矩形加上文字
/*
<text> 元素用于定义文本。
属性:
主要属性有:x,y,dx,dy,rotate,textLength,lengthAdjust
x,y表示文本的横纵坐标。
dx,dy表示移动的横纵坐标。
rotate表示旋转的度数。
*/
//下面的运算不在解释
g_s.append("text")
.attr("x", function (d, i) {
return xScale(i) + rectPadding / 2;
})
.attr("y", function (d) {
return yScale(d);
})
.attr("dx", function () {
(xScale.step() - rectPadding) / 2;
})
.attr("dy", 20)
.text(function (d) {
return d;
})
至此一个完整的柱状图就已经完成了,下篇文章就是图表交互了,敬请期待。。。。。