利用D3.js实现数据可视化的简单示例

目录

一、D3.js选择器

二、数据绑定相关方法

三、DOM操作方法

四、事件监听

五、实现折线图案例

1.首先引入 D3.js 库。

2.然后获取数据(这里定义了销售数据数组作为数据)。

3.接着创建一个 svg 元素作为画布

4.定义 x 轴和 y 轴的比例尺,x 轴使用 scaleBand 比例尺来处理离散的月份数据,y 轴使用 scaleLinear 比例尺根据销售金额的范围来确定坐标范围

5.分别添加 x 轴和 y 轴到 svg 画布上。

6.定义折线生成器

7.使用数据绘制折线和数据点

8.监听事件并添加处理函数


使用D3.js过程中,我们一般需要创建画布、绑定数据、选择元素、操作元素、监听元素事件等,因此,需要先了解D3.js的选择器、数据绑定方式、DOM操作方法、事件监听等。

一、D3.js选择器

1. d3.select() :. 

   - 选择第一个匹配的 DOM 元素。

   - 用法:`d3.select(selector)`,其中 `selector` 是 CSS 选择器字符串。

2. d3.selectAll() :

   - 选择所有匹配的 DOM 元素。

   - 用法:`d3.selectAll(selector)`,其中 `selector` 是 CSS 选择器字符串。

二、数据绑定相关方法

1.enter() :

   - 为数据绑定过程中未匹配的元素创建新的 DOM 元素。

   - 用法:`selection.enter()`。

2.exit() :

   - 为数据绑定过程中多余的元素(即数据减少时)提供操作。

   - 用法:`selection.exit()`。

3.data() :

   - 将数据绑定到 DOM 元素上。

   - 用法:`selection.data(data)`,其中 `data` 是要绑定的数据。

三、DOM操作方法

1.attr() :

   - 获取或设置 DOM 元素的属性。

   - 用法:`selection.attr(name, value)`。

2.style() :

   - 获取或设置 DOM 元素的样式。

   - 用法:`selection.style(name, value)`。

3.text() :

   - 获取或设置 DOM 元素的文本内容。

   - 用法:`selection.text(value)`。

4.html() :

   - 获取或设置 DOM 元素的 HTML 内容。

   - 用法:`selection.html(value)`。

5.append() :

    - 在选定的元素中添加新的子元素。

    - 用法:`selection.append(name)`,其中 `name` 是新元素的标签名。

6.remove() :

    - 移除选定的元素。

    - 用法:`selection.remove()`。

四、事件监听

1.on() :

    - 为 DOM 元素添加事件监听器。

    - 用法:`selection.on(eventName, listener)`。

五、实现折线图案例

DOCTYPE html><html lang="en">
<head>
  <meta charset="UTF-8"> 
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>D3.js实现折线图案例title>
  <style>
    svg {
      width: 600px;
      height: 400px;
      border: 1px solid #ccc;
    }
  style>
