前端图片剪切上传功能是常见的功能,在开发过程中,研发一个这样的功能要花的时间也会很多,现在把一个研发好了的图片剪切插件发出来。支持剪切和大小缩放。
wxml
1 <!--图片展示 --> 2 <view bindtap=\'upEwm\' data-which=\'1\'> 3 <view>第一个图</view> 4 <image style=\'width:200rpx;height:200rpx;background-color:red\' src=\'{{headImg}}\'></image> 5 </view> 6 <view bindtap=\'upEwm\' data-which=\'2\'> 7 <view>第二个图</view> 8 <image style=\'width:200rpx;height:200rpx;background-color:red\' src=\'{{ewmImg}}\'></image> 9 </view> 10 11 12 <!--裁剪图片浮层--> 13 <view class=\'fixed-upimg\' wx:if="{{imageFixed}}"> 14 <view class="wx-content-info"> 15 <!-- <view class="wx-content-info" wx:if="{{imageSrc}}"> --> 16 <view wx:if="{{isShowImg}}" class="wx-corpper" style="width:{{cropperInitW}}rpx;height:{{cropperInitH}}rpx;background:#000"> 17 <view bindtap=\'upLoad\' class="wx-corpper-content" style="width:{{cropperW}}rpx;height:{{cropperH}}rpx;left:{{cropperL}}rpx;top:{{cropperT}}rpx"> 18 <image src="{{imageSrc}}" style="width:{{cropperW}}rpx;height:{{cropperH}}rpx"></image> 19 <view class="wx-corpper-crop-box" bindtouchstart="contentStartMove" bindtouchmove="contentMoveing" style="width:{{cutW}}rpx;height:{{cutH}}rpx;left:{{cutL}}rpx;top:{{cutT}}rpx"> 20 <view class="wx-cropper-view-box"> 21 <!-- <view class="wx-cropper-viewer"> 22 <image src="{{imageSrc}}" style="width:{{cropperW}}rpx;height:{{cropperH}}rpx;left:{{cropperL - cutL}}rpx;top:{{cropperT - cutT}}rpx"></image> 23 </view> --> 24 <view class="wx-cropper-dashed-h"></view> 25 <view class="wx-cropper-dashed-v"></view> 26 <view class="wx-cropper-line-t" data-drag="top" catchtouchstart="dragStart" catchtouchmove="dragMove"></view> 27 <view class="wx-cropper-line-r" data-drag="right" catchtouchstart="dragStart" catchtouchmove="dragMove"></view> 28 <view class="wx-cropper-line-b" data-drag="bottom" catchtouchstart="dragStart" catchtouchmove="dragMove"></view> 29 <view class="wx-cropper-line-l" data-drag="left" catchtouchstart="dragStart" catchtouchmove="dragMove"></view> 30 <view class="wx-cropper-point point-t" data-drag="top" catchtouchstart="dragStart" catchtouchmove="dragMove"></view> 31 <view class="wx-cropper-point point-tr" data-drag="topTight"></view> 32 <view class="wx-cropper-point point-r" data-drag="right" catchtouchstart="dragStart" catchtouchmove="dragMove"></view> 33 <view class="wx-cropper-point point-rb" data-drag="rightBottom" catchtouchstart="dragStart" catchtouchmove="dragMove"></view> 34 <view class="wx-cropper-point point-b" data-drag="bottom" catchtouchstart="dragStart" catchtouchmove="dragMove"></view> 35 <view class="wx-cropper-point point-bl" data-drag="bottomLeft"></view> 36 <view class="wx-cropper-point point-l" data-drag="left" catchtouchstart="dragStart" catchtouchmove="dragMove"></view> 37 <view class="wx-cropper-point point-lt" data-drag="leftTop"></view> 38 </view> 39 </view> 40 </view> 41 <!-- <view class="wx-cropper-drag-box"></view> --> 42 </view> 43 <canvas canvas-id="myCanvas" style="position:absolute;border: 1px solid red; width:{{imageW}}rpx;height:{{imageH}}rpx;top:-9999px;left:-9999px;"></canvas> 44 <button type="primary" bindtap="getImageInfo" style="position:fixed;bottom:120rpx;width:90%;left:50%;transform:translate3d(-50%,0,0)"> 确认提交 </button> 45 46 </view> 47 </view>
wxcss
1 /* pages/wx-cropper/index.wxss */ 2 .fixed-upimg{ 3 position: fixed; 4 top: 0; 5 left: 0; 6 right: 0; 7 bottom: 0; 8 background-color: #fff; 9 } 10 .wx-content-info{ 11 position: fixed; 12 top: 130rpx; 13 left: 0; 14 right: 0; 15 bottom: 0; 16 17 } 18 19 .wx-corpper{ 20 position: relative; 21 overflow: hidden; 22 -webkit-user-select: none; 23 -moz-user-select: none; 24 -ms-user-select: none; 25 user-select: none; 26 -webkit-tap-highlight-color: transparent; 27 -webkit-touch-callout: none; 28 box-sizing: border-box; 29 } 30 31 .wx-corpper-content{ 32 position: absolute; 33 top: 0; 34 right: 0; 35 bottom: 0; 36 left: 0; 37 } 38 39 .wx-corpper-content image { 40 display: block; 41 width: 100%; 42 min-width: 0 !important; 43 max-width: none !important; 44 height: 100%; 45 min-height: 0 !important; 46 max-height: none !important; 47 image-orientation: 0deg !important; 48 margin: 0 auto; 49 } 50 51 /* 移动图片效果 */ 52 .wx-cropper-drag-box{ 53 position: absolute; 54 top: 0; 55 right: 0; 56 bottom: 0; 57 left: 0; 58 cursor: move; 59 background: rgba(0,0,0,0.6); 60 z-index: 1; 61 } 62 63 /* 内部的信息 */ 64 .wx-corpper-crop-box{ 65 position: absolute; 66 width: 500rpx; 67 height: 500rpx; 68 background: rgba(255,255,255,0.3); 69 z-index: 2; 70 } 71 72 .wx-corpper-crop-box .wx-cropper-view-box { 73 position: relative; 74 display: block; 75 width: 100%; 76 height: 100%; 77 overflow: visible; 78 outline: 1px solid #69f; 79 outline-color: rgba(102, 153, 255, .75) 80 } 81 82 /* 横向虚线 */ 83 .wx-cropper-dashed-h{ 84 position: absolute; 85 top: 33.33333333%; 86 left: 0; 87 width: 100%; 88 height: 33.33333333%; 89 border-top: 1px dashed rgba(255,255,255,0.5); 90 border-bottom: 1px dashed rgba(255,255,255,0.5); 91 } 92 93 /* 纵向虚线 */ 94 .wx-cropper-dashed-v{ 95 position: absolute; 96 left: 33.33333333%; 97 top: 0; 98 width: 33.33333333%; 99 height: 100%; 100 border-left: 1px dashed rgba(255,255,255,0.5); 101 border-right: 1px dashed rgba(255,255,255,0.5); 102 } 103 104 /* 四个方向的线 为了之后的拖动事件*/ 105 .wx-cropper-line-t{ 106 position: absolute; 107 display: block; 108 width: 100%; 109 background-color: #69f; 110 top: 0; 111 left: 0; 112 height: 1px; 113 opacity: 0.1; 114 cursor: n-resize; 115 } 116 117 .wx-cropper-line-t::before{ 118 content: \'\'; 119 position: absolute; 120 top: 50%; 121 right: 0rpx; 122 width: 100%; 123 -webkit-transform: translate3d(0,-50%,0); 124 transform: translate3d(0,-50%,0); 125 bottom: 0; 126 height: 41rpx; 127 background: transparent; 128 z-index: 11; 129 } 130 131 .wx-cropper-line-r{ 132 position: absolute; 133 display: block; 134 background-color: #69f; 135 top: 0; 136 right: 0px; 137 width: 1px; 138 opacity: 0.1; 139 height: 100%; 140 cursor: e-resize; 141 } 142 .wx-cropper-line-r::before{ 143 content: \'\'; 144 position: absolute; 145 top: 0; 146 left: 50%; 147 width: 41rpx; 148 -webkit-transform: translate3d(-50%,0,0); 149 transform: translate3d(-50%,0,0); 150 bottom: 0; 151 height: 100%; 152 background: transparent; 153 z-index: 11; 154 } 155 156 .wx-cropper-line-b{ 157 position: absolute; 158 display: block; 159 width: 100%; 160 background-color: #69f; 161 bottom: 0; 162 left: 0; 163 height: 1px; 164 opacity: 0.1; 165 cursor: s-resize; 166 } 167 168 .wx-cropper-line-b::before{ 169 content: \'\'; 170 position: absolute; 171 top: 50%; 172 right: 0rpx; 173 width: 100%; 174 -webkit-transform: translate3d(0,-50%,0); 175 transform: translate3d(0,-50%,0); 176 bottom: 0; 177 height: 41rpx; 178 background: transparent; 179 z-index: 11; 180 } 181 182 .wx-cropper-line-l{ 183 position: absolute; 184 display: block; 185 background-color: #69f; 186 top: 0; 187 left: 0; 188 width: 1px; 189 opacity: 0.1; 190 height: 100%; 191 cursor: w-resize; 192 } 193 .wx-cropper-line-l::before{ 194 content: \'\'; 195 position: absolute; 196 top: 0; 197 left: 50%; 198 width: 41rpx; 199 -webkit-transform: translate3d(-50%,0,0); 200 transform: translate3d(-50%,0,0); 201 bottom: 0; 202 height: 100%; 203 background: transparent; 204 z-index: 11; 205 } 206 207 .wx-cropper-point{ 208 width: 5px; 209 height: 5px; 210 background-color: #69f; 211 opacity: .75; 212 position: absolute; 213 z-index: 3; 214 } 215 216 .point-t{ 217 top: -3px; 218 left: 50%; 219 margin-left: -3px; 220 cursor: n-resize; 221 } 222 223 .point-tr{ 224 top: -3px; 225 left: 100%; 226 margin-left: -3px; 227 cursor: n-resize; 228 } 229 230 .point-r{ 231 top: 50%; 232 left:100%; 233 margin-left: -3px; 234 margin-top: -3px; 235 cursor: n-resize; 236 } 237 238 .point-rb{ 239 left: 100%; 240 top: 100%; 241 -webkit-transform: translate3d(-50%,-50%,0); 242 transform: translate3d(-50%,-50%,0); 243 cursor: n-resize; 244 width: 24rpx; 245 height: 24rpx; 246 background-color: #69f; 247 position: absolute; 248 z-index: 1112; 249 opacity: 1; 250 } 251 252 .point-b{ 253 left:50%; 254 top: 100%; 255 margin-left: -3px; 256 margin-top: -3px; 257 cursor: n-resize; 258 } 259 260 .point-bl{ 261 left:0%; 262 top: 100%; 263 margin-left: -3px; 264 margin-top: -3px; 265 cursor: n-resize; 266 } 267 268 .point-l{ 269 left:0%; 270 top: 50%; 271 margin-left: -3px; 272 margin-top: -3px; 273 cursor: n-resize; 274 } 275 276 .point-lt{ 277 left:0%; 278 top: 0%; 279 margin-left: -3px; 280 margin-top: -3px; 281 cursor: n-resize; 282 } 283 284 /* 裁剪框预览内容 */ 285 .wx-cropper-viewer{ 286 position: relative; 287 width: 100%; 288 height: 100%; 289 overflow: hidden; 290 } 291 292 .wx-cropper-viewer image{ 293 position: absolute; 294 z-index: 2; 295 }
js
1 // pages/wx-cropper/index.js 2 // 手机的宽度 3 var windowWRPX = 750 4 // 拖动时候的 pageX 5 var pageX = 0 6 // 拖动时候的 pageY 7 var pageY = 0 8 9 var pixelRatio = wx.getSystemInfoSync().pixelRatio 10 11 // 调整大小时候的 pageX 12 var sizeConfPageX = 0 13 // 调整大小时候的 pageY 14 var sizeConfPageY = 0 15 16 var initDragCutW = 0 17 var initDragCutL = 0 18 var initDragCutH = 0 19 var initDragCutT = 0 20 21 // 移动时 手势位移与 实际元素位移的比 22 var dragScaleP = 2 23 24 Page({ 25 /** 26 * 页面的初始数据 27 */ 28 data: { 29 imageNum: \'\', //上传的图片id 30 headImg: \'\', //头像上传 31 ewmImg: \'\', //二维码上传 32 imageFixed: false, //裁剪浮层 33 // imageSrc: \'http://topmdrt-static.oss-cn-shenzhen.aliyuncs.com/images/testimg2.jpeg\', 34 imageSrc: \'\', //要裁剪的图片 35 returnImage: \'\', 36 isShowImg: false, 37 // 初始化的宽高 38 cropperInitW: windowWRPX, 39 cropperInitH: windowWRPX, 40 // 动态的宽高 41 cropperW: windowWRPX, 42 cropperH: windowWRPX, 43 // 动态的left top值 44 cropperL: 0, 45 cropperT: 0, 46 47 // 图片缩放值 48 scaleP: 0, 49 imageW: 0, 50 imageH: 0, 51 52 // 裁剪框 宽高 53 cutW: 400, 54 cutH: 400, 55 cutL: 0, 56 cutT: 0, 57 }, 58 59 /** 60 * 生命周期函数--监听页面加载 61 */ 62 onReady: function (options) { 63 }, 64 65 /** 66 * 生命周期函数--监听页面初次渲染完成 67 */ 68 onLoad: function () { 69 var _this = this 70 71 // wx.showLoading({ 72 // title: \'图片加载中...\', 73 // }) 74 75 wx.getImageInfo({ 76 src: _this.data.imageSrc, 77 success: function success(res) { 78 var innerAspectRadio = res.width / res.height; 79 console.log(innerAspectRadio) 80 // 根据图片的宽高显示不同的效果 保证图片可以正常显示 81 if (innerAspectRadio >= 1) { 82 _this.setData({ 83 cropperW: windowWRPX, 84 cropperH: windowWRPX / innerAspectRadio, 85 // 初始化left right 86 cropperL: Math.ceil((windowWRPX - windowWRPX) / 2), 87 cropperT: Math.ceil((windowWRPX - windowWRPX / innerAspectRadio) / 2), 88 // 裁剪框 宽高 89 // cutW: windowWRPX - 200, 90 // cutH: windowWRPX / innerAspectRadio - 200, 91 cutL: Math.ceil((windowWRPX - windowWRPX + 340) / 2), 92 cutT: Math.ceil((windowWRPX / innerAspectRadio - (windowWRPX / innerAspectRadio - 20)) / 2), 93 // 图片缩放值 94 scaleP: res.width * pixelRatio / windowWRPX, 95 // 图片原始宽度 rpx 96 imageW: res.width * pixelRatio, 97 imageH: res.height * pixelRatio 98 }) 99 } else { 100 _this.setData({ 101 cropperW: windowWRPX * innerAspectRadio, 102 cropperH: windowWRPX, 103 // 初始化left right 104 cropperL: Math.ceil((windowWRPX - windowWRPX * innerAspectRadio) / 2), 105 cropperT: Math.ceil((windowWRPX - windowWRPX) / 2), 106 // 裁剪框的宽高 107 // cutW: windowWRPX * innerAspectRadio - 66, 108 // cutH: 400, 109 cutL: Math.ceil((windowWRPX * innerAspectRadio - (windowWRPX * innerAspectRadio - 20)) / 2), 110 cutT: Math.ceil((windowWRPX - 340) / 2), 111 // 图片缩放值 112 scaleP: res.width * pixelRatio / windowWRPX, 113 // 图片原始宽度 rpx 114 imageW: res.width * pixelRatio, 115 imageH: res.height * pixelRatio 116 }) 117 } 118 _this.setData({ 119 isShowImg: true 120 }) 121 wx.hideLoading() 122 } 123 }) 124 }, 125 126 // 拖动时候触发的touchStart事件 127 contentStartMove(e) { 128 pageX = e.touches[0].pageX 129 pageY = e.touches[0].pageY 130 }, 131 132 // 拖动时候触发的touchMove事件 133 contentMoveing(e) { 134 var _this = this 135 // _this.data.cutL + (e.touches[0].pageX - pageX) 136 // console.log(e.touches[0].pageX) 137 // console.log(e.touches[0].pageX - pageX) 138 var dragLengthX = (pageX - e.touches[0].pageX) * dragScaleP 139 var dragLengthY = (pageY - e.touches[0].pageY) * dragScaleP 140 var minX = Math.max(_this.data.cutL - (dragLengthX), 0) 141 var minY = Math.max(_this.data.cutT - (dragLengthY), 0) 142 var maxX = _this.data.cropperW - _this.data.cutW 143 var maxY = _this.data.cropperH - _this.data.cutH 144 this.setData({ 145 cutL: Math.min(maxX, minX), 146 cutT: Math.min(maxY, minY), 147 }) 148 console.log(`${maxX} ----- ${minX}`) 149 pageX = e.touches[0].pageX 150 pageY = e.touches[0].pageY 151 }, 152 153 // 获取图片 154 getImageInfo() { 155 var _this = this 156 console.log(\'shengcheng:\' + _this.data.imageSrc) 157 wx.showLoading({ 158 title: \'图片生成中...\', 159 }) 160 // wx.downloadFile({ 161 // url:_this.data.imageSrc, //仅为示例,并非真实的资源 162 // success: function (res) { 163 // 将图片写入画布 164 const ctx = wx.createCanvasContext(\'myCanvas\') 165 // ctx.drawImage(res.tempFilePath) 166 ctx.drawImage(_this.data.imageSrc) 167 168 ctx.draw(true, () => { 169 // 获取画布要裁剪的位置和宽度 均为百分比 * 画布中图
请发表评论