最近作項目的時候,須要作一個截圖功能。用了一個別人寫的截圖工具,發現截出的圖質量降低了,可是咱們圖片要用來作識別, 須要保證截出的圖質量不降低。並且也不支持經過拖動來調整截圖框的大小。因此這個截圖工具沒法知足需求。由於因此,就本身動手寫了一個截圖組件。git
下面介紹一下實現原理和使用方法。github
組件wxml
的層次結構圖以下:json
original canvas
用來繪製原圖大小的圖片,這樣能保證截圖後的質量不會降低,這個canvas是隱藏的。movable-area
是movable-view
的容器,是官方提供的拖拽移動組件,用來移動截取框的四個角。這個組件支持多個點同時移動。scale canvas
用來繪製適應屏幕比例大小的圖片(aspectFit),由於一般原圖大小是超過屏幕長寬的。(一開始白線框和圖片都在這一層,但後來發現每次移動都要繪製一次圖片,這樣會形成卡頓、性能降低。因此就想到經過增長一個move canvas
來專門繪製白線框來下降繪製圖片帶來的資源消耗,由於圖片是靜止的,不須要重複繪製。)move canvas
是根據四個movable-view
的位置繪製出截圖框。最後截圖,經過四個點的位置計算出截圖框的位置,而後放大對應原圖大小的位置,獲得在原圖中的(x, y, width, height)
,最後經過官方提供的canvas
接口截圖。canvas
wx.canvasToTempFilePath({ x: x, y: y, width: w, height: h, destWidth: w, destHeight: h, canvasId: 'originalCanvas', success: function (res) { } )}
假設咱們的應用文件結構以下:app
./ ├── app.js ├── app.json ├── app.wxss ├── pages │ └── index │ ├── index.js │ ├── index.json │ ├── index.wxml │ └── index.wxss └── welCropper ├── welCropper.js ├── welCropper.wxml └── welCropper.wxss
調用組件時,須要傳入cropperData
、cropperMovableItems
、cropperChangableData
,由於數據和事件都是綁定在Page
上的,因此要避免使用組件裏面已經被佔用的命名。
/pages/index/index.wxmlxss
<!-- 引入組件 --> <import src="/welCropper/welCropper.wxml" /> <!-- 調用組件 --> <template is="welCropper" data="{{data:cropperData, cropperMovableItems:cropperMovableItems, cropperChangableData:cropperChangableData}}"></template> <!-- 用於選擇圖片,傳入cropper中 --> <button bindtap='selectTap'>select image</button>
/pages/index/index.jside
// 獲取顯示區域長寬 const device = wx.getSystemInfoSync() const W = device.windowWidth const H = device.windowHeight - 50 let cropper = require('../../welCropper/welCropper.js'); console.log(device) Page({ data: { }, onLoad: function () { var that = this // 初始化組件數據和綁定事件 cropper.init.apply(that, [W, H]); }, selectTap() { var that = this wx.chooseImage({ count: 1, // 默認9 sizeType: ['original', 'compressed'], // 能夠指定是原圖仍是壓縮圖,默認兩者都有 sourceType: ['album', 'camera'], // 能夠指定來源是相冊仍是相機,默認兩者都有 success(res) { const tempFilePath = res.tempFilePaths[0] console.log(tempFilePath) // 將選取圖片傳入cropper,並顯示cropper // mode=rectangle 返回圖片path // mode=quadrangle 返回4個點的座標,並不返回圖片。這個模式須要配合後臺使用,用於perspective correction let modes = ["rectangle", "quadrangle"] let mode = modes[0] //rectangle, quadrangle that.showCropper({ src: tempFilePath, mode: mode, sizeType: ['original', 'compressed'], //'original'(default) | 'compressed' callback: (res) => { if (mode == 'rectangle') { console.log("crop callback:" + res) wx.previewImage({ current: '', urls: [res] }) } else { wx.showModal({ title: '', content: JSON.stringify(res), }) console.log(res) } // that.hideCropper() //隱藏,我在項目裏是點擊完成就上傳,因此若是回調是上傳,那麼隱藏掉就好了,不用previewImage } }) } }) } })
最後引入組件的樣式
/pages/index/index.wxss工具
@import "/welCropper/welCropper.wxss";
wx.canvasToTempFilePath
輸出的是.png
圖片,截出來的圖有可能遠遠大於原圖(好比3通道圖變成4通道的圖)welCropper
文件夾複製到本身項目,引入調用就好了。
movable-view
顯示出來是這樣的: