最終生成的樣式
注釋已經打好,詳情看代碼
<template> <view class="canvas-box"> <!-- 導航欄 --> <view class="nav-box"> <view class="title-top" :style="'padding-top:' + statusBarHeight + 'rpx'"> <u-icon class="title-icon" name="arrow-left" color="#ffffff" size="36" @click="getBack"></u-icon> <text>海報分享</text> </view> </view> <!-- 開發完成之前,取消 fixed;opacity: 0;--> <canvas style="width: 346px;height: 500px;position: fixed;opacity: 0;" class="canvas" canvas-id="canvasID"></canvas> <!-- 完成海報制作后,需要把canvas移到看不見的地方,或者隱藏,把image顯示出來 --> <image :src="imgUrl" mode=""></image> <view class="footer"> <view class="download" @click="saveImage"> <!-- 小於符號圖標 --> <u-icon name="download" color="#ffffff" size="34"></u-icon> <text>保存到相冊</text> </view> </view> </view> </template> <script> export default { data() { return { imgUrl: '', statusBarHeight: 0, avatar: '../../../../static/images/default-chat-avatar.png', //頭像地址 hello: '../../../../static/images/share/weixin-hi.png', // hello圖標 mony: '../../../../static/images/share/mony.png' //圓的錢圖標 } }, created() { this.$tool.getSystemInfo().then(res => { this.statusBarHeight = res }) }, mounted() { let ctx = uni.createCanvasContext('canvasID', this); // ctx.setFillStyle("transparent"); //設置canvas背景顏色 // ctx.fillRect(0, 0, 346, 500) //設置canvas畫布大小 this.fillRoundRect(ctx, 0, 0, 346, 500, 15); //繪制一個圓角矩形 this.fillRoundRect(ctx, 0, 0, 346, 182, 15, '#333231'); //繪制一個圓角矩形 this.drawCircular(ctx, this.avatar, 36, 32, 50, 50) //繪制圓形頭像 ctx.setFontSize(18) ctx.setFillStyle("#ffffff") ctx.fillText('明天依然是晴天', 98, 65) ctx.drawImage(this.hello, 240, 10, 86, 86) //二維碼 ctx.font = '20px normal' ctx.setFillStyle("#09CFB1") ctx.fillText('我為“賢馬”帶鹽', 30, 122) ctx.font = '16px normal' ctx.setFillStyle("#ffffff") ctx.fillText('“閑么?上賢馬做兼職”', 20, 152) // 繪制職位標題,多余文字自動換行 ctx.setFontSize(28) ctx.setFillStyle("#333333") let str = '店鋪實習生ZAra重慶龍湖時代' // 字符串總長度 let _strLength = str.length // 總結截取次數 let _strNum = Math.ceil(_strLength / 9) // 每次開始截取字符串的索引 let _strHeight = 0 // 繪制的字體 x,y的初始位置 let _strX = 27, _strY = 223 let strIndex = 223 // 開始截取 for (let i = 0; i < _strNum; i++) { strIndex = _strY + i * 40 ctx.fillText(str.substr(_strHeight + i * 9, 9), _strX, _strY + i * 40) } strIndex += 30 ctx.setFontSize(14) ctx.setFillStyle("#1BB99A") let strtitle = '環境好/結算快/時間短' ctx.fillText(strtitle, _strX, strIndex) ctx.setFontSize(20) ctx.setFillStyle("#333231") ctx.fillText('16元/小時', _strX, 418) this.drawCircular(ctx, this.mony, _strX, 429, 14, 14) //繪制圓形頭像 ctx.setFontSize(12) ctx.setFillStyle("#F7BA65") ctx.fillText('已預付', _strX + 20, 440) // 繪制微信二維碼 ctx.drawImage(this.hello, 208, 370, 120, 120) //二維碼 ctx.draw(false, () => { // 返回canvas圖片信息 uni.canvasToTempFilePath({ canvasId: 'canvasID', success: (res) => { this.imgUrl = res.tempFilePath // console.log(res.tempFilePath) }, fail: function(err) { console.log(err) } }) }) }, methods: { getBack() { uni.navigateBack({ delta: 1 }); }, saveImage() { //點擊保存 var _this = this; uni.saveImageToPhotosAlbum({ filePath: _this.imgUrl, success() { uni.showModal({ title: "保存成功", content: "圖片已成功保存到相冊,快去分享到您的圈子吧", showCancel: false }) } }) }, // 將網絡圖片轉為臨時圖片地址 async getImageInfo({imgSrc}) { return new Promise((resolve, errs) => { uni.downloadFile({ src: imgSrc, success: function(image) { resolve(image); }, fail(err) { errs(err); } }); }); }, // 繪制圓形頭像 drawCircular(ctx, url, x, y, width, height) { //畫圓形頭像 var avatarurl_width = width; var avatarurl_heigth = height; var avatarurl_x = x; var avatarurl_y = y; ctx.save(); //先保存狀態,已便於畫完園再用 ctx.beginPath(); //開始繪制 ctx.arc(avatarurl_width / 2 + avatarurl_x, avatarurl_heigth / 2 + avatarurl_y, avatarurl_width / 2, 0, Math .PI * 2, false); ctx.setFillStyle("#FFFFFF") ctx.fill() //保證圖片無bug填充 ctx.clip(); //剪切 ctx.drawImage(url, avatarurl_x, avatarurl_y, avatarurl_width, avatarurl_heigth); //推進去圖片 ctx.restore(); }, // 繪制帶圓角的矩形方法 fillRoundRect(cxt, x, y, width, height, radius, fillColor) { //圓的直徑必然要小於矩形的寬高 if (2 * radius > width || 2 * radius > height) { return false; } cxt.save(); cxt.translate(x, y); //繪制圓角矩形的各個邊 this.drawRoundRectPath(cxt, width, height, radius); cxt.fillStyle = fillColor || '#fff'; //若是給定了值就用給定的值否則給予默認值 cxt.fill(); cxt.restore(); }, drawRoundRectPath(cxt, width, height, radius) { cxt.beginPath(0); //從右下角順時針繪制,弧度從0到1/2PI cxt.arc(width - radius, height - radius, radius, 0, Math.PI / 2); //矩形下邊線 cxt.lineTo(radius, height); //左下角圓弧,弧度從1/2PI到PI cxt.arc(radius, height - radius, radius, Math.PI / 2, Math.PI); //矩形左邊線 cxt.lineTo(0, radius); //左上角圓弧,弧度從PI到3/2PI cxt.arc(radius, radius, radius, Math.PI, (Math.PI * 3) / 2); //上邊線 cxt.lineTo(width - radius, 0); //右上角圓弧 cxt.arc(width - radius, radius, radius, (Math.PI * 3) / 2, Math.PI * 2); //右邊線 cxt.lineTo(width, height - radius); cxt.closePath(); } } } </script> <style lang="scss" scoped> .canvas-box { height: 100vh; display: flex; align-items: center; justify-content: center; background-color: #1ABC9C; /deep/.nav-box { width: 100%; padding: 0 20rpx; position: absolute; z-index: 9999; top: 0; left: 0; .title-top { font-size: 36rpx; font-weight: 550; color: #FFFFFF; display: flex; justify-content: center; align-items: center; position: relative; margin-bottom: 30rpx; .title-icon { position: absolute; left: 0; } } } image { width: 335px; height: 500px; } .footer { display: flex; align-items: center; justify-content: space-between; position: absolute; justify-content: center; padding: 0 40rpx; width: 100%; left: 0; bottom: 10%; .download { border: 1rpx solid #ffffff; color: #ffffff; display: flex; align-items: center; } view { padding: 0 20rpx; height: 78rpx; text-align: center; line-height: 78rpx; font-size: 30rpx; border-radius: 36rpx; } } } </style>