微信小程式之canvas畫布
阿新 • • 發佈:2021-02-11
一、前言
只要幹不死,就要往死幹!!!
本次帶來的是關於微信小程式之畫布的相關功能,具體詳見程式碼↓
二、圖例
功能點:顏色選擇、直線、矩形、圓形、畫筆、輸入框、線條寬度、還有特定圖示、橡皮擦 、撤銷、清空等功能
三、程式碼
本次提供展示js、wxml、wxss 程式碼示例
1、js篇
var app = getApp(); var ctx; //畫布 var startx; var starty; var movex; var movey; var stopx; var stopy; var tools = 'line'; // 預設選擇的工具 var canvasList = []; var guahua = '../../../../images/guahua.png'; var tuhen = '../../../../images/tuhen.png'; var aohen = '../../../../images/aohen.png'; var polie = '../../../../images/polie.png'; var tuoqi = '../../../../images/tuoqi.png'; var oldx = ''; var oldy = ''; var color = "#000000"; Page({ /** * 頁面的初始資料 */ data: { canvasWidth: '', canvasHeight: '336', lineWidth: 2, canvasList: [], isShowInput: 'true', //是否顯示輸入框 或者是否獲取焦點 inputTop: '', //input框顯示邊距 inputLeft: '', textInfo: '', value_input: '', isfocus: true, canvasbg: '', flag: "true", //遮罩層顯示 colorone: ['#FE0000', '#00FEFF', '#0000FE', '#01FF02'], colortwo: ['#FF00FE', '#FEFE00', '#000000', '#FFFFFF'], color: '#000000', car_imagelist: [], //車輛照片陣列 linshicarid: [], //臨時車輛ID car_order: '', editable: false, //編輯許可權 statusBarHeight: '', //狀態列高度 }, // 選擇顏色 select_colorone: function(e) { console.log(e); var p = e.currentTarget.dataset.p; this.setData({ color: this.data.colorone[p] }) }, select_colortwo: function(e) { console.log(e); var p = e.currentTarget.dataset.p; this.setData({ color: this.data.colortwo[p] }) }, color_cancle: function() { this.setData({ flag: "true" }) color = this.data.color; }, color_sure: function() { this.setData({ flag: "true", }) switch (tools) { case 'line': this.line(); break case 'box': this.box(); break case 'circle': this.circle(); break case 'pan': this.pan(); break } }, //繪圖動作函式監聽 // 開始 ringstart: function(e) { startx = e.changedTouches[0].x; starty = e.changedTouches[0].y; ctx.moveTo(startx, starty); // ctx.lineTo(startx, starty); console.log(startx, starty); if (tools == 'text') { this.setData({ isShowInput: '', inputTop: starty, inputLeft: startx, value_input: '', isfocus: true, }) console.log(this.data.isfocus); if (this.data.textInfo != "") { //繪製文字 ctx.setFontSize(14) ctx.fillText(this.data.textInfo, oldx, oldy); ctx.draw(true, this.saveCanvasImage()); } } }, // 繪製中 ringmove: function(e) { movex = e.changedTouches[0].x; movey = e.changedTouches[0].y; switch (tools) { case 'pan': ctx.lineTo(movex, movey); ctx.stroke(this.data.color); ctx.draw(true, this.saveCanvasImage()); ctx.moveTo(movex, movey); break case 'rubber': //橡皮擦 ctx.clearRect(movex - 8, movey - 8, 15, 15); ctx.draw(true, this.saveCanvasImage()); break } }, // 繪製結束 ringchend: function(e) { stopx = e.changedTouches[0].x; stopy = e.changedTouches[0].y; switch (tools) { case 'guahua': //刮花 this.drawImagestoCanvas(guahua); break case 'aohen': //凸痕 this.drawImagestoCanvas(aohen); break case 'tuhen': //凹痕 this.drawImagestoCanvas(tuhen); break case 'polie': //破裂 this.drawImagestoCanvas(polie); break case 'tuoqi': //脫漆 this.drawImagestoCanvas(tuoqi); break case 'rubber': //橡皮 break case 'line': //畫線 ctx.beginPath(); ctx.moveTo(startx, starty); ctx.lineTo(stopx, stopy); ctx.stroke(this.data.color); ctx.draw(true, this.saveCanvasImage()); break case 'box': //畫矩形 ctx.beginPath(); ctx.setStrokeStyle(this.data.color) ctx.strokeRect(startx, starty, stopx - startx, stopy - starty) ctx.draw(true, this.saveCanvasImage()); break case 'circle': //畫圓 ctx.beginPath(); ctx.arc(startx, starty, stopx - startx > stopy - starty ? stopx - startx : stopy - starty, 0, 2 * Math.PI); ctx.stroke(this.data.color); ctx.draw(true, this.saveCanvasImage()); break } }, // 畫圖工具函式監聽 // 右邊工具欄 guahua: function() { //刮花 tools = 'guahua'; this.hiddenInput(); }, tuhen: function() { //凸痕 tools = 'tuhen'; this.hiddenInput(); }, aohen: function() { //凹痕 tools = 'aohen'; this.hiddenInput(); }, polie: function() { //破裂 tools = 'polie'; this.hiddenInput(); }, tuoqi: function() { //脫漆 tools = 'tuoqi'; this.hiddenInput(); }, rubber: function() { //橡皮 tools = 'rubber'; this.hiddenInput(); }, back: function(e) { // 撤銷 this.hiddenInput(); // canvasList.pop(); canvasList.splice(canvasList.length - 1, 1); var image = canvasList.pop(); console.log(canvasList); ctx.drawImage(image, 0, 0, 383, 209); ctx.draw(false); }, cancle: function() { // 清空 this.hiddenInput(); ctx.restore(); ctx.draw(); this.drawImages(); //清空陣列集合 canvasList = []; }, // 繪製圖片到畫布中 {右側工具中 刮花 凸痕 凹痕 破裂 脫漆} drawImagestoCanvas: function(imgUrl) { ctx.drawImage(imgUrl, startx - 10, starty - 11, 22, 22); ctx.draw(true, this.saveCanvasImage()); }, //快取繪製圖片 saveCanvasImage: function() { this.setData({ textInfo: '' }) var than = this; wx.canvasToTempFilePath({ canvasId: 'ringcanvas', success: res => { console.log(res.tempFilePath); canvasList = canvasList.concat(canvasList.push(res.tempFilePath)); console.log('快取繪圖'); console.log(canvasList); }, fail: err => { } }) }, color: function() { //設定顏色 this.setData({ flag: '' }) }, line: function() { // 直線 tools = 'line'; this.hiddenInput(); }, box: function() { //矩形 tools = 'box'; this.hiddenInput(); }, circle: function() { //圓 tools = 'circle'; this.hiddenInput(); }, pan: function() { // 畫筆 tools = 'pan'; this.hiddenInput(); }, text: function() { //寫字 tools = 'text'; }, minus: function() { this.hiddenInput(); //畫筆粗細 減 if (this.data.lineWidth > 1) { this.setData({ lineWidth: this.data.lineWidth - 1 }) ctx.setLineWidth(this.data.lineWidth); } else { } }, add: function() { //畫筆粗細 加 this.hiddenInput(); this.setData({ lineWidth: this.data.lineWidth + 1 }) ctx.setLineWidth(this.data.lineWidth); }, hiddenInput: function() { this.setData({ isShowInput: true }) }, // 獲取輸入框的值 inputText: function(e) { var value = e.detail.value; if (value == "") { } else { this.setData({ textInfo: value }) // 儲存前一input位置的xy oldx = startx; oldy = starty; } console.log(e); }, /** * 生命週期函式--監聽頁面載入 */ onLoad: function(options) { // 設定導航欄標題 app.setNavigationtitle('環車檢查'); // 獲取螢幕資訊 wx.getSystemInfo({ success: (res) => { console.log(res) var statusBarHeight = res.statusBarHeight; //狀態列高度 this.setData({ canvasWidth: res.screenWidth - 38, statusBarHeight: statusBarHeight }) }, }) // 初始化畫布物件 ctx = wx.createCanvasContext('ringcanvas', this); }, drawImages: function() { //載入時就繪製背景圖片 var image = '../../../../images/ringcar_bg.png'; // ctx.drawImage(image, 0, 0, this.data.canvasWidth, 336); // ctx.draw(); var manager = wx.getFileSystemManager(); manager.readFile({ filePath: '../../../../images/ringcar_bg.png', // 選擇圖片返回的相對路徑 encoding: 'base64', // 編碼格式 success: res => { // 轉碼成功的回撥 console.log(res); var baseImg = 'data:image/png;base64,' + res.data; console.log(baseImg); // 後續的邏輯處理 } }) }, /** * 生命週期函式--監聽頁面初次渲染完成 */ onReady: function() { }, /** * 生命週期函式--監聽頁面顯示 */ onShow: function() { }, /** * 生命週期函式--監聽頁面隱藏 */ onHide: function() { }, // 網路請求函式 request: function(url, data, type) { //寫自己的邏輯函式 }, })
2、wxml篇
<view class="view_"> <view class="canvas_container" style="margin-left:{{statusBarHeight}}px"> <view> <image class="ringcar_checkcanvas" src="http://39.108.15.203:8000/AppSvc/Images/RecCheckBack01.png"></image> </view> <canvas disable-scroll="true" class="ringcar_checkcanvas" canvas-id="ringcanvas" bindtouchstart="{{editable ? 'ringstart' : ''}}" bindtouchmove="{{editable ? 'ringmove' : ''}}" bindtouchend="{{editable ? 'ringchend' : ''}}"> </canvas> <!-- 畫布右側功能鍵 --> <view class="ringcar_checkright_r"> <!-- 刮花 --> <view class="{{editable?'righttool_container':'editable'}}" bindtap="{{editable?'guahua':''}}" hover-class="select_color"> <icon class="iconfont iconcircle" style="color:#0608FB"></icon> <text>刮花</text> </view> <view class="{{editable?'righttool_container':'editable'}}" bindtap="{{editable?'tuhen':''}}" hover-class="select_color"> <icon class="iconfont icontriangle" style="color:#F20909"></icon> <text>凸痕</text> </view> <!-- 凹痕 --> <view class="{{editable?'righttool_container':'editable'}}" bindtap="{{editable?'aohen':''}}" hover-class="select_color"> <icon class="iconfont iconaohen" style="color:#F20909"></icon> <text>凹痕</text> </view> <!-- 破裂 --> <view class="{{editable?'righttool_container':'editable'}}" bindtap="{{editable?'polie':''}}" hover-class="select_color"> <icon class="iconfont iconerr" style="color:#F20909"></icon> <text>破裂</text> </view> <!-- 脫漆 --> <view class="{{editable?'righttool_container':'editable'}}" bindtap="{{editable?'tuoqi':''}}" hover-class="select_color"> <icon class="iconfont iconforbid" style="color:#0B8E1E"></icon> <text>脫漆</text> </view> <view class="{{editable?'righttool_container':'editable'}}" bindtap="{{editable?'rubber':''}}" hover-class="select_color"> <icon class="iconfont iconrubber"></icon> <text>橡皮</text> </view> <view class="{{editable?'righttool_container':'editable'}}" bindtap="{{editable?'back':''}}" hover-class="select_color"> <icon class="iconfont iconrevocation"></icon> <text>撤銷</text> </view> <view class="{{editable?'righttool_container':'editable'}}" bindtap="{{editable?'cancle':''}}" hover-class="select_color"> <icon class="iconfont icondelete"></icon> <text>清空</text> </view> </view> <!-- 畫布底部功能鍵 --> <view class="ringcar_checkbottom_t"> <view class="{{editable?'bottom_tool':'editable_tool'}}" bindtap="{{editable?'color':''}}" hover-class="select_color"> <view style="background:red;color:#ffffff">顏色</view> </view> <view class="{{editable?'bottom_tool':'editable_tool'}}" bindtap="{{editable?'line':''}}" hover-class="select_color"> <icon class="iconfont iconline"></icon> </view> <view class="{{editable?'bottom_tool':'editable_tool'}}" bindtap="{{editable?'box':''}}" hover-class="select_color"> <icon class="iconfont iconbox"></icon> </view> <view class="{{editable?'bottom_tool':'editable_tool'}}" bindtap="{{editable?'circle':''}}" hover-class="select_color"> <icon class="iconfont iconcircle"></icon> </view> <view class="{{editable?'bottom_tool':'editable_tool'}}" bindtap="{{editable?'pan':''}}" hover-class="select_color"> <icon class="iconfont iconpan"></icon> </view> <view class="{{editable?'bottom_tool':'editable_tool'}}" bindtap="{{editable?'text':''}}" hover-class="select_color"> <icon class="iconfont icontext"></icon> </view> <view class="{{editable?'bottom_tool':'editable_tool'}}"> <view style="background:#ffffff">線條:</view> </view> <view class="{{editable?'bottom_tool':'editable_tool'}}" bindtap="{{editable?'minus':''}}" hover-class="select_color"> <icon class="iconfont iconminus" style="color:#0076FF"></icon> </view> <view class="{{editable?'bottom_tool':'editable_tool'}}"> <view type="number" value="{{lineWidth}}" bindinput="{{editable?'line_width':''}}">{{lineWidth}}</view> </view> <view class="{{editable?'bottom_tool':'editable_tool'}}" bindtap="{{editable?'add':''}}" hover-class="select_color"> <icon class="iconfont iconadd" style="color:#0076FF"></icon> </view> </view> </view> </view> <!-- 畫布輸入框 --> <view> <input hidden="{{isShowInput}}" value="{{value_input}}" focus="{{isfocus}}" class="canvas_text" style="top:{{inputTop}}px;left:{{inputLeft}}px" bindinput="inputText"></input> </view> <!-- 顏色選擇框 --> <view class="zhezhao" hidden="{{flag}}"> <view class="zhezhaoview"> <view class="select"> <view>選擇顏色</view> <view style="background:{{color}}; width:40px;higth:40px;color: rgba(255, 255, 255, 0);">1</view> </view> <view class="colorview"> <view wx:for="{{colorone}}" bindtap="select_colorone" data-p="{{index}}" wx:key="index" class="color" style="background:{{item}}"></view> </view> <view class="colorview"> <view wx:for="{{colortwo}}" bindtap="select_colortwo" data-p="{{index}}" wx:key="index" class="color" style="background:{{item}}"></view> </view> <view class="more">更多</view> <view class="right"> <view bindtap="color_cancle">取消</view> <view bindtap="color_sure">設定</view> </view> </view> </view>
3、wxss篇
page { background: #f8f8f8; } .view_{ display: flex; flex-direction: row; margin-bottom: 40px; } .canvas_container{ width: 421px; height: 100%; float: left; } .ringcar_checkcanvas { width: 383px; height: 209px; position: absolute; } /* 右邊工具 */ .ringcar_checkright_r { margin-left: 383px; font-size: 10px; color: #888; float: left; width: 38px; height: 264px; display: flex; flex-direction: column; justify-content: space-around; align-items: center; } /* 右邊工具view */ .righttool_container { width: 38px; background: white; display: flex; height: 33px; flex-direction: column; justify-content: center; align-items: center; } icon{ font-size:8px; } .righttool_container text{ font-size:8px; } /* 畫布下面工具 */ .ringcar_checkbottom_t { width: 381px; position: absolute; margin-top: 209px; font-size: 12px; text-align: center; line-height: 53px; height: 53px; border: 1px #f8f8f8 solid; display: flex; flex-direction: row; justify-content: space-around; align-items: center; } .bottom_tool { width: 10%; background: white; } .ringcar_checkbottom_t input { background: white; width: 26px; height: 30px; color: rgba(136, 136, 136, 1); font-size: 14px; font-family: Arial; border: 1px solid rgba(187, 187, 187, 1); } .canvas_text { position: fixed; border: 1px #888 dashed; height: auto; width: 200px; } .right_container{ width: auto; height: 100%; float: left; } /* 底部item條目 */ .ringcar_checkbottom_list { /* margin-bottom: 50px; */ } .testitem { width: 100%; font-size: 12px; color: #888; margin-bottom: 1px; background: white; height: 30px; } .testitem view { float: left; line-height: 30px; margin-left: 4px; } .iconright{ float: right; } /* 選中顏色樣式 */ .select_color { background: #ddd; } /* 彈出遮罩層 */ .zhezhao { position: fixed; width: 100%; height: 100%; top: 0px; background: rgba(0, 0, 0, 0.4); overflow: hidden; } .zhezhaoview { margin: 10px; background: white; border-radius: 5px; height: 80%; width: (100% - 20px); justify-content: center; align-items: center; } .select { height: 30px; line-height: 30px; margin-bottom: 5px; display: flex; flex-direction: row; justify-content: space-around; align-items: center; padding-top: 2px; } .colorview { text-align: center; display: flex; height: 40px; flex-direction: row; align-items: center; justify-content: space-around; width: 100%; margin-top: 10px; } .more { border: 1px #ddd solid; width: 98%; text-align: center; font-size: 14px; height: 40px; margin-top: 10rpx; margin-left: 10rpx; line-height: 40px; } .color { float: left; border: 1px #ccc solid; height: 40px; width: 23%; } .right { color: red; margin-top: 20px; font-size: 12px; float: right; width: 50%; display: flex; flex-direction: row; justify-content: space-around; align-items: center; } .car_imagecontainer { float: left; position: relative; } .car_image { width: 60px; height: 60px; } #deleteerr { width: 12px; height: 12px; right: 2px; top: 2px; border: 1px black solid; font-size: 12px; color: red; position: absolute; } .add_image { float: left; text-align: center; font-size: 22px; width: 60px; height: 60px; } /* 許可權狀態樣式 底色*/ .editable { background: #f5f5f5; color: #aaa; width: 38px; background: white; display: flex; flex-direction: column; justify-content: center; align-items: center; } .editable_tool { width: 10%; background: #f5f5f5; color: #aaa; }
爾等勿噴!謝謝