当前位置: 首页 > news >正文

d3.js 基础学习

1. 下载安装

  1. npm 安装

    npm install d3
  2. 类型支持(ts)

    npm install @types/d3
  3. 导入

    import * as d3 from "d3"

2. 如何使用d3.js画图

eg:

d3.select('body')
.append('svg')
.attr('width',500)
.attr('height',500)
  • 这行代码的意思是:选择 body 标签,添加 svg 元素,设置 svg 元素的宽度和高度为 500。

2.1 选择和操作

  • d3选择元素提供了两个函数

    • select

    • selectAll

  • 选择元素后可以操作元素,操作元素主要分为增加 ( append )、插入 ( insert )、删除元素 ( remove ) 和设置获取元素属性 ( attr, style )。下面用一个例子展示 D3 选择和操作元素,便于理解,大家可以自己逐行添加运行。

2.2 数据绑定

  • D3中数据绑定提供了datum()和data()两个函数

    • datum():绑定一个数据到选择集上

      • 这个方法不会进行数据绑定的(update、enter、exit),只能在现有的元素上绑定数据。如果 value 是数组会自动转成字符串

    • data():更常用, 绑定一个数组到选择集上,数组的各项值分别与选择集的各元素绑定

      var body = d3.select("body");
      var p = body.selectAll("p");
      ​
      p.data(dataset).text(function(d, i){return d;});

  • 数据绑定是将数据绑定到DOM元素上,这是D3最大的特色,也是D3的设计哲学

2.3 插入,删除元素

插入元素涉及的函数有两个

  • append() :在选择集末尾插入元素

    body.append("p").text("append p element");

  • insert() : 在选择集前面插入元素

    在 body 中 id 为 myid 的元素前添加一个段落元素。
    body.insert("p","#pear-id").text("insert p element");

2.4 . 比例尺

  • 原因在于真实数据与创建数据可视化的视觉元素大小之间存在差异。

let scale = d3.scaleLinear().domain([0,10000]).range([0,100])
  • 其中 scaleLinear() 对应法则,domain() 是定义域,range() 是值域。

3. 做一个简单的图表

3.1 画布

  • HTML 5 提供两种强有力的“画布”:SVGCanvas

3.1.1 添加画布
  1. 使用 D3 在 body 元素中添加 svg

var svg = d3.select("body")     //选择文档中的body元素.append("svg")          //添加一个svg元素.attr("width", width)       //设定宽度.attr("height", height);    //设定高度
  1. 绘制矩形

<svg><rect></rect><rect></rect>
</svg>
  • 矩形的属性

    • x:矩形左上角的 x 坐标

    • y:矩形左上角的 y 坐标

    • width:矩形的宽度

    • height:矩形的高度

  1. 绑定属性

    var dataset = [ 250 , 210 , 170 , 130 , 90 ];
    .
    .
    svg.selectAll("rect")   //选择svg内所有的矩形.data(dataset)  //绑定数组.enter()        //指定选择集的enter部分.append("rect") //添加足够数量的矩形元素.attr("fill","steelblue");//是给矩形元素设置颜色

3.2 比例尺

var min = d3.min(dataset); //得到最小值
var max = d3.max(dataset); //得到最大值var scaleLinear = d3.scaleLinear().domain([min, max]).range([0, 300]);scaleLinear(0.9);    //返回 0
scaleLinear(2.3);    //返回 175
scaleLinear(3.3);    //返回 300
  • 其中,d3.scaleLinear() 返回一个线性比例尺。domain() 和 range() 分别设定比例尺的定义域和值域。在这里还用到了两个函数,它们经常与比例尺一起出现:

    • d3.max()

    • d3.min() 这两个函数能够求数组的最大值和最小值,是 D3 提供的。按照以上代码,

3.3 坐标轴

  • D3 中提供了专门的坐标轴模块d3-axis,只需要几行代码就可以生成各种各样的坐标轴。一般情况下,坐标轴要与比例尺一起使用。记住这句话,离开比例尺的坐标轴就是耍流氓。

  • <g>分组元素 ,是 SVG 画布中的元素,意思是 group。此元素是将其他元素进行组合的容器,在这里是用于将坐标轴的其他元素分组存放。

  • D3 提供了轴生成器:d3.axisTop()、d3.axisRight()、 d3.axisBottom()、d3.axisLeft()。它为我们完成了以上工作。

3.3.1 定义坐标轴
var dataset = [2.5, 2.1, 1.7, 1.3, 0.9]; //数据
//定义线性比例尺
var xScale = d3.scaleLinear().domain([0, d3.max(dataset)]).range([0, 250]);
//定义坐标轴
var axis = d3.axisBottom(xScale) //定义一个axis并指定刻度的方向为bottom(朝下)且指定比例尺为xScale.ticks(7); //指定刻度的数量

4. 动态图表

  • transition() 启动过渡效果

4. 树状图

树状图,可表示节点之间的包含与被包含关系。

4.1 树状图知识点:

d3.hierarchy(),层级布局,需要和tree生成器一起使用,来得到绘制树所需要的节点数据和边数据; d3.hierarchy().sum() ,后序遍历; d3.tree(),创建一个树状图生成器; d3.tree().size(),定义树的大小; d3.tree().separation(),定义邻居节点的距离; node.descendants()得到所有的节点,已经经过转换的数据; node.links(),得到所有的边,已经经过转换的数据; d3.linkHorizontal(),创建一个贝塞尔生成曲线生成器,当然不止只有水平的,还有垂直的(d3.linkVertical())

4.2 案例

<script lang="ts" setup>
​
import * as d3 from 'd3'
import {onMounted} from "vue";
​
// var width:any = svg.attr("width");
// var height:any = svg.attr("height");
​
​
onMounted(() => {interface HierarchyNode {name: string;value?: number;children?: HierarchyNode[];}// 需要渲染的数据var dataset = {name: "中国",children: [{name: "浙江",children: [{name: "杭州", value: 100},{name: "宁波", value: 100},{name: "温州", value: 100},{name: "绍兴", value: 100}]},{name: "广西",children: [{name: "桂林",children: [{name: "秀峰区", value: 100},{name: "叠彩区", value: 100},{name: "象山区", value: 100},{name: "七星区", value: 100}]},{name: "南宁", value: 100},{name: "柳州", value: 100},{name: "防城港", value: 100}]},{name: "黑龙江",children: [{name: "哈尔滨", value: 100},{name: "齐齐哈尔", value: 100},{name: "牡丹江", value: 300},{name: "大庆", value: 100}]},{name: "新疆",children:[{name: "乌鲁木齐"},{name: "克拉玛依"},{name: "吐鲁番"},{name: "哈密"}]}]};
​//定义边界var marge = {top: 50, bottom: 0, left: 10, right: 0};var svg = d3.select("svg")
​var g = svg.append("g").attr("transform", "translate(" + marge.top + "," + marge.left + ")");var scale = svg.append("g").attr("transform", "translate(" + marge.top + "," + marge.left + ")");//扁平化获得树状数据var hierarchyData = d3.hierarchy<HierarchyNode>(dataset).sum(function (d) {console.log(d.value)return d.value;});console.log(hierarchyData)//创建一个树状图var tree = d3.tree().size([400, 200]).separation(function (a, b) {return (a.parent == b.parent ? 1 : 2) / a.depth})//初始化树状图,也就是传入数据,并得到绘制树的基本数据var treeData = tree(hierarchyData);//得到边和节点(已经完成转换的)var nodes = treeData.descendants();var links = treeData.links();
​// 定义节点类型接口interface TreeNode {x: number; // 节点的 x 坐标y: number; // 节点的 y 坐标// 如果需要,可以添加其他属性,例如子节点children?: TreeNode[];}
​// 创建树形贝塞尔曲线生成器const Bézier_curve_generator = d3.linkHorizontal<TreeNode, TreeNode>().x((d) => d.y) // x 坐标使用 y 属性.y((d) => d.x); // y 坐标使用 x 属性
​//绘制边g.append("g").selectAll("path").data(links).enter().append("path").attr("d", function (d) {var start = {x: d.source.x, y: d.source.y};var end = {x: d.target.x, y: d.target.y};return Bézier_curve_generator({source: start, target: end});}).attr("fill", "none").attr("stroke", "yellow").attr("stroke-width", 1);//建立用来放在每个节点和对应文字的分组<g>var gs = g.append("g").selectAll("g").data(nodes).enter().append("g").attr("transform", function (d) {var cx = d.x;var cy = d.y;return "translate(" + cy + "," + cx + ")";});
​//绘制节点gs.append("circle").attr("r", 6).attr("fill", "white").attr("stroke", "blue").attr("stroke-width", 1);
​//文字gs.append("text").attr("x", function (d) {return d.children ? -40 : 8;})  // 如果某节点有子节点,则对应的文字前移.attr("y", -5).attr("dy", 10).text(function (d) {return d.data.name;})
​
})
​
</script>
​
<template><div class="container">
​<svg>
​</svg></div>
</template>
​
<style lang="less">
​
</style>

