Canvas之使用图像

Canvas之使用图像

js 复制代码
const img = new Image();
img.src='exercises/imgs/01.png'
img.onload = function () {
    ctx.drawImage(img, 0, 90, 400, 220);
};
js 复制代码
const img = new Image();
img.src='exercises/imgs/01.png'
img.onload = function () {
    ctx.drawImage(img, 44, 0, 200, img.height,100,(400-img.height)/2,200,img.height);
};

Canvas 可以引入图像,可以是image,video,canvas 格式。image 可以是图片路径或者是base64格式。

当我们创建了一个图片之后,需要在图片加载之后进行绘制,因为图片的绘制速度远大于图片的加载速度。

可以只放图像坐标,就显示原大小。可以放入图像宽高,就表示显示在画布上的大小。还可以加入两组数据,前一组表示原图片截图坐标,大小,后一组表示放在画布上的坐标,大小。当然可能经过了两次缩放。

js 复制代码
const video = document.querySelector('video');
video.addEventListener('play', function () {
    draw();
})
ctx.arc(200, 200, 150, 0, Math.PI * 2);

// ctx.filter = 'invert(0.8)';
ctx.clip();
function draw() {
    ctx.clearRect(0, 0, 400, 400);
    if (video.currentTime < 1) {
        ctx.filter = "blur(5px)";
    } else {
        ctx.filter = "none";
    }
    ctx.drawImage(video, 0, 0, 400, 400);
    requestAnimationFrame(draw);
}

视频可以通过抓取视频中的每一帧来得到图片,引入到 Canvas 中。同样,可以在视频播放之后进行图片的获取。

js 复制代码
canvas1 = document.createElement('canvas');
document.body.append(canvas1);
canvas1.width = 200;
canvas1.height = 200;

const ctx = canvas1.getContext('2d');

//绘制同心圆
for (let i = 0; i < 5; i++) {
    ctx.beginPath();
    ctx.arc(100, 100, 20 * (i + 1), 0, Math.PI * 2);
    ctx.stroke();
}
js 复制代码
canvas2 = document.createElement('canvas');
document.body.append(canvas2);
canvas2.width = 400;
canvas2.height = 400;

const ctx = canvas2.getContext('2d');

ctx.beginPath();
ctx.drawImage(canvas1, 0, 0, 100, 100, 150, 150, 100, 100);

Canvas 可以作为图像源引入 Canvas ,类似于图像的引入。

js 复制代码
const btn = document.querySelectorAll('button')[0];
btn.onclick = function () {
    const url = canvas1.toDataURL();
    const a = document.createElement('a');
    a.href = url;
    a.download = 'canvas.png';
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
}

当我们想下载 Canvas 图像时,可以右键下载,和正常图片一样。也可以进行编程式下载。

由于浏览器限制用户访问本地文件资源,所以可以采取点击链接下载的方式来进行。首先创建一个 a 元素,将它的地址设置为 canvas 的 base64 格式。然后设置为下载模式,最后模拟元素点击,就可以下载了。toDataURL() 默认为 png 格式,可以通过传参改变格式。

js 复制代码
const img = new Image();
img.crossOrigin = 'anonymous';//允许跨域
img.src = 'exercises/imgs/01.png';
img.onload = function () {
    ctx.drawImage(img, 0, 0);
}

使用这种模式可能会出现同源问题。是由于浏览器只能使用本地文件资源或者本地服务器。如果使用其他路径资源,可能导致画布被污染。可以设置 crossOrigin ,然后使用本地服务器。

js 复制代码
const img = new Image();
img.src = '/girl.jpg';
img.onload = function () {
    ctx.drawImage(img, 50, 0, 300, 400);
    const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
    for (let i = 0; i < imageData.data.length; i += 4) {
        const r = imageData.data[i];
        const g = imageData.data[i + 1];
        const b = imageData.data[i + 2];
        const a = imageData.data[i + 3];
    }
    ctx.putImageData(imageData, 0, 0);
};

我们在引入一个图片之后可以拿到一个区域的像素对象。里面包含了像素宽度,高度和像素值的数组。因为一个像素包含四个通道,所以分成四份。

所有的像素并不是又分别形成一个数组,而是依次放到原数组中。所以只存在一个一维数组。我们可以得到某一个坐标的像素值。

要想操作每个像素,可以使用 for 循环,不过要每四个一组。ctx.getImageData(x , y , width , height)可以进行获取,然后进行设置。之后需要使用 ctx.putImageData(imageData,x,y) 才能正常应用设置的像素值变化。比如灰度,反差色等。

js 复制代码
const img = new Image();
img.src = 'exercises/imgs/03.png';
img.onload = function () {
    const pattern = ctx.createPattern(bgCanvas, 'repeat');
    const pattern2 = ctx.createPattern(img, '');
    ctx.strokeStyle = pattern;
    ctx.fillStyle = pattern2;
    ctx.lineWidth = 30;
    ctx.rect(15, 15, 330, 330);
    ctx.stroke();
    ctx.fill()
};

可以引入图像源来作为背景,和之前一样,可以是img,video,canvas等。可以选择进行填充或者描边。

先使用 ctx.createPattern(imgSource , repetition) 来创建一个图案对象,第二个参数必须填写,填 null 或者 '' 是默认横纵重复。然后将填充或描边后的对象赋值到相关样式中。

平铺样式时,是以画布为原点进行平铺。会出现某些区域显示不完全。

相关推荐
Hilaku6 分钟前
AVIF vs. JPEG XL:2025年,我们该为网站选择哪种下一代图片格式?
前端·javascript·html
nlp研究牲16 分钟前
latex中既控制列内容位置又控制列宽,使用>{\centering\arraybackslash}p{0.85cm}
服务器·前端·人工智能·算法·latex
前端拿破轮19 分钟前
HomeBrew创始人都写不出来的翻转二叉树到底怎么做?
前端·算法·typescript
长夜月26 分钟前
React 19 中的新特性
前端
星眠26 分钟前
学习低代码编辑器第三天
前端·面试
VillenK34 分钟前
vban2.0中table的使用
前端·vue.js
Dolphin_海豚37 分钟前
vapor 中的 ast 是如何被 transform 到 IR 的
前端·vue.js·源码
Jimmmmmmm1 小时前
pnpm如何避免幻影依赖:从node_modules演进史说起
前端
拾光拾趣录1 小时前
如何优雅地实现每 5 秒轮询请求?
前端·javascript
snowbitx1 小时前
Vue开发尝试一下
前端