由於需求須要對圖片進行操做,放大,位移,旋轉等
思路也是參考別的博客
這個寫的比較全
https://blog.csdn.net/king096...
我看的第一篇是這個
https://www.jb51.net/article/...css
實現思路
1 在一個區域裏繪製圖片,
2 記錄全部圖片的座標,旋轉角度,尺寸,中心點,縮放比例
3 建立cavnas畫布,白底色,而後根據記錄的圖片的一些狀態繪製
4 根據canvas生產出圖片canvas
先上效果
藍框爲拖拽區域
紅框爲cavnas繪製部分
貼代碼
wxml
canvas標籤正常狀況下應該是隱藏或者讓他定位到十萬八千里外
由於須要展現效果,因此就沒有隱藏,實際上線能夠本身隱藏掉app
<view class="container"> <button class="mini-btn" bindtap="generate" type="primary" size="mini">生成圖片</button> <block wx:for="{{materialList}}" wx:key="index"> <image class="img-list" bindtap="addImg" data-index="{{index}}" mode="aspectFit" src="{{item.image}}"></image> </block> {{itemList.length}} <view class="img-box" id="img-box"> <!-- *************操做區域************* --> <block wx:for="{{itemList}}" wx:key="index"> <!-- 圓心座標 <text style='position:absolute;top:{{item.y}}px;left:{{item.x}}px;width:2px;height:2px;background-color:yellow;z-index:500'></text> --> <!-- {{item.scale}}---{{item.r}} --> <view class='touchWrap' style='transform: scale({{item.scale}});top:{{item.top}}px;left:{{item.left}}px; '> <view class='imgWrap {{item.active? "touchActive":""}}' style="transform: rotate({{item.angle}}deg);"> <view> <image style="width:{{item.height}}px; height:{{item.width}}px" class="item-img" src='{{item.image}}' bindload='loadImg' data-index="{{index}}" data-id='{{item.id}}' bindtouchstart='wraptouchStart' bindtouchmove='WraptouchMove'></image> </view> <!-- <image src='{{item.image}}' bindload='loadImg' bindtouchend='WraptouchEnd'></image> --> <image class='x' hidden="{{!item.active}}" bindtap="hiddenImg" data-index="{{index}}" src='../../assets/img/wqy-close.png' style='transform: scale({{item.oScale}});transform-origin:center;' data-id='{{item.id}}'></image> <image class='o' hidden="{{!item.active}}" data-index="{{index}}" src='../../assets/img/wqy-stretch.png' style='transform: scale({{item.oScale}});transform-origin:center;' data-id='{{item.id}}' bindtouchstart='touchStart' bindtouchmove='touchMove'> </image> </view> </view> </block> </view> <canvas class='maskCanvas' canvas-id="maskCanvas" style='width:{{canvasWidth}}px; height:{{canvasHeight}}px;'></canvas> </view>
js部分測試
/* * @Description: * @Author: 冷山冷杉 <wqy.mail@foxmail.com> * @Date: 2020-06-04 11:58:14 * @LastEditTime: 2020-06-05 16:14:51 * @LastEditors: 冷山冷杉 <wqy.mail@foxmail.com> * @FilePath: \mini-fullalumni\pages\photoTest\photoTest.js */ const app = getApp() const maskCanvas = wx.createCanvasContext('maskCanvas', this) let items = [] Page({ data: { itemList: [ ], materialList: [ { id: null, image: 'https://img3.doubanio.com/view/subject/m/public/s9074663.jpg',//圖片地址 top: 0,//初始圖片的位置 left: 0, x: 0, //初始圓心位置,可再downImg以後又寬高和初始的圖片位置得出 y: 0, scale: 1,//縮放比例 1爲不縮放 angle: 0,//旋轉角度 active: true //斷定點擊狀態 }, { id: null, image: 'https://img9.doubanio.com/view/subject/m/public/s3893375.jpg', top: 0, left: 0, x: 0, y: 0, scale: 1, angle: 0, active: false } ], canvasWidth: null, canvasHeight: null }, onReady() { const query = wx.createSelectorQuery() query.select('#img-box').boundingClientRect() query.selectViewport().scrollOffset() query.exec((res) => { this.setData({ canvasWidth: res[0].width, canvasHeight: res[0].height }) }) // wx.getSystemInfo({ // 獲取系統信息 // success: sysData => { // this.sysData = sysData // // 設置畫布寬高,this.sysData.windowWidth爲屏幕的寬度 // this.setData({ // canvasWidth: this.sysData.windowWidth, // 若是以爲不清晰的話,能夠把全部組件、寬高放大一倍 // canvasHeight: this.sysData.windowWidth // }) // } // }) }, addImg(e) { let index = e.currentTarget.dataset.index let materialList = this.data.materialList let itemList = this.data.itemList if (itemList.length) { materialList[index].id = itemList[itemList.length - 1].id + 1 } else { materialList[index].id = 1 } itemList.push(JSON.parse(JSON.stringify(materialList[index]))) this.setData({ itemList }) }, loadImg(e) { let index = e.currentTarget.dataset.index let itemList = this.data.itemList // x,y爲圓心的距離, +25: 按鈕定位的距離 + 按鈕自身大小/2 itemList[index].width = e.detail.width itemList[index].height = e.detail.height itemList[index].x = e.detail.width / 2 + 25 itemList[index].y = e.detail.height / 2 + 25 this.setData({ itemList }) }, hiddenImg(e) { let index = e.currentTarget.dataset.index let itemList = this.data.itemList itemList.splice(index, 1) this.setData({ itemList }) }, wraptouchStart: function (e) { let items = this.data.itemList; for (let i = 0; i < items.length; i++) { //旋轉數據找到點擊的 items[i].active = false; if (e.currentTarget.dataset.id == items[i].id) { items[i].active = true; //開啓點擊屬性 items[i].lx = e.touches[0].clientX; // 記錄點擊時的座標值 items[i].ly = e.touches[0].clientY; } } this.setData({ //賦值 itemList: items }) }, WraptouchMove: function (e) { let index = e.currentTarget.dataset.index let items = this.data.itemList; //移動時的座標值也寫圖片的屬性裏 items[index]._lx = e.touches[0].clientX; items[index]._ly = e.touches[0].clientY; //追加改動值 items[index].left += items[index]._lx - items[index].lx; // x方向 items[index].top += items[index]._ly - items[index].ly; // y方向 items[index].x += items[index]._lx - items[index].lx; items[index].y += items[index]._ly - items[index].ly; //把新的值賦給老的值 items[index].lx = e.touches[0].clientX; items[index].ly = e.touches[0].clientY; this.setData({//賦值就移動了 itemList: items }) }, // 觸摸開始事件 items是this.data.itemList的全局變量,便於賦值 全部的值都應給到對應的對象裏 touchStart: function (e) { //找到點擊的那個圖片對象,並記錄 let items = this.data.itemList; let index = e.currentTarget.dataset.index for (let i = 0; i < items.length; i++) { items[i].active = false; if (e.currentTarget.dataset.id == items[i].id) { items[i].active = true; } } //獲取做爲移動前角度的座標 items[index].tx = e.touches[0].clientX; items[index].ty = e.touches[0].clientY; //移動前的角度 items[index].anglePre = this.countDeg(items[index].x, items[index].y, items[index].tx, items[index].ty) //獲取圖片半徑 items[index].r = this.getDistancs(items[index].x, items[index].y, items[index].left, items[index].top) }, // 觸摸移動事件 touchMove: function (e) { let items = this.data.itemList; let index = e.currentTarget.dataset.index // items[index].x = e.detail.width / 2 // items[index].y = e.detail.height / 2 // this.setData({itemList: items}) //記錄移動後的位置 items[index]._tx = e.touches[0].clientX; items[index]._ty = e.touches[0].clientY; //移動的點到圓心的距離 * 由於圓心的座標是相對與父元素定位的 ,全部要減去父元素的OffsetLeft和OffsetTop來計算移動的點到圓心的距離 items[index].disPtoO = this.getDistancs(items[index].x, items[index].y, items[index]._tx, items[index]._ty) items[index].scale = items[index].disPtoO / items[index].r; //手指滑動的點到圓心的距離與半徑的比值做爲圖片的放大比例 items[index].oScale = 1 / items[index].scale;//圖片放大響應的右下角按鈕同比縮小 //移動後位置的角度 items[index].angleNext = this.countDeg(items[index].x, items[index].y, items[index]._tx, items[index]._ty) //角度差 items[index].new_rotate = items[index].angleNext - items[index].anglePre; //疊加的角度差 items[index].angle += items[index].new_rotate; //用過移動後的座標賦值爲移動前座標 items[index].tx = e.touches[0].clientX; items[index].ty = e.touches[0].clientY; items[index].anglePre = this.countDeg(items[index].x, items[index].y, items[index].tx, items[index].ty) //賦值setData渲染 this.setData({ itemList: items }) }, /* *參數1和2爲圖片圓心座標 *參數3和4爲手點擊的座標 *返回值爲手點擊的座標到圓心的角度 */ countDeg: function (cx, cy, pointer_x, pointer_y) { var ox = pointer_x - cx; var oy = pointer_y - cy; var to = Math.abs(ox / oy); var angle = Math.atan(to) / (2 * Math.PI) * 360;//鼠標相對於旋轉中心的角度 if (ox < 0 && oy < 0)//相對在左上角,第四象限,js中座標系是從左上角開始的,這裏的象限是正常座標系 { angle = -angle; } else if (ox <= 0 && oy >= 0)//左下角,3象限 { angle = -(180 - angle) } else if (ox > 0 && oy < 0)//右上角,1象限 { angle = angle; } else if (ox > 0 && oy > 0)//右下角,2象限 { angle = 180 - angle; } return angle; }, getDistancs(cx, cy, pointer_x, pointer_y) { var ox = pointer_x - cx; var oy = pointer_y - cy; return Math.sqrt( ox * ox + oy * oy ); }, generate: function () { maskCanvas.save(); maskCanvas.beginPath(); //一張白圖 maskCanvas.setFillStyle('#fff'); maskCanvas.fillRect(0, 0, this.data.windowWidth, this.data.canvasHeight) maskCanvas.closePath(); maskCanvas.stroke(); this.data.itemList.forEach((val, index) => { maskCanvas.save(); maskCanvas.translate(0, 0); maskCanvas.beginPath(); maskCanvas.translate(val.x, val.y); // 圓心座標 maskCanvas.rotate(val.angle * Math.PI / 180); maskCanvas.translate(-(val.width * val.scale / 2) - 25, -(val.height * val.scale / 2) - 25) maskCanvas.drawImage(val.image, 0, 0, val.width * val.scale, val.height * val.scale); maskCanvas.restore(); }) maskCanvas.draw(false, (e) => { wx.canvasToTempFilePath({ canvasId: 'maskCanvas', success: res => { this.setData({ canvasTemImg: res.tempFilePath }) console.log(res.tempFilePath); } }, this) }) } })
cssthis
page{ height:100%; } .img-list{ width: 100rpx; height: 100rpx } .container{ height: 100%; } .img-box { position: relative; width: 80%; overflow: hidden; margin: auto; border: 1px solid blue; height: 60%; } .maskCanvas { /* display: none; */ position: absolute; left: 0; bottom: 0; border:1px solid red; } .o, .x { width: 40rpx; height: 40rpx; position: absolute; } .o{ bottom: -20px; right: -20px; } .x{ top: -20px; left: -20px } .touchWrap { position: absolute; } .imgWrap{ border: 1px solid transparent; } .touchActive{ border: 1px solid black; }
jasonspa
{ "navigationBarTitleText": "照片測試", "usingComponents": {}, "disableScroll": true }
這是個demo,本身大概測過沒問題
由於頁面簡潔,若是要放在頁面上換樣式,可能會有問題
僅供參考,僅供參考!.net