JavaScript和 HTML5 Canvas实现图像绘制与处理

JavaScript 和 HTML5 Canvas 实现图像绘制与处理的讲解:

一、创建 Canvas 元素和获取绘图上下文

在 HTML 页面中,我们首先创建一个 <canvas> 元素,并为其指定宽度和高度属性:

html 复制代码
<canvas id="myCanvas" width="800" height="600"></canvas>

然后,在 JavaScript 代码中,通过 document.getElementById 方法获取这个 <canvas> 元素:

javascript 复制代码
var canvas = document.getElementById('myCanvas');

接下来,使用 getContext 方法获取 2D 绘图上下文,以便进行后续的绘制操作:

javascript 复制代码
var ctx = canvas.getContext('2d');

二、绘制基本图形

  1. 矩形
  • fillRect(x, y, width, height) 方法用于绘制填充的矩形。其中, x 和 y 是矩形左上角的坐标, width 是矩形的宽度, height 是矩形的高度。

例如:

javascript 复制代码
ctx.fillStyle ='red'; 
ctx.fillRect(10, 10, 100, 100); 
 

上述代码将绘制一个左上角坐标为 (10, 10) 、宽度为 100 像素、高度为 100 像素的红色填充矩形。

  • strokeRect(x, y, width, height) 方法用于绘制矩形边框。边框的样式由 strokeStyle 和 lineWidth 属性控制。

示例:

javascript 复制代码
ctx.strokeStyle = 'blue';
ctx.lineWidth = 5; 
ctx.strokeRect(150, 10, 100, 100);

这将绘制一个左上角坐标为 (150, 10) 、宽度为 100 像素、高度为 100 像素的蓝色边框矩形,边框宽度为 5 像素。

  1. 线条
  • beginPath() 方法用于开始一条新的路径。

  • moveTo(x, y) 方法用于设置线条的起始点。

  • lineTo(x, y) 方法用于从起始点到指定点绘制一条直线。

  • stroke() 方法用于实际绘制线条。

例如:

javascript 复制代码
ctx.beginPath();
ctx.moveTo(20, 200);
ctx.lineTo(200, 20);
ctx.strokeStyle = 'green';
ctx.stroke();

上述代码首先开始一条新路径,将起始点设置为 (20, 200) ,然后绘制一条到 (200, 20) 的直线,并使用绿色绘制线条。

  1. 圆形

arc(x, y, radius, startAngle, endAngle, anticlockwise) 方法用于绘制圆形或弧形。

其中, x 和 y 是圆心的坐标, radius 是半径, startAngle 和 endAngle 是以弧度表示的起始角度和结束角度, anticlockwise 是一个布尔值,表示绘制方向是逆时针(true)还是顺时针(false)。

示例:

javascript 复制代码
ctx.beginPath();
ctx.arc(300, 200, 50, 0, 2 * Math.PI);
ctx.fillStyle = 'yellow';
ctx.fill();

这将绘制一个圆心在 (300, 200) 、半径为 50 像素的黄色填充圆形。

三、绘制图像

  1. 首先创建一个 Image 对象,并设置其 src 属性指向要绘制的图像的路径:
javascript 复制代码
var image = new Image();
image.src = 'image.jpg'; 
 
  1. 由于图像的加载是异步的,我们需要在图像加载完成后才能进行绘制。可以通过为 Image 对象添加 onload 事件处理程序来实现:
javascript 复制代码
image.onload = function() {
    // 在这里进行图像的绘制操作
};
  1. 以下是几种常见的 drawImage 方法的使用方式:
  • drawImage(image, x, y) :在指定的 (x, y) 坐标位置绘制原始大小的图像。

  • drawImage(image, x, y, width, height) :在指定的 (x, y) 坐标位置绘制指定大小的图像。

  • drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight) :从源图像的 (sx, sy) 位置开始,截取 sWidth x sHeight 大小的区域,并将其绘制到目标位置 (dx, dy) ,绘制的大小为 dWidth x dHeight 。

示例:

javascript 复制代码
image.onload = function() {
    ctx.drawImage(image, 50, 50); 
};

四、图像处理

  1. 缩放

缩放图像可以通过调整 drawImage 方法中指定的绘制宽度和高度来实现。

例如,将图像缩小一半:

javascript 复制代码
image.onload = function() {
    ctx.drawImage(image, 0, 0, image.width / 2, image.height / 2); 
};
 
  1. 旋转

旋转图像需要以下几个步骤:

首先,使用 save 方法保存当前的绘图状态,以确保后续的旋转操作不会影响到之前的绘制内容。

然后,使用 translate 方法将旋转中心移动到指定位置。

接着,使用 rotate 方法进行旋转。

最后,绘制图像,并使用 restore 方法恢复之前保存的绘图状态。

示例:

javascript 复制代码
image.onload = function() {
    ctx.save();
    ctx.translate(200, 200);
    ctx.rotate(Math.PI / 4);
    ctx.drawImage(image, -image.width / 2, -image.height / 2);
    ctx.restore();
};
  1. 像素操作

使用 getImageData 方法可以获取图像的像素数据。

getImageData 方法接受四个参数:起始的 x 坐标、起始的 y 坐标、获取的宽度和高度。

获取到的 ImageData 对象包含 width 、 height 和 data 属性。 data 属性是一个一维数组,其中每个像素由四个值(RGBA)表示,分别对应红、绿、蓝和透明度通道。

对像素数据进行处理后,使用 putImageData 方法将处理后的像素数据放回 Canvas 中。

示例:

javascript 复制代码
var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);

