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

d3_v7绘制折线图

<!DOCTYPE html>
<html><head><meta charset='utf-8'><title>需求</title><script src="https://d3js.org/d3.v7.min.js"></script><style>* {margin: 0;padding: 0;}html, body {width: 100%;height: 100%;display: flex;justify-content: center;align-items: center;}#graph-container {width: 50%;height: 30%;position: relative;display: flex;flex-direction: column;/*一定要加position: relative*/}#graph{width: 100%;flex: 1;}.chart-title {text-align: center;color: #333;margin-bottom: 20px;}#zhe-xian-tooltip {position: absolute;padding: 12px;background: rgba(0, 0, 0, 0.85);color: white;border-radius: 6px;pointer-events: none;font-size: 14px;font-family: sans-serif;opacity: 0;}.zhe-xian-circle{fill: #e63946;stroke: white;stroke-width: 2;transition: r 0.2s;}.zhe-xian-line {fill: none;stroke: #e63946;stroke-width: 3;stroke-linejoin: round;}</style>
</head>
<body>
<button id="myButton" style="margin-right: 40px">数据变更</button><div id="graph-container"><h2 class="chart-title">标题</h2><div id="graph"><div id="zhe-xian-tooltip"></div></div></div>
<script>const generateData = () => {return Array.from({length: Math.floor(Math.random() * 12) + 5}, (_, index) => ({time: index + 1,count: Math.floor(Math.random() * 100) // 生成0-99的随机整数}));}const drawZheXianGraph = (dataset, container, update) => {dataset.sort((a, b) => a.time - b.time);//按照月份排序console.log("绘制图形数据", dataset);const element = document.getElementById(container);const width = element.offsetWidth;  // 宽度(含 padding + border)const height = element.offsetHeight; // 高度(含 padding + border)const margin = {left: 50,right: 30,top: 30,bottom: 50}if (!update) {d3.select(`#${container}`).append('svg').attr('width', width).attr('height', height);}const svg = d3.select(`#${container}`).select('svg');//定义x轴比例尺const xScale = d3.scaleBand().domain(dataset.map(item => item.time)).range([margin.left, width - margin.right]).padding(0) // 设置柱子之间的间隙.paddingInner(1); // 设置柱子内部的间隙console.log(xScale(1), xScale(2));// 获取所有count值组成的数组const counts = dataset.map(item => item.count);const maxCount = Math.max(...counts);//定义y轴比例尺const yScale = d3.scaleLinear().domain([0, maxCount]).range([height - margin.bottom, margin.top]);//定义绘制折线的函数const line = d3.line().x(function (d) {return xScale(d.time) + xScale.bandwidth() / 2;}).y(function (d) {return yScale(d.count);})// .curve(d3.curveCardinal) //曲线.curve(d3.curveLinear) //直线const xAxis = d3.axisBottom(xScale).tickFormat(function (d, i) {return dataset[i].time;});const yAxis = d3.axisLeft(yScale);// 每个区域绘制一个矩形用于触发事件const _w = (width - margin.left - margin.right) / (dataset.length - 1);const tooltip = d3.select('#zhe-xian-tooltip');function showTooltip(event, d) {tooltip.transition().duration(200).style("opacity", 0.9);tooltip.html(`time: ${d.time}<br>count: ${d.count}`).style("left", (xScale(d.time) + xScale.bandwidth() / 2 + 10) + "px").style("top", (yScale(d.count) - 10) + "px");}function hideTooltip() {tooltip.transition().duration(500).style("opacity", 0);}if (update) {//更新x轴和y轴svg.select(".zhe-xian-x-axis").transition().duration(500).call(xAxis);svg.select(".zhe-xian-y-axis").transition().duration(500).call(yAxis)svg.selectAll(".zhe-xian-line").datum(dataset).join("path").attr("class", "zhe-xian-line").transition().duration(500).attr("d", line)svg.selectAll('.zhe-xian-circle').data(dataset).join("circle").attr("class", "zhe-xian-circle").attr("r", 5).style('cursor', 'pointer').on('mouseover', showTooltip).on('mouseout', hideTooltip).transition().duration(500).attr('cx', function (d) {return xScale(d.time) + xScale.bandwidth() / 2;}).attr('cy', function (d) {return yScale(d.count);})} else {svg.append('path').datum(dataset).attr('class', 'zhe-xian-line').attr('d', line)svg.append('g').attr('class', 'zhe-xian-x-axis').attr('transform', 'translate(0,' + (height - margin.bottom) + ')').call(xAxis);svg.append('g').attr('class', 'zhe-xian-y-axis').attr('transform', 'translate(' + margin.left + ',0)').call(yAxis);// 绘制圆点svg.selectAll('.zhe-xian-circle').data(dataset).enter().append('circle').attr('class', 'zhe-xian-circle').attr('cx', function (d) {return xScale(d.time) + xScale.bandwidth() / 2;}).attr('cy', function (d) {return yScale(d.count);}).attr('r', 5)  //修改圆点大小.style('cursor', 'pointer').on('mouseover', showTooltip).on('mouseout', hideTooltip);svg.append("text").attr("class", "axis-label").attr("transform", "rotate(-90)").attr("x", -height/2).attr("y", margin.left-30).style("text-anchor", "middle").text("数量");svg.append("text").attr("class", "axis-label").attr("x", width / 2).attr("y", height-10).style("text-anchor", "middle").text("月份");}}drawZheXianGraph(generateData(), "graph", false)// 绑定点击事件document.getElementById('myButton').addEventListener('click', function () {console.log("我被点击了")drawZheXianGraph(generateData(), "graph", true)// 这里可以添加更多自定义逻辑});
</script>
</body>
</html>

http://www.xdnf.cn/news/3891.html

相关文章:

  • 启发式算法-遗传算法
  • C++ - 类和对象 #类的默认成员函数 #构造函数 #析构函数 #拷贝构造函数 #运算符重载函数 #赋值运算符重载函数
  • AI 入门:关键概念
  • 高等数学同步测试卷 同济7版 试卷部分 上 做题记录 第四章 不定积分同步测试卷 B卷
  • n8n 快速入门1:构建一个简单的工作流
  • 强化学习机器人模拟器——GridWorld:一个用于强化学习的 Python 环境
  • unorder_map/set的底层实现---C++
  • ESP32S3 多固件烧录方法、合并多个固件为单一固件方法
  • LangChain4J-XiaozhiAI 项目分析报告
  • 线程间通信--线程间顺序控制
  • C++类_局部类
  • 安装与配置Go语言开发环境 -《Go语言实战指南》
  • C#与西门子PLC通信:S7NetPlus和HslCommunication使用指南
  • JavaWeb:SpringBootWeb快速入门
  • 五、shell脚本--函数与脚本结构:搭积木,让脚本更有条理
  • JavaScript 中的 Proxy 与 Reflect 教程
  • 比特、字节与布尔逻辑:计算机数据存储与逻辑运算的底层基石
  • PMP-第四章 项目整合管理(一)
  • 享元模式(Flyweight Pattern)
  • MOS管极间电容参数学习
  • spring中的@ComponentScan注解详解
  • stm32week14
  • 主机电路安全防护系统哪个厂家做
  • 招聘绩效效果评估方案与优化路径
  • 35、C# 中的反射(Reflection)
  • 深入理解 Spring MVC:DispatcherServlet 与视图解析机制​
  • 快速弄懂POM设计模式
  • 1991年-2023年 上市公司-重污染企业数据 -社科数据
  • GitHub 趋势日报 (2025年05月03日)
  • 多模态大语言模型arxiv论文略读(五十九)