资讯专栏INFORMATION COLUMN

d3入门篇(四):绘制完整柱状图添加过渡效果

Jason / 3358人阅读

摘要:这篇学习笔记是入门篇的最后一部分,将前几篇的内容整合到一起,绘制带过渡效果的柱状图,这次先给大家看一下结果图。

这篇学习笔记是入门篇的最后一部分,将前几篇的内容整合到一起,绘制带过渡效果的柱状图,这次先给大家看一下结果图。

结果

前言

先放结果图是想反馈一下在整合基础知识绘制完整柱状图遇到的几个问题:

整个柱状图的布局,比如哪些元素包在一个标签下,哪些元素是嵌套关系;

如果不采用translate,transform 翻转height属性的值,如何让矩形正常方向显示;

如何绘制文字;

如何为柱状图添加过渡效果;

坐标轴的位置如何确定,x轴如何划分刻度,如何让刻度显示在矩形的正下方;

!!!! 接下来将逐个解决上述出现的问题!!!!

Problem1:柱状图的整体布局

Solution

(1)为了绘制时,图形四周留有空白区域,我们首先设置一个padding值;
var padding={top:40,bottom:40,left:40,right:40};//定义间隔
(2)我们考虑在svg画布上进行绘制,采用如下的结构进行绘图:
    
        //将x轴包裹在一个g标签下
        
        //将y轴包裹在一个g标签下
        
        //将整个柱状图的矩形及文字包裹在一个g标签下
        
            //将柱形图的每个矩形与它相应的值包裹在一个g标签下
            
                
                
            
        
    
Problem2:如何按照垂直向上的方向显示矩形

Solution
之前的几篇文章我都是通过transform变换实现了矩形的翻转,这篇文章介绍一个新的思路。
首先确定一个矩形需要四要素(x,y,width,height),同时我们需要注意,画布的坐标轴方向为水平向右和垂直向下。height是我们数据可视化的展示部分,即数据的绑定部分,x,y确定了绘制矩形的左上角坐标。
这里提供一个思路:
如果按照正常垂直向下的方向绘制矩形时,要求矩形的bottom处在同一水平线上,y+height==固定值;也就是数据(height)大的部分,我们希望矩形的绘制起始点(y)的值较小,数据小(height)的部分,我们希望矩形的绘制起始点(y)的值较大。
因此我们可以通过定义比例尺完成这个功能,将dataset中大的数值,映射出range中小的数值。

//定义y方向比例尺
var yScale=d3.scaleLinear()
.domain([0,d3.max(dataset)])
.range([height-padding.top-padding.bottom,0]);
//定义y的值
.attr("y",function (d,i) {
    return yScale(d)
})
//定义height
.attr("height",function (d,i) {
    return height-padding.top-padding.bottom-yScale(d);
})

可以看出来‘y’+‘height’==height-padding.top-padding.bottom(这是一个固定的值)
Problem3:如何绘制文字

Solution
在Problem1中已经解决的布局方案问题,我们的方法是将矩形与文字包在一个g标签下,所以绘制文字与绘制矩形的方法相同,在标签下添加标签,同时需要设定:
(1)文字的显示位置:x,y
(2)文本信息:text
(3)文字位置的偏移值:dx,dy

graph.append("text")
.style("fill","pink")
.attr("x",function(d,i){
    return xScale(i);
})
.text(function (d) {
    return d
})
.attr("y",function (d,i) {
    return yScale(d);
})
Problem4:如何为柱状图添加过渡效果

Solution
为柱状图添加过渡效果,我们需要调用以下API:

.transition():为这个元素添加过渡;

.duration():设定元素从起始状态到终止状态的过渡时间;

.delay():设定元素执行过渡效果的时间间隔;

.ease():设定过渡的动画效果;

在为元素添加过渡效果时,初始状态,终止状态尤为重要,柱状图为例分析一下元素的两个状态:

明确柱形图为每个矩形添加过渡时,只有两个属性值需要改变,一个是y的值,一个是height的值;

起始状态:柱状图的起始状态非常好理解,就是矩形不显示的状态,即y值设定为前文提到的固定值,height设定为0;
终止状态:柱状图的终止状态应该是矩形元素和文字都可视化固定显示出来,即为正常绑定元素时设定的相关属性值。

//为矩形添加过渡效果
.attr("y",function (d) {
    var min=yScale.domain()[0];
    return yScale(min);
})
.attr("height",function(d,i){
    return 0;
})
.transition()
.duration(2000)
.delay(function(d,i){
    return i*400;
})
.ease(d3.easeBackOut)
.attr("y",function (d,i) {
    return yScale(d)
})
.attr("height",function (d,i) {
    return height-padding.top-padding.bottom-yScale(d);
})
Problem5:格式化显示坐标轴

Solution
在开始学习坐标轴的时候,只实现了添加y轴,在这次完整柱状图实现中,尝试添加x轴却遇到了问题。在这个例子中我们一共绑定了8个数据,那么如何让x轴的刻度均匀的显示在每个矩形的下方呢?
在定义x轴的时候我用了ScaleBand()这个方法:

//在range返回等差数列
var xScale=d3.scaleBand()
.domain(d3.range(dataset.length))
.rangeRound([0,dataset.length*(rectWidth+(rectPadding/2))]);
var xAxis=d3.axisBottom(xScale)
.ticks(5);

既然比例尺返回一个等差数列,所以我们要求在柱状图区域,每个矩形和空白间隔这个整体是相同的,所以我的实现是每个矩形左右各是半个rectPadding。先设置x的值,然后width设置成矩形宽度减去半个间隔。(不理解的可以自己画一张图就可以了)