head>
<body>
  <script src="https://d3js.org/d3.v7.min.js">script>  <script>
    // 销售数据
    const salesData = [      { month: 'Jan', amount: 12000 },      { month: 'Feb', amount: 15000 },      { month: 'Mar', amount: 18000 },      { month: 'Apr', amount: 16000 },      { month: 'May', amount: 20000 },      { month: 'Jun', amount: 22000 }    ];
    // 定义 svg 画布
    const svg = d3.select('body').append('svg');
    // 定义 x 轴比例尺
    const xScale = d3.scaleBand()
     .domain(salesData.map(d => d.month))
     .range([0, 500])
     .padding(0.2);
    // 定义 y 轴比例尺
    const yScale = d3.scaleLinear()
     .domain([0, d3.max(salesData, d => d.amount)])
     .range([300, 0]);
    // 添加 x 轴
    svg.append('g')
     .attr('transform', 'translate(50,300)')
     .call(d3.axisBottom(xScale));
    // 添加 y 轴
    svg.append('g')
     .attr('transform', 'translate(50,0)')
     .call(d3.axisLeft(yScale));
    // 添加折线
    const line = d3.line()
     .x(d => xScale(d.month) + 25)
     .y(d => yScale(d.amount));

    svg.append('path')
     .datum(salesData)
     .attr('fill', 'none')
     .attr('stroke', 'steelblue')
     .attr('stroke-width', 2)
     .attr('d', line);
    // 添加数据点
    svg.selectAll('.dot')
     .data(salesData)
     .enter()
     .append('circle')
     .attr('class', 'dot')
     .attr('cx', d => xScale(d.month) + 25)
     .attr('cy', d => yScale(d.amount))
     .attr('r', 5)     .attr('fill', 'blue');
    // 添加提示框(简单示例,未完整实现交互)
    svg.selectAll('.dot')
     .on('mouseover', function (event, d) {
        d3.select(this).attr('r', 8);
        // 这里可以进一步完善提示框内容和样式的显示 
       console.log(`Month: ${d.month}, Amount: ${d.amount}`);
      })
     .on('mouseout', function (event, d) {
        d3.select(this).attr('r', 5);
      });
  script>
body>
html>

1.首先引入 D3.js 库。

    <script src="https://d3js.org/d3.v7.min.js">script>  <script>

2.然后获取数据(这里定义了销售数据数组作为数据)。

3.接着创建一个 svg 元素作为画布

    const svg = d3.select('body').append('svg');

4.定义 x 轴和 y 轴的比例尺,x 轴使用 scaleBand 比例尺来处理离散的月份数据,y 轴使用 scaleLinear 比例尺根据销售金额的范围来确定坐标范围

    // 定义 x 轴比例尺
    const xScale = d3.scaleBand()
     .domain(salesData.map(d => d.month))
     .range([0, 500])
     .padding(0.2);

  • d3.scaleBand():创建一个分带(离散)比例尺,适用于处理分类数据。
  • domain(salesData.map(d => d.month)):设置比例尺的输入域(Domain)。这里从salesData数组中提取每个数据对象的month属性,形成一个包含所有月份的数组作为输入域。
  • range([0, 500]):设置比例尺的输出范围(Range),将输入域映射到从 0 到 500 的区间。
  • padding(0.2):设置每个类别之间的间隔为带宽的 20%,避免数据标签相互重叠。

    // 定义 y 轴比例尺
    const yScale = d3.scaleLinear()
     .domain([0, d3.max(salesData, d => d.amount)])
     .range([300, 0]);


    const yScale = d3.scaleLinear()
     .domain([0, d3.max(salesData, d => d.amount)])
     .range([300, 0]);

  • d3.scaleLinear():创建一个线性比例尺,用于处理连续数据。
  • domain([0, d3.max(salesData, d => d.amount)]):设置输入域。这里输入域的下限是 0,上限是salesData数组中amount属性的最大值,通过d3.max函数计算得出。
  • range([300, 0]):设置输出范围。在 SVG 坐标系中,y 轴是从上到下递增的,所以这里将较大的数据值映射到较小的 y 坐标,范围是从 300(底部)到 0(顶部)。

5.分别添加 x 轴和 y 轴到 svg 画布上。

// 添加 x 轴
    svg.append('g')
     .attr('transform', 'translate(50,300)')
     .call(d3.axisBottom(xScale));

// 添加 y 轴
    svg.append('g')
     .attr('transform', 'translate(50,0)')
     .call(d3.axisLeft(yScale));

  • svg.append('g'):在 SVG 元素中添加一个<g>(分组)元素,用于容纳坐标轴的所有组件。
  • attr('transform', 'translate(50,300)'):对<g>元素应用平移变换,将其移动到坐标 (50, 300) 的位置。这是为了将 x 轴放置在合适的位置上。
  • call(d3.axisBottom(xScale)):调用d3.axisBottom函数创建一个底部坐标轴,并将xScale比例尺应用到该坐标轴上,然后将坐标轴添加到<g>元素中。
  • call(d3.axisLeft(yScale)) 调用d3.axisLeft函数创建一个左侧坐标轴,并将yScale比例尺应用到该坐标轴上,然后将坐标轴添加到<g>元素中。

