| <template> |
| <view class="content"> |
| <view class="cropper-wrapper" :style="{ height: cropperOpt.height + 'px' }"> |
| <canvas |
| class="cropper" |
| :disable-scroll="true" |
| @touchstart="touchStart" |
| @touchmove="touchMove" |
| @touchend="touchEnd" |
| :style="{ width: cropperOpt.width, height: cropperOpt.height, backgroundColor: 'rgba(0, 0, 0, 0.8)' }" |
| canvas-id="cropper" |
| id="cropper" |
| ></canvas> |
| <canvas |
| class="cropper" |
| :disable-scroll="true" |
| :style="{ |
| position: 'fixed', |
| top: `-${cropperOpt.width * cropperOpt.pixelRatio}px`, |
| left: `-${cropperOpt.height * cropperOpt.pixelRatio}px`, |
| width: `${cropperOpt.width * cropperOpt.pixelRatio}px`, |
| height: `${cropperOpt.height * cropperOpt.pixelRatio}` |
| }" |
| canvas-id="targetId" |
| id="targetId" |
| ></canvas> |
| </view> |
| <view class="cropper-buttons safe-area-padding" :style="{ height: bottomNavHeight + 'px' }"> |
| <!-- #ifdef H5 --> |
| <view class="upload" @tap="uploadTap">选择图片</view> |
| <!-- #endif --> |
| <!-- #ifndef H5 --> |
| <view class="upload" @tap="uploadTap">重新选择</view> |
| <!-- #endif --> |
| <view class="getCropperImage" @tap="getCropperImage(false)">确定</view> |
| </view> |
| </view> |
| </template> |
| |
| <script> |
| import WeCropper from './weCropper.js'; |
| export default { |
| props: { |
| // 裁剪矩形框的样式,其中可包含的属性为lineWidth-边框宽度(单位rpx),color: 边框颜色, |
| // mask-遮罩颜色,一般设置为一个rgba的透明度,如"rgba(0, 0, 0, 0.35)" |
| boundStyle: { |
| type: Object, |
| default() { |
| return { |
| lineWidth: 4, |
| borderColor: 'rgb(245, 245, 245)', |
| mask: 'rgba(0, 0, 0, 0.35)' |
| }; |
| } |
| } |
| // // 裁剪框宽度,单位rpx |
| // rectWidth: { |
| // type: [String, Number], |
| // default: 400 |
| // }, |
| // // 裁剪框高度,单位rpx |
| // rectHeight: { |
| // type: [String, Number], |
| // default: 400 |
| // }, |
| // // 输出图片宽度,单位rpx |
| // destWidth: { |
| // type: [String, Number], |
| // default: 400 |
| // }, |
| // // 输出图片高度,单位rpx |
| // destHeight: { |
| // type: [String, Number], |
| // default: 400 |
| // }, |
| // // 输出的图片类型,如果发现裁剪的图片很大,可能是因为设置为了"png",改成"jpg"即可 |
| // fileType: { |
| // type: String, |
| // default: 'jpg', |
| // }, |
| // // 生成的图片质量 |
| // // H5上无效,目前不考虑使用此参数 |
| // quality: { |
| // type: [Number, String], |
| // default: 1 |
| // } |
| }, |
| data() { |
| return { |
| // 底部导航的高度 |
| bottomNavHeight: 50, |
| originWidth: 200, |
| width: 0, |
| height: 0, |
| cropperOpt: { |
| id: 'cropper', |
| targetId: 'targetCropper', |
| pixelRatio: 1, |
| width: 0, |
| height: 0, |
| scale: 2.5, |
| zoom: 8, |
| cut: { |
| x: (this.width - this.originWidth) / 2, |
| y: (this.height - this.originWidth) / 2, |
| width: this.originWidth, |
| height: this.originWidth |
| }, |
| boundStyle: { |
| lineWidth: uni.upx2px(this.boundStyle.lineWidth), |
| mask: this.boundStyle.mask, |
| color: this.boundStyle.borderColor |
| } |
| }, |
| // 裁剪框和输出图片的尺寸,高度默认等于宽度 |
| // 输出图片宽度,单位px |
| destWidth: 200, |
| // 裁剪框宽度,单位px |
| rectWidth: 200, |
| // 输出的图片类型,如果'png'类型发现裁剪的图片太大,改成"jpg"即可 |
| fileType: 'jpg', |
| src: '', // 选择的图片路径,用于在点击确定时,判断是否选择了图片 |
| }; |
| }, |
| onLoad(option) { |
| let rectInfo = uni.getSystemInfoSync(); |
| this.width = rectInfo.windowWidth; |
| this.height = rectInfo.windowHeight - this.bottomNavHeight; |
| this.cropperOpt.width = this.width; |
| this.cropperOpt.height = this.height; |
| this.cropperOpt.pixelRatio = rectInfo.pixelRatio; |
| |
| if (option.destWidth) this.destWidth = option.destWidth; |
| if (option.rectWidth) { |
| let rectWidth = Number(option.rectWidth); |
| this.cropperOpt.cut = { |
| x: (this.width - rectWidth) / 2, |
| y: (this.height - rectWidth) / 2, |
| width: rectWidth, |
| height: rectWidth |
| }; |
| } |
| this.rectWidth = option.rectWidth; |
| if (option.fileType) this.fileType = option.fileType; |
| // 初始化 |
| this.cropper = new WeCropper(this.cropperOpt) |
| .on('ready', ctx => { |
| // wecropper is ready for work! |
| }) |
| .on('beforeImageLoad', ctx => { |
| // before picture loaded, i can do something |
| }) |
| .on('imageLoad', ctx => { |
| // picture loaded |
| }) |
| .on('beforeDraw', (ctx, instance) => { |
| // before canvas draw,i can do something |
| }); |
| // 设置导航栏样式,以免用户在page.json中没有设置为黑色背景 |
| uni.setNavigationBarColor({ |
| frontColor: '#ffffff', |
| backgroundColor: '#000000' |
| }); |
| uni.chooseImage({ |
| count: 1, // 默认9 |
| sizeType: ['compressed'], // 可以指定是原图还是压缩图,默认二者都有 |
| sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有 |
| success: res => { |
| this.src = res.tempFilePaths[0]; |
| // 获取裁剪图片资源后,给data添加src属性及其值 |
| this.cropper.pushOrign(this.src); |
| } |
| }); |
| }, |
| methods: { |
| touchStart(e) { |
| this.cropper.touchStart(e); |
| }, |
| touchMove(e) { |
| this.cropper.touchMove(e); |
| }, |
| touchEnd(e) { |
| this.cropper.touchEnd(e); |
| }, |
| getCropperImage(isPre = false) { |
| if(!this.src) return this.$u.toast('请先选择图片再裁剪'); |
| |
| let cropper_opt = { |
| destHeight: Number(this.destWidth), // uni.canvasToTempFilePath要求这些参数为数值 |
| destWidth: Number(this.destWidth), |
| fileType: this.fileType |
| }; |
| this.cropper.getCropperImage(cropper_opt, (path, err) => { |
| if (err) { |
| uni.showModal({ |
| title: '温馨提示', |
| content: err.message |
| }); |
| } else { |
| if (isPre) { |
| uni.previewImage({ |
| current: '', // 当前显示图片的 http 链接 |
| urls: [path] // 需要预览的图片 http 链接列表 |
| }); |
| } else { |
| uni.$emit('uAvatarCropper', path); |
| this.$u.route({ |
| type: 'back' |
| }); |
| } |
| } |
| }); |
| }, |
| uploadTap() { |
| const self = this; |
| uni.chooseImage({ |
| count: 1, // 默认9 |
| sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有 |
| sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有 |
| success: (res) => { |
| self.src = res.tempFilePaths[0]; |
| // 获取裁剪图片资源后,给data添加src属性及其值 |
| |
| self.cropper.pushOrign(this.src); |
| } |
| }); |
| } |
| } |
| }; |
| </script> |
| |
| <style scoped lang="scss"> |
| @import '../../libs/css/style.components.scss'; |
| |
| .content { |
| background: rgba(255, 255, 255, 1); |
| } |
| |
| .cropper { |
| position: absolute; |
| top: 0; |
| left: 0; |
| width: 100%; |
| height: 100%; |
| z-index: 11; |
| } |
| |
| .cropper-buttons { |
| background-color: #000000; |
| color: #eee; |
| } |
| |
| .cropper-wrapper { |
| position: relative; |
| @include vue-flex; |
| flex-direction: row; |
| justify-content: space-between; |
| align-items: center; |
| width: 100%; |
| background-color: #000; |
| } |
| |
| .cropper-buttons { |
| width: 100vw; |
| @include vue-flex; |
| flex-direction: row; |
| justify-content: space-between; |
| align-items: center; |
| position: fixed; |
| bottom: 0; |
| left: 0; |
| font-size: 28rpx; |
| } |
| |
| .cropper-buttons .upload, |
| .cropper-buttons .getCropperImage { |
| width: 50%; |
| text-align: center; |
| } |
| |
| .cropper-buttons .upload { |
| text-align: left; |
| padding-left: 50rpx; |
| } |
| |
| .cropper-buttons .getCropperImage { |
| text-align: right; |
| padding-right: 50rpx; |
| } |
| </style> |