相关文章:

  • XML 编码
  • 迈威通信闪耀工博会,以创新科技赋能工业自动化
  • 小红书2024秋招后端开发(Java工程师、C++工程师等)
  • Webpack 特性探讨:CDN、分包、Tree Shaking 与热更新
  • idea2024设置中文
  • websokets交叉编译
  • SpringBoot 注解 @AutoConfiguration 在 2.7 版本中被新增(使用方法)
  • Android常用C++特性之std::lock_guard
  • Spring自动装配的5种方式
  • Android中大量使用建造者模式(Builder Pattern)的原因可以归结为以下几点:
  • 【华为HCIP实战课程三】动态路由OSPF的NBMA环境建立邻居及排错,网络工程师
  • [Linux]僵尸进程,孤儿进程,环境变量
  • NGINX+LUA编译安装
  • 关于Obj文件格式介绍与Unity加载Obj文件代码参考
  • 9.24作业
  • Apache的80端口被占用以及访问时报错403
  • ECMAScript6(0):ES6简明参考手册
  • Elasticsearch 参考指南(升级前重新索引)
  • gf框架之分页模块(五) - 自定义分页
  • HTTP 简介
  • JavaScript 是如何工作的:WebRTC 和对等网络的机制!
  • JSONP原理
  • magento 货币换算
  • tweak 支持第三方库
  • weex踩坑之旅第一弹 ~ 搭建具有入口文件的weex脚手架
  • 翻译:Hystrix - How To Use
  • 记一次用 NodeJs 实现模拟登录的思路
  • 我有几个粽子,和一个故事
  • 一个6年java程序员的工作感悟,写给还在迷茫的你
  • 在Docker Swarm上部署Apache Storm:第1部分
  • [Shell 脚本] 备份网站文件至OSS服务(纯shell脚本无sdk) ...
  • TPG领衔财团投资轻奢珠宝品牌APM Monaco
  • ​LeetCode解法汇总1410. HTML 实体解析器
  • ​七周四次课(5月9日)iptables filter表案例、iptables nat表应用
  • (react踩过的坑)Antd Select(设置了labelInValue)在FormItem中initialValue的问题
  • (附源码)spring boot校园健康监测管理系统 毕业设计 151047
  • (黑马出品_高级篇_01)SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式
  • (十二)Flink Table API
  • (转)fock函数详解
  • (自用)gtest单元测试
  • .java 9 找不到符号_java找不到符号
  • .net 获取url的方法
  • .ui文件相关
  • @Bean, @Component, @Configuration简析
  • @vue/cli脚手架
  • [20140403]查询是否产生日志
  • [20170713] 无法访问SQL Server
  • [Angular] 笔记 7:模块
  • [BT]BUUCTF刷题第4天(3.22)
  • [CISCN2019 华东北赛区]Web2
  • [flink]部署模式
  • [flutter]一键将YAPI生成的api.json文件转为需要的Dart Model类的脚本
  • [godot] 采用状态机时,如何处理攻击时移动?如“冲撞”
  • [HITCON 2017]SSRFme 1
  • [HNOI2006]鬼谷子的钱袋