D3.js使用过程中的常见问题(D3版本D3V4)

目录

一、学习D3我必须要学习好SVG矢量图码?
二、如何理解D3给Dom节点绑定数据时的Update、Enter和Exit模式
三、D3绑定数据时用datum与data有什么不一样?
四、SVG图中用attr来设置属性和用style来设置样式时,用style来设置样式的权重会更高
五、D3使用链式写法时,写完transition动画后不能链着继续写append添加元素操作
六、如何给path设置缓动?
七、D3普通的缓动动画
八、给节点添加title,鼠标mouseover显示普通提示文本效果
九、getBBox按长方形获取节点的大小、长宽及坐标等等信息
十、使用遮罩制作动画
十一、D3常用的SVG元素类型有哪些?
十二、D3对svg元素设备位置一般有两种方式,使用坐标x、y或者使用transform来设置。
十三、数据可视化(不限D3)于要了解的一些基础概念
十四、笛卡尔坐标绘图适合制作普通线状、柱状等图;极坐标绘图适合制作螺旋形图表

本文同步发布于 http://www.kt5.cn/fe/2019/11/04/d3-js/

前言

        上一回合写到《D3.js从入门到“放弃”指南》代码中D3结合了react全家桶来写可能有点副格略高。在这里回归原点,整理好D3使用过程中或者学习过程中遇到过的常见问题。这里主要是新手专区,把新手入门D3时常见的问题记录下来,D3高手不喜勿喷,当然也延续了自己的习惯,持续更新,把常见的问题记录下来好处就是平时可以当自己的Q&A顺手拿来使用,毕竟人的大脑有限。

        点击查看所有在线Demo

一、学习D3我必须要学习好SVG矢量图码?

我觉得得SVG适量图是必须的,为什么要学习SVG图呢?因为D3.js堪称SVG中的jQuery,稍稍熟悉点jQuery的话,会更容易上手D3,当然你如果想用D3输出Canvas图或者你牛逼哄哄的说老子就只用D3来玩Canvas怎么嘀也可以,但SVG图操作起来更加灵活,更加方便调试,在Chrome中调试SVG图更加直观。D3只是一个作图工具,你完全也可以手写SVG的XML代码来完成作图,如下面是一个手画简单柱状图:

复制代码
            <svg class="chart" width="100%" height="120">
                <g transform="translate(0,0)">
                    <rect width="0.7619047619047619em" height="19"></rect>
                    <text x="0.6619047619047619em" y="10" dy=".35em">4</text>
                </g>
                <g transform="translate(0,20)">
                    <rect width="1.5238095238095237em" height="19"></rect>
                    <text x="1.4238095238095236em" y="10" dy=".35em">8</text>
                </g>
                <g transform="translate(0,40)">
                    <rect width="2.857142857142857em" height="19"></rect>
                    <text x="2.757142857142857em" y="10" dy=".35em">15</text>
                </g>
                <g transform="translate(0,60)">
                    <rect width="3.0476190476190474em" height="19"></rect>
                    <text x="2.9476190476190474em" y="10" dy=".35em">16</text>
                </g>
                <g transform="translate(0,80)">
                    <rect width="4.380952380952381em" height="19"></rect>
                    <text x="4.280952380952382em" y="10" dy=".35em">23</text>
                </g>
                <g transform="translate(0,100)">
                    <rect width="8em" height="19"></rect>
                    <text x="7.9em" y="10" dy=".35em">42</text>
                </g>
            </svg>
View Code
复制代码

 

二、如何理解D3给Dom节点绑定数据时的Update、Enter和Exit模式

代码如下:

复制代码
// Update…
var p4 = d3.select("#my_p_4")
  .selectAll("p") // 选择所有的P元素
  .data([4, 8, 15, 16, 23, 40]) // 给所有的P元素相应绑定数据(当然P元素有可能与数组元素个数不相等,则要转入下面的Enter和exit操作)
  .text(function (d) { return d; }); // 改变所有的P元素的text为相应的数组的值

p4.enter().append("p") // 如果原有P节点元素小于数组的元素个数,则要给父节点append节点补足
    .text(function (d) { return d; });