.attr("x",function (d,i) {
    return (i*rectWidth)+(i+1)*(rectPadding/2);
})
.attr("width",rectWidth-rectPadding/2)

代码部分

import * as d3 from "d3";

var dataset = [45, 70, 12, 79, 4, 127, 33, 150];
var width = 600;//svg画布宽
var height = 600;//svg画布高
var rectWidth = 50;//每个矩形的默认宽度
var rectPadding=10;//每个矩形间的间隔
var padding={top:40,bottom:40,left:40,right:40};//定义间隔
//定义画布
var svg = d3.select("body")
.append("svg")
.attr("width", width)
.attr("height", height)
.style("background-color", "yellow");
//定义矩形比例尺

var yScale=d3.scaleLinear()
.domain([0,d3.max(dataset)])
.range([height-padding.top-padding.bottom,0]);
var yAxis=d3.axisLeft(yScale)
.ticks(5);
svg.append("g")
.attr("transform",`translate(${padding.top},${padding.left})`)
.call(yAxis);

var xScale=d3.scaleBand()
.domain(d3.range(dataset.length))
.rangeRound([0,dataset.length*(rectWidth+(rectPadding/2))]);
var xAxis=d3.axisBottom(xScale)
.ticks(5);
svg.append("g")
.attr("transform",`translate(${padding.left},${height-padding.top})`)
.call(xAxis);

//定义矩形
var g=d3.selectAll("svg")
.append("g")
.attr("transform",`translate(${padding.top},${padding.left})`);

var graph=g.selectAll("rect")
.data(dataset)
.enter()
.append("g");

graph.append("rect")
.style("fill","blue")
.attr("x",function (d,i) {
    return (i*rectWidth)+(i+1)*(rectPadding/2);
})
.attr("width",rectWidth-rectPadding/2)
.attr("y",function (d) {
    var min=yScale.domain()[0];
    return yScale(min);
})
.attr("height",function(d,i){
    return 0;
})
.transition()
.duration(2000)
.delay(function(d,i){
    return i*400;
})
//.ease(d3.easeBackOut)
.attr("y",function (d,i) {
    return yScale(d)
})
.attr("height",function (d,i) {
    return height-padding.top-padding.bottom-yScale(d);
})

graph.append("text")
.style("fill", "pink")
.attr("x", function (d, i) {
    return (i * rectWidth) + (i + 1) * (rectPadding / 2);
})
.attr("dx", 10)
.attr("y", function (d) {
    var min = d3.min(dataset);
    return yScale(min)
})
.text(function (d) {
    return d
})
.transition()
.duration(2000)
.delay(function (d, i) {
    return i * 400;
})
.attr("y", function (d, i) {
    return yScale(d);
})
附录

接下来会写进阶篇的学习笔记

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/100135.html

相关文章

  • d3入门(三):比例尺坐标轴

    摘要:为了根据显示刻度灵活变化宽高,而不是定死,特别是数据差异性很大的时候,我们希望图表显示范围都在画布里面,这时就会引入比例尺的概念来进行缩放。根据这些规则,会为我们返回一个比例尺函数。 这篇文章继续介绍d3的基础知识 比例尺 在绘制柱状图时,我们往往会定义很大的画布,然而我们要可视化的数据确很小,这时会出现很多留白 的情况。为了根据显示刻度灵活变化宽高,而不是定死,特别是数据差异性很大的...

    tomato 评论0 收藏0
  • 声明式与响应式——前端新一代数据可视化方案

    摘要:数据可视化图表图表作为数据可视化最常见的表现形式之一,往往被以偏概全的认为图表就是数据可视化。严格来说,数据可视化应该是连接数据与视觉的一个映射关系,将数据映射成人更容易感知其规律的可视化结果。 题目中的新一代是个相对的概念,事实上本文即将介绍的方法已经有了生产环境可用的实现方案(这也侧面佐证了其可行性),但考虑到此方法与现在大部分前端项目中所使用的数据可视化方案相比仍有一些优势,因此...

    xuhong 评论0 收藏0
  • SegmentFault 技术周刊 Vol.35 - WebGL:打开网页看大片

    摘要:在文末,我会附上一个可加载的模型方便学习中文艺术字渲染用原生可以很容易地绘制文字,但是原生提供的文字效果美化功能十分有限。 showImg(https://segmentfault.com/img/bVWYnb?w=900&h=385); WebGL 可以说是 HTML5 技术生态链中最为令人振奋的标准之一,它把 Web 带入了 3D 的时代。 初识 WebGL 先通过几个使用 Web...

    objc94 评论0 收藏0
  • 【数据科学系统学习】Python # 数据分析基本操作[三] matplotlib

    摘要:有一些表示常见图形的对象称为块,完整的集合位于。中的绘图函数在中,有行标签列标签分组信息。密度图通过计算可能会产生观测数据的连续概率分布的估计而产生的。在探索式数据分析工作中,同时观察一组变量的散布图是很有意义的。 我们在上一篇介绍了 pandas,本篇介绍 matplotlib。 绘图和可视化 一个用于创建出版质量图表的桌面绘图包。 Matplotlib API入门 Figure ...

    BDEEFE 评论0 收藏0
  • D3的一点理解

    摘要:的一点理解用其官网的话来说是一个用于数据可视化的库。其将数据与绑定,通过建立数据与元素样式之间的关系,来表现数据,实现可视化。它也是上星第多的库。 D3的一点理解 D3 用其官网的话来说: D3.js is a JavaScript library for manipulating documents based on data. D3 helps you bring data to...

    ideaa 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<