for (var i = 0; i < imageData.data.length; i += 4) {
    var r = imageData.data[i];
    var g = imageData.data[i + 1];
    var b = imageData.data[i + 2];
    var a = imageData.data[i + 3];

    // 在此处进行像素级别的处理,例如调整颜色值
    imageData.data[i] = 255 - r;
    imageData.data[i + 1] = 255 - g;
    imageData.data[i + 2] = 255 - b;
}

ctx.putImageData(imageData, 0, 0);

五、绘制文本

  1. 可以使用 fillText 方法绘制填充的文本,或者使用 strokeText 方法绘制文本边框。

示例:

javascript 复制代码
ctx.font = '20px Arial';
ctx.fillStyle = 'black';
ctx.fillText('Hello Canvas!', 50, 50);

上述代码将使用 20 像素大小的 Arial 字体,在 (50, 50) 位置绘制黑色填充的文本 "Hello Canvas!" 。

  1. 可以通过设置 textAlign 属性来控制文本的水平对齐方式,可选值包括 start (默认,左对齐)、 end (右对齐)、 center (居中对齐)等。

例如:

javascript 复制代码
ctx.textAlign = 'center';
ctx.fillText('Centered Text', canvas.width / 2, 100);

这将在画布的中间位置绘制水平居中的文本。

  1. 还可以通过设置 textBaseline 属性来控制文本的垂直对齐方式,可选值包括 top 、 hanging 、 middle 、 alphabetic (默认)、 ideographic 、 bottom 等。

例如:

javascript 复制代码
ctx.textBaseline = 'bottom';
ctx.fill.fillText('Bottom Aligned Text', 100, canvas.height - 20);

这将在指定位置绘制底部对齐的文本。

六、图形组合模式

  1. globalCompositeOperation 属性用于控制新绘制的图形与已有图形的组合方式。

常见的组合模式包括:

  • source-over :新图形覆盖在旧图形上(默认)。

  • destination-over :新图形在旧图形下面。

  • source-in :只显示新图形与旧图形重叠的部分,且新图形在旧图形内部。

  • destination-in :只显示旧图形与新图形重叠的部分,且新图形在旧图形内部。

  • source-out :只显示新图形不与旧图形重叠的部分。

  • destination-out :只显示旧图形不与新图形重叠的部分。

  • source-atop :只显示新图形与旧图形重叠的部分,以及旧图形不与新图形重叠的部分。

  • destination-atop :只显示旧图形与新图形重叠的部分,以及新图形不与旧图形重叠的部分。

  • lighter :两图形颜色值相加。

  • copy :显示新图形,删除旧图形。

  • xor :异或操作,只显示新图形与旧图形不重叠的部分以及重叠部分的颜色反转。

示例:

javascript 复制代码
ctx.globalCompositeOperation = 'destination-over';
 

上述代码将设置组合模式为新图形在旧图形下面。

七、应用渐变

  1. 线性渐变

使用 createLinearGradient 方法创建线性渐变对象。

示例:

javascript 复制代码
var linearGradient = ctx.createLinearGradient(0, 0, canvas.width, 0);
linearGradient.addColorStop(0,'red');
linearGradient.addColorStop(1, 'blue');
ctx.fillStyle = linearGradient;
ctx.fillRect(0, 0, canvas.width, canvas.height);

在上述代码中,首先创建了一个从画布左上角到右上角的线性渐变对象。然后,通过 addColorStop 方法添加颜色停止点,0 表示起点位置,1 表示终点位置。最后,将渐变设置为填充样式,并绘制一个填充矩形。

  1. 径向渐变

使用 createRadialGradient 方法创建径向渐变对象。

示例:

javascript 复制代码
var radialGradient = ctx.createRadialGradient(canvas.width / 2, canvas.height / 2, 0, canvas.width / 2, canvas.height / 2, canvas.width / 2);
radialGradient.addColorStop(0,'red');
radialGradient.addColorStop(1, 'blue');
ctx.fillStyle = radialGradient;
ctx.fillRect(0, 0, canvas.width, canvas.height);
 

上述代码创建了一个以画布中心为圆心,从半径 0 到半径 canvas.width / 2 的径向渐变,并进行了填充绘制。

八、绘制阴影

  1. 可以通过以下几个属性来设置阴影效果:
  • shadowColor :阴影的颜色。

  • shadowBlur :阴影的模糊程度。

  • shadowOffsetX :阴影在 x 方向的偏移量。

  • shadowOffsetY :阴影在 y 方向的偏移量。

示例:

javascript 复制代码
ctx.shadowColor = 'rgba(0, 0, 0, 0.5)';
ctx.shadowBlur = 10;
ctx.shadowOffsetX = 5;
ctx.shadowOffsetY = 5;

上述代码设置了一个半透明的黑色阴影,模糊程度为 10 像素,在 x 方向偏移 5 像素,在 y 方向偏移 5 像素。

相关推荐
今天又是充满希望的一天15 分钟前
C++分布式系统知识
开发语言·c++
zth41302125 分钟前
SegmentSplay‘s Super STL(v2.2)
开发语言·c++·算法
悟空瞎说41 分钟前
深度解析:Vue3 为何弃用 defineProperty,Proxy 到底强在哪里?
前端·javascript
leafyyuki43 分钟前
告别 Vuex 的繁琐!Pinia 如何以更优雅的方式重塑 Vue 状态管理
前端·javascript·vue.js
沐知全栈开发1 小时前
《jEasyUI 格式化列》
开发语言
0xDevNull1 小时前
JDK 25 新特性概览与实战教程
java·开发语言·后端
某人辛木1 小时前
nodejs下载安装
开发语言·前端·javascript
笨笨饿1 小时前
34_数据结构_栈
c语言·开发语言·数据结构·人工智能·嵌入式硬件·算法
爱码驱动1 小时前
文件操作和IO
java·开发语言·io·文件操作
坊钰1 小时前
Java 反射机制
java·开发语言