// Exit…
p4.exit().remove(); // 如果原有P节点元素大于数组的元素个数,则要执行删除操作,以保证p节点元素个数与传入的data数组元素个数相当
复制代码

 

三、D3绑定数据时用datum与data有什么不一样?

用data是给所有的节点去绑定对应的data里面的数组元素值并一一匹配,而使用datum是给所有的节点绑定一样的数据值。

 

四、SVG图中用attr来设置属性和用style来设置样式时,用style来设置样式的权重会更高

style设置权重其实比用css样式表来设置更高,代码如下:

d3.select("#my_chart_2 rect")
.style("width", 20) // 同样设宽度用style生效
.attr("width", 40); // 同样设宽度用attr权重没style高,会失效

 

五、D3使用链式写法时,写完transition动画后不能链着继续写append添加元素操作

一般可以这么操作,先定义变量暂存节点再单独写动画或者单独写append追加元素操作,代码如下:

复制代码
        var g = chart.append("g")
        .style('fill-opacity', 0);  
        .transition()
        .duration(1000)
        .style('fill-opacity', 1); // 动画渐现  

        /*g.selectAll("rect") // 绘画所有的矩形
            .data(data)
            .enter()
            .append("path")...
        */
复制代码

 

六、如何给path设置缓动?

如画饼图时,想加上缓动动画,代码如下:

        let arc = d3.arc() // 定义单个圆弧
            .innerRadius(0)
            .padAngle(0);
        let pie = d3.pie() // 定义饼图
            .sort(null)
            .value(function (d) { return d.population; });
复制代码
        g.selectAll(".arc") // 画环图
            .data(pie(data))
            .enter().append("path")    
            .attr("cursor", "pointer")
            .attr("class", "arc")
            .attr('stroke', function (d) { return colors(d.data.age); })
            .style("fill", function (d) { return colors(d.data.age); })
            .each(function(d) { // 储存当前起始与终点的角度、并设为相等
                let tem = {...d, endAngle: d.startAngle};
                d.outerRadius = radius - 10;
                this._currentData = tem; 
            })
            .transition()
            .duration(100)
            .delay(function (d, i) { return i * 100; })
            .attrTween("d", function(next) { // 动态设置d属性、生成缓动画
              var i = d3.interpolate(this._currentData, next);
              this._currentData = i(0); // 重设当前角度
              return function(t) {
                return arc(i(t));
              };
            });
复制代码

或者单独定义好缓动函数,代码如下:

复制代码
        g.selectAll(".arc") // 画环图
            .data(pie(data))
            .enter().append("path")
            .each(function(d) { // 储存当前起始与终点的角度、并设为相等
                let tem = {...d, endAngle: d.startAngle};
                d.outerRadius = radius - 10;
                this._currentData = tem; 
            })
            .on("mouseover", arcTween(radius + 50, 0))
        .on("mouseout", arcTween(radius - 10, 150))
            .attr("cursor", "pointer")
            .attr("class", "arc")
            .style("fill", function (d) { return colors(d.data.age); })
            .transition()
            .duration(750)
            .attrTween("d", function(next) { // 动态设置d属性、生成动画
              var i = d3.interpolate(this._currentData, next);
              this._currentData = i(0); // 重设当前角度
              return function(t) {
                return arc(i(t));
              };
            });      

         function arcTween(outerRadius, delay) { // 设置缓动函数
          return function() {
            d3.select(this).transition().delay(delay).attrTween("d", function(d) {
              var i = d3.interpolate(d.outerRadius, outerRadius);
              return function(t) { d.outerRadius = i(t); return arc(d); };
            });
          };
        }
复制代码

 

七、D3普通的缓动动画

如果想要给柱图添加每条柱由左到右按顺序缓动弹出,代码如下:

复制代码
        g.selectAll(".bar")// 画柱图
            .data(data)
            .enter().append("rect")
            .attr("x", function (d) { return x(d.letter); })
            .attr("y", height) // 控制动画由下而上
            .attr("width", x.bandwidth())
            .attr("height", 0) // 控制动画由下而上
            .transition()
            .duration(200)
            .ease(d3.easeBounceInOut) // 这里还有d3.easeLinear、d3.easeCubicOut等等多种效果,可自行查看API 
            .delay(function (d, i) { return i * 200; })
            .attr("y", function (d) { return y(d.frequency); })
            .attr("height", function (d) { return height - y(d.frequency); });
复制代码

 

八、给节点添加title,鼠标mouseover显示普通提示文本效果

当需要hover提示文本效果时,可以添加title,或者如果想要更加丰富的自定义效果可以使用开源的d3插件d3-tip,也可以自己写一个hover效果,实现起来的思想就是on('mouseover',callback)方式,代码如下:

复制代码
        g.append("g")//
            .selectAll('rect')
            .data(data)
            .enter()
            .append('rect')
//... .append(
'title') // 在后面添加title .text(function(d) { return d.name; });
复制代码

 

九、getBBox按长方形获取节点的大小、长宽及坐标等等信息

在应用场景中,我们经常也会遇到要获得某元素的长宽等信息,实现代码如下:

复制代码
        label.insert("rect", "text") // 生成背景白块
            .datum(function () { return this.nextSibling.getBBox(); }) // 这里在text前插入一个rect,并按照text的属性来设置长宽及坐标
            .attr('fill', '#fff') 
            .attr("x", function (d) { return d.x; })
            .attr("y", function (d) { return d.y; })
            .attr("width", function (d) { return d.width; })
            .attr("height", function (d) { return d.height; });
复制代码

 

十、使用遮罩制作动画

当你实现不想花那么多时间去在作图时实现动画,可以考虑在SVG遮罩里面加动画来实现同样的效果,代码如下:

复制代码
        chart.append("defs").append("clipPath") // 添加长方形方块,遮罩作用
            .attr("id", "clip")
           .append("rect")
            .attr("height", height)
            .attr("width", 0) // 用遮罩实现线动画
            .transition()
            .duration(1000)           
            .attr("width", width);

        let serie = g.selectAll(".serie") // 生成两线条
            .data(series)
            .enter().append("g")  
            .attr("class", "serie");

        serie.append("path") // 绘画线条
            .attr('clip-path', 'url(#clip)')         
            .attr("class", "line")
            .style("stroke", function (d) { return z(d[0].key); })
            .attr('fill', 'none')
            .attr("d", line);
复制代码

 

十一、D3常用的SVG元素类型有哪些?

circle, line, rect, path, svg, g, defs, clipPath, text, title

 

十二、D3对svg元素设置位置一般有两种方式,使用坐标x、y或者使用transform来设置。

一般来说,是两者配合使用,transform后再设置x, y坐标或者再结合dx, dy位置来设置节点的位置。

 

十三、数据可视化(不限D3)于要了解的一些基础概念

x轴, y轴, tick, legend, serie, brush, zoom, 散点, 线状图, 面积图, 柱状图, 饼图, 打包图, 弦图, 打包图, 雷达图, 力向导图, 树状图, 堆栈图, 组合线状/组合柱状图, 标签云图, geomap地图等

对应到D3API中必备的知识:d3-selection(D3 选择器)  d3-shape(D3 作图图形图)  d3-transition(D3 过渡动画)  d3-axis(D3 坐标)  d3-scale(D3 比例尺生成工具)

 

十四、笛卡尔坐标绘图适合制作普通线状、柱状等图;极坐标绘图适合制作螺旋形图表

如笛卡尔坐标画线会用到普通的d3.line,而极坐标画线会用到d3.lineRadial。

 

交流与学习

  1. 本文作者Fast Mover  欢迎大家留言及多多指教
  2. 版权声明:欢迎转载学习 => 请标注信息来源于http://www.cnblogs.com/fastmover/p/7794519.html
  3. 本文所有的在线Demo

 

 
posted @   Fast Mover  阅读(6319)  评论(0编辑  收藏  举报
编辑推荐:
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· 展开说说关于C#中ORM框架的用法!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
友情链接: A4纸尺寸 | 卡通头像 | +申请友情链接
点击右上角即可分享
微信分享提示