【D3.js 01】

news2025/1/20 3:39:52

D3.js 01

    • 说在前面
    • 1 概述
    • 2 配置Web环境
    • 3 HTML
    • 4 SVG
    • 5 DOM
    • 6 JS
    • 7 常用接口
    • 8 D3语法基础
    • 9 使用D3查询SVG
    • 10 使用D3设置SVG中属性
    • 11 修改整组属性
    • 12 使用D3添加与删除SVG元素
    • 13 数据读取 —— CSV数据
    • 14 D3.js的数值计算
    • 15 比例尺
      • Scale - Linear
      • Scale - Band
    • 16 引入坐标轴
    • 17 DATA-JOIN

说在前面

最近需要使用到D3.js,所以在B站上找到清华的D3.js教程,同时在这里做相关的自学笔记
原视频链接如下:

【数据可视化编程-使用D3.js(2022)】 https://www.bilibili.com/video/BV1qg411X7bB/?share_source=copy_web&vd_source=773b408053db6c74535b5afe2aa8feb9

1 概述

D3.js是目前最主流的,社区规模最大的,支持定制图元级别可视化效果的框架

相关文档:https://github.com/xswei/d3js_doc
D3画廊:https://observablehq.com/@d3/gallery

其他如Echarts不支持图元级别定制,但是支持图表混搭

之后课程会介绍动画与交互,可视化图表绘制,其他常用接口

D3: Data-Driven Documents
通过D3提供的接口基于数据操控文档(画布)的各个图元

接口约等于D3.js提供的函数调用

主要参考资料:

https://d3js.org/ 官网,文档,样例
https://developer.mozilla.org/zh-CN/docs/Web/SVG/Attribute SVG 属性参考
https://github.com/d3/d3 官方样例仓库
https://observablehq.com/@d3/gallery 官方样例仓库
https://github.com/xswei/d3js_doc d3.js资源汇总,包括示例、书籍、API文档等
https://github.com/Shao-Kui/D3.js-Demos

2 配置Web环境

D3.js基于JS,用于在Web前端控制HTML中的元素

  • 使用VScode,安装Live Server
  • 直接应用常用框架:Python Simple HTTP Server(不推荐),Node.js Simple HTTP Server,Flask, Express等

3 HTML

HyperText Markup Language
HTML包含大量元素(标签)

  • 元素之间类别不同,如矩形,直线,文本,圆等等
  • 元素包含属性,如位置,大小,色调,文本风格等等

<script> :JS脚本或者脚本链接
D3.js或Echart的编程主要写于此标签中
<svg>:对于D3最重要的标签
主要操作的对象画布,同时包括所有图元应用的标签,如<rect>, <circle>, <path>

D3.js是JS的外库,必须先将其导入
如同Python的import
Java的import
C/C++的include
node.js的require
这里通过Script标签导入

  • 直接通过互联网链接 - <script src="https://d3js.org/d3.v7.min.js"></script>
  • 通过本地服务器链接 - ./d3.min.js
  • 通过unpkg链接 - https://unpkg.com/browse/d3@5.15.0/dist/d3.js
    尽量使用本地的d3.min.js库

4 SVG

D3的绘制画布
Scalable Vector Graphics 可缩放矢量图形

5 DOM

文档对象模型
在这里插入图片描述

对于根节点的操作会影响子节点
常用父节点<svg>中的<g>

  • Axis可以封装为一个group
  • Legend(图例)可以封装为一个group

6 JS

解释型
不需要编译
JS语句类似于C与C++
变量声明不需指定类型 int double function等,直接let, var const
运算操作基本等同C,C++和Java
下面是函数定义:

function abc(a) { return a + 5; }
const p = function(a, b){return a + b;}
let f = datum => datum.value;
let myFunction = (a, b) => a + b
let f = (d, i) => { console.log(d);return d + I;}

一个变量可以是一个函数
类似于C/C++中的函数指针
const myFunction = function(a, b){ return a + b; }
回调(CallBack)
JS脚本中常见将函数作为变量输入用于实现异步编程

setTimeout( funciton() {
	console.log('hello world')
}, 1000);

在D3中存在大量类似调用

  • 将函数作为参数给图元
  • 为每个数据点指定不同颜色
  • 配置坐标轴

7 常用接口

模版字符串

let a = 10;
let myString = `abc-${a}`;
// myString最终为'abc-10'

数组 a = [1, 2, 3]
对象 a = {name: ‘Zane’, age: 24, lab: ‘cs’}
D3数据可视化常见对象数组

a = [{name:'Zane', age: 20, dept: 'cs'},
		 {name:'LJD', age: 21, dept: 'cs'},
		 {name: 'LH', age: 22, dept: 'ee'}]

数组排序 a.sort()
- 可以通过加入回调函数来替代缺省的排序方案,如为日期排序
- a.sort(function(a, b){ return new Date(b.date) - new Date(a.date); }
数组查询 a.find()
a.find( d => d.name === ‘Zane’)

将字符串转为数值 +(‘3.14’)
D3.js经常读取CSV,JSON等文件,涉及大量数组,对象操作

8 D3语法基础

使用D3获取,修改,增加以及删除节点(图元)
数据读取 - CSV
数值计算
比例尺:1. 线性比例尺 Linear Scale
2. 条带比例尺 Band Scale
坐标轴绘制: Margin
Data-Join基础
基于D3与Data-Doin绘制柱状图

9 使用D3查询SVG

d3.select(‘#rect1’) 永远返回第一个
d3.selectAll(‘.class1’) 返回所有
ID前加#,Class前加.,标签前不加

层级查询
d3.select(‘#maingroup rect’)
d3.select(‘.tick text’)
d3.selectAll(‘#secondgroup rect’)

10 使用D3设置SVG中属性

常见属性:

  • id, class (特殊属性,可使用.attr设置)
  • x, y, cx, cy (注意屏幕坐标系)
  • fill, stroke
  • height, width, r (圆的半径)
  • transform -> translate, rotate, scale

SVG的属性非常多,并且属性的取值范围和类型各不相同

  1. 尽可能记住常见的属性来提高编程速度
  2. 遇见不认识的or想要设置某个属一定要查阅文档

https://developer.mozilla.org/zh-CN/docs/Web/SVG/Attribute

<rect id='rect3' class='class1' stroke='black' height='200' width='66' fill='#7289AB' x='300' y='-100'>

屏幕空间的坐标系与常见坐标系不同
左上方为原点
y,x分别垂直向下、水平向右

element.attr(…)
设置元素属性: element.attr(‘attr_name’, ‘attr_value’)

  • 两参数:属性名,属性值
  • rect1.attr(‘y’, ‘100’)
  • d3.select(‘#rect1’).attr(‘y’, ‘100’)

获取元素属性: element.attr(‘attr_name’)

  • 一参数: 属性名

链式调用:

  • selection.attr(…).attr(…).attr(…)
  • .attr(…)返回的是选择的图元本身

11 修改整组属性

DOM
父节点的属性会影响子节点
子节点的属性相对于父节点
以下代码可以直接移动组内的所有元素
d3.select(‘#maingroup’).attr(‘transform’, ‘translate(200, 100)’)

12 使用D3添加与删除SVG元素

  • element.append(…)

    • const myRect = svg.append(‘rect’);
    • const myRect = d3.select(‘#mainsvg’).append(‘rect’)
    • const myRect = d3.select(‘#mainsvg’).append(‘rect’).attr(‘x’, ‘100’)
  • D3的链式添加(调用)

    • const myRect = d3.select(‘#mainsvg’).append(‘g’).attr(‘id’, ‘maingroup’)
    • .append(‘rect’).attr(‘fill’, ‘yellow’)
  • element.remove()

    • 小心使用
    • 因为将移除整个标签
    • d3.select(‘#rect1’).remove()

在debug过程中可以使用’opacity’属性hack出移除效果

  • element.attr(‘opacity’, ‘0’)

13 数据读取 —— CSV数据

第一行是属性列表,后面每一行对应一条数据
CSV本质上是纯文本,区别于EXCEL格式

  • d3.csv(…):

    • 读取目标路径下的某一CSV文件
    • d3.csv(‘static/data/hello.csv’);
  • d3.csv是一个JavaScript异步函数:

    • 不可以直接获得其返回值
    • 不可以有 let myData = d3.csv(‘static/data/hello.csv’);
  • d3.csv(‘path/to/data.csv’).then( data => { // ‘数据读取后的代码逻辑’ } )

    • 需要通过.then( data => {…} )的方式获得读取后的数据
    • then(…)中的 data => {…} 是一个函数
    • 该函数接收的是输入参数,也即data,是读取后的数据
  • JavaScript异步机制

    • d3.csv是异步函数,即便没有读取完毕数据,后面的代码依旧继续执行
    • d3.csv被调用后的返回值是一个JavaScript的Promise对象(object)
    • Promise 询问:数据读取完毕后需要做什么,做什么即对应.then()中函数的内容

读取后的数据格式(接口)与原本的CSV结构不同

14 D3.js的数值计算

数据可视化常常涉及对数据的处理与计算
下面三个接口分别用于计算数组的最大值,最小值,[最小值, 最大值]

  • d3.max(array)

  • 返回数组中的最大值

  • d3.min(array)

  • 返回数组中的最小值

  • d3.extent(array)

  • 同时以数组的形式返回最小值与最大值

数组中的内容可以是任意对象

  • 每个对象可能包含多个属性
  • 具体需要那个属性的最值可以通过回调函数提示d3.max, d3.min与d3.extent

15 比例尺

比例尺用于将实际数据空间映射到屏幕(画布)空间,也即两个空间转化
用于映射数据和创建坐标轴,区别主要在于数据的尺度不同

Scale - Linear

d3.scaleLinear():

  • 定义一个线性比例尺,返回的是一个函数
  • 如 let scale = d3.scaleLinear(); // scale是函数

scale.domain([min_d, max_d]).range([min, max]):

  • 设置比例尺的定义域与值域
  • 线性比例尺的定义域和值域都是连续的(Continuous),需要给出最大值与最小值
  • const scale = d3.scaleLinear().domain([20, 80]).range([0, 120]);

比例尺本质上是函数

  • scale(20) // 0
  • scale(50) // 60

常常结合读取的数据与d3.max等接口连用

  • const xScale = d3.scaleLinear().domain([0, d3.max(data, d => d.value)]).range([0, innerWidth]);

Scale - Band

d3.scaleBand():

  • 定义一个条带比例尺,返回一个函数
  • let scale = d3.scaleBand();

scale.domain(array).range([min, max]):

  • 设置比例尺的定义域和值域
  • Band比例尺的定义域是离散的(Discrete),值域是连续的
  • 如 const scale = d3.scaleBand().domain([‘a’, ‘b’, ‘c’]).range([0, 120]);
  • 比例尺本质上是函数:
    • scale(‘b’) // 40
    • scale(‘c’) // 80

d3.scaleBand()常常结合JS的array.map接口一同使用:

  • let a = [{name: ‘Zane’, value: 6}, {name: ‘LiHao’, value: 7}, {name:‘Ljd’, value: 8}]
  • a.map(d => d.name) // [‘Zane’, ‘LiHao’, ‘Ljd’]
  • const yScale = d3.scaleBand()
  • .domain(data.map(d => d.name))
  • .range([0, innerHeight])
  • .padding(0.1)

scale.padding(0.1):
设置条带间距占各自区域的比重

scale.bandwidth():
返回条带长度

16 引入坐标轴

一个坐标轴为一个group,也即<g>
通常需要两个坐标轴

坐标轴中包含:

  • 一个<path>用于横跨坐标轴的覆盖范围
  • 若干个刻度.tick,每个刻度也是一个group
  • 每个刻度下属包含一个<line>和一个<text>
    • <line>用于展示轴线,如左到右或上到下
    • <text>用于展示刻度值,如实数,姓名,日期
  • (可选)一个标签用于描述坐标轴

坐标轴的定义需要比例尺

定义坐标轴(获得结果仍是函数)

  • const yAxis = d3.axisLeft(yScale);
  • const xAxis = d3.axisBottom(xScale);
  • axisLeft: 左侧坐标轴
  • axisBottom: 底侧坐标轴
  • 坐标轴的刻度对应比例尺的定义域
  • 坐标轴在画布的绘制对应比例尺的值域
  • 仅仅是对坐标轴的定义,没有绘制

绘制坐标轴

  • const yAxisGroup = g.append(‘g’).call(yAxis);
  • const xAxisGroup = g.append(‘g’).call(xAxis);
  • 实际配置后会发现<g>中增加了与坐标轴相关的元素

任何坐标轴在初始化之后会默认放置在坐标原点,需要进一步平移

关于 selection.call(…)

  • 函数的输入为另一个函数
  • 另一个函数以selection本身(也即图元)作为输入
  • 另一个函数将根据函数体的内容修改selection对应的图元
  • 定义一个空白的<g>,D3会帮助我们定义好另一个函数,我们通过.call(…)让<g>得以在另一个函数中修改
    • const yAxis = d3.axisLeft(yScale);
    • const yAxisGroup = g.append(‘g’).call(yAxis);

配置坐标轴
可以对坐标轴的风格进行修改

  • 坐标轴本质上是图元的集合
  • d3.selectAll(‘.tick text’).attr(‘font-size’, ‘2em’);
  • .tick是D3对于坐标轴定义的统一class

坐标轴的标签加入不在D3.Axis接口的负责范围内:

  • 通过对坐标轴的<g>标签.append(‘text’)来实现
  • 左(纵)轴坐标需要.attr(‘transform’, ‘rotate(-90)’)来旋转
  • 纵轴坐标旋转后,x/y会颠倒甚至取值范围相反
  • 回忆DOM: 父节点属性会影响子节点,而坐标轴默认的’fill’属性是’none’,因此请一定手动设置文字颜色.attr(‘fill’, ‘black’)

Margin
SVG对于D3.js是一个画布
SVG范围外的任何内容属于画布之外,浏览器不予显示

  • 而坐标轴通常初始化在所在父节点的左上角

定义Margin:

  • const margin = {top: 60, right: 30, bottom: 60, left: 200}

计算实际操作的inner长/宽

  • const innerWidth = width - margin.left - margin.right;
  • const innerHeight = height - margin.top - margin,.bottom;

在SVG下额外定义一个组作为新的根节点

- const g = svg.append('g').attr('id', 'maingroup')
.attr('transform', `translate(${margin.left}, ${margin.top})`)

HTML确实在样式表中提供margin属性,然而设置其他图元的位置,仍
需要计算innerWidth(Height)

调用示例

const yAxis = d3.axisLeft(yScale) // .tickSize(-innerWidth);
const xAxis = d3.axisBottom(xScale) // .tickSize(-innerHeight);

const yAxisGroup = g.append('g').call(yAxis)
.append('text')
.text('Name')
.attr('font-size', '3em')
.attr('transform', 'rotate(-90)') // y-axis label needs an additional transform;
.attr('x', -innerHeight / 2)
.attr('y', -120)
.attr('fill', 'black')
const xAxisGroup = g.append('g').call(xAxis)
.attr('transform', `translate(${0}, ${innerHeight})`)
.append('text')
.text('Value')
.attr('font-size', '3em')
.attr('x', innerWidth / 2)
.attr('y', 50)
.attr('fill', 'black');

d3.selectAll('.tick text).attr('font-size', '2em');

g.append('text').text('Members of CSCG').attr('font-size', '3em')
.attr('x', innerWidth / 2 - 200).attr('y', -10)

17 DATA-JOIN

本质上是将数据与图元进行绑定
以数据为中心的可视化操作(Data-Driven)

  • 根据数据自动调整图元属性
  • .attr(…)接口可以基于图元自己绑定的数据自动调整属性值

数据发生变化时可以自动对图元增删改查

  • 不需要手动添加,修改,删除图元
  • 根据数据的增删改,自动增删改图元

d3.selectAll(‘.class’).data(dataArray)
dataArray在保证是数组的前提下可以是任何形式如数值数组,对象数组

。。。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/884142.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

通过网络和SD卡连接开发板

SD卡 有时候相关代码改动以后想验证能否正常工作&#xff0c;如果编译代码又需要好久&#xff0c;所以可以通过SD卡拷贝到板子里验证&#xff1a; 将SD卡插入读卡器&#xff0c;将读卡器插入ubuntu主机上&#xff0c;将相关带动的代码文件拷贝到SD卡中。假设你的板子已经具备…

LLMs大模型plugin开发实战

一、概述 ChatGPT是通用语言大模型&#xff0c;如果用户想要在与大模型进行交互时能够使用到企业私有的数据&#xff0c;那么可以通过开发plugin&#xff08;插件&#xff09;的方式来实现&#xff0c;另外GPT3.5模型的训练数据是截止到2021年9月&#xff0c;如果想让模型能够…

leetcode228. 汇总区间

题目 给定一个 无重复元素 的 有序 整数数组 nums 。 返回 恰好覆盖数组中所有数字 的 最小有序 区间范围列表 。也就是说&#xff0c;nums 的每个元素都恰好被某个区间范围所覆盖&#xff0c;并且不存在属于某个范围但不属于 nums 的数字 x 。 列表中的每个区间范围 [a,b]…

python矩阵形状和乘法

python矩阵的形状 A np.array([[[1],[2],[3]],[[4],[5],[6]]])AA np.array([[1,2,3],[4,5,6]])print(A) print(A.shape) print(AA) print(AA.shape)python矩阵的乘法 A np.array([[1, 2, 3, 4],[1, 2, 3, 4],[1, 1, 1, 1],[1, 1, 1, 1]]) B np.array([[1],[2],[1],[2]])C …

由主机的IP地址计算主机所在子网的广播地址(子网划分)

子网掩码是一个与IP地址相对应的、长32bit的二进制串&#xff0c;它由一串1和跟随的一串0组成。 其中&#xff0c;1对应于IP地址中的网络号及子网号&#xff0c;而0对应于主机号。计算机只需将IP地址和其对应的子网掩码逐位“与”&#xff08;逻辑AND运算&#xff09;&#xff…

新物联网卡智能管理系统源代码下载

新物联网卡智能管理系统源代码现已开放供大家使用。该系统具有强大的物联网卡管理功能&#xff0c;可以帮助您实现自动化管理&#xff0c;提高效率。 相比其他同类系统&#xff0c;本系统具有更高的灵活性和可定制性&#xff0c;能够满足您的各种需求。 授权机制已删除&#…

【C++11保姆级教程】delete和default关键字

文章目录 前言一、delete关键字1.1 什么是delete关键字&#xff1f;1.2delete关键字的语法和用法1.3delete关键字的作用和优势 二、default关键字2.1 什么是default关键字&#xff1f;2.2default关键字的语法和用法2.3 default关键字的作用和优势 总结 前言 欢迎来到本教程&am…

谁是 “凶手” !

找“凶手” 解题方法&#xff01;&#x1f575;️‍ 近日&#xff0c;日本米花町发生了一起凶杀案&#xff0c;警察通过排查确定杀人凶手必为4个嫌疑犯中的一个。 以下为4个嫌疑犯的供词&#xff1a; A说&#xff1a;不是我。 B说&#xff1a;是C。 C说&#xff1a;是D。 D说&…

Mybatis多表查询与动态SQL的使用

目录 1. Mybatis多表查询 1.1 添加文章表实体类 1.2 文章Interface 1.3 文章.xml 1.4 lombok的toString()有关对象打印的说明 1.5 场景: 一个用户查询多篇文章 2. 复杂情况: 动态SQL的使用 2.1 为什么要使用动态SQL? 2.2 <if>标签 2.3 <trim>标签 2.4 <where&g…

如何在 iOS 上安装并使用 ONLYOFFICE 文档

借助 iOS 版文档应用&#xff0c;您可在移动端设备上访问存储于 ONLYOFFICE 账户中的文件&#xff0c;查看和编辑现有文本文档、电子表格和演示文稿&#xff0c;创建新文档并对其进行整理&#xff0c;以及连接第三方云存储服务。您可与其他门户网站用户协作编辑文档&#xff0c…

【第三阶段】kotlin语言的可空性

1.kotlin语言默认是不可空类型&#xff0c;不能随意给null fun main() {var name:String"kotlin"namenull }执行结果 报错&#xff1a; Null can not be a value of a non-null type String2.声明可空类型 &#xff1f; fun main() {var name:String ?namenull…

语聚AI公测发布,大语言模型时代下新的生产力工具

语聚AI 公测发布 距离语聚AI内测上线已经过去近1个月。 这期间&#xff0c;我们共邀请了近百位资深用户与行业专家加入语聚AI产品体验。通过大家的热情参与积极反馈&#xff0c;我们不断优化并完善了语聚AI的功能与使用体验。 经过研发团队不懈的努力&#xff0c;今天语聚AI终…

[谦实思纪 01]整理自2023雷军年度演讲——《成长》(上篇)武大回忆(梦想与成长)

文章目录 [谦实思纪]整理自2023雷军年度演讲 ——《成长》&#xff08;上篇&#xff09;武大回忆&#xff08;梦想与成长&#xff09;0. 写在前面1. 梦开始的地方1.1 要有梦想&#xff0c;要用目标量化梦想 2. 在两年内修完所有的学分。2.1 别老自己琢磨&#xff0c;找个懂的人…

【C++】STL案例1-评委打分

0.前言 1.系统自动生成的评委评分代码&#xff1a; #include <iostream> using namespace std; #include <deque> #include <vector> #include <algorithm> #include <string>//选手类 class Player { public:Player(string name, float score)…

Python:LVGL与触摸屏的调试记录

在移远模块EC-600M上驱动电容触摸屏&#xff0c;触摸屏控制IC为FT6206。 一、接口 TP屏的管脚如下&#xff0c;有6PIN。使用I2C接口通讯 所以我们用模块的I2C1通道&#xff0c;模块的IO口电压也是1.8v 二、I2C从地址 FT6x06芯片相对于主机来说是一个I2C设备 因此需要一个I2C…

3.1 命名空集using声明

博主介绍&#xff1a;爱打游戏的计算机专业学生 博主主页&#xff1a;夏驰和徐策 所属专栏&#xff1a;夏驰和徐策带你从零开始学C 前言&#xff1a; 第2章介绍的内置类型是由C语言直接定义的。这些类型&#xff0c;比如数字和字符&#xff0c;体现了大 多数计算机硬件本身具…

Python弹球小游戏

给在校的小妹妹做个游戏玩&#xff1a;. 弹珠游戏主要是靠坐标xy&#xff0c;接板长度&#xff0c;球的半径等决定&#xff1a; # -*- coding: utf-8 -*- # Author : Codeooo # Time : 2022/04/29import sys import time import random import pygame as pgprint("&q…

TCP三次握手,四次挥手,SYN泛洪攻击

目录 一.三次握手 二.SYN泛洪攻击概念 三.四次挥手 一.三次握手 当客户端调用connect连接服务器时,底层会发生“三次握手”&#xff0c;握手成功&#xff0c;建立连接,connect解阻塞&#xff0c;继续执行。 TCP报头&#xff1a; 三次握手过程&#xff1a; 客户端发出SYN请求…

P16 电路定理——巧妙-灵性-智慧

1、诺顿定理的证明 诺顿定理的证明&#xff0c; 回忆戴维南定理的证明是&#xff0c;在a,b两端加上一个电流源&#xff0c;再根据叠加定理&#xff0c;就解电压Uab。 对偶原理&#xff1a; 在a,b两端加上一个电压源u&#xff0c;再根据叠加定理求A中的独立源作用是给到a&#x…

下一代计算:嵌入AI的云/雾/边缘/量子计算

计算系统在过去几十年中推动了计算机科学的发展&#xff0c;现在已成为企业世界的核心&#xff0c;提供基于云计算、雾计算、边缘计算、无服务器计算和量子计算的服务。现代计算系统解决了现实世界中许多需要低延迟和低响应时间的问题。这有助于全球各地的青年才俊创办初创企业…