
測重點主要頭像的圓角
wxml:
<view catchtouchmove="preventTouchMove" wx:if="{{canvas_haoBao}}"> <view class='warp_' style="overflow-y: scroll;"> <view style='' style='position: absolute;z-index: 2;webkit-transform: translate(-50%,-50%);transform: translate(-50%,-50%);top: 50%;left: 50%;'> <canvas canvas-id="myCanvass" style="width:750rpx;height:1100rpx;" /> <view style='padding-bottom: 0;box-sizing: border-box;width:100%'> <!-- <view class='note'>已保存到相冊,快去分享給好友吧</view> --> <view bindtap='saveImg' class='btn'>保存到手機相冊</view> </view> <view class='canvas_close_' catchtap='isShowHaoBao' style="position: absolute;top: -30rpx;right: 30rpx;">×</view> </view> <view class='pop_bg_fix'></view> </view> </view>
wxss:
.warp_ .btn{width: 68%;height: 88rpx;line-height: 88rpx;font-size: 28rpx;border-radius: 90rpx;background: #e8474d;text-align: center;color: #fff;margin: auto;} .warp_ image{border-radius: 0 !important;} .warp_ .note{text-align: center;color: #fff;margin-bottom: 28rpx;font-size: 28rpx;margin-top: 60rpx;} .pop_bg_fix{position: fixed;top: 0;left: 0;width: 100vw;height: 100vh;background: rgba(0, 0, 0, .6);} .warp_{width: 100vw;height: 100vh;box-sizing: border-box;line-height: 1.5;position: fixed;top: 0;left: 0;z-index: 9999991;} .canvas_close_{margin: 30rpx auto 0;width: 50rpx;height: 50rpx;background: #999;text-align: center;line-height: 50rpx;font-size: 50rpx;color: #fff;border-radius: 50%;} image{width: 100%;height: 100%;}
wxjs:
Page({ onLoad: function (options) { this.canvasImg() }, canvasImgs() { let that = this; var res = wx.getSystemInfoSync() var rpx = res.windowWidth / 375 console.log(rpx) that.setData({ rpx: res.windowWidth / 375 }) const ctx = wx.createCanvasContext('myCanvass'); //ctx.setFillStyle('#5c8ef3'); //為創建的canvans上下文添充顏色 如果沒有設置 fillStyle,默認顏色為 black。 // ctx.fillRect(0, 10 * rpx, 750 * rpx, 600 * rpx) // ctx.drawImage(this.data.img, 0 * rpx, 0 * rpx, 266 * rpx, 133 * rpx); ctx.save(); // 先保存狀態 已便於畫完圓再用 // 制作圓角矩形 // this.roundRect(ctx, 10 * rpx, 20 * rpx, 355 * rpx, 540 * rpx, 10 * rpx); // this.roundRect(ctx, 10 * rpx, 500 * rpx, 355 * rpx, 10 * rpx, 20 * rpx); // ctx.drawImage(this.data.img, 0 * rpx, 130 * rpx, 266 * rpx, 130 * rpx); //二維碼 ctx.drawImage("/image/gonglue_pic5.png", 55 * rpx, 40 * rpx, 260 * rpx, 420 * rpx); //底部 this.roundRect(ctx, 55 * rpx, 460 * rpx, 260 * rpx, 60 * rpx, 0 * rpx); //圓角圖片代碼開始 var avatarurl_width = 45 * rpx; //繪制的頭像寬度 var avatarurl_heigth = 45 * rpx; //繪制的頭像高度 var avatarurl_x = 65 * rpx; //繪制的頭像在畫布上的位置 var avatarurl_y = 466 * rpx; //繪制的頭像在畫布上的位置 ctx.save(); ctx.beginPath(); //開始繪制 //先畫個圓 前兩個參數確定了圓心 (x,y) 坐標 第三個參數是圓的半徑 四參數是繪圖方向 默認是false,即順時針 ctx.arc(avatarurl_width / 2 + avatarurl_x, avatarurl_heigth / 2 + avatarurl_y, avatarurl_width / 2, 0, Math.PI * 2, false); ctx.clip();//畫好了圓 剪切 原始畫布中剪切任意形狀和尺寸。一旦剪切了某個區域,則所有之后的繪圖都會被限制在被剪切的區域內 這也是我們要save上下文的原因 ctx.drawImage('/image/gonglue_pic5.png', avatarurl_x, avatarurl_y, avatarurl_width, avatarurl_heigth); // 推進去圖片,必須是https圖片 ctx.restore(); //恢復之前保存的繪圖上下文 恢復之前保存的繪圖上下午即狀態 還可以繼續繪制 ctx.draw(); //可將之前在繪圖上下文中的描述(路徑、變形、樣式)畫到 canvas 中 ctx.setFillStyle("#333"); ctx.setFontSize(10 * rpx); //字大小 ctx.setTextAlign('left'); //是否居中顯示,參考點畫布中線 ctx.fillText('小橋流水', 120 * rpx, 480 * rpx); ctx.setFillStyle("#999"); ctx.setFontSize(10 * rpx); //字大小 ctx.setTextAlign('left'); //是否居中顯示,參考點畫布中線 ctx.fillText('邀您一起加入芬香', 120 * rpx, 495 * rpx); ctx.setFillStyle("#999"); ctx.setFontSize(10 * rpx); //字大小 ctx.setTextAlign('left'); //是否居中顯示,參考點畫布中線 ctx.fillText('分享東京優惠好貨', 120 * rpx, 508 * rpx); ctx.drawImage("/image/ma.png", 245 * rpx, 440 * rpx, 60 * rpx, 60 * rpx) ctx.setFillStyle("#999"); ctx.setFontSize(10 * rpx); //字大小 ctx.setTextAlign('left'); //是否居中顯示,參考點畫布中線 ctx.fillText('長安識別', 255 * rpx, 510 * rpx); that.setData({ canvas_hidden: false }) ctx.draw(true, function () { setTimeout(function () { wx.hideLoading() // that.setData({ // canvas_hidden: false // }) }, 1000) }); setTimeout(function () { // that.saveImg() }, 1100) // ctx.draw(); }, // 多行文本 dealWords: function (options) { options.ctx.setFontSize(options.fontSize); //設置字體大小 var allRow = Math.ceil(options.ctx.measureText(options.word).width / options.maxWidth); //實際總共能分多少行 var count = allRow >= options.maxLine ? options.maxLine : allRow; //實際能分多少行與設置的最大顯示行數比,誰小就用誰做循環次數 var endPos = 0; //當前字符串的截斷點 for (var j = 0; j < count; j++) { var nowStr = options.word.slice(endPos); //當前剩余的字符串 var rowWid = 0; //每一行當前寬度 if (options.ctx.measureText(nowStr).width > options.maxWidth) { //如果當前的字符串寬度大於最大寬度,然后開始截取 for (var m = 0; m < nowStr.length; m++) { rowWid += options.ctx.measureText(nowStr[m]).width; //當前字符串總寬度 if (rowWid > options.maxWidth) { if (j === options.maxLine - 1) { //如果是最后一行 options.ctx.fillText(nowStr.slice(0, m - 1) + '...', options.x, options.y + (j + 1) * 18); //(j+1)*18這是每一行的高度 } else { options.ctx.fillText(nowStr.slice(0, m), options.x, options.y + (j + 1) * 18); } endPos += m; //下次截斷點 break; } } } else { //如果當前的字符串寬度小於最大寬度就直接輸出 options.ctx.fillText(nowStr.slice(0), options.x, options.y + (j + 1) * 18); } } }, /** * 制作圓角 * @param {CanvasContext} ctx canvas上下文 * @param {number} x 圓角矩形選區的左上角 x坐標 * @param {number} y 圓角矩形選區的左上角 y坐標 * @param {number} w 圓角矩形選區的寬度 * @param {number} h 圓角矩形選區的高度 * @param {number} r 圓角的半徑 */ roundRect(ctx, x, y, w, h, r) { ctx.save(); // 開始繪制 ctx.beginPath() // 因為邊緣描邊存在鋸齒,最好指定使用 transparent 填充 // 這里是使用 fill 還是 stroke都可以,二選一即可 ctx.setFillStyle('#fff') // ctx.setStrokeStyle('red') // 左上角 ctx.arc(x + r, y + r, r, Math.PI, Math.PI * 1.5) // border-top ctx.moveTo(x + r, y) ctx.lineTo(x + w - r, y) ctx.lineTo(x + w, y + r) // 右上角 ctx.arc(x + w - r, y + r, r, Math.PI * 1.5, Math.PI * 2) // border-right ctx.lineTo(x + w, y + h - r) ctx.lineTo(x + w - r, y + h) // 右下角 ctx.arc(x + w - r, y + h - r, r, 0, Math.PI * 0.5) // border-bottom ctx.lineTo(x + r, y + h) ctx.lineTo(x, y + h - r) // 左下角 ctx.arc(x + r, y + h - r, r, Math.PI * 0.5, Math.PI) // border-left ctx.lineTo(x, y + r) ctx.lineTo(x + r, y) // 這里是使用 fill 還是 stroke都可以,二選一即可,但是需要與上面對應 ctx.fill() // ctx.stroke() ctx.closePath() // 剪切 ctx.clip() ctx.restore(); }, saveImg() { let that = this; var res = wx.getSystemInfoSync() var rpx = res.windowWidth / 375 that.setData({ rpx: res.windowWidth / 375 }) wx.canvasToTempFilePath({ x: 0, y: 0, width: 375 * rpx, //畫布寬高 height: 1000 * rpx, destWidth: 750 * rpx, //畫布寬高*dpr 以iphone6為准 destHeight: 2000 * rpx, //放大2倍以上,解決保存的圖片模糊的問題 canvasId: 'myCanvass', success: function (res) { //console.log(res.tempFilePath) //生成的臨時圖片路徑 wx.saveImageToPhotosAlbum({ filePath: res.tempFilePath, success: function (res) { App.util._toast("您的分享海報已存入手機相冊,趕快去分享給好友吧!") }, fail: function (err) { //console.log(err) if (err.errMsg === "saveImageToPhotosAlbum:fail:auth denied" || err.errMsg === "saveImageToPhotosAlbum:fail auth deny" || err.errMsg === "saveImageToPhotosAlbum:fail authorize no response") { // 這邊微信做過調整,必須要在按鈕中觸發,因此需要在彈框回調中進行調用 wx.showModal({ title: '提示', content: '需要您授權保存相冊', showCancel: false, success: modalSuccess => { wx.openSetting({ success(settingdata) { // console.log("settingdata", settingdata) if (settingdata.authSetting['scope.writePhotosAlbum']) { wx.showModal({ title: '提示', content: '授權成功,請重新生成海報', showCancel: false, }) } else { wx.showModal({ title: '提示', content: '獲取權限失敗,將無法保存到相冊哦~', showCancel: false, }) } }, fail(failData) { //console.log("failData", failData) }, complete(finishData) { // console.log("finishData", finishData) } }) } }) } } }) } }) }, })