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

news2024/11/27 20:37:01

目录

一、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);
      });

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

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

相关文章

Leetcode 将有序数组转换为二叉搜索树

算法思想及代码解析&#xff1a; 这段代码的目的是将一个有序数组转换为 高度平衡的二叉搜索树&#xff08;Balanced Binary Search Tree, BST&#xff09;。以下是算法的详细解释&#xff1a; 1. 什么是高度平衡的二叉搜索树&#xff1f; 二叉搜索树&#xff1a;对于树中的每…

15 go语言(golang) - 并发编程goroutine原理及数据安全

底层原理 Go 的 goroutine 是一种轻量级的线程实现&#xff0c;允许我们在程序中并发地执行函数。与传统的操作系统线程相比&#xff0c;goroutine 更加高效和易于使用。 轻量级调度 用户态调度&#xff1a;Go 运行时提供了自己的调度器&#xff0c;这意味着 goroutine 的创建…

ESP-KeyBoard:基于 ESP32-S3 的三模客制化机械键盘

概述 在这个充满挑战与机遇的数字化时代&#xff0c;键盘已经成为我们日常学习、工作、娱乐生活必不可少的设备。而在众多键盘中&#xff0c;机械键盘&#xff0c;以其独特的触感、清脆的敲击音和经久耐用的特性&#xff0c;已经成为众多游戏玩家和电子工程师的首选。本文将为…

PyTorch基础05_模型的保存和加载

目录 一、模型定义组件——重构线性回归 二、模型的加载和保存 2、序列化保存对象和加载 3、保存模型参数 一、模型定义组件——重构线性回归 回顾之前的手动构建线性回归案例&#xff1a; 1.构建数据集&#xff1b;2.加载数据集(数据集转换为迭代器)&#xff1b;3.参数初…

《Python基础》之函数的用法

一、简介 在 Python 中&#xff0c;函数是一段可重用的代码块&#xff0c;用于执行特定的任务。函数可以帮助你将代码模块化&#xff0c;提高代码的可读性和可维护性。 函数的用途 代码重用&#xff1a;通过函数&#xff0c;你可以将常用的代码块封装起来&#xff0c;避免重复…

java:aqs实现自定义锁

aqs采用模板方式设计模式&#xff0c;需要重写方法 package com.company.aqs;import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.AbstractQueuedSynchronizer; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock;…

【小白学机器学习34】基础统计2种方法:用numpy的方法np().mean()等进行统计,pd.DataFrame.groupby() 分组统计

目录 1 用 numpy 快速求数组的各种统计量&#xff1a;mean, var, std 1.1 数据准备 1.2 直接用np的公式求解 1.3 注意问题 1.4 用print() 输出内容&#xff0c;显示效果 2 为了验证公式的背后的理解&#xff0c;下面是详细的展开公式的求法 2.1 均值mean的详细 2.2 方差…

vue2 中使用 Ag-grid-enterprise 企业版

文章目录 问题Vue2 引入企业版不生效npm run dev 时卡住了94% after seal 卡在这里了测试打包源 git 解决方案记录 问题 我想用企业版的树状表格 Vue2 引入企业版不生效 编译引入 // vue.config.js module.exports {transpileDependencies: ["ag-grid-enterprise"…

RESTful快速开发

&#xff08;3&#xff09;RESTful快速开发 &#xff08;2&#xff09;中的控制器仍然存在大量的冗余代码 问题1&#xff1a; 每个方法的RequestMapping注解中都定义了访问路径/users&#xff0c;重复性太高 问题2&#xff1a;每个方法的RequestMapping注解中都要使用method属…

万能门店小程序管理系统 doPageGetFormList SQL注入漏洞复现

0x01 产品简介 万能门店小程序管理系统是一款功能强大的工具,旨在为各行业商家提供线上线下融合的全方位解决方案。是一个集成了会员管理和会员营销两大核心功能的综合性平台。它支持多行业使用,通过后台一键切换版本,满足不同行业商家的个性化需求。该系统采用轻量后台,搭…

