微信小程序·上传头像剪切图片到本地
微信小程序·上传头像剪切图片到本地
组件化
![](https://www.linwute.com/wp-content/uploads/2022/11/image-4.png)
.wxml 子组件文件
<view class="container"> <view class="top {{moving?'bg-5':'bg-9'}}" style="height:{{(systemInfo.windowHeight-300)/2}}px;"></view> <view class="left {{moving?'bg-5':'bg-9'}}" style="width: {{(systemInfo.windowWidth-300)/2}}px;top: {{(systemInfo.windowHeight-300)/2}}px;height: 300px;"></view> <view class="right {{moving?'bg-5':'bg-9'}}" style="width: {{(systemInfo.windowWidth-300)/2}}px;top: {{(systemInfo.windowHeight-300)/2}}px;height: 300px;"></view> <view class="bottom {{moving?'bg-5':'bg-9'}}" style="top:{{(systemInfo.windowHeight-300)/2+300}}px;"></view> <canvas canvas-id="myCanvas" class="canvas"> </canvas> <movable-area scale-area class="movable-area" style="top: {{(systemInfo.windowHeight-300)/2}}px;left: {{(systemInfo.windowWidth-300)/2}}px;"> <movable-view scale-min="1" animation="{{false}}" bindscale="onScale" bindchange="onMove" x="{{x}}" y="{{y}}" scale direction="all" style="width: {{image_w}}px;height: {{image_h}}px;"> <image class="image" bindload="onImageLoad" src="{{imageUrl}}"></image> </movable-view> </movable-area> <view class="footer"> <view class="button" bindtap="cancel">取消</view> <view class="button" style="background-color: #4CE0E0;color: #fff;" bindtap="getImage">确定</view> </view> </view>
.wxss 子组件文件
.container { width: 100%; height: 100%; position: fixed; top: 0; left: 0; width: 100%; height: 100%; box-sizing: border-box; background: #000; z-index: 80; } .top { position: fixed; top: 0; left: 0; width: 100%; z-index: 99; } .left { position: fixed; left: 0; z-index: 99; } .right { position: fixed; right: 0; z-index: 99; } .bottom { position: fixed; bottom: 0; left: 0; width: 100%; z-index: 99; } .bg-5 { background: rgba(0, 0, 0, 0.3); } .bg-9 { background: rgba(0, 0, 0, 0.8); transition-duration: .5s; transition-property: background; } .canvas { position: absolute; top: 0; left: -1000px; width: 300px; height: 300px; } .movable-area { position: fixed; width: 300px; height: 300px; } .image { width: 100%; height: 100%; display: flex; } .footer { position: absolute; left: 0; bottom: 0; padding-bottom: env(safe-area-inset-bottom); height: calc(140rpx + env(safe-area-inset-bottom)); width: 100%; display: flex; justify-content: flex-start; align-items: center; z-index: 100; background-color: rgba(0, 0, 0, 0.8); box-sizing: border-box; } .button { width: 300rpx; height: 100rpx; display: flex; justify-content: center; align-items: center; background-color: #fff; border-radius: 100rpx; margin-left: 50rpx; }
.js 子组件文件
const debounce = function (fn, delay = 3000) { let timer = null const _debounce = function (...args) { if (timer) clearTimeout(timer) timer = setTimeout(() => { fn.apply(this, args) }, delay) } return _debounce } Component({ properties: { imageUrl: { type: String, value: '' }, show: { type: Boolean, value: false } }, data: { moving: false, }, lifetimes: { ready() { this.context = wx.createCanvasContext('myCanvas', this); this.setData({ systemInfo: wx.getSystemInfoSync() }) } }, methods: { // 初始化图片大小 onImageLoad: function (e) { let { width, height } = e.detail, h = 300, w = 300, x = 0, y = 0; if (width < height) { h = height * w / width; y = -(h - 300) / 2; } if (height < width) { w = width * h / height; x = -(w - 300) / 2; } this.x = x; this.y = y; this.scale = 1; this.setData({ image_w: w, image_h: h, original_w: width, original_h: height, x, y }) this.getDramParams(); }, getDramParams: function () { let { original_w, original_h, image_w, image_h } = this.data, { x, y, scale } = this; //console.log(x, y, scale) let sourceX = Math.abs(original_h * x / image_h), sourceY = Math.abs(original_w * y / image_w); this.context.drawImage(this.properties.imageUrl, sourceX / scale, sourceY / scale, Math.min(original_h, original_w) / scale, Math.min(original_h, original_w) / scale, 0, 0, 300, 300); this.context.draw() }, // 获取图片 getImage: function () { wx.canvasToTempFilePath({ canvasId: 'myCanvas', success: res => { //console.log(res) this.setData({ image: res.tempFilePath, show: false }) this.triggerEvent('returnImageUrl', { imageUrl: res.tempFilePath }) } }, this) }, // 拖动图片 onMove: function (e) { //console.log(e) let { x, y } = e.detail; this.x = x; this.y = y; this.setBg(); debounce(this.getDramParams(), 300) }, onScale: function (e) { let { x, y, scale } = e.detail; this.x = x; this.y = y; this.scale = scale; this.setBg(); debounce(this.getDramParams(), 300) }, setBg: function () { if (!this.data.moving) { this.setData({ moving: true }) } if (this.timer) clearInterval(this.timer); let count = 0; this.timer = setInterval(() => { count += 1000; if (count >= 1000) { clearInterval(this.timer); this.setData({ moving: false }) } }, 1000); }, cancel: function (e) { this.setData({ show: false }) } } })
父组件 引用方式: imageUrl 本地图像图片地址 bind:returnImageUrl 为接收剪切后保存图片地址
<img_photo imageUrl="{{url}}" bind:returnImageUrl="putImageUrl" ></img_photo>
1,104 Views