vue2制作长方形容器,正方形网格散点图,并且等比缩放拖动

需求:有个长方形的容器,但是需要正方形的网格线,网格线是等比缩放的并且可以无线拖动的,并且添加自适应缩放和动态切换,工具是plotly.js,已完成功能如下

1.正方形网格

2.散点分组

3.自定义悬浮框的数据

4.根据窗口大小自适应缩放

5.解决数据过大或者过小网格线较少问题

6.解决项目引入plotly.js失败问题

1.效果

录像有点看不清,项目运行的话是正方形的

2.下载插件

2.1下载plotly.js

npm install plotly.js-dist-min

github的插件地址 ,里面有引入步骤

GitHub - plotly/plotly.js: Open-source JavaScript charting library behind Plotly and Dash 

plotly.js官网如下(全英文),里面有案例可以看

Plotly javascript graphing library in JavaScript

2.2下载linq.js

npm install linq

2.3 引入(解决引入报错)

通常都是第一种import的方式引入

// ES6 module
import Plotly from 'plotly.js-dist-min'// CommonJS
var Plotly = require('plotly.js-dist-min')

注意!!!如果引入后运行代码提示BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default. 可以看看这篇文章,完美解决Vue-解决BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default._breaking change: webpack < 5 used to include polyf-CSDN博客

3.代码详解

3.1 添加容器

   <div id="gd" ref="chart" style="width: 100%; height: 90vh"></div>

 3.2 模拟散点数据

{"points": [{"id": 1553,"project_id": 11,"name": "1504","x": -2.456,"y": 25440.3437,"z": -2.5487},{"id": 1554,"project_id": 11,"name": "1503","point_type": 2,"x": -1.7427000000000001,"y": 25440.4148,"z": -2.5736},{"id": 1555,"project_id": 11,"name": "1502","point_type": 1,"x": 0.5841,"y": 25440.6208,"z": -0.7072},]
}

3.3 画散点图

需要准备容器的id,data和layout还有配置项,有俩种写法,不做数据切换的时候可以用Plotly.newPlot,做数据切换的时候使用Plotly.react ,其他功能看看这个Function reference in JavaScript

    Plotly.react("gd",this.data,this.layout,this.options);

 3.4 配置data

配置项地址: 