6.定义折线生成器

// 添加折线
    const line = d3.line()
     .x(d => xScale(d.month) + 25)
     .y(d => yScale(d.amount));

    svg.append('path')
     .datum(salesData)
     .attr('fill', 'none')
     .attr('stroke', 'steelblue')
     .attr('stroke-width', 2)
     .attr('d', line);

  • d3.line():创建一个折线生成器。
  • x(d => xScale(d.month) + 25):定义折线在 x 方向上的坐标获取方式。对于每个数据点,通过xScale比例尺将月份数据映射到 x 坐标,并加上 25 是为了使折线稍微偏离坐标轴一点,让数据点在坐标轴刻度的中间位置。
  • y(d => yScale(d.amount)):定义折线在 y 方向上的坐标获取方式。通过yScale比例尺将销售金额数据映射到 y 坐标。
  • svg.append('path'):在 SVG 元素中添加一个<path>元素,用于绘制折线。
  • datum(salesData):将salesData数组绑定到<path>元素上。
  • attr('fill', 'none'):设置填充颜色为无。
  • attr('stroke', 'steelblue'):设置描边颜色为钢蓝色。
  • attr('stroke-width', 2):设置描边宽度为 2。
  • attr('d', line):将折线生成器生成的路径描述设置给<path>元素的d属性,从而绘制出折线。

7.使用数据绘制折线和数据点

// 添加数据点
    svg.selectAll('.dot')
     .data(salesData)
     .enter()
     .append('circle')
     .attr('class', 'dot')
     .attr('cx', d => xScale(d.month) + 25)
     .attr('cy', d => yScale(d.amount))
     .attr('r', 5)
     .attr('fill', 'blue');

  • svg.selectAll('.dot'):选择所有类名为.dot的元素。由于此时可能还没有这些元素,这一步主要是为后续的数据绑定和元素创建做准备。
  • data(salesData):将salesData数据绑定到选择的元素上。如果选择的元素数量少于数据点数量,enter()方法将用于创建新的元素。
  • enter():返回一个占位符选择集,用于创建新的元素来匹配多余的数据点。
  • append('circle'):为每个多余的数据点创建一个<circle>元素。
  • attr('class', 'dot'):为创建的<circle>元素设置类名为.dot
  • attr('cx', d => xScale(d.month) + 25):设置圆形的cx(圆心的 x 坐标)。通过xScale比例尺将数据中的月份转换为 x 坐标,并加上 25 使圆形位于坐标轴刻度中间。
  • attr('cy', d => yScale(d.amount)):设置圆形的cy(圆心的 y 坐标)。通过yScale比例尺将数据中的销售金额转换为 y 坐标。
  • attr('r', 5):设置圆形的半径为 5。
  • attr('fill', 'blue'):设置圆形的填充颜色为蓝色。

8.监听事件并添加处理函数

// 添加提示框(简单示例,未完整实现交互)
    svg.selectAll('.dot')
     .on('mouseover', function (event, d) {
        d3.select(this).attr('r', 8);
        // 这里可以进一步完善提示框内容和样式的显示
        console.log(`Month: ${d.month}, Amount: ${d.amount}`);
      })
     .on('mouseout', function (event, d) { 
       d3.select(this).attr('r', 5);
      });

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

猎板 HDI 多阶工艺:高密度互连的核心技术

一、猎板HDI引言 随着电子设备不断向小型化、高性能化和多功能化发展&#xff0c;PCB&#xff08;印刷电路板&#xff09;的设计与制造面临着前所未有的挑战。HDI&#xff08;高密度互连&#xff09;技术应运而生&#xff0c;而其中的多阶工艺更是满足了对更高布线密度、更小尺…

