Loading... ##### 一、在 components 中新建 canvasCom 文件夹并新建 canvasCom.vue 文件 ###### 1、写入 html 代码 ```html <template> <view class="wrap" :style="'width:' + width + 'px;height: ' + height + 'px;'"> <image class="img" :src="imageSrc"></image> <canvas class="canvas" canvas-id="myCanvas" id="myCanvas" :class="isPointerEvents ? 'pointerEvents' : 'noPointerEvents'" @longtap="longtap"></canvas> </view> </template> ``` ###### 2、写入 css 代码 ```scss .wrap { position: relative; .img, .canvas { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } .pointerEvents { pointer-events: all; } .noPointerEvents { pointer-events: none; } } ``` ###### 3、写入 js 代码 ```js export default { name: "canvasCom", props: { // 宽 --- 数值 width: { type: Number, default: 300 }, // 高 --- 数值 height: { type: Number, default: 300 }, // 元素 --- 数组对象 info: { type: Array, default: [] } }, data() { return { // 图片 imageSrc: '', // 是否可触摸 isPointerEvents: false, // 判断平台 type: uni.getSystemInfoSync(), }; }, mounted() { // 绘制 this.drawImage(); // 判断平台 if (this.type.uniPlatform == 'mp-weixin') { this.isPointerEvents = true; } else if (this.type.uniPlatform == 'web') { // 开启后 h5 可以使用系统长按功能 this.isPointerEvents = false; } }, methods: { // 绘制图片 async drawImage() { const ctx = uni.createCanvasContext('myCanvas', this); ctx.drawImage(await this.baseFun(this.info[0].src), this.info[0].x == 'center' ? await this.centerImg( this.width, this .info[0].width) : this.info[0].x, this.info[0].y, this.info[0].width, this.info[0].height); ctx.drawImage(await this.baseFun(this.info[1].src), this.info[1].x == 'center' ? await this.centerImg(this.width, this .info[1].width) : this.info[1].x, this.info[1].y, this.info[1].width, this.info[1].height); ctx.drawImage(await this.baseFun(this.info[4].src), this.info[4].x == 'center' ? await this.centerImg( this.width, this .info[4].width) : this.info[4].x, this.info[4].y, this.info[4].width, this.info[4].height); // 设置字体样式 ctx.font = this.info[2].font; // 设置文本颜色 ctx.fillStyle = this.info[2].fillStyle; // 绘制文本 let text = this.info[2].content; ctx.fillText(text, await this.centerText(text, ctx), 50); ctx.font = this.info[3].font; ctx.fillStyle = this.info[3].fillStyle; let text_ = this.info[3].content; ctx.fillText(text_, await this.centerText(text_, ctx), 100); ctx.draw(false, () => { uni.canvasToTempFilePath({ canvasId: 'myCanvas', success: (res) => { this.imageSrc = res.tempFilePath; }, fail: (err) => { console.error('Canvas to temp file path failed: ', err); } }, this); }); }, // 将图片转换为 base64 baseFun(url) { let isImg = /^https?:\/\//i; return new Promise((resolve, reject) => { if (isImg.test(url)) { // 网络图片 uni.request({ url: url, responseType: 'arraybuffer', success: (res) => { let base64Img = 'data:image/jpeg;base64,' + uni.arrayBufferToBase64(res .data); resolve(base64Img); }, fail: (err) => { reject(err); } }); } else { // 本地图片 resolve(url); } }) }, // 计算文字居中 centerText(str, ctx) { return new Promise((resolve, reject) => { const query = uni.createSelectorQuery().in(this); query.select('#myCanvas').boundingClientRect(data => { let textWidth = ctx.measureText(str).width; let width = data.width / 2 - textWidth / 2; if (width) { resolve(width); } else { reject('获取失败') } }).exec(); }) }, // 计算图片居中 centerImg(domWidth, imgWidth) { return new Promise((resolve, reject) => { let width = domWidth / 2 - imgWidth / 2; if (width) { resolve(width); } else { reject('获取失败') } }) }, // 长按事件 longtap() { console.log('长按'); if (this.type.uniPlatform == 'mp-weixin') { // 微信小程序长按保存 uni.saveImageToPhotosAlbum({ filePath: this.imageSrc, success: function() { console.log('save success'); } }); } }, } } ``` > 注:经过尝试,目前还没有更好的方案将 info 自动化绘制 ##### 二、父组件调用 ###### 1、html 代码 ```html <canvas-com :width="width" :height="height" :info="info"></canvas-com> ``` ###### 2、js 代码 ```js import canvasCom from '@/components/canvasCom/canvasCom.vue'; export default { data() { return { width: 300, height: 300, info: [{ type: 'img', src: '/static/logo.png', width: 300, height: 300, x: 0, // center --- 居中 其他值可以为数值 y: 0 }, { type: 'img', src: '/static/logo.png', width: 100, height: 100, x: 'center', // center --- 居中 其他值可以为数值 y: 100 }, { type: 'text', content: '主标题', font: 'bold 20px Arial', fillStyle: '#000000', x: 'center', // center --- 居中 其他值可以为数值 y: 50 }, { type: 'text', content: '副标题', font: 'bold 15px Arial', fillStyle: '#666666', x: 'center', // center --- 居中 其他值可以为数值 y: 100 }, { type: 'img', src: 'https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/logo.png', width: 161, height: 56, x: 'center', // center --- 居中 其他值可以为数值 y: 240 } ] }; }, components: { canvasCom }, } ``` ##### 三、效果展示 ![效果图][1] [1]: https://www.renlmingj.cn/usr/uploads/2024/05/2595403116.png 最后修改:2024 年 06 月 13 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 如果觉得我的文章对你有用,请随意赞赏