下面是“html5 worker实例(二) 图片变换效果”的完整攻略:
简介
HTML5的Worker API提供了一种用于创建 Web Worker 的标准化方式,并且在主线程和工作线程之间提供了一种通用的消息传递机制。本文将以使用 Worker 来处理 图片变换 效果为例,以便更好地理解 Worker 的使用。
使用 Worker 实现图片的变换效果
在实现图片的变换效果之前,我们可以先来看一下 Worker 的使用方式。Worker 可以用于在主线程之外的上下文中运行脚本,例如在浏览器全局作用域之外的一个独立线程中。下面是使用的步骤:
- 创建 Worker
- 发送消息到 Worker
- 接收 Worker 返回的消息
- 关闭 Worker
Worker 可以与主线程之间进行数据和方法的通信,这也是实现图片变换效果的基础。
实现图片变换效果
下面是实现图片变换效果的详细步骤:
1. 创建Worker
首先,我们需要在主线程中创建一个 Worker。下面是示例代码:
var worker = new Worker("worker.js");
2. 加载图片
为了将这幅图像交给 Worker 来处理,我们可以将其修改成流,并发给 Worker:
var canvas = document.createElement("canvas");
canvas.width = img.width;
canvas.height = img.height;
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0);
var imageData = ctx.getImageData(0, 0, img.width, img.height);
worker.postMessage(imageData); // 发送数据给Worker
3. 接收和处理 Worker 返回的数据
我们可以在 worker 线程中处理图像数据,并将处理结果发送回主线程。
self.onmessage = function(event) {
var imageData = event.data; // 接收主线程传来的图像数据
var data = imageData.data;
for (var i = 0; i < data.length; i += 4) {
var r = data[i], g = data[i+1], b = data[i+2], a = data[i+3];
// 处理图像数据
}
self.postMessage(imageData); // 将处理过后的图像数据发送回主线程
};
4. 关闭 Worker
要停止工作线程,请使用 Worker.terminate() 方法来发送终止信号。在收到此消息后,任何正在进行的操作都会立即停止,并且 Worker 将被视为已非工作。下面是示例代码:
worker.terminate();
示例
下面展示两个用 Worker 处理图片的例子:
示例 1:生成水印
可以使用Worker API来批量使用图片添加水印,避免使用同步方法,导致浏览器界面的卡顿。下面是一个使用 Worker 来添加水印的示例:
/* 主线程中 */
var src = 'http://example.com/image.jpg';
var worker = new Worker('worker.js');
worker.onmessage = (e) => {
let img = e.data;
document.body.appendChild(img);
worker.terminate(); // 关闭 worker
};
let addWatermark = (imageData, text) => {
for (let i = 0; i < imageData.data.length; i += 4) {
if ((i+1)%4 != 0) {
imageData.data[i] = (imageData.data[i] + text.charCodeAt(i%text.length)) / 2;
}
}
return imageData;
};
let img = new Image();
img.crossOrigin = 'anonymous';
img.src = src;
img.onload = () => {
let canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
let ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0);
let imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
imageData = addWatermark(imageData, 'Hello, Watermark!');
worker.postMessage(imageData);
};
Worker 线程中的代码如下:
/* worker.js */
self.onmessage = (e) => {
let imageData = e.data;
imageData = addWatermark(imageData, 'Hello, Watermark!');
self.postMessage(data);
};
let addWatermark = (imageData, text) => {
for (let i = 0; i < imageData.data.length; i += 4) {
if ((i+1)%4 != 0) {
imageData.data[i] = (imageData.data[i] + text.charCodeAt(i%text.length)) / 2;
}
}
return imageData;
};
示例 2:高清图像压缩
在我们使用手机或者相机拍照时,往往会生成比较大的图像,如果这些图像需要被上传到服务器,那么我们需要对这些图像进行压缩。下面是使用Worker 来压缩图像的例子:
/* 主线程中 */
let input = document.querySelector('input');
let worker = new Worker('worker.js');
worker.onmessage = (e) => {
let blob = e.data;
let url = URL.createObjectURL(blob);
console.log(url);
};
let previewImage = (file) => {
let reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => {
let img = new Image();
img.src = reader.result;
img.onload = () => {
let canvas = document.createElement('canvas');
let ctx = canvas.getContext('2d');
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
let Quality = 0.6; // 图片压缩质量值
let type = 'image/png'; // 压缩后生成的类型
let data = canvas.toDataURL(type, Quality);
let arr = data.split(',');
let mime = arr[0].match(/:(.*?);/)[1] || '';
let bStr = atob(arr[1]);
let n = bStr.length;
let u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bStr.charCodeAt(n);
}
worker.postMessage(u8arr.buffer, [u8arr.buffer]);
};
};
};
input.onchange = (e) => {
previewImage(e.target.files[0]);
};
Worker 线程中的代码如下:
/* worker.js */
self.onmessage = (e) => {
let buffer = e.data;
let blob = new Blob(buffer, 'image/png');
self.postMessage(blob);
};
总结
通过上述两个示例,我们可以看到使用 Worker API 可以批量修改图片来加水印或者压缩等操作,避免了主线程中的卡顿,让浏览器能够有更加流畅的用户体验。同时,Worker API的使用还可以有效的提高代码的可维护性和扩展性。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:html5 worker 实例(二) 图片变换效果 - Python技术站