VUE 的前置知识

一、JavaScript----导图导出 1. JS 提供的导入导出机制&#xff0c;可以实现按需导入 1.1 在html页面中可以把JS文件通过 <script src"showMessage.js"></script> 全部导入 1.2 通过在JS文件中写export关键字导出通过 <script src"showMessage…

---Arrays类

一 java 1.Arrays类 1.1 toString&#xff08;&#xff09; 1.2 arrays.sort( )-----sort排序 1&#xff09;直接调用sort&#xff08;&#xff09; Arrays.sort() 方法的默认排序顺序是 从小到大&#xff08;升序&#xff09;。 2&#xff09;定制排序【具体使用时 调整正负…

【H2O2|全栈】JS进阶知识(六)ES6(2)

目录 前言 开篇语 准备工作 Set和Map 基本概念 Set 相互转化 常见属性和API 数组去重 并集、交集和差集 Map 转化 常见的属性和API Set和Map的区别 This的指向 function函数 箭头函数 修改this 使用方式 三种方式的异同 案例 更改this指向为obj 求数组数…

Node基本使用

1. 创建自定义全局指令 1.1 新建一个空的文件夹, 创建一个cli.js文件 1.2 在cli.js写入内容 /usr/bin/env就是让系统使用node来执行你的脚本文件。 #! /usr/bin/env node1.3 执行终端指令 // 在文件夹 node-project 的终端下执行指令npm init执行完后package.json结构如下,…

Python编程技巧:多变量赋值的优雅艺术

在Python编程的世界里&#xff0c;有许多令人惊叹的语法特性&#xff0c;而多变量赋值就像是一颗闪耀的明珠&#xff0c;它不仅让代码更优雅&#xff0c;还能提升程序的执行效率。今天我们就深入探讨这个看似简单却蕴含深意的编程技巧。 基础认识 传统的变量赋值方式&#xff…

Transformer架构笔记

Attention is All You Need. 3.Model Architecture 3.1 整体架构如图 3.2 Encoder与Decoder Encoder&#xff1a;由 N 6 N6 N6个相同的Block/Layer堆叠而成。每个Block有两个子层sub-layer&#xff1a;多头注意力和MLP&#xff08;FFN&#xff0c;前馈神经网络&#xff09;&…

网络安全简单入门与扫描

网络安全简单入门 内容大纲 策略制定安全工具其他 1、安全策略 1.1、安全三要素 要全面地认识一个安全问题,我们有很多种办法,但首先要理解安全问题的组成属性。前人通过无数实践,最后将安全的属性总结为安全三要素,简称CIA。 安全三要素是安全的基本组成元素,分别是机密性…

在WPF程序中实现PropertyGrid功能

使用C#开发过Windows Forms的都知道&#xff0c;在Windows Forms程序中&#xff0c;有一个PropertyGrid控件&#xff0c;可以用于显示对象的属性&#xff0c;在WPF中并没有默认提供此功能的控件&#xff0c;今天以一个简单的小例子&#xff0c;简述在WPF中借助WinForm的Propert…

大模型时代的具身智能系列专题(十四)

冯晨团队 冯晨是纽约大学的副教授。他对通过多学科使用启发研究实现机器人主动和协作感知和学习感兴趣&#xff0c;这些研究源自建筑、制造和运输领域。在纽约大学之前&#xff0c;冯晨是马萨诸塞州剑桥市三菱电机研究实验室 (MERL) 计算机视觉小组的研究科学家&#xff0c;专…

力扣-Hot100-栈【算法学习day.40】

前言 ###我做这类文档一个重要的目的还是给正在学习的大家提供方向&#xff08;例如想要掌握基础用法&#xff0c;该刷哪些题&#xff1f;&#xff09;我的解析也不会做的非常详细&#xff0c;只会提供思路和一些关键点&#xff0c;力扣上的大佬们的题解质量是非常非常高滴&am…

