示例:
请求图片:
async function getImg(url) {
return new Promise((resolve, reject) => {
fetch(url)
.then(res => res.blob())
.then(res => {
var a = new FileReader();
a.readAsDataURL(res);
a.onload = function(ev) {
const img = new Image();
img.src = ev.target.result;
resolve([null, img]);
};
}).catch(e => {
reject([e]);
});
});
}
请求视频:
async function getVideoFrame(url) {
return new Promise((resolve, reject) => {
const video = document.createElement('video');
video.crossOrigin = '*';
video.src = url;
video.addEventListener('loadedmetadata', e => {
const canvas = document.createElement('canvas');
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
canvas.getContext('2d').drawImage(video, 0, 0, canvas.width, canvas.height);
const img = new Image();
img.src = canvas.toDataURL('image/png');
resolve([null, img]);
});
video.addEventListener('error', e => {
reject(['video load error']);
});
});
}
生成二维码:
async function getQr(txt, options) {
return new Promise((resolve, reject) => {
QRCode.toDataURL(txt, {
margin: 0,
width: options.width || 200,
// errorCorrectionLevel: 'H',
}, function(err, url) {
if (err) {
reject([err]);
} else {
const img = new Image();
img.src = url;
resolve([null, img]);
}
});
});
}
实现圆角矩形:
// radius 是一个数字或数组:
// 如果是一个数字,则4个角均是圆角
// 如果是一个数组,必须是一个[topLeft,topRight,bottomRight,bottomLeft]
function fillRoundRect(ctx, x, y, width, height, radius, /*optional*/ fillColor) {
//圆的直径必然要小于矩形的宽高
if (2 * radius > width || 2 * radius > height) {
return false;
}
ctx.save();
ctx.translate(x, y);
//绘制圆角矩形的各个边
drawRoundRectPath(ctx, width, height, radius);
ctx.fillStyle = fillColor || '#000'; //若是给定了值就用给定的值否则给予默认值
ctx.fill();
ctx.restore();
}
function drawRoundRectPath(ctx, width, height, radius) {
if (!isNaN(radius)) {
radius = [radius, radius, radius, radius];
}
ctx.beginPath(0);
//从右下角顺时针绘制,弧度从0到1/2PI
ctx.arc(width - radius[2], height - radius[2], radius[2], 0, Math.PI / 2);
//矩形下边线
ctx.lineTo(radius[2], height);
//左下角圆弧,弧度从1/2PI到PI
ctx.arc(radius[3], height - radius[3], radius[3], Math.PI / 2, Math.PI);
//矩形左边线
ctx.lineTo(0, radius[3]);
//左上角圆弧,弧度从PI到3/2PI
ctx.arc(radius[0], radius[0], radius[0], Math.PI, Math.PI * 3 / 2);
//上边线
ctx.lineTo(width - radius[0], 0);
//右上角圆弧
ctx.arc(width - radius[1], radius[1], radius[1], Math.PI * 3 / 2, Math.PI * 2);
//右边线
ctx.lineTo(width, height - radius[1]);
ctx.closePath();
}
文字自动换行:
/*
str:要绘制的字符串
canvas:canvas对象
initX:绘制字符串起始x坐标
initY:绘制字符串起始y坐标
lineHeight:字行高,自己定义个值即可
*/
function canvasTextAutoLine(str, ctx, initX, initY, maxWidth, lineHeight) {
var lineWidth = 0;
var lastSubStrIndex = 0;
for (let i = 0; i < str.length; i++) {
lineWidth += ctx.measureText(str[i]).width;
if (lineWidth > maxWidth) {
ctx.fillText(str.substring(lastSubStrIndex, i), initX, initY);
initY += lineHeight;
lineWidth = 0;
lastSubStrIndex = i;
}
if (i === str.length - 1) {
ctx.fillText(str.substring(lastSubStrIndex, i + 1), initX, initY);
}
}
}
垂直水平剧中自适应图片:
function drawImgInArea(img, ctx, area) {
const areaScale = area.width / area.height;
const imgScale = img.width / img.height;
let imgWidth = img.width;
let imgHeight = img.height;
if (areaScale > imgScale) {
// 竖图
imgHeight = area.height;
imgWidth = imgHeight * imgScale;
ctx.drawImage(img, area.x + (area.width - imgWidth) / 2, area.y, imgWidth, imgHeight);
} else {
imgWidth = area.width;
imgHeight = imgWidth / imgScale;
ctx.drawImage(img, area.x, area.y + (area.height - imgHeight) / 2, imgWidth, imgHeight);
}
}
图片滤镜:黑白照片
function darkImgFilter(img) {
return new Promise((resolve) => {
const canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
const ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0, img.width, img.height);
const imgData = ctx.getImageData(0, 0, img.width, img.height);
//我这个图片大小是235*235,这里指从(10,10)获取宽235高235的像素的data
const data = imgData.data;//每个像素的data是个数组(红,绿,蓝,透明度)
//遍历每个像素
for (var i = 0, len = data.length; i < len; i += 4) {
var black = (imgData.data[i] + imgData.data[i + 1] + imgData.data[i + 2]) / 3;
if (black >= 100) {
black = 255;
} else {
black = 0;
}
imgData.data[i] = black;
imgData.data[i + 1] = black;
imgData.data[i + 2] = black;
}
//在指定位置输出图片
ctx.putImageData(imgData, 0, 0);
const image = new Image();
image.src = canvas.toDataURL('image/png');
resolve([null, image]);
});
}
base64转blob,进行图片预览:
function base64ToBlobUrl(base64) {
var arr = base64.split(','), mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
const blob = new Blob([u8arr], { type: mime });
const blobUrl = URL.createObjectURL(blob);
return blobUrl;
}
下载图片
function downloadImg(url,name) {
const a = document.createElement('a');
a.style.display = 'none';
a.href = url;
a.download = name;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
}
作图:伪代码
const canvas = document.createElement('canvas');
canvas.width = 1080;
canvas.height = 1920;
const ctx = canvas.getContext('2d');
// 将图片画到canvas上。
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
// 圆角矩形
fillRoundRect(ctx, 0, 0, 100, 100, [10,10,10,10], '#fff');
// 二维码
ctx.drawImage(qrImg, 0, 0, 100, 100);
// 在指定范围内,自适应图片
drawImgInArea(img, ctx, {
x: 0,
y: 0,
width: 100,
height: 100,
});
// 绘制字体
ctx.font = '20px "Helvetica"';
ctx.fillStyle = '#333';
ctx.textBaseline = 'top';
canvasTextAutoLine(txt, ctx, 0, 0, 100, 20);
// 到处图片
const base = canvas.toDataURL('image/png', 0.4);
const blobUrl = base64ToBlobUrl(base);
downloadImg(blobUrl,'test.png');