Scatter traces in JavaScript

 通过linq根据数据源的point_type进行分组,一共分为4组散点数据图例分别为点组1234,

  1. x,y:点在图形的位置,格式为[1,2,3,4]
  2. text:点名称
  3. type: "scatter" 散点图
  4. marker:给散点根据组设置不同的样式,这个点目前没看到有自定义样式的选项,但是可供选择的样式有很多,可以根据官网进行配置

  5. name:图例的名称

  6. hovertemplate:鼠标滑到点上显示的悬浮框样式

  7. customdata:自定义数据,作用就是把z的数据添加到悬浮框中

      const groupedData = Enumerable.from(data).groupBy((point) => point.point_type).select((group) => {const xValues = group.select((point) => point.x).toArray();const yValues = group.select((point) => point.y).toArray();const zValues = group.select((point) => point.z).toArray();const textValues = group.select((point) => point.name).toArray();return {x: xValues,y: yValues,text: textValues,type: "scatter",mode: "markers",marker: {size: 12,sizemode: "diameter",symbol: (() => {switch (group.key()) {case 1:return "232";case 2:return "222";case 3:return "diamond";default:return "triangle-up";}})(),},name: (() => {switch (group.key()) {case 1:return "点组1";case 2:return "点组2";case 3:return "点组3";default:return "点组4";}})(),hovertemplate: `点名:%{text} <br> X: %{x}<br>Y: %{y}<br>Z:%{customdata}<br><extra></extra>`,customdata: zValues, //自定义数据};}).toArray();

3.5 配置layout(重点)

  正方形网格代码,必须设置

         scaleanchor: "y", // 将X轴的缩放锚定到Y轴

         scaleratio: 1, // 设置X轴和Y轴的比例为1:1

并且后续需要设置xaxis.dtick和yaxis.dtick的刻度间隔设置为一致,不然不是正方形

        xaxis: {dtick: null, // 设置X轴刻度间隔(不需要设置范围,只需要对齐yaxis的间隔设置一致就可以使图形是正方形并且等比缩放了)scaleanchor: "y", // 将X轴的缩放锚定到Y轴scaleratio: 1, // 设置X轴和Y轴的比例为1:1autorange: true,// range: [1, 5], // 初始X轴范围},

代码我写了备注,有些细节注意!!如果要做数据切换必须设置   uirevision: "true",  autorange: true

dragmode:“pan”,,配置项还有:"zoom" | "pan" | "select" | "lasso" | "drawclosedpath" | "drawopenpath" | "drawline" | "drawrect" | "drawcircle" | "orbit" | "turntable" | false

showlegend:显示图例

legend:调整图例的位置,不然默认是在右侧

      layout: {margin: { t: 0 }, //canvas对顶部的距离xaxis: {dtick: null, // 设置X轴刻度间隔(不需要设置范围,只需要对齐yaxis的间隔设置一致就可以使图形是正方形并且等比缩放了)scaleanchor: "y", // 将X轴的缩放锚定到Y轴scaleratio: 1, // 设置X轴和Y轴的比例为1:1autorange: true,// range: [1, 5], // 初始X轴范围},yaxis: {// dtick: 1000, // 设置Y轴刻度间隔dtick: null, // 设置X轴刻度间隔autorange: true,// range: [1, 100], // 初始Y轴范围},// dragmode: "zoom",dragmode: "pan", // 启用平移功能showlegend: true,uirevision: "true",legend: {x: 0.5, // 图例的x坐标y: 1, // 图例的y坐标xanchor: "center", // 图例水平居中yanchor: "bottom", // 图例底部对齐orientation: "h", // 图例横向排列},},

3.6 设置 

这段代码意思就是为了保证无论数据过大还是过小的情况下都能显示多个网格线,不会导致数据只会出现一条网格线,并且数据更新的时候都得重新设置

  this.layout.xaxis.autorange = true;

      this.layout.yaxis.autorange = true;

      this.layout.uirevision = maxY; uirevision必须和上一条数据不一致不然可能会导致数据更新失败

   calculateDtick(maxY, maxX, minY, minX) {// 计算绝对值const absX = Math.abs(maxX);const absY = Math.abs(maxY);// 取较大的绝对值const maxAbs = Math.max(absX, absY);const minAbs = Math.min(minY, minY);// 最大值减最小值除以 5(也就是默认分为5等分)let cz = Math.abs(maxAbs - minAbs);let result = cz / 5;// 将结果转换为整数,并且确保结果是 10 的倍数let roundedResult = Math.round(result / 10) * 10;console.log(roundedResult, "rounded result");// 确保 dtick 不为 0if (roundedResult < 1) {roundedResult = 1;}this.layout.xaxis.dtick = roundedResult;this.layout.yaxis.dtick = roundedResult;console.log(this.data,this.layout,this.options,this.layout.xaxis.dtick,"data数据");this.layout.xaxis.autorange = true;this.layout.yaxis.autorange = true;this.layout.uirevision = maxY;// newPlotPlotly.react("gd",this.data,this.layout,this.options// /* JSON object */ {//   data: ,//   layout: ,//   options: ,// });},

4.完整代码

<template><div style="width: 100%; height: 100%"><button @click="updateChart()">修改代码</button><button @click="updateChartOne()">修改代码22</button><div id="gd" ref="chart" style="width: 100%; height: 90vh"></div></div>
</template><script>
import Plotly from "plotly.js-dist-min";
import dataJson from "@/utils/data.json";
import Enumerable from "linq";
export default {data() {return {data: [],layout: {margin: { t: 0 }, //canvas对顶部的距离xaxis: {dtick: null, // 设置X轴刻度间隔(不需要设置范围,只需要对齐yaxis的间隔设置一致就可以使图形是正方形并且等比缩放了)scaleanchor: "y", // 将X轴的缩放锚定到Y轴scaleratio: 1, // 设置X轴和Y轴的比例为1:1autorange: true,// range: [1, 5], // 初始X轴范围},yaxis: {// dtick: 1000, // 设置Y轴刻度间隔dtick: null, // 设置X轴刻度间隔autorange: true,// range: [1, 100], // 初始Y轴范围},// dragmode: "zoom",dragmode: "pan", // 启用平移功能showlegend: true,uirevision: "true",legend: {x: 0.5, // 图例的x坐标y: 1, // 图例的y坐标xanchor: "center", // 图例水平居中yanchor: "bottom", // 图例底部对齐orientation: "h", // 图例横向排列},},options: {scrollZoom: true, //启用缩放功能displayModeBar: false, //不显示操作栏responsive: true, //制作响应式图表// tickmode: auto,// nticks: 10000,},};},mounted() {this.getData(dataJson.points, false);},methods: {updateChart() {this.getData([{id: 2711,project_id: 11,name: "aa222",x: 10,y: 22,z: 332,},],);},// 2126.474 1205.8596 1930.9592 850.2585updateChartOne() {this.getData([{id: 2711,project_id: 11,name: "aa222",point_type: 2,x: 2126.474,y: 1205.8596,z: 332,},{id: 2712,project_id: 11,name: "aa333",point_type: 1,x: 850.2585,y: 1930.9592,z: 1110,},{id: 2712,project_id: 11,name: "aa333",point_type: 1,x: 1000,y: 1000,z: 1110,},],);},// 模拟数据getData(data) {// this.layout.xaxis.range = [];// this.layout.yaxis.range = [];const groupedData = Enumerable.from(data).groupBy((point) => point.point_type).select((group) => {const xValues = group.select((point) => point.x).toArray();const yValues = group.select((point) => point.y).toArray();const zValues = group.select((point) => point.z).toArray();const textValues = group.select((point) => point.name).toArray();// 假设我们有一个函数可以根据 point_type 计算 z 值return {x: xValues,y: yValues,text: textValues,type: "scatter",mode: "markers",marker: {size: 12,sizemode: "diameter",symbol: (() => {switch (group.key()) {case 1:return "232";case 2:return "222";case 3:return "diamond";default:return "triangle-up";}})(),},name: (() => {switch (group.key()) {case 1:return "点组1";case 2:return "点组2";case 3:return "点组3";default:return "点组4";}})(),hovertemplate: `点名:%{text} <br> X: %{x}<br>Y: %{y}<br>Z:%{customdata}<br><extra></extra>`,customdata: zValues, //自定义数据};}).toArray();const maxY = Enumerable.from(data).max("$.y");const maxX = Enumerable.from(data).max("$.x");const minY = Enumerable.from(data).min("$.y");const minX = Enumerable.from(data).min("$.x");var len_str = (Math.ceil(maxY - minX) + "").length;let numStr = Math.pow(10, len_str - 1); // 初始化公共间最大间隔,console.log("最大 y 值:", maxY, maxX, minY, minX, numStr);// this.layout.xaxis.range = [1, maxX];// this.layout.yaxis.range = [1, maxY];this.data = groupedData;console.log(groupedData);this.calculateDtick(maxY, maxX, minY, minX);},calculateDtick(maxY, maxX, minY, minX) {// 计算绝对值const absX = Math.abs(maxX);const absY = Math.abs(maxY);// 取较大的绝对值const maxAbs = Math.max(absX, absY);const minAbs = Math.min(minY, minY);// 最大值减最小值除以 5(也就是默认分为5等分)let cz = Math.abs(maxAbs - minAbs);let result = cz / 5;// 将结果转换为整数,并且确保结果是 10 的倍数let roundedResult = Math.round(result / 10) * 10;console.log(roundedResult, "rounded result");// 确保 dtick 不为 0if (roundedResult < 1) {roundedResult = 1;}this.layout.xaxis.dtick = roundedResult;this.layout.yaxis.dtick = roundedResult;console.log(this.data,this.layout,this.options,this.layout.xaxis.dtick,"data数据");this.layout.xaxis.autorange = true;this.layout.yaxis.autorange = true;this.layout.uirevision = maxY;// newPlotPlotly.react("gd",this.data,this.layout,this.options// /* JSON object */ {//   data: ,//   layout: ,//   options: ,// });},},
};
</script><style lang="scss" scoped></style>

文章到此结束,希望对你有所帮助~

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring Boot 2 学习指南与资料分享

Spring Boot 2 学习资料 Spring Boot 2 学习资料 Spring Boot 2 学习资料 在当今竞争激烈的 Java 后端开发领域&#xff0c;Spring Boot 2 凭借其卓越的特性&#xff0c;为开发者们开辟了一条高效、便捷的开发之路。如果你渴望深入学习 Spring Boot 2&#xff0c;以下这份精心…

【PyQt】如何在mainwindow中添加菜单栏

[toc]如何在mainwindow中添加菜单栏 如何在mainwindow中添加菜单栏 主要有两种方法&#xff1a; 1.直接创建mainwindow进行添加 2.使用ui文件加载添加 第二种方法更为常见&#xff0c;可以应用到实际 1.直接创建mainwindow进行添加 import sysfrom PyQt5.QtWidgets import …

Vue如何构建项目

目录 1.安装Node.js 2.换源(建议) 3.选择一个目录 4.创建一个vue项目 5.验证是否成功 1.安装Node.js 安装18.3或更⾼版本的 Nodejs 点击下载->Node.Js中文网 node -v npm -v 安装好后在windows的cmd窗口下运行 如果能运行出结果就说明安装好了。 2.换源(建议) //…

uniapp 小程序 textarea 层级穿透,聚焦光标位置错误怎么办?

前言 在开发微信小程序时&#xff0c;使用 textarea 组件可能会遇到一些棘手的问题。最近我在使用 uniapp 开发微信小程序时&#xff0c;就遇到了两个非常令人头疼的问题&#xff1a; 层级穿透&#xff1a;由于 textarea 是原生组件&#xff0c;任何元素都无法遮盖住它。当其…

[c语言日寄]精英怪:三子棋(tic-tac-toe)3命慢通[附免费源码]

哈喽盆友们&#xff0c;今天带来《c语言》游戏中[三子棋boss]速通教程&#xff01;我们的目标是一边编写博文&#xff0c;一边快速用c语言实现三子棋游戏。准备好瓜子&#xff0c;我们计时开始&#xff01; 前期规划 在速通中&#xff0c;我们必须要有清晰的前期规划&#xf…

Chatper 4: Implementing a GPT model from Scratch To Generate Text

文章目录 4 Implementing a GPT model from Scratch To Generate Text4.1 Coding an LLM architecture4.2 Normalizing activations with layer normalization4.3 Implementing a feed forward network with GELU activations4.4 Adding shortcut connections4.5 Connecting at…

【Vim Masterclass 笔记13】第 7 章:Vim 核心操作之——文本对象与宏操作 + S07L28:Vim 文本对象

文章目录 Section 7&#xff1a;Text Objects and MacrosS07L28 Text Objects1 文本对象的含义2 操作文本对象的基本语法3 操作光标所在的整个单词4 删除光标所在的整个句子5 操作光标所在的整个段落6 删除光标所在的中括号内的文本7 删除光标所在的小括号内的文本8 操作尖括号…

Termora跨平台 SSH/SFTP/Terminal 客户端工具

前言 Termora一款强大的终端模拟与SSH客户端工具&#xff0c;集SFTP传输、跨平台兼容、Zmodem协议、SSH端口转发、配置同步、宏录制、关键词高亮、密钥管理、多会话命令发送及数据加密于一体&#xff0c;专为追求高效远程工作的您设计。无论是开发、管理还是日常任务&#xff…

音视频入门基础:RTP专题(1)——RTP官方文档下载

一、引言 实时传输协议&#xff08;Real-time Transport Protocol&#xff0c;简写RTP&#xff09;是一个网络传输协议&#xff0c;由IETF的多媒体传输工作小组1996年在《RFC 1889》中公布的。 RTP作为因特网标准在《RFC 3550》有详细说明。而《RFC 3551》详细描述了使用最小…

JVM之垃圾回收器ZGC概述以及垃圾回收器总结的详细解析

ZGC ZGC 收集器是一个可伸缩的、低延迟的垃圾收集器&#xff0c;基于 Region 内存布局的&#xff0c;不设分代&#xff0c;使用了读屏障、染色指针和内存多重映射等技术来实现可并发的标记压缩算法 在 CMS 和 G1 中都用到了写屏障&#xff0c;而 ZGC 用到了读屏障 染色指针&a…

Redis复制(replica)

Redis主从复制 [Redis主从复制]&#xff08;replica&#xff09;是一个多Redis实例进行数据同步的过程&#xff0c;其中一个实例是主实例&#xff08;Master&#xff09;&#xff0c;其他实例是从实例&#xff08;Slave&#xff09;。主实例负责处理命令请求&#xff0c;而从实…

React:构建用户界面的JavaScript库

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

如何使用 Excel 进行多元回归分析?

多元回归分析&#xff0c;一种统计方法&#xff0c;用来探索一个因变量&#xff08;即结果变量&#xff09;与多个自变量&#xff08;即预测变量&#xff09;之间的关系。广泛用于预测、趋势分析以及因果关系的分析。 听起来这个方法很复杂&#xff0c;但其实在 Excel 中可以很…

Android 调用系统服务接口获取屏幕投影(需要android.uid.system)

媒体投影 借助 Android 5&#xff08;API 级别 21&#xff09;中引入的 android.media.projection API&#xff0c;您可以将设备屏幕中的内容截取为可播放、录制或投屏到其他设备&#xff08;如电视&#xff09;的媒体流。 Android 14&#xff08;API 级别 34&#xff09;引入…

PostgreSQL技术内幕22:vacuum full 和 vacuum

文章目录 0.简介1.概念及使用方式2.工作原理2.1 主要功能2.2 清理流程2.3 防止事务id环绕说明 3.使用建议 0.简介 在之前介绍MVCC文章中介绍过常见的MVCC实现的两种方式&#xff0c;一种是将旧数据放到回滚段&#xff0c;一种是直接生成一条新数据&#xff08;对于删除是不删除…

C#,图片分层(Layer Bitmap)绘制,反色、高斯模糊及凹凸贴图等处理的高速算法与源程序

1 图像反色Invert 对图像处理的过程中会遇到一些场景需要将图片反色&#xff0c;反色就是取像素的互补色&#xff0c;比如当前像素是0X00FFFF&#xff0c;对其取反色就是0XFFFFFF – 0X00FFFF 0XFF0000&#xff0c;依次对图像中的每个像素这样做&#xff0c;最后得到的就是原…

STM32 FreeRTOS 的任务挂起与恢复以及查看任务状态

目录 任务的挂起与恢复的API函数 任务挂起函数 任务恢复函数 任务恢复函数&#xff08;中断中恢复&#xff09; 函数说明 注意事项 查看任务状态 任务的挂起与恢复的API函数 vTaskSuspend()&#xff1a;挂起任务, 类似暂停&#xff0c;可恢复 vTaskResume()&#xff1a…

vscode 扩展Cline、Continue的差别?

Cline和Continue都是VSCode的AI编程插件&#xff0c;它们在功能、用户体验、性能、适用场景以及配置和使用步骤等方面存在一些差别&#xff1a; 一、功能差异 编辑功能 Cline&#xff1a;能够分析项目的文件结构和源代码抽象语法树&#xff08;AST&#xff09;&#xff0c;通…

Unity 3D游戏开发从入门进阶到高级

本文精心整理了Unity3D游戏开发相关的学习资料&#xff0c;涵盖入门、进阶、性能优化、面试和书籍等多个维度&#xff0c;旨在为Unity开发者提供全方位、高含金量的学习指南.欢迎收藏。 学习社区 Unity3D开发者 这是一个专注于Unity引擎的开发者社区&#xff0c;汇聚了众多Un…

LLM实现视频切片合成 前沿知识调研

1.相关产品 产品链接腾讯智影https://zenvideo.qq.com/可灵https://klingai.kuaishou.com/即梦https://jimeng.jianying.com/ai-tool/home/Runwayhttps://aitools.dedao.cn/ai/runwayml-com/Descripthttps://www.descript.com/?utm_sourceai-bot.cn/Opus Cliphttps://www.opu…