JS实现动态点图酷炫效果
实现目标

分析问题
整个图主要是用canvas实现,其中难点是将线的长度控制在一定范围内、并且透明度随长度变化。
前置知识
canvas绘制点、线、三角形、弧形
// 点ctx.moveTo(this.x, this.y);ctx.arc(this.x, this.y, this.r,0, 2 * Math.PI, false);ctx.fillStyle = "white";ctx.fill();// 线ctx.beginPath();ctx.moveTo(p1.x, p1.y);ctx.lineTo(p2.x, p2.y);// 三角形ctx.beginPath();ctx.moveTo(p1.x, p1.y);ctx.lineTo(p2.x, p2.y);ctx.lineTo(p3.x, p3.y);ctx.closePath();// 弧形ctx.beginPath();ctx.arc(100, 100, 50, 0, Math.PI / 2, false); // 从 0° 到 90°(顺时针)ctx.strokeStyle = "blue";ctx.lineWidth = 3;ctx.stroke();
代码实战
实现思路
随机生成n个点,然后随机选m个 三个随机点(属于n个点中) 组成的集合绘制三角形。
<head><style>* {margin: 0 auto;padding: 0;}canvas {position: fixed;background: black;width: 100%;height: 100%;}</style>
</head>
<body><canvas></canvas><script src="./index.js"></script>
</body>
// 获取 canvas节点
let cts = document.querySelector("canvas");
let ctx = cts.getContext("2d");
// 设置宽高
cts.width = window.innerWidth;
cts.height = window.innerHeight;class Point {constructor(x, y) {this.x = x;this.y = y;this.r = 1;}draw() {ctx.moveTo(this.x, this.y);ctx.arc(this.x, this.y, this.r,0, 2 * Math.PI, false);ctx.fillStyle = "white";ctx.fill();}
}class Graph {constructor() {// 圆点个数this.pointSize = 500;this.maxHeight = window.innerHeight;this.maxWidth = window.innerWidth;// 对角线this.maxLine = Math.sqrt(this.maxHeight * this.maxHeight + this.maxWidth * this.maxWidth);// 所有点集this.points = new Array(this.pointSize).fill(0).map(() =>new Point(Math.random() * this.maxWidth, Math.random() * this.maxHeight))}// 绘制 p1-p2 直线drawLine(p1, p2) {let tLine = Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2));let at = 0.2 - tLine / 500;// this.maxLine;// 太长的线不绘制if (tLine > 100) return;ctx.moveTo(p1.x, p1.y);ctx.lineTo(p2.x, p2.y);ctx.strokeStyle = `rgba(255, 255, 255, ${at})`;}// 绘制三角形drawRan(p1, p2, p3) {if (!p1 || !p2 || !p3) return;ctx.beginPath();this.drawLine(p1, p2);this.drawLine(p2, p3);ctx.stroke();}draw() {// 绘制所有圆点for (let i = 0; i < this.pointSize; i++) {let p1 = this.points[i];p1.draw();}// 选取随机的三点绘制三角形for (let i = 0; i < this.pointSize * this.pointSize / 10; i++) {let t1 = Math.floor(Math.random() * this.pointSize);let t2 = Math.floor(Math.random() * this.pointSize);let t3 = Math.floor(Math.random() * this.pointSize);let p1 = this.points[t1];let p2 = this.points[t2];let p3 = this.points[t3];this.drawRan(p1, p2, p3);}}
}let init = () => {let g = new Graph();g.draw();
}
init();
优化
点集动态移动(弧形),随机选点、弧形半径随机。
let cts = document.querySelector("canvas");
let ctx = cts.getContext("2d");let setWH = () => {cts.width = window.innerWidth;cts.height = window.innerHeight;
}
let clearBG = () => {ctx.clearRect(0, 0, cts.width, cts.height);
}class Point {constructor(x, y) {this.px = x;this.py = y;this.r = 1;this.radius = 500 * Math.random();this.angle = 0;}draw() {ctx.moveTo(this.x, this.y);ctx.arc(this.x, this.y, this.r,0, 2 * Math.PI, false);ctx.fillStyle = "white";ctx.fill();}move() {this.x = this.px + this.radius * Math.cos(this.angle);this.y = this.py + this.radius * Math.sin(this.angle);this.angle = (this.angle + 0.05) % (Math.PI * 2);}
}class Graph {constructor() {this.pointSize = 500;this.maxHeight = window.innerHeight;this.maxWidth = window.innerWidth;this.maxLine = Math.sqrt(this.maxHeight * this.maxHeight + this.maxWidth * this.maxWidth);this.points = new Array(this.pointSize).fill(0).map(() =>new Point(Math.random() * this.maxWidth, Math.random() * this.maxHeight))}drawLine(p1, p2) {let tLine = Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2));let at = 0.2 - tLine / 500;// this.maxLine;if (tLine > 100) return;ctx.moveTo(p1.x, p1.y);ctx.lineTo(p2.x, p2.y);ctx.strokeStyle = `rgba(255, 255, 255, ${at})`;}drawRan(p1, p2, p3) {if (!p1 || !p2 || !p3) return;ctx.beginPath();this.drawLine(p1, p2);this.drawLine(p2, p3);ctx.stroke();}draw() {for (let i = 0; i < this.pointSize; i++) {let p1 = this.points[i];p1.move();p1.draw();}for (let i = 0; i < this.pointSize * this.pointSize / 10; i++) {let t1 = Math.floor(Math.random() * this.pointSize);let t2 = Math.floor(Math.random() * this.pointSize);let t3 = Math.floor(Math.random() * this.pointSize);let p1 = this.points[t1];let p2 = this.points[t2];let p3 = this.points[t3];this.drawRan(p1, p2, p3);}}
}let timer = null;let init = () => {setWH();let g = new Graph();timer = setInterval(() => {clearBG();g.draw();}, 1000)
}
init();相关文章:
JS实现动态点图酷炫效果
实现目标 分析问题 整个图主要是用canvas实现,其中难点是将线的长度控制在一定范围内、并且透明度随长度变化。 前置知识 canvas绘制点、线、三角形、弧形 // 点ctx.moveTo(this.x, this.y);ctx.arc(this.x, this.y, this.r,0, 2 * Math.PI, false);ctx.fillStyle …...
【第十三届“泰迪杯”数据挖掘挑战赛】【2025泰迪杯】【思路篇】A题解题全流程(持续更新)
【第十三届“泰迪杯”数据挖掘挑战赛】【2025泰迪杯】A题解题全流程-思路(持续更新) 写在前面: 1、A题、C题将会持续更新,陆续更新发布文章 2、赛题交流咨询Q群:1037590285 3、全家桶依旧包含: 代码、…...
爱普生晶体单元FC2012AN在5G RedCap中的应用
在 5G 技术向物联网领域深度渗透的今天,RedCap(5G 轻量化)作为衔接中高速物联网场景的关键技术,正加速推动工业、医疗、可穿戴等领域的智能化升级。爱普生 FC2012AN 低 ESR 晶体单元凭借其突破性的小尺寸、低功耗与高稳定性设计&a…...
vue 两种路由模式
一、两种模式比较 在vue.js中,路由模式分为两种:hash 模式和 history 模式。这两种模式决定了URL的结构和浏览器历史记录的管理方式。 1. hash 模式带 #,#后面的地址变化不会引起页面的刷新。换句话说,hash模式不会将#后面的地址…...
Java-servlet(十)使用过滤器,请求调度程序和Servlet线程(附带图谱表格更好对比理解)
Java-servlet(十)使用过滤器,请求调度程序和Servlet线程 前言一、Servlet 间通信(了解即可)二、Servlet 请求处理:getAttribute 和 getParameter 的区别与应用1.getAttribute 方法2.getParameter 方法 三、…...
ue5 学习笔记 FPS游戏制作35 GameMode与GameInstance
文章目录 相似GameMode介绍声明设置生效调用 GameInstance介绍声明设置生效调用 相似 两者都用来保存公共的数据和方法 数据都在内存里,关闭程序后数据消失 GameMode 介绍 生命周期跟随关卡,关卡销毁GameMode也跟随销毁 内部可以定义属性和方法 声明…...
rocky9.4 升级SSH 9.9p2
echo "##################################开始升级Openssh##################################################################################" ##ssh变量---------------------------------------- sshnumber9.9p2 sshnumber1ssh -V 2>&1 | cut -d, -f…...
基于WebSocket的金融数据实时推送系统架构设计对接多国金融数据API
基于WebSocket的金融数据实时推送系统架构设计 ——高可用、低延迟与全球化数据支持的技术实践 一、实时数据推送的技术演进 在证券交易、外汇监控、量化策略等场景中,毫秒级延迟可能带来完全不同的业务结果。早期基于HTTP轮询的方案存在三大核心问题:…...
山洪预警秒级响应-AI本地化部署在极端降雨短临预测中的技术突破。AI智能体开发与大语言模型的本地化部署、优化技术
极端降雨预测的技术痛点与边缘破局 1. 传统预警系统的三重瓶颈 延迟致命:WRF模式在1km分辨率下3小时预报耗时>45分钟,错过山洪黄金响应期 地形干扰大:复杂地形区(如横断山脉)降水预测误差超50% 数…...
矿山自动化监测解决方案
1.行业现状 为贯彻落实《中共中央国务院关于推进安全生产领域改革发展的意见》《“十四五”矿山安全生产规划》(应急〔2022〕64号)、《国务院安委会办公室关于加强矿山安全生产工作的紧急通知》(安委办〔2021〕3号)等有关工作部署…...
pytorch学习(b站小土堆学习)
1 环境配置 参考链接 2. dir 和 help函数 dir():用于查看某一模块函数的方法 help(): 用于查看某方法的使用方法 3. dataset类实战 利用Image对象打开图片,利用os模块的地址拼接组成图片路径 当我们用方括号访问元素对象时,…...
微信小程序:解决tabbar切换时,页面不刷新问题
在微信小程序中,默认情况下切换 tabBar 页面时,页面不会重新加载或刷新(而是保持之前的状态)。如果你需要在切换 tabBar 时触发数据刷新或重新执行某些逻辑,可以通过以下方法解决: 方法 1:…...
【最新】探索CFD的未来:从OpenFOAM到深度学习,全面解析计算流体力学的顶级资源与前沿技术
计算流体力学(CFD)作为现代工程与科学研究的核心工具,正以前所未有的速度迈向智能化与多物理场耦合的新时代。本文全面梳理了在线学习CFD的顶级资源,涵盖了从传统数值模拟到深度学习驱动的物理信息模型的广泛领域,旨在为研究者、工程师和学生提供一站式参考指南。内容分为…...
算法专题一:双指针算法(下)
书接上回 5.有效三角形个数 力扣: 有效三角形的个数 在做这道题前我们先讲一个数学知识:已知 a < b < c ,此时 ab>c 可以得出 有效三角形。 所以,我们做这道题时,可以不使用暴力算法。 可以优化为先排序ÿ…...
数据库部署在服务器表不存在解决方案
MySQL 数据库表不存在错误解决方案 MySqlException (0x80004005): Table store.SysLogOperate doesnt exist 服务器用的mysql5.6 用这个表syslogoperate只是全是小写 看起来你在使用 Pomelo.EntityFrameworkCore.MySql 作为 MySQL 数据库的提供程序,并且在初始化…...
咪咕MG101_晨星MSO9380芯片_安卓5.1.1_免拆卡刷固件包
咪咕MG101_晨星MSO9380芯片_安卓5.1.1_免拆卡刷固件包(内有教程) 刷机教程简单说明: 1、把下载好的刷机包,U盘里建立一个upgrade文件夹,固件放入此文件夹里,放入U盘中,注意升级包为压缩包不要对…...
cJSON类型及type值详解
cJSON的核心结构体 cJSON的核心结构体就是一个cJSON,理解了这个结构体,基本上对cJSON的使用就有了个基本概念了。该结构体具体定义如下: typedef struct cJSON { struct cJSON*next,*prev; /* 遍历数组或对象链的前向或后向链表指…...
T11 TensorFlow入门实战——优化器对比实验
🍨 本文為🔗365天深度學習訓練營 中的學習紀錄博客🍖 原作者:K同学啊 | 接輔導、項目定制 一、前期准备 1. 导入数据 # Import the required libraries import pathlib import matplotlib.pyplot as plt import tensorflow as t…...
2023年3月全国计算机等级考试真题(二级C语言)
😀 第1题 下列叙述中错误的是 A. 向量是线性结构 B. 非空线性结构中只有一个结点没有前件 C. 非空线性结构中只有一个结点没有后件 D. 只有一个根结点和一个叶子结点的结构必定是线性结构 概念澄清 首先,我们需要明确几个关键概念…...
在MFC中使用Qt(四):使用属性表(Property Sheet)实现自动化Qt编译流程
前言 首先回顾下前面文章介绍的: 在MFC中使用Qt(一):玩腻了MFC,试试在MFC中使用Qt!(手动配置编译Qt) 在MFC中使用Qt(二):实现Qt文件的自动编译流…...
Python-八股总结
目录 1 python 垃圾处理机制2 yield3 python 多继承,两个父类有同名方法怎么办?4 python 多线程/多进程/协程4.1 多线程与GIL全局解释器锁4.2 多进程4.3 协程 5 乐观锁/悲观锁6 基本数据结构**1. 列表(List)****2. 元组࿰…...
局域网数据同步软件,局域网数据备份的方法
局域网数据备份的方法: 局域网数据备份是确保数据安全性的重要措施,以下是一些常用的局域网数据备份方法: 1.使用NAS设备备份 特点:网络附加存储(NAS)设备提供了一种便捷的备份方式。 操作:…...
ngx_http_core_init_main_conf
定义在 src\http\ngx_http_core_module.c static char * ngx_http_core_init_main_conf(ngx_conf_t *cf, void *conf) {ngx_http_core_main_conf_t *cmcf conf;ngx_conf_init_uint_value(cmcf->server_names_hash_max_size, 512);ngx_conf_init_uint_value(cmcf->serv…...
座舱与智驾“双轮驱动”,芯擎科技打造智能汽车“芯”标杆
在比亚迪、吉利、奇瑞等各大主机厂打响“全民智驾”的关键时期,以芯擎科技为代表中国芯片厂商开始“放大招”。 2025年3月27日,芯擎科技在南京举办了“擎随芯动、智融万象”生态科技日,重磅发布了“星辰一号”、“星辰一号Lite”,…...
《新能源汽车 DEEA 平台开发策略》
一、引言 在新能源汽车行业加速向智能化、电动化转型的当下,电子电气架构(EEA)成为汽车技术创新的关键领域。DEEA 平台作为应对行业变革的重要举措,其开发策略对于提升汽车产品竞争力、满足市场多样化需求意义重大。本策略围绕平台…...
R语言实现轨迹分析--traj和lcmm包体会
R语言实现轨迹分析–traj和lcmm包体会 轨迹分析是对重复测量数据的一种归纳,转化为一种分类变量,比如手术后1~7天内的疼痛评分,可以形成术后急性痛轨迹。形成的轨迹作为一个分类变量,可以用于预测疾病的预后ÿ…...
Spring Boot中对同一接口定义多个切面的示例,分别通过接口方式和注解方式实现切面排序,并对比差异
以下是Spring Boot中对同一接口定义多个切面的示例,分别通过接口方式和注解方式实现切面排序,并对比差异: 一、接口方式实现切面排序 1. 定义接口 // 服务接口 public interface MyService {void methodA();void methodB(); }// 接口实现类…...
从零开始:Windows 系统中 PowerShell 配置 FFmpeg 的详细步骤
在Windows系统中不想每次都 cd 到FFmpeg目录中应用,现在可以通过PowerShell在任意目录下应用了。 PowerShell 基础概念 跨平台脚本工具 PowerShell 是微软开发的命令行外壳和脚本语言,支持 Windows、Linux 和 macOS 系统。其核心优势在于面向对象的操作…...
《新凯来 :中国半导体设备制造行业从“跟随者”向“挑战者”的角色转变》
《新凯来 :中国半导体设备制造行业从“跟随者”向“挑战者”的角色转变》 一、技术突破再升级二、生态布局加速三、市场与资本动态四、未来挑战与应对五、行业意义 新凯来作为国产半导体设备领域的领军企业,其技术突破与市场进展持续引发行业关注。结合最…...
Java-拼图小游戏跟学笔记
阶段项目-01-项目介绍和界面搭建_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV17F411T7Ao?p144 代码 1.主界面分析(组件) JFrame:最外层的窗体 JMenuBar:最上层的菜单 JLabel:管理文字和图片的容器 1.界面 --关闭模式-- DO_NOTHING_ON_CLOSE:当用户…...
