291 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			Vue
		
	
	
	
		
		
			
		
	
	
			291 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			Vue
		
	
	
	
|  | <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> |