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>
运行结果: