喜欢还请收藏点个小心心
WEB版的
<canvas type="2d" id="canvas"></canvas>
// 绘画数据
const params = [
// 文字
{ type: "text", text: "这里是文字", left: 100, top: 20, width: 100, textAlign: 'center' },
// 图片
{ type: "img", url: "https://img.alicdn.com/tfs/TB1GvVMj2BNTKJjy0FdXXcPpVXa-520-280.jpg", left: 0, top: 40, width: 500, height: 280, },
// 圆形图片 radius 为 true
{ type: "img", url: "https://img.alicdn.com/tfs/TB1GvVMj2BNTKJjy0FdXXcPpVXa-520-280.jpg", radius: true, left: 0, top: 340, width: 150, height: 150, },
// 圆角图片 radius 为数字
{ type: "img", url: "https://img.alicdn.com/tfs/TB1GvVMj2BNTKJjy0FdXXcPpVXa-520-280.jpg", radius: 10, left: 270, top: 340, width: 150, height: 150, },
]
// 画布参数
const option = { dom: "#canvas", params, width: 500, height: 500, dpr: 1 };
// 解析参数
async function parseParams(ctx, params) {
let data = [];
for (let item of params) {
let { type, url } = item;
let obj = { ...item };
if (type == 'img') {
// 图片是url地址,需要先下载图片
obj.img = await downloadImage(obj);
drawImage(ctx, obj);
}
if (type === 'text') drawText(ctx, obj)
}
return data;
}
// 下载图片
async function downloadImage(item) {
return new Promise((resolve, reject) => {
if (!item.url) return;
// 把图片数据resolve回去,这里是需要做同步处理的。
const img = new Image();
img.onload = () => resolve(img)
img.src = item.url;
})
}
// 绘制文本数据
function drawText(ctx, item) {
ctx.save();
let { text, width, height, left, top, color = "#444", textAlign, font = '20px' } = item;
// 设置文本颜色
ctx.fillstyle = color;
// 设置文本大小
ctx.font = font;
// 设置水平对齐方式
ctx.textAlign = textAlign || "center";
// 设置垂直对齐方式
ctx.textBaseline = "middle";
ctx.fillText(text, left, top);
}
// 绘制图片
function drawImage(ctx, item) {
ctx.save()
let { img, width, height, left, top, radius } = item;
if (radius === true) {
ctx.beginPath()
ctx.arc(width / 2 + left, height / 2 + top, width / 2, 0, Math.PI * 2, false);
ctx.clip();
} else if (typeof radius === 'number') {
// 处理圆角
let a = { x: left + radius, y: top };
let b = { x: left + width, y: top };
let c = { x: left + width, y: top + height };
let d = { x: left, y: top + height };
let e = { x: left, y: top };
ctx.beginPath();
ctx.moveTo(a.x, a.y);
ctx.arcTo(b.x, b.y, c.x, c.y, radius);
ctx.arcTo(c.x, c.y, d.x, d.y, radius);
ctx.arcTo(d.x, d.y, e.x, e.y, radius);
ctx.arcTo(e.x, e.y, a.x, a.y, radius);
ctx.clip();
}
ctx.drawImage(img, left, top, width, height);
ctx.restore()
}
// 初始化
async function onInitCanvas(obj) {
let ctx = null;
let { dom, params, width = 500, height = 200, dpr = 1 } = obj;
if (!ctx) {
let canvas = document.querySelector('#canvas');
canvas.width = width * dpr;
canvas.height = height * dpr;
canvas.style.width = width + 'px';
canvas.style.height = height + 'px';
ctx = canvas.getContext("2d");
}
// 解析数据
if (Array.isArray(params) && params.length) await parseParams(ctx, params);
}
onInitCanvas(option)
支付宝小程序canvas生成海报
<canvas type="2d" id="canvas" style="{{style}}" width="{{width}}" height="{{height}}"></canvas>
Component({
mixins: [],
data: {
style: {},
width: '',
height: '',
dpr: 1,
option: { dom: '#canvas', width: 750, height: 800, },
params: [
// 文字
{ type: "text", text: "这里是文字", left: 100, top: 20, width: 100, textAlign: 'center', color: '#ffffff' },
// 图片
{ type: "img", url: "https://img.alicdn.com/tfs/TB1GvVMj2BNTKJjy0FdXXcPpVXa-520-280.jpg", left: 0, top: 40, width: 375, height: 280, },
// 圆形图片 radius 为 true
{ type: "img", url: "https://img.alicdn.com/tfs/TB1GvVMj2BNTKJjy0FdXXcPpVXa-520-280.jpg", radius: true, left: 0, top: 340, width: 50, height: 50, },
// 圆角图片 radius 为数字
{ type: "img", url: "https://img.alicdn.com/tfs/TB1GvVMj2BNTKJjy0FdXXcPpVXa-520-280.jpg", radius: 10, left: 150, top: 340, width: 150, height: 150, },
]
},
props: {},
didMount() {
let dpr = my.getSystemInfoSync().pixelRatio;
let { width = 500, height = 200, } = this.data.option;
this.setData({
width: width + 'px',
height: height + 'px',
dpr,
style: {
width: width + 'px', height: height + 'px'
}
});
this.onInitCanvas()
},
didUpdate() { },
didUnmount() { },
methods: {
// 解析参数
async parseParams(ctx, params, canvas) {
let data = [];
for (let item of params) {
let { type, url } = item;
let obj = { ...item };
if (type == 'img') {
// 图片是url地址,需要先下载图片
obj.img = await this.downloadImage(obj, canvas);
}
data.push(obj)
}
let timer = setTimeout(() => {
clearTimeout(timer)
this.asyncDraw(ctx, data);
}, 500)
},
async asyncDraw(ctx, params) {
params.forEach(e => {
if (e.type === 'text') this.drawText(ctx, e);
if (e.type === 'img') this.drawImage(ctx, e);
})
},
// 下载图片
async downloadImage(item, canvas) {
return new Promise((resolve, reject) => {
if (!item.url) return;
// 把图片数据resolve回去,这里是需要做同步处理的。
const img = canvas.createImage();
img.onload = () => resolve(img)
img.src = item.url;
})
},
// 绘制文本数据
drawText(ctx, item) {
ctx.save();
let { text, width, height, left, top, color = "#444", textAlign, font = '22px' } = item;
console.log(font);
// 设置文本颜色
ctx.fillStyle = color
// 设置文本大小
ctx.font = font + ' Arial';
// 设置水平对齐方式
ctx.textAlign = textAlign || "center";
// 设置垂直对齐方式
ctx.textBaseline = "middle";
ctx.fillText(text, left, top);
},
// 绘制图片
drawImage(ctx, item) {
ctx.save();
let { dpr } = this.data;
let { img, width, height, left, top, radius } = item;
if (radius === true) {
ctx.beginPath()
ctx.arc(width / 2 + left, height / 2 + top, width / 2, 0, Math.PI * 2, false);
ctx.clip();
} else if (typeof radius === 'number') {
// 处理圆角
let a = { x: left + radius, y: top };
let b = { x: left + width, y: top };
let c = { x: left + width, y: top + height };
let d = { x: left, y: top + height };
let e = { x: left, y: top };
ctx.beginPath();
ctx.moveTo(a.x, a.y);
ctx.arcTo(b.x, b.y, c.x, c.y, radius);
ctx.arcTo(c.x, c.y, d.x, d.y, radius);
ctx.arcTo(d.x, d.y, e.x, e.y, radius);
ctx.arcTo(e.x, e.y, a.x, a.y, radius);
ctx.clip();
}
ctx.drawImage(img, left, top, width, height);
ctx.restore()
},
// 初始化
async onInitCanvas() {
let { option, params } = this.data;
let { dom = "#canvas" } = option;
const query = my.createSelectorQuery();
query.select(dom).node().exec(res => {
const canvas = res[0].node;
let ctx = canvas.getContext("2d");
this.parseParams(ctx, params, canvas);
})
}
},
});
网友评论