canvas是HTML5新增的元素,可以在网页上绘制图像,也可以结合其他HTML功能结合制作简单的小游戏,也是数据可视化、weGL的基础,功能非常强大。此外,还有two.js、thress.js、d3.js可视化库,这些库提供了方便的API,扩展了可视化的应用场景,丰富了可视化生态。
本篇文章,主要介绍使用canvas对图像进行简单处理,以及canvas对图像数据转换的一些基本应用。
在前端开发的业务中,有时候需要在网页中动态绘制比较复杂的图像,图像中存在图片,因此就使用canvas进行绘制。
ctx.drawImage():
参数:
let ctx = canvas.getContext('2d');
let img = document.getElementById('img');
img.onload = function (){
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
}
有时候我们需要把绘制好的图片传给服务器端或者做其他的操作,因此就需要获取文件内容
canvas.toDataURL()可以把绘制的图片读取为base64格式的数据
canvas.toDataURL():
let url = canvsa.toDataURL();
console.log(res);
效果如下:
这样可以通过img进行展示和下载
如果不想用base64格式保存或者传输,还可以使用toBlob()方法读取为blob类型的数据
canvas.toBlob():
参数:
方法返回一个blob对象
canvas.toBlob((res) => {
console.log(res)
});
效果如下:
可以通过blob对象的一些方法和File构造器结合使用生成一个文件
canvas.toBlob((res) => {
res.arrayBuffer().then(buffer => {
let file = new File(Array.prototype.slice.call(buffer,0, buffer.byteLength), 'qrcode.png');
});
});
blob数据 也可以通过URL.createOjectDataURL()转换成一个地址
canvas.toBlob((res) => {
let blobUrl = URL.createObjectURL(res);
console.log(blobUrl)
});
canvas除了可以绘制元素之外,还可以对图像数据进行绘制,这些数据通常是用一维数组存储的记录rgb数值的数据
canvas可以通过getImageData()方法获得图像数据
let ctx = canvas.getContext('2d);
let img = document.getElementById('img');
img.onload = function (){
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
let imgData = ctx.getIamgeData(img);
console.log(imageData);
}
可以看到imageData对象中有一个data属性,就是一个一维数组,然后可以把它重新绘制
ctx.putImageData(imageData, 0, 0, 0, 0 , canvas.width, canvas.height);
这样就又重新绘制上去了,我们也可以对数据进行操作后再绘制
let ctx = canvas.getContext('2d);
let img = document.getElementById('img');
img.onload = function (){
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
let imgData = ctx.getImageData(img);
for(let i = 0, len = imageData.data.length; i < len; i++){
imageData.data[i] = imageData.data[i] *2;
}
ctx.putImageData(imageData, 0, 0);
}
效果如下:
我们也可以自己生成类似的数据进行绘制
使用 ImageData构造函数创建一个ImageData对象,然后创建一个Unit8ClampedArray数据用于存储rgb数值,赋值给ImageData对象,然后通过putIamgeData绘制
ImageData()构造函数接收三个参数
参数:
let ctx = canvas.getContext('2d);
let width = 300
let height = 300
let data = new Uint8ClampedArray(width * height * 4);
for(let i = 0; i < data.length; i++){
data[i] = Math.floor(Math.random() * 256) * 2;
}
let imageData = new ImageData(data, width, height);
ctx.putImageData(imageData, 0, 0);
效果如下