【作业九】RNN-SRN-Seq2Seq

点击查看作业内容 目录 1 实现SRN &#xff08;1&#xff09;使用numpy实现 &#xff08;2&#xff09;在&#xff08;1&#xff09;的基础上&#xff0c;增加激活函数tanh &#xff08;3&#xff09;使用nn.RNNCell实现 &#xff08;4&#xff09;使用nn.RNN实现 2 使用R…

Emgu (OpenCV)

Emgu Github Emgu 环境&#xff1a; Emgu CV 4.9.0 netframework 4.8 1、下载 libemgucv-windesktop-4.9.0.5494.exe 安装后&#xff0c;找到安装路径下的runtime文件夹复制到c#项目Debug目录下 安装目录 c# Debug目录

YOLOv8模型pytorch格式转为onnx格式

一、YOLOv8的Pytorch网络结构 model DetectionModel((model): Sequential((0): Conv((conv): Conv2d(3, 64, kernel_size(3, 3), stride(2, 2), padding(1, 1))(act): SiLU(inplaceTrue))(1): Conv((conv): Conv2d(64, 128, kernel_size(3, 3), stride(2, 2), padding(1, 1))(a…

澳洲房产市场数据清洗、聚类与可视化综合分析

本项目涉及数据清洗及分析时候的思路&#xff0c;如果仅在CSDN中看&#xff0c;可能会显得有些乱&#xff0c;建议去本人和鲸社区对应的项目中去查看&#xff0c;源代码和数据集都是免费下载的。 声明&#xff1a;本项目的成果可无偿分享&#xff0c;用于学习交流。但请勿用于…

IT服务团队建设与管理

在 IT 服务团队中&#xff0c;需要明确各种角色。例如系统管理员负责服务器和网络设备的维护与管理&#xff1b;软件工程师专注于软件的开发、测试和维护&#xff1b;运维工程师则保障系统的稳定运行&#xff0c;包括监控、故障排除等。通过清晰地定义每个角色的职责&#xff0…

go-zero(八) 中间件的使用

go-zero 中间件 一、中间件介绍 中间件&#xff08;Middleware&#xff09;是一个在请求和响应处理之间插入的程序或者函数&#xff0c;它可以用来处理、修改或者监控 HTTP 请求和响应的各个方面。 1.中间件的核心概念 请求拦截&#xff1a;中间件能够在请求到达目标处理器之…

Qt Graphics View 绘图架构

Qt Graphics View 绘图架构 "QWGraphicsView.h" 头文件代码如下&#xff1a; #pragma once#include <QGraphicsView>class QWGraphicsView : public QGraphicsView {Q_OBJECTpublic:QWGraphicsView(QWidget *parent);~QWGraphicsView();protected:void mouseM…

【eNSP】动态路由协议RIP和OSPF

动态路由RIP&#xff08;Routing Information Protocol&#xff0c;路由信息协议&#xff09;和OSPF&#xff08;Open Shortest Path First&#xff0c;开放式最短路径优先&#xff09;是两种常见的动态路由协议&#xff0c;它们各自具有不同的特点和使用场景。本篇会对这两种协…

差分 + 模拟,CF 815A - Karen and Game

目录 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 二、解题报告 1、思路分析 2、复杂度 3、代码详解 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 815A - Karen and Game 二、解题报告 1、思路分析 一个经典的差分数组的…

vue3【实战】响应式的登录界面

效果预览 WEB 端效果 移动端效果 技术方案 vue3 vite Element Plus VueRouter UnoCSS TS vueUse AutoImport 技术要点 响应式设计 移动端&#xff1a;图片切换为绝对定位&#xff0c;下移一层&#xff0c;成为背景图片 <el-imageclass"w-screen h-screen lt-md…