<template> <view v-if="openState"> <!-- 品牌 --> <uni-popup ref="brandscenter" type="center" @change="change" :style="{height: MobilePhoneHeight +'px',width: MobilePhoneWidth +'px'}"> <view style="display: flex; flex-direction: column;"> <view :style="{height: MobilePhoneHeight +'px',width: MobilePhoneWidth +'px'}" style="border-radius: 30upx; position: relative; overflow: hidden;"> <view class="board-container"> <!-- 遮罩 --> <view class="board" :style="{width: data.editorWidth +'px',height: data.editorHeight +'px'}" :class="{'board-out':colorPanelShow}"> <canvas class="board-canvas" canvas-id="drawCanvas" disable-scroll="true" @touchstart="touchStart" @touchmove="touchMove" @touchend="touchEnd"></canvas> </view> <!-- 工具 --> <Toolbar :penColor="currentColor" @penWidthChange="penWidthChangeHandler" @toolItemTap="toolItemTapHandler" @colorPickTap="colorPickTapHandler" :toolArr="toolArr" style="position: fixed; bottom: 0; width: 100%; z-index: 101;"></Toolbar> </view> </view> </view> </uni-popup> </view> </template> <script> import Toolbar from '../../components/toolbar/toolbar.vue' import uniPopup from './common/uni-popup/uni-popup.vue'; import Env from '@/util/Env.js'; export default { components: { Toolbar, uniPopup }, onShareAppMessage(res) { return { title: '你绝对看不出我画的是什么?', path: '/pages/index/index' } }, data() { return { historylist: [], colorPanelShow: false, drawInfos: [], curDrawArr: [], startX: 0, startY: 0, drawContext: {}, currentColor: '#000', begin: false, bgColor: 'rgba(255, 255, 255, 0)', toolArr: [ // { // title: '清空', // icon: '../../static/png/tool_clear.png', // selectIcon: '../../static/png/tool_clear_s.png', // select: false, // url: 'clear' // }, { title: '撤销', icon: '../../static/png/tool_eraser.png', selectIcon: '../../static/png/tool_eraser.png', select: false, url: 'eraser' }, // { // title: '画笔', // icon: '../../static/png/tool_pen.png', // selectIcon: '../../static/png/tool_pen_s.png', // select: true, // url: 'pen' // }, // { // title: '颜色', // icon: '../../static/png/tool_color.png', // selectIcon: '../../static/png/tool_color_s.png', // select: false, // url: 'color' // }, { title: '确认', icon: '../../static/png/icon_confirm.png', selectIcon: '../../static/png/icon_confirm.png', select: false, url: 'save' } ], lineWidth: 6, penMode: true, rectMode: false, hollowRectMode: false, circleMode: false, hollowCircleMode: false, lastHollowRect: {}, lastHollowCircle: {}, MobilePhoneHeight: 0, MobilePhoneWidth: 0, pixelRate: 1, data: {}, openState: false, canvas_neto: [] } }, onLoad() { }, methods: { uploadDIY(tempFilePaths) { uni.showLoading({ title: '生成中...', mask: true }) var _this = this wx.request({ url: Env.getDevBaseURL() + '/api/AliossSign/getSign', method: 'GET', data: '', header: { 'content-type': 'application/x-www-form-urlencoded', 'Accept': 'application/json' }, success: function(res) { var atter = res.data let time = new Date().getTime() + Math.floor((Math.random() * 1000) + 1) wx.uploadFile({ url: atter.host.replace("http:", "https:"), filePath: tempFilePaths, name: 'file', formData: { 'key': atter.dir + time + '.png', 'OSSAccessKeyId': atter.accessid, 'policy': atter.policy, 'Signature': atter.signature, 'success_action_status': '200', 'callback': atter.callback, }, success: function(res) { if (res.statusCode != 200) { console.log({ errCode: '599', msg: '其他错误' }) return; } if (res.statusCode == 200) { uni.showToast({ title: '生成涂鸦成功', icon: 'none', duration: 3000 }) // console.log(atter.host + '/' + atter.dir + time + '.png') let url = atter.host + '/' + atter.dir + time + '.png' _this.$emit('tuyaimg', url) _this.$refs['brandscenter'].close() _this.openState = false } }, fail: function(err) { wx.showToast({ title: '生成涂鸦成功失败!', icon: 'none', duration: 1200 }) }, complete: function(err) { // console.log('总共' + successUp + '张上传成功,' + failUp + '张上传失败!'); } }) } }) }, change() {}, cancelBrand() { this.clearDrawBoard() this.$refs['brandscenter'].close() this.openState = false }, open(e) { this.canvas_neto = [] this.currentColor = '#000' this.lineWidth = 6 this.openState = true this.data = e.data //获取屏幕宽高 let that = this wx.getSystemInfo({ success: function(res) { that.MobilePhoneHeight = res.windowHeight // 屏幕高度 that.MobilePhoneWidth = res.windowWidth // 屏幕高度 that.pixelRate = res.windowWidth / 750; }, }) this.$nextTick(() => { this.$refs['brandscenter'].open() setTimeout(function() { this.drawContext = uni.createCanvasContext('drawCanvas', this); this.initBoard(); this.fillWelcomeBackground(this.drawContext); }.bind(this), 500) }) }, colorPickTapHandler(obj) { this.colorPanelShow = false; this.toolArr.forEach(item => { item.select = false; if (item.title === '画笔') { item.select = true; } }) this.rectMode = false; this.hollowRectMode = false; this.circleMode = false; this.hollowCircleMode = false; this.penMode = true; this.currentColor = obj.color; this.drawContext.strokeStyle = obj.color; }, penWidthChangeHandler(width) { this.lineWidth = width; this.drawContext.setLineWidth(width); this.drawContext.setLineCap('round') // 让线条圆润 }, toolItemTapHandler(index) { const that = this; let url = this.toolArr[index]['url']; switch (url) { case 'clear': this.clearDrawBoard(); break; case 'eraser': this.canvas_restore() // this.drawContext.strokeStyle = 'rgba(255, 255, 255, 0)'; this.colorPanelShow = false; break; case 'pen': this.drawContext.strokeStyle = this.currentColor; this.colorPanelShow = false; this.rectMode = false; this.hollowRectMode = false; this.circleMode = false; this.hollowCircleMode = false; this.penMode = true; break; case 'color': this.colorPanelShow = !this.colorPanelShow; // this.drawMode = this.colorPanelShow ? false : true; break; case 'save': if (that.canvas_neto.length < 1) { that.cancelBrand(); return false } uni.canvasToTempFilePath({ canvasId: 'drawCanvas', success: function(res) { // console.log('回调参数:' + JSON.stringify(res)) that.uploadDIY(res.tempFilePath); // console.log('回调参数:' + JSON.stringify(res)); // 在H5平台下,tempFilePath 为 base64 // uni.saveImageToPhotosAlbum({ // filePath: res.tempFilePath, // success: function(res) { // console.log('回调参数:' + JSON.stringify(res)) // // console.log('成功回调参数:' + JSON.stringify(res)); // // that.$api.msgSuccess('保存成功'); // }, // fail: function(res) { // console.log('回调参数:' + JSON.stringify(res)) // // console.log('失败回调参数:' + JSON.stringify(res)); // // that.$api.msgSuccess('保存成功'); // } // }); }, fail: function(res) { console.log('fail' + JSON.stringify(res)); } }, that) break; case 'close': this.cancelBrand(); break; // case 'hollowRect': // this.hollowRectMode = true; // this.rectMode = false; // this.circleMode = false; // this.hollowCircleMode = false; // this.penMode = false; // this.colorPanelShow = false; // this.drawContext.strokeStyle = this.currentColor; // // this.drawContext.restore(); // break; // case 'hollowCircle': // this.hollowRectMode = false; // this.rectMode = false; // this.circleMode = false; // this.hollowCircleMode = true; // this.penMode = false; // this.colorPanelShow = false; // this.drawContext.strokeStyle = this.currentColor; // break; // case 'rect': // this.hollowRectMode = false; // this.rectMode = true; // this.circleMode = false; // this.hollowCircleMode = false; // this.penMode = false; // this.colorPanelShow = false; // this.drawContext.strokeStyle = this.currentColor; // break; // case 'circle': // this.hollowRectMode = false; // this.rectMode = false; // this.circleMode = true; // this.hollowCircleMode = false; // this.penMode = false; // this.colorPanelShow = false; // this.drawContext.strokeStyle = this.currentColor; // break; default: break; } if (url === 'clear' || url === 'save' || url === 'share' || url === 'close' || url === 'eraser') { return; } this.toolArr.forEach((item, indexPath) => { item.select = false; if (indexPath === index) { item.select = true; } }) }, clearDrawBoard() { this.canvas_neto = [] this.initBoard(); this.fillBackground(this.drawContext); }, initBoard() { this.drawContext.setLineCap('round') // 让线条圆润 this.drawContext.strokeStyle = this.currentColor; this.drawContext.setLineWidth(this.lineWidth); }, touchStart(e) { this.initBoard(); if (this.penMode) { // console.log('我能够进行绘制--touchStart---x' + e.touches[0].x + '----y----' + e.touches[0].y); this.lineBegin(e.touches[0].x, e.touches[0].y) this.canvas_neto.push({ point_x: e.touches[0].x, point_y: e.touches[0].y, currentColor: this.currentColor, lineWidth: this.lineWidth, list: [], }) this.draw(true); } else if (this.rectMode) { // this.rectBegin(e.touches[0].x, e.touches[0].y) } else if (this.hollowRectMode) { // this.hollowRectBegin(e.touches[0].x, e.touches[0].y) } else if (this.hollowCircleMode) { // this.hollowCircleBegin(e.touches[0].x, e.touches[0].y) } else if (this.circleMode) { // this.circleBegin(e.touches[0].x, e.touches[0].y) } this.curDrawArr.push({ x: e.touches[0].x, y: e.touches[0].y }); }, touchMove(e) { if (this.begin) { if (this.penMode) { // console.log('我能够进行绘制--touchMove----x' + e.touches[0].x + '----y----' + e.touches[0].y); this.lineAddPoint(e.touches[0].x, e.touches[0].y); this.draw(true); this.canvas_neto[this.canvas_neto.length - 1].list.push({ x: e.touches[0].x, y: e.touches[0].y }) } else if (this.rectMode) { // this.drawRect(e.touches[0].x, e.touches[0].y, true); } else if (this.hollowRectMode) { // this.drawHollowRect(e.touches[0].x, e.touches[0].y, true); } else if (this.hollowCircleMode) { // this.drawHollowCircle(e.touches[0].x, e.touches[0].y, true); } else if (this.circleMode) { // this.drawCircle(e.touches[0].x, e.touches[0].y, true); } this.curDrawArr.push({ x: e.touches[0].x, y: e.touches[0].y }); } }, touchEnd(e) { // console.log('结束的坐标x:' + e.changedTouches[0].x + '结束的坐标y:' + e.changedTouches[0].y ); if (this.penMode) { // console.log('我能够进行绘制--touchEnd----x' + e.changedTouches[0].x + '----y----' + e.changedTouches[0].y); this.canvas_neto[this.canvas_neto.length - 1].list.push({ x: e.changedTouches[0].x, y: e.changedTouches[0].y }) this.curDrawArr = []; this.lineEnd(); } else if (this.rectMode) { // this.drawRect(e.changedTouches[0].x, e.changedTouches[0].y, true); } else if (this.hollowRectMode) { // this.drawHollowRect(e.changedTouches[0].x, e.changedTouches[0].y, true); } else if (this.hollowCircleMode) { // this.drawHollowCircle(e.changedTouches[0].x, e.changedTouches[0].y, true); } else if (this.circleMode) { // this.drawCircle(e.changedTouches[0].x, e.changedTouches[0].y, true); } }, hollowRectBegin(x, y) { this.begin = true; this.drawContext.beginPath() this.startX = x; this.startY = y; }, rectBegin(x, y) { this.begin = true; this.drawContext.beginPath() this.startX = x; this.startY = y; }, hollowCircleBegin(x, y) { this.begin = true; this.drawContext.beginPath() this.startX = x; this.startY = y; }, circleBegin(x, y) { this.begin = true; this.drawContext.beginPath() this.startX = x; this.startY = y; }, /** * 这里是画实体矩形 */ // drawRect(x, y, isReverse) { // let width = (x - this.startX) ? (x - this.startX) : (this.startX - x); // let height = (y - this.startY) ? (y - this.startY) : (this.startY - y); // this.drawContext.rect(this.startX, this.startY, width, height); // this.drawContext.setFillStyle(this.currentColor); // this.drawContext.fill(); // this.draw(isReverse); // }, /** * 这里是画空心矩形 * 方法是根据四个坐标点画 * 四条线进行连接 */ // drawHollowRect(x, y, isReverse) { // let pointLT = {}; // let pointRB = {}; // let pointRT = {}; // let pointLB = {}; // let center = {}; // pointLT.X = (this.startX <= x) ? this.startX : x; // pointLT.Y = (this.startY <= y) ? this.startY : y; // pointRB.X = (this.startX >= x) ? this.startX : x; // pointRB.Y = (this.startY >= y) ? this.startY : y; // pointRT.X = pointRB.X; // pointRT.Y = pointLT.Y; // pointLB.X = pointLT.X; // pointLB.Y = pointRB.Y; // let width = (x - this.startX) ? (x - this.startX) : (this.startX - x); // let height = (y - this.startY) ? (y - this.startY) : (this.startY - y); // this.drawContext.rect(this.startX, this.startY, width, height); // this.drawContext.setStrokeStyle(this.currentColor); // this.drawContext.stroke(); // this.draw(isReverse); // this.lastHollowRect = { // x: this.startX, // y: this.startY, // width: Math.abs(width), // height: Math.abs(height), // pointLT: pointLT // } // this.clearLastHollowRect(); // }, // clearLastHollowRect() { // console.log('上一个矩形对象:' + JSON.stringify(this.lastHollowRect)); // this.drawContext.clearRect(this.lastHollowRect.pointLT.X + this.lineWidth / 2, this.lastHollowRect.pointLT.Y + this // .lineWidth / 2, this.lastHollowRect.width - this.lineWidth, this.lastHollowRect.height - this.lineWidth); // }, // clearLastHollowCircle(x, y, r, cxt) { //(x,y)为要清除的圆的圆心,r为半径,cxt为context // var stepClear = 1; //别忘记这一步 // clearArc(x, y, r); // function clearArc(x, y, radius) { // var calcWidth = radius - stepClear; // var calcHeight = Math.sqrt(radius * radius - calcWidth * calcWidth); // var posX = x - calcWidth; // var posY = y - calcHeight; // var widthX = 2 * calcWidth; // var heightY = 2 * calcHeight; // if (stepClear <= radius) { // cxt.clearRect(posX, posY, widthX, heightY); // stepClear += 1; // clearArc(x, y, radius); // } // } // }, /** * 这里是画 * 实心圆 */ // drawCircle(x, y, isReverse) { // let pointLT = {}; // let pointRB = {}; // let pointRT = {}; // let pointLB = {}; // let center = {}; // pointLT.X = (this.startX <= x) ? this.startX : x; // pointLT.Y = (this.startY <= y) ? this.startY : y; // pointRB.X = (this.startX >= x) ? this.startX : x; // pointRB.Y = (this.startY >= y) ? this.startY : y; // pointRT.X = pointRB.X; // pointRT.Y = pointLT.Y; // pointLB.X = pointLT.X; // pointLB.Y = pointRB.Y; // center.X = (pointRB.X + pointLT.X) / 2; // center.Y = (pointRB.Y + pointLT.Y) / 2; // let dx = pointRB.X - pointLT.X; // let dy = pointRB.Y - pointLT.Y; // let r = Math.sqrt(dx * dx + dy * dy) / 2; // // console.log('圆心坐标:' + JSON.stringify(center)); // // console.log('半径:' + JSON.stringify(r)); // this.drawContext.arc(center.X, center.Y, r, 0, 2 * Math.PI); // this.drawContext.setFillStyle(this.currentColor); // this.drawContext.fill(); // // this.drawContext.stroke(); // this.draw(isReverse); // }, /** * 这里是画 * 空心圆 */ // drawHollowCircle(x, y, isReverse) { // let pointLT = {}; // let pointRB = {}; // let center = {}; // pointLT.X = (this.startX <= x) ? this.startX : x; // pointLT.Y = (this.startY <= y) ? this.startY : y; // pointRB.X = (this.startX >= x) ? this.startX : x; // pointRB.Y = (this.startY >= y) ? this.startY : y; // center.X = (pointRB.X + pointLT.X) / 2; // center.Y = (pointRB.Y + pointLT.Y) / 2; // let dx = pointRB.X - pointLT.X; // let dy = pointRB.Y - pointLT.Y; // let r = Math.sqrt(dx * dx + dy * dy) / 2; // // console.log('圆心坐标:' + JSON.stringify(center)); // // console.log('半径:' + JSON.stringify(r)); // this.drawContext.arc(center.X, center.Y, r, 0, 2 * Math.PI); // // this.drawContext.setFillStyle(this.currentColor); // // this.drawContext.fill(); // this.drawContext.stroke(); // this.drawContext.beginPath(); // this.drawContext.arc(center.X, center.Y, r - this.lineWidth / 2, 0, 2 * Math.PI); // this.drawContext.setFillStyle(this.bgColor); // this.drawContext.fill(); // this.draw(isReverse); // // this.clearLastHollowCircle(center.X, center.Y, r - this.lineWidth / 2, this.drawContext); // }, // 开始绘制线条 lineBegin: function(x, y) { this.begin = true; this.drawContext.beginPath() this.startX = x; this.startY = y; this.drawContext.moveTo(this.startX, this.startY) this.lineAddPoint(x, y); }, // 绘制线条中间添加点 lineAddPoint: function(x, y) { this.drawContext.moveTo(this.startX, this.startY) this.drawContext.lineTo(x, y); this.drawContext.stroke(); this.startX = x; this.startY = y; }, // 绘制线条结束 lineEnd: function() { this.drawContext.closePath(); this.begin = false; }, // canvas上下文设置背景为透明色 fillBackground: function(context) { const query = uni.createSelectorQuery().in(this); query.select('.board').boundingClientRect(data => { // console.log("得到布局位置信息" + JSON.stringify(data)); context.setFillStyle(this.bgColor); context.fillRect(0, 0, data.width, data.height); //TODO context的宽和高待定 context.fill(); context.draw(); }).exec(); }, // canvas上下文设置背景为透明色 fillWelcomeBackground: function(context) { const query = uni.createSelectorQuery().in(this); query.select('.board').boundingClientRect(data => { // console.log("得到布局位置信息" + JSON.stringify(data)); context.setFillStyle(this.bgColor); context.fillRect(0, 0, data.width, data.height); //TODO context的宽和高待定 context.fill(); let pikaqiuW = 318; let pikaqiuH = 288; let pikaqiuX = (data.width - 318) / 2; let pikaqiuY = 80; context.draw(); }).exec(); }, // 绘制canvas // isReverse: 是否保留之前的像素 draw(isReverse = false, cb) { this.drawContext.draw(isReverse, () => { if (cb && typeof(cb) == "function") { cb(); } }); }, // 撤销方法 canvas_restore(e) { // console.log(this.canvas_neto) var that = this var canvas_neto = that.canvas_neto if (canvas_neto.length < 1) { /* uni.showToast({ title: '不能再继续撤销了', icon: 'none' }); */ this.$refs['brandscenter'].close(); return false } this.drawContext.clearRect(0, 0, that.data.editorWidth, that.data.editorHeight) canvas_neto.splice(canvas_neto.length - 1, 1); for (let i = 0; i < canvas_neto.length; i++) { this.drawContext.beginPath() this.drawContext.moveTo(canvas_neto[i].point_x, canvas_neto[i].point_y) this.drawContext.setLineCap('round') // 让线条圆润 this.drawContext.strokeStyle = canvas_neto[i].currentColor; this.drawContext.setLineWidth(canvas_neto[i].lineWidth); for (let j = 0; j < canvas_neto[i].list.length; j++) { this.drawContext.lineTo(canvas_neto[i].list[j].x, canvas_neto[i].list[j].y) this.drawContext.stroke() } } this.drawContext.draw(); }, } } </script> <style lang="scss"> .board-container { height: 100%; width: 100%; .board { position: absolute; top: 0; left: 0; bottom: 0; right: 0; margin: auto; transform: translateY(0); display: block; z-index: 100; .board-canvas { width: 100%; height: 100%; z-index: 100; } } .board-out { transform: translateY(100%); display: none; } } </style>