绘图仪 -- Web前端开发和Canvas绘图

Canvas绘图介绍

Canvas绘图是HTML5中引入的一个非常强大的特性,它允许开发者使用JavaScript在网页上绘制图形、图表、动画等。<canvas>元素提供了一个通过JavaScript和Canvas API进行绘图的环境。

创建绘图仪对象

// 定义一个名为 XYPlotter 的函数,该函数用于创建一个二维图形绘制器,接受一个参数 id,该参数是 canvas 元素的 ID  
function XYPlotter(id) {  // 通过提供的 id 获取 canvas DOM 元素  this.canvas = document.getElementById(id);  // 获取 canvas 的 2D 渲染上下文,用于后续的绘图操作  this.ctx = this.canvas.getContext("2d");  // 设置绘图区域的 x 轴最小值,这里初始化为 0  this.xMin = 0;  // 设置绘图区域的 y 轴最小值,这里也初始化为 0  // 注意:在 canvas 中,y 轴是向下的,因此 0 对应于 canvas 的顶部  this.yMin = 0;  // 设置绘图区域的 x 轴最大值,这里使用 canvas 的宽度  // 这意味着绘图区域的宽度与 canvas 的宽度相同  this.xMax = this.canvas.width;  // 设置绘图区域的 y 轴最大值,这里使用 canvas 的高度  // 这意味着绘图区域的高度与 canvas 的高度相同  // 注意:这并不意味着图形的实际显示区域会占满整个 canvas,只是定义了绘图的坐标范围,具体的图形需要进一步转换坐标来适应这个范围 this.yMax = this.canvas.height;  }  

添加绘制线条

// 在 XYPlotter 类的原型上添加一个名为 plotLine 的方法,用于绘制一条直线  
// 该方法接受五个参数:x0, y0(起点的 x, y 坐标),x, y(终点的 x, y 坐标),以及 color(线条的颜色)  
this.plotLine = function(x0, y0, x, y, color) {  // 使用 moveTo 方法设置线条的起点坐标  this.ctx.moveTo(x0, y0);  // 使用 lineTo 方法设置线条的终点坐标,此时线条的起点和终点已经确定,但尚未绘制  this.ctx.lineTo(x, y);  // 设置线条的颜色  this.ctx.strokeStyle = color;  // 使用 stroke 方法实际绘制线条,此时会根据 moveTo 和 lineTo 设置的起点和终点,以及 strokeStyle 设置的颜色来绘制线条  this.ctx.stroke();  // 注意:在调用 plotLine 方法之前,需要确保 XYPlotter 的实例已经正确创建,  // 并且其 canvas 和 ctx 属性已经通过构造函数初始化。  // 此外,由于 canvas 的坐标系统默认左上角为原点 (0,0),且 y 轴向下延伸,因此在绘制图形时需要注意坐标的转换,以确保图形按照预期的方式显示。  
}  

完整代码:

<!DOCTYPE html>  
<html>  
<body>  
<canvas id="myCanvas" width="400px" height="400px" style="width:100%;max-width:400px;border:1px solid black"></canvas>  <script>  
// 创建一个绘图仪   
let myPlotter = new XYPlotter("myCanvas");  // 绘制一条线  
myPlotter.plotLine(0, 0, myPlotter.xMax, myPlotter.yMax, "red");  // 绘图仪对象  
function XYPlotter(id) {  // 获取指定ID的canvas元素  this.canvas = document.getElementById(id);  // 获取canvas的2D渲染上下文  this.ctx = this.canvas.getContext("2d");  // 设置x轴的最小值  this.xMin = 0;  // 设置y轴的最小值  this.yMin = 0;  // 设置x轴的最大值,默认为canvas的宽度  this.xMax = this.canvas.width;  // 设置y轴的最大值,默认为canvas的高度  this.yMax = this.canvas.height;  // 绘制线条  this.plotLine = function(x0, y0, x, y, color) {  // 移动到线条的起始点  this.ctx.moveTo(x0, y0);  // 绘制线条到终点  this.ctx.lineTo(x, y);  // 设置线条的颜色  this.ctx.strokeStyle = color;  // 绘制线条  this.ctx.stroke();  }  }   
</script>  </body>  
</html>

运行结果:

添加转换 XY 值

// 定义一个变换函数,用于调整canvas的坐标系  
// 这个函数将canvas的坐标系统从默认的左上角为原点(0,0),y轴向下,  
// 转换为以左上角为原点(0,0),但y轴向上的坐标系统,类似于数学中的笛卡尔坐标系  this.transformXY = function() {   // 参数依次为:a(水平缩放), b(水平倾斜), c(垂直倾斜), d(垂直缩放), e(水平移动), f(垂直移动)  // 在这里,我们设置a=1(不改变x轴方向的缩放),b=0(不在x轴方向倾斜),  // c=0(不在y轴方向倾斜),d=-1(将y轴方向反转,实现y轴向上),  // e=0(不在x轴方向移动),f=canvas.height(在y轴方向移动,使得原坐标系的(0,0)位于canvas的左上角)  this.ctx.transform(1, 0, 0, -1, 0, this.canvas.height);  }

完整代码:

<!DOCTYPE html>  
<html>  
<body>  
<canvas id="myCanvas" width="400px" height="400px" style="width:100%;max-width:400px;border:1px solid black"></canvas>  <script>  
// 创建一个绘图仪 
let myPlotter = new XYPlotter("myCanvas");  
myPlotter.transformXY(); // 调用变换函数,以调整canvas的坐标系  // 绘制一条线  
myPlotter.plotLine(0, 0, myPlotter.xMax, myPlotter.yMax, "red"); // 从(0,0)绘制到(xMax, yMax)的红色线条  // 绘图仪对象  
function XYPlotter(id) {    this.canvas = document.getElementById(id);    this.ctx = this.canvas.getContext("2d");   this.xMin = 0;    this.yMin = 0;    this.xMax = this.canvas.width;   this.yMax = this.canvas.height;  // XY变换函数  this.transformXY = function() {  // 变换canvas的坐标系,使得y轴向上为正  this.ctx.transform(1, 0, 0, -1, 0, this.canvas.height);  }  // 绘制线条的函数  this.plotLine = function(x0, y0, x, y, color) {  // 移动到线条的起始点  this.ctx.moveTo(x0, y0);  // 绘制线条到终点  this.ctx.lineTo(x, y);  // 设置线条的颜色  this.ctx.strokeStyle = color;  // 绘制线条  this.ctx.stroke();  }  }  
</script>  
</body>  
</html>

运行结果:

添加绘制点

// 绘制点集的方法// n:要绘制的点的数量// xArr:一个数组,包含每个点的x坐标// yArr:一个数组,包含每个点的y坐标// color:用于填充圆的颜色// radius(默认为3):圆的半径  
this.plotPoints = function(n, xArr, yArr, color, radius = 3) {  // 遍历点集中的每一个点  for (let i = 0; i < n; i++) {  // 设置填充颜色  this.ctx.fillStyle = color;  // 开始一个新的路径  this.ctx.beginPath();  // 绘制一个椭圆(当宽度和高度相等时,它就是一个圆)  // 参数依次为:中心点x坐标, 中心点y坐标, 半径x, 半径y, 旋转角度, 起始角度, 结束角度  // 在这里,我们绘制的是圆,所以半径x和半径y相等,旋转角度为0,起始角度为0,结束角度为2π  this.ctx.ellipse(xArr[i], yArr[i], radius, radius, 0, 0, Math.PI * 2);  // 填充当前路径(即圆)  this.ctx.fill();  }  
}

绘制一些随机点

// 创建一个绘图仪实例,关联到ID为"myCanvas"的canvas元素  
let myPlotter = new XYPlotter("myCanvas");  // 定义要绘制的点的数量  
numPoints = 500;  // 创建一个数组,用于存储x坐标的随机值  
// 首先,使用Array(numPoints).fill(0)创建一个长度为numPoints且所有元素都为0的数组  
// 然后,使用map函数遍历这个数组,对于每个元素,生成一个0到myPlotter.xMax之间的随机数作为x坐标  
// 这样,xPoints数组就包含了numPoints个x坐标的随机值  
const xPoints = Array(numPoints).fill(0).map(function(){return Math.random() * myPlotter.xMax});  // 创建一个数组,用于存储y坐标的随机值  
// 类似于xPoints的创建过程,但这次是生成y坐标的随机值  
const yPoints = Array(numPoints).fill(0).map(function(){return Math.random() * myPlotter.yMax});  // 调用绘图仪的plotPoints方法,绘制这些点  
// 传入点的数量(numPoints),x坐标数组(xPoints),y坐标数组(yPoints),以及点的颜色("blue")  
myPlotter.plotPoints(numPoints, xPoints, yPoints, "blue");

完整代码:

<!DOCTYPE html>  
<html>  
<body>  
<canvas id="myCanvas" width="400px" height="400px" style="width:100%;max-width:400px;border:1px solid black"></canvas>  <script>  
// 创建一个XY绘图仪  
let myPlotter = new XYPlotter("myCanvas");  // 创建随机XY点  
numPoints = 500;  
const xPoints = Array(numPoints).fill(0).map(function(){return Math.random() * myPlotter.xMax});  
const yPoints = Array(numPoints).fill(0).map(function(){return Math.random() * myPlotter.yMax});  // 绘制点  
myPlotter.plotPoints(numPoints, xPoints, yPoints, "blue");  // 绘图仪对象  
function XYPlotter(id) {    this.canvas = document.getElementById(id);   this.ctx = this.canvas.getContext("2d");    this.xMin = 0;  this.yMin = 0;   this.xMax = this.canvas.width;   this.yMax = this.canvas.height;  // 绘制点集的方法  this.plotPoints = function(n, xArr, yArr, color, radius = 3) {  // 遍历点集中的每一个点  for (let i = 0; i < n; i++) {  // 设置填充颜色  this.ctx.fillStyle = color;  // 开始一个新的路径  this.ctx.beginPath();  // 绘制一个圆(通过ellipse方法,宽度和高度相等时即为圆)  this.ctx.ellipse(xArr[i], yArr[i], radius, radius, 0, 0, Math.PI * 2);  // 填充当前路径(即圆)  this.ctx.fill();  }  }  } // 绘图仪对象结束  
</script>  </body>  
</html>

运行结果:

结合以上方法:

function XYPlotter(id) {  this.canvas = document.getElementById(id);  this.ctx = this.canvas.getContext("2d");  this.xMin = 0;  this.yMin = 0;  this.xMax = this.canvas.width;  this.yMax = this.canvas.height;  // 绘图线函数  this.plotLine = function(x0, y0, x, y, color) {  this.ctx.moveTo(x0, y0);  this.ctx.lineTo(x, y);  this.ctx.strokeStyle = color;  this.ctx.stroke();  };  // 变换 XY 函数(翻转Y轴)  this.transformXY = function() {  this.ctx.transform(1, 0, 0, -1, 0, this.canvas.height);  };  // 绘制点集函数  this.plotPoints = function(n, xArr, yArr, color, radius = 3) {  for (let i = 0; i < n; i++) {  this.ctx.fillStyle = color;  this.ctx.beginPath();  this.ctx.ellipse(xArr[i], yArr[i], radius, radius, 0, 0, Math.PI * 2);  this.ctx.fill();  }  };  
}

将其保存在"myplotlib.js"文件中

执行代码:

<!DOCTYPE html>  
<html>  
<script src="myplotlib.js"></script>  
<body>  
<canvas id="myCanvas" width="400px" height="400px" style="width:100%;max-width:400px;border:1px solid black"></canvas>  <script>  // 创建一个绘图仪  let myPlotter = new XYPlotter("myCanvas");  myPlotter.transformXY(); // 变换XY轴,翻转Y轴  // 创建随机XY点  let numPoints = 500;  const xPoints = Array(numPoints).fill(0).map(function(){return Math.random() * myPlotter.xMax}); // 生成x坐标数组  const yPoints = Array(numPoints).fill(0).map(function(){return Math.random() * myPlotter.yMax}); // 生成y坐标数组  // 绘制点  myPlotter.plotPoints(numPoints, xPoints, yPoints, "blue"); // 使用蓝色绘制点  // 绘制一条线  myPlotter.plotLine(0, 0, myPlotter.xMax, myPlotter.yMax, "red"); // 使用红色从左下角绘制到右上角  
</script>  </body>  
</html>

运行结果:

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

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

相关文章

Mapboxgl 实现弧线功能

更多精彩内容尽在 dt.sim3d.cn &#xff0c;关注公众号【sky的数孪技术】&#xff0c;技术交流、源码下载请添加VX&#xff1a;digital_twin123 代码如下&#xff1a; const mapCenter [-0.5, 51.8];// please use your own token! const map new mapboxgl.Map({container: …

怎样才算精通 Excel?

最强AI视频生成&#xff1a;小说文案智能分镜智能识别角色和场景批量Ai绘图自动配音添加音乐一键合成视频百万播放量https://aitools.jurilu.com/ 高赞回答很系统&#xff0c;但普通人这么学&#xff0c;没等精通先学废了&#xff01; 4年前&#xff0c;我为了学数据分析&#…

iOS Object-C 创建类别(Category) 与使用

有时候使用系统给出类或者第三方的类,但是呢它们自带的属性和方法又太少,不够我们的业务使用,这时候就需要给“系统的类或者第三方类”创建一个类别(Category),把自己的想添加的属性和方法写进来. Category模式用于向已经存在的类添加方法从而达到扩展已有类的目的 一:创建Ca…

继承(二)

隐藏/重定义&#xff1a;子类和父类有同名的成员&#xff0c;子类成员隐藏了父类的成员。 重载&#xff1a;同一个作用域&#xff0c;重载了参数。 &#xff08;在实际中最好不要定义同名函数&#xff09; 子类对象不能初始化父类对象&#xff0c;用父类成员初始化子类成员。…

开关电源之结构分析

如有技术问题及技术需求请加作者微信! 开关电源之结构分析 1、开关电源的结构 常用开关电源,主要是为电子设备提供直流电源供电。电子设备所需要的直流电压,范围一般都在几伏到十几伏,而交流市电电源供给的电压为220V(110V),频率为50Hz(60Hz)。开关电源的作用就是把一…

【Unity】线性代数基础:矩阵、矩阵乘法、转置矩阵、逆矩阵、正交矩阵等

文章目录 矩阵&#xff08;Matrix&#xff09;矩阵能干啥&#xff1f;矩阵基本运算矩阵加减法矩阵和标量的乘法矩阵和矩阵的乘法矩阵的转置矩阵相等 特殊的矩阵方块矩阵对称矩阵对角元素&#xff08;Diagonal Elements&#xff09;对角矩阵&#xff08;Diagonal Matrix&#xf…

C语言-函数

一、函数的概念 其实在C语⾔也引⼊函数&#xff08;function&#xff09;的概念&#xff0c;有些翻译为&#xff1a;⼦程序&#xff0c;⼦程序这种翻译更加准确⼀些。C语⾔中的函数就是⼀个完成某项特定的任务的⼀⼩段代码。这段代码是有特殊的写法和调⽤⽅法的。C语⾔的程序其…

hs_err_pid.log分析

hs_err_pid.log 文件是 Java 虚拟机&#xff08;JVM&#xff09;在遇到致命错误&#xff08;如崩溃或内部错误&#xff09;时生成的错误日志文件。这个文件包含了关于崩溃的详细信息&#xff0c;可以帮助开发者或系统管理员诊断和解决问题。 hs_err_pid.log文件位置和命名 文…

基于springboot3实现单点登录(二):认证服务端搭建

前言 上文我们介绍了oauth2.0的相关理论和流程&#xff0c;本文我们继续实现。 Oauth2协议中有个很重要的概念&#xff0c;叫做”端点“&#xff0c; 以下整理了一些常用的端点及其参考访问路径及使用场景的信息&#xff0c;供参考。 这些端点在oauth2.0协议的整个生命周期…

python自动化笔记:操作mysql数据库

操作mysql数据库常见方法 1、第三方库&#xff1a;pymysql1.1、安装pymysql1.2、连接数据库1.3、连接指定数据库1.4 创建数据库、创建表1.5、表中插入数据1.6、批量插入数据1.7、获取查询结果数据1.8、防sql注入&#xff0c;sql语句中一般用占位符传值 2、标准库 &#xff1a;m…

【《Kafka 入门指南:从零基础到精通》】

前言&#xff1a; &#x1f49e;&#x1f49e;大家好&#xff0c;我是书生♡&#xff0c;本阶段和大家一起分享和探索KAFKA&#xff0c;本篇文章主要讲述了&#xff1a;消息队列的基础知识&#xff0c;KAFKA消息队列等等。欢迎大家一起探索讨论&#xff01;&#xff01;&#x…

rocketMQ5.0事务消息实战

事务消息逻辑 docker部署容器&#xff0c;并且创建消息 dd首先我们来docker 部署rocketMQ与rocketMQDashBoard docker ps查看rocketMQ 容器名称 docker ps 进入容器内部 docker exec -it rmqnamesrv /bin/bash 创建事务消息 MeessageType: TRANSACTION sh mqadmin upda…

Linux驱动.之I2C,iic驱动层(二)

一、 Linux下IIC驱动架构 本篇只分析&#xff0c;一个整体框架。 1、首先说说&#xff0c;单片机&#xff0c;的i2c硬件接口图&#xff0c;一个i2c接口&#xff0c;通过sda和scl总线&#xff0c;外接了多个设备device&#xff0c;通过单片机&#xff0c;来控制i2c的信号发生&…

解锁数据“智能”背后的秘密

在这个被数据洪流包围的时代&#xff0c;每一秒都有无数的信息在生成、传递、分析。但你是否曾好奇&#xff0c;这些数据是如何从简单的数字、文字转化为推动社会进步、改变生活方式的“智能”力量的&#xff1f;今天&#xff0c;就让我们一起揭开数据“智能”背后的神秘面纱&a…

C语言文达学院班级管理系统-计算机毕业设计源码03499

摘 要 本文阐述了一个C语言文达学院班级管理系统的设计与实现过程。该系统充分利用ASP.NET的轻量级、灵活性和可扩展性&#xff0c;旨在为文达学院提供高效、便捷的班级管理系统。通过详细的需求分析、技术选型、系统设计、开发实现、测试与调试以及部署与上线等步骤&#xff0…

通过python管理mysql

打开防火墙端口&#xff1a; 使用 firewall-cmd 命令在防火墙的 public 区域中永久添加 TCP 端口 7500&#xff08;FRP 控制台面板端口&#xff09;、7000&#xff08;FRP 服务端端口&#xff09;以及端口范围 6000-6100&#xff08;一组客户端端口&#xff09;。这些端口是 FR…

Unity补完计划 之 动态控制TileMap

本文仅作笔记学习和分享&#xff0c;不用做任何商业用途 本文包括但不限于unity官方手册&#xff0c;unity唐老狮等教程知识&#xff0c;如有不足还请斧正 1.TileMap &TileBase Unity - Scripting API: Tilemap &#xff0c;看手册内容太多了故介绍几个常用的公共方法 首…

【凌鸥学园】电机电控课程学习,挑战自我!

电控达人集结号&#xff01;凌鸥学园精心打造的电机电控课程&#xff0c;现面向全体爱好者及专业人士免费开放&#xff01; 课程内容从基础原理到高级应用&#xff0c;全方位助力你快速掌握电机电控精髓&#xff0c;实现技能飞跃&#xff01; 挑战成功&#xff0c;双重奖励等…

12. 矩阵中的路径

comments: true difficulty: 中等 edit_url: https://github.com/doocs/leetcode/edit/main/lcof/%E9%9D%A2%E8%AF%95%E9%A2%9812.%20%E7%9F%A9%E9%98%B5%E4%B8%AD%E7%9A%84%E8%B7%AF%E5%BE%84/README.md 面试题 12. 矩阵中的路径 题目描述 给定一个 m x n 二维字符网格 board…

Java的反射原理

反射允许程序在运行时检查或修改其类、接口、字段和方法的行为。反射主要通过java.lang.reflect包中的类和接口实现&#xff0c;它主要用于以下目的&#xff1a; 在运行时分析类的能力&#xff1a;通过反射&#xff0c;可以在运行时检查类的结构&#xff0c;比如它的方法、构造…