RT_Thread内核源码分析(三)——线程

目录 1. 线程结构 2. 线程创建 2.1 静态线程创建 2.2 动态线程创建 2.3 源码分析 2.4 线程内存结构 3. 线程状态 3.1 线程状态分类 3.2 就绪状态和运行态 3.3 阻塞/挂起状态 3.3.1 阻塞工况 3.4 关闭状态 3.4.1 线程关闭接口 3.4.2 静态线程关闭 3.4.3 动态线程关…

043 商品详情

文章目录 详情页数据表结构voSkuItemVo.javaSkuItemSaleAttrVo.javaAttrValueAndSkuIdVo.javaSpuAttrGroupVo.javaGroupAttrParamVo.java pom.xmlSkuSaleAttrValueDao.xmlSkuSaleAttrValueDao.javaAttrGroupDao.xmlAttrGroupServiceImpl.javaSkuInfoServiceImpl.javaSkuSaleAtt…

硬件知识 cadence16.6 原理图输出为pdf 网络名下划线偏移 (ORCAD)

1. cadence原理图输出为PDF网络名下划线偏移 生这种情况的原因 1. 设计的原理图图纸大小比正常的 A4图纸大。 2. 打印为PDF 的时候&#xff0c;打印机的设置有问题。 2.cadence原理图输出为 PDF网络名下划线偏移的情况 可以看到上图&#xff0c;网络名往上漂移。 3. 解决办法 …

Spring-boot3.4最新版整合swagger和Mybatis-plus

好家伙,今天终于开始用spring-boot3开始写项目了&#xff0c;以后要彻底告别1.x和2.x了&#xff0c;同样的jdk也来到了最低17的要求了,废话不多说直接开始 这是官方文档的要求jdk最低是17 maven最低是3.6 一. 构建工程,这一步就不需要给大家解释了吧 二. 整合Knife4j 1.大于 …

从零开始:如何使用第三方视频美颜SDK开发实时直播美颜平台

开发一个具有实时美颜功能的直播平台&#xff0c;能够显著提高用户体验和内容质量。而利用第三方视频美颜SDK可以大大简化开发过程&#xff0c;加快产品上市速度。本篇文章&#xff0c;小编将从零开始&#xff0c;详细讲解如何使用第三方视频美颜SDK开发一个实时直播美颜平台。…

ROS入门学习ONE

ros入门玩法1&#xff1a;控制小龟龟 终端1输入 sudo apt install ros-noetic-rqt-steering 新建终端2&#xff08;快捷键CtrlAltT)&#xff0c;打开控制台 roscore //启动ros系统 回到原终端 rosrun rosrun rqt_robot_steering rqt_robot_steering 新建终端3&#xff0c;…

shell脚本(二)

声明&#xff01; 学习视频来自B站up主 泷羽sec 有兴趣的师傅可以关注一下&#xff0c;如涉及侵权马上删除文章&#xff0c;笔记只是方便各位师傅的学习和探讨&#xff0c;文章所提到的网站以及内容&#xff0c;只做学习交流&#xff0c;其他均与本人以及泷羽sec团队无关&#…

简单理解下基于 Redisson 库的分布式锁机制

目录 简单理解下基于 Redisson 库的分布式锁机制代码流程&#xff1a;方法的调用&#xff1a;具体锁的实现&#xff1a;riderBalance 方法&#xff1a;tryLock 方法&#xff08;重载&#xff09;&#xff1a;tryLock 方法&#xff08;核心实现&#xff09;&#xff1a; 简单理解…

小鹏汽车智慧材料数据库系统项目总成数据同步

1、定时任务处理 2、提供了接口 小鹏方面提供的推送的数据表结构&#xff1a; 这几个表总数为100多万&#xff0c;经过条件筛选过滤后大概2万多条数据 小鹏的人给的示例图&#xff1a; 界面&#xff1a; SQL: -- 查询车型 select bmm.md_material_id, bmm.material_num, bm…