image-cropper.wxml:
<view class="imageCropper">
<canvas class="canvas" canvas-id="myCanvas" style="width:{{canvasWidth}}px;height:{{canvasHeight}}px">
<movable-area class="movableArea" style="width:{{canvasWidth}}px;height:{{canvasHeight}}px;">
<movable-view wx:if="{{src}}" style="width:{{cut1Width}}px;height:{{cut1Height}}px" class="movableBox" x="{{x}}" y="{{y}}" direction="all" bindchange="movableChange"></movable-view>
<image src="{{src}}" id="photo" style="width:{{canvasWidth}}px;height:{{canvasHeight}}px"></image>
</movable-area>
</canvas>
<view class="footBox flex_around f30" style="background: none;"><view class="cf p30 box_b" bindtap="hide">取消</view><view class="cf p30 box_b" bindtap="cut">确定</view></view>
</view>
image-cropper.js
let common = getApp().globalData.commonFun
let util = getApp().globalData.utilFun
Component({
options: {},
properties: {},
options: {styleIsolation: "apply-shared"},
data: {
canvasHeight: 0,
canvasWidth: 0,
x: 0,
y: 0,
src: '',
cutWidth: 0,
cut1Width: 0,
cutHeight: 0,
cut1Height: 0,
aspectRatio: 0,
},
attached: function () {},
methods: {
async setPageData(res) {
//console.log(res)
let imgWidth = res.imgWidth,imgHeight = res.imgHeight,w = Number(imgWidth) / 2 * 0.7,h = Number(imgHeight) / 2 * 0.7,imgInfo = await this.singleImgInfo(res.imgSrc),ch = 0,cw = 0,x = this.data.x,y = this.data.y;
if (imgWidth == imgHeight) {
if (imgInfo.width >= imgWidth && imgInfo.height >= imgHeight) {
if (imgInfo.width > imgInfo.height) {
ch = Number(h) + 4;cw = Number(h) / Number(imgInfo.height) * Number(imgInfo.width);x = (cw - w) / 2 - 2;
} else {
cw = Number(w) + 4;ch = Number(w) / Number(imgInfo.width) * Number(imgInfo.height);y = (ch - h) / 2 - 2;
}
} else {
if (imgInfo.width < imgWidth && imgInfo.height >= imgHeight) {
if (imgInfo.width > imgInfo.height) {
ch = Number(res.imgHeight) + 4;cw = Number(res.imgHeight) / Number(imgInfo.height) * Number(imgInfo.width);x = (cw - w) / 2 / 2 - 42;
} else {
cw = Number(w) + 4;ch = Number(w) / Number(imgInfo.width) * Number(imgInfo.height);y = (ch - h) / 2 - 2;
}
} else if (imgInfo.width >= imgWidth && imgInfo.height < imgHeight) {
if (imgInfo.width > imgInfo.height) {
ch = Number(h) + 4;cw = Number(h) / Number(imgInfo.height) * Number(imgInfo.width);x = (cw - w) / 2 - 2;
} else {
cw = Number(w) + 4;ch = Number(w) / Number(imgInfo.width) * Number(imgInfo.height);y = (ch - h) / 2 - 2;
}
} else {
if (imgInfo.width > imgInfo.height) {
ch = Number(h) + 4;cw = Number(h) / Number(imgInfo.height) * Number(imgInfo.width);x = (cw - w) / 2 - 2;
} else {
cw = Number(w) + 4;ch = Number(w) / Number(imgInfo.width) * Number(imgInfo.height);y = (ch - h) / 2 - 2;
}
}
}
} else {
if (imgInfo.width >= imgWidth && imgInfo.height >= imgHeight) {
if (imgInfo.width > imgInfo.height) {
ch = Number(h) + 4;cw = Number(imgHeight / 2) / Number(imgInfo.height) * Number(imgInfo.width) + 8x = (cw - w) / 2 - 2;
} else {
cw = Number(w) + 4;ch = Number(w) / Number(imgInfo.width) * Number(imgInfo.height) + 8y = (ch - h) / 2 - 2;
}
} else {
if (imgInfo.width < imgWidth && imgInfo.height >= imgHeight) {
if (imgInfo.width > imgInfo.height) {
ch = Number(h) + 4;cw = Number(imgHeight / 2) / Number(imgInfo.height) * Number(imgInfo.width) + 8x = (cw - w) / 2 - 2;
} else {
cw = Number(w) + 4;ch = Number(w) / Number(imgInfo.width) * Number(imgInfo.height) + 8y = (ch - h) / 2 - 2;
}
} else if (imgInfo.width >= imgWidth && imgInfo.height < imgHeight) {
if (imgInfo.width > imgInfo.height) {
ch = Number(h) + 4;cw = Number(imgHeight / 2) / Number(imgInfo.height) * Number(imgInfo.width) + 8x = (cw - w) / 2 - 2;
} else {
cw = Number(w) + 4;ch = Number(w) / Number(imgInfo.width) * Number(imgInfo.height) + 8y = (ch - h) / 2 - 2;
}
} else {
if (imgInfo.width > imgInfo.height) {
ch = Number(h) + 4;cw = Number(imgHeight / 2) / Number(imgInfo.height) * Number(imgInfo.width) + 8x = (cw - w) / 2 - 2;
} else {
cw = Number(w) + 4;ch = Number(w) / Number(imgInfo.width) * Number(imgInfo.height) + 8y = (ch - h) / 2 - 2;
}
}
}
}
this.setData({
x,
y,
canvasHeight: ch,
canvasWidth: cw,
cutWidth: res.imgWidth,
cutHeight: res.imgHeight,
cut1Width: w,
cut1Height: h,
src: res.imgSrc,
aspectRatio: res.imgWidth / res.imgHeight
});
let that = this;
const ctx = wx.createCanvasContext('myCanvas', this)
setTimeout(function () {
wx.createSelectorQuery().in(that).select('#photo').boundingClientRect(function (rect) {
ctx.drawImage(res.imgSrc, 0, 0, cw, ch)
ctx.draw();
//确保不同大小的图片,切图不会变形
that.setData({
x: x,
y: y
});
}).exec()
}, 100)
},
singleImgInfo(res) {
return new Promise((resolve, reject)=>{
getImageInfo({
src: res,
complete(rs) {
resolve(rs)
}
});
})
},
hide() {
this.triggerEvent('myevent', {
type: "hide"
})
},
//裁剪框移动事件
movableChange: function (e) {
console.log(e.detail);
this.setData({
x: e.detail.x,
y: e.detail.y
})
},
//截图
cut: function () {
const that = this;
wx.canvasToTempFilePath({
x: that.data.x,
y: that.data.y,
width: that.data.cut1Width,
height: that.data.cut1Height,
destWidth: that.data.cutWidth,
destHeight: that.data.cutHeight,
canvasId: 'myCanvas',
success(res) {
that.triggerEvent('myevent', { cut_src: res.tempFilePath,cutWidth: that.data.cutWidth, cutHeight: that.data.cutHeight,type: "confirm" })
}
}, this)
},
}
})
image-cropper.wxss
.movableArea {width: 100%;height: auto;position: relative;background: rgba(0, 0, 0, 0.3)}
.movableBox {border: 2px dashed #fff}
.imageCropper {background: rgba(14, 13, 13, .8);position: fixed;top: 0;left: 0;width: 100vw;height: 100vh;z-index: 1;}
.canvas {position: fixed;top: 50%;left: 50%;transform: translate(-50%, -60%);}
.footBox {position: fixed;left: 50%;transform: translateX(-50%);z-index: 10;width: 750rpx;bottom: 0;padding-bottom: constant(safe-area-inset-bottom);padding-bottom: env(safe-area-inset-bottom);background: #ffffff;}
.p30 {padding: 30rpx}
.flex_around {display: -webkit-flex;display: flex;justify-content: space-around;}
.cf {color: #fff;}
.box_b {box-sizing: border-box;-moz-box-sizing: border-box;-webkit-box-sizing: border-box;}
page.json
{
"navigationBarTitleText": "选择照片",
"usingComponents": {"image-cropper": "/pages/image-cropper/image-cropper"}
}
page.wxml
<image-cropper id="cutImg" bindgetTempFilePath="getCutsrc"></image-cropper>
<view wx:if="{{cut_src}}" class="fyj_cutDiv text-center"><image style="width:{{cutWidth}}px;height:{{cutHeight}}px" src="{{cut_src}}" mode="widthFix"></image></view>
</view>
page.js
Page({
data: {cut_src:
''
,cutWidth:0,cutHeight:0,},
onLoad:
function
(options) {
let that = this;
wx.chooseImage({
count: 1,
sizeType: ['original', 'compressed'],
sourceType: ['album', 'camera'],
success(res) {
let val = {cropScale: "1:1",imgHeight: "750",imgSrc: res.tempFilePaths[0],imgWidth: "750",}
if (that.selectComponent("#cutImg")) {that.selectComponent("#cutImg").setPageData(val)}
}
})
},
getCutsrc:function(e){
console.log(e);
this.setData({cut_src: e.detail.cut_src,cutWidth: e.detail.cutWidth,cutHeight: e.detail.cutHeight})}
})