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

Canvas绘图介绍

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

创建绘图仪对象

javascript 复制代码
// 定义一个名为 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;  
 
}  

添加绘制线条

javascript 复制代码
// 在 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 轴向下延伸,因此在绘制图形时需要注意坐标的转换,以确保图形按照预期的方式显示。  
}  

完整代码:

html 复制代码
<!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 值

javascript 复制代码
// 定义一个变换函数,用于调整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);  
  
}

完整代码:

html 复制代码
<!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>

运行结果:

添加绘制点

javascript 复制代码
// 绘制点集的方法
    // 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();  
  }  
}

绘制一些随机点

javascript 复制代码
// 创建一个绘图仪实例,关联到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");

完整代码:

javascript 复制代码
<!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>

运行结果:

结合以上方法:

javascript 复制代码
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"文件中

执行代码:

html 复制代码
<!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>

运行结果:

相关推荐
活宝小娜1 小时前
vue不刷新浏览器更新页面的方法
前端·javascript·vue.js
程序视点1 小时前
【Vue3新工具】Pinia.js:提升开发效率,更轻量、更高效的状态管理方案!
前端·javascript·vue.js·typescript·vue·ecmascript
coldriversnow2 小时前
在Vue中,vue document.onkeydown 无效
前端·javascript·vue.js
我开心就好o2 小时前
uniapp点左上角返回键, 重复来回跳转的问题 解决方案
前端·javascript·uni-app
开心工作室_kaic2 小时前
ssm161基于web的资源共享平台的共享与开发+jsp(论文+源码)_kaic
java·开发语言·前端
刚刚好ā2 小时前
js作用域超全介绍--全局作用域、局部作用、块级作用域
前端·javascript·vue.js·vue
沉默璇年4 小时前
react中useMemo的使用场景
前端·react.js·前端框架
yqcoder4 小时前
reactflow 中 useNodesState 模块作用
开发语言·前端·javascript
2401_882727574 小时前
BY组态-低代码web可视化组件
前端·后端·物联网·低代码·数学建模·前端框架
SoaringHeart4 小时前
Flutter进阶:基于 MLKit 的 OCR 文字识别
前端·flutter