vue uni-app 裁剪图片(裁剪头像)插件vue-image-cropper
一、项目预览。效果:一个手指拖动,可以移动图片,两个手指拖动可以缩放。下载该项目:git clone https://github.com/Q956164483/vue-image-cropper.git运行:npm icdvue-image-croppernpm run serve二、应用在自己的项目。1.复制“vue-image-cropper”项目中的 ./src/components/im
·
一、项目预览。
效果:
一个手指拖动,可以移动图片,两个手指拖动可以缩放。
下载该项目:
git clone https://github.com/Q956164483/vue-image-cropper.git
运行:
npm i
cd vue-image-cropper
npm run serve
二、应用在自己的项目。
1.复制“vue-image-cropper”项目中的 ./src/components/imageCropper.vue文件 (imageCropper.vue需要引入exif-small.js)
2.在需要使用的页面直接引入imageCropper组件,并绑定cropperConfig配置参数和裁剪之后的回调函数callback。
3.安装lrz。
npm i lrz -S
<image-cropper ref="imageCropper" :cropperConfig="cropperConfig" :callback="loadImage"></image-cropper>
cropperConfig: {
width: 1, // 裁剪宽度(比例)
height: 1, // 裁剪高度(比例)
quality: 0.7, // 图片质量(0~1之间)
maxWidth: 750 // 导出的图片的最大宽度
}
loadImage (data) {
console.log(data);//data为图片base64字符串,可以直接放入img的src
}
三、本人修改了部分代码,可以直接复制源码。
可以选择支持一下博主,花个几十积分,我的代码:
uni-app的图片裁剪nice-cropper.rar_uniapp图片裁剪,uniapp图片裁剪-互联网文档类资源-CSDN下载
如果饭都吃不起,就选择如下:
安装lrz:
npm i lrz -S
1.效果。
2.imageCropper.vue的代码:
<template>
<div ref="cropperPage" class="cropper-page" v-show="isShow">
<div @click="cancel()" class="icon icon-back"></div>
<input ref="file" type="file" accept="image/*" @change="readImage">
<img alt="" class="cropper-img" :style="imageStyle" ref="img">
<div class="cover box box-ac box-jc" :style="{height: coverHeight + 'px'}">
<!-- 请调整图片 -->
</div>
<div ref="cropBox" class="cropper-box" @touchstart.prevent="touchStart" @touchmove.prevent="touchMove"></div>
<div class="cover cover box box-ac box-jc" :style="{height: coverHeight + 'px'}">
<div class="box box-f1 box-jc box-fh">
<div class="btn" @click="cancel">取消</div>
<!--重选checkPhoto-->
</div>
<div class="box box-f1 box-jc box-fh">
<div class="btn sure" @click="confirm">确定</div>
</div>
</div>
</div>
</template>
<script>
import lrz from 'lrz'
const getDinstance = function(point0, point1) {
return Math.sqrt(Math.pow(point0.pageY - point1.pageY, 2) + Math.pow(point0.pageX - point1.pageX, 2))
}
export default {
name: 'imageCropper',
props: {
//裁剪确认后的回调,结果是图片数据。
callback: {
type: Function,
default () {}
},
cropperConfig: {
type: Object,
default () {
return {
width: 1,//裁剪宽度(比例)
height: 1,//裁剪高度(比例)
quality: 0.7,//图片质量(0~1之间)
maxWidth: 640//导出的图片最大宽度
}
}
}
},
data() {
return {
coverHeight: 0,
cropperHeight: 0,
imgInitTop: 0,
amplitude: 0,
imageState: {
left: 0,
top: 0,
scale: 1,
width: 0,
height: 0,
originX: 0,
originY: 0
},
distance: 0,
imageStyle: {
top: '0',
transform: 'translate3d(0px, 0px, 0px) scale(1)',
transformOrigin: 'left top'
},
cropBoxRect: {},
touchPos: {
x: 0,
y: 0
},
isShow: false,
minScale: 0,
info: '',
orientation: ''
}
},
watch: {
'imageState': {
handler(val) {
this.imageStyle.transform = 'translate3d(-' + val.left + 'px, -' + val.top + 'px, 0px) scale(' + val.scale + ')'
},
deep: true
}
},
methods: {
cancel() {
this.file = null
this.isShow = false
},
checkPhoto() {
this.$refs.file.click()
},
readImage($event) {
var self = this
var file = $event.target.files[0]
lrz(file)
.then(rst => {
self.orientation = 1
self.$refs.img.onload = () => {
self.initCropper()
}
self.$refs.img.src = rst.base64
$event.target.value = null
})
},
initCropper() {
this.isShow = true // 显示裁剪界面
this.$nextTick(() => {
let cropperPage = this.$refs.cropperPage
let pageWidth = cropperPage.clientWidth
let pageHeight = cropperPage.clientHeight
let cropBox = this.$refs.cropBox
let cropBoxWidth = cropBox.clientWidth
let cropBoxHeight = Math.floor(cropBoxWidth * (+this.cropperConfig.height) / (+this.cropperConfig.width))
this.$refs.cropBox.style.height = cropBoxHeight + 'px'
this.coverHeight = (pageHeight - cropBoxHeight) / 2
let cropBoxTop = this.coverHeight
this.imageState.left = 0
this.imageState.top = 0
this.imageStyle.top = cropBoxTop + 'px'
this.cropBoxRect = {
left: 0,
top: cropBoxTop,
width: pageWidth,
height: cropBoxHeight
}
let img = this.$refs.img
var width = this.imageState.width = img.naturalWidth
var height = this.imageState.height = img.naturalHeight
// 计算imageState
if (width > height) {
this.minScale = this.imageState.scale = this.cropBoxRect.height / height
this.imageState.left = (width * this.imageState.scale - this.cropBoxRect.width) / 2
} else {
this.minScale = this.imageState.scale = this.cropBoxRect.width / width
this.imageState.top = (height * this.imageState.scale - this.cropBoxRect.height) / 2
}
})
},
confirm() {
let self = this
let imageState = this.imageState
let cropBoxRect = this.cropBoxRect
// 导出图片的最大宽度
let maxWidth = this.cropperConfig.maxWidth
let scale2 = maxWidth / cropBoxRect.width
let scale = imageState.scale * scale2
let width = cropBoxRect.width * scale2
let height = cropBoxRect.height * scale2
let left = imageState.left * scale2
let top = imageState.top * scale2
let image = this.$refs.img
let canvas = document.createElement('canvas')
let ctx = canvas.getContext('2d')
// ios 的照片有拍摄的角度信息 参考 http://www.bcty365.com/content-142-3055-1.html
let orientation = this.orientation
switch (orientation) {
case 1:
canvas.width = width
canvas.height = height
ctx.drawImage(image, left / scale, top / scale, width / scale, height / scale, 0, 0, width, height)
break
case 6:
canvas.width = height
canvas.height = width
ctx.rotate(90 * Math.PI / 180)
ctx.drawImage(image, left / scale, top / scale, width / scale, height / scale, 0, -height, width, height)
break
case 8:
canvas.width = height
canvas.height = width
ctx.rotate(-90 * Math.PI / 180)
ctx.drawImage(image, left / scale, top / scale, width / scale, height / scale, -width, 0, width, height)
break
case 3:
canvas.width = width
canvas.height = height
ctx.rotate(180 * Math.PI / 180)
ctx.drawImage(image, left / scale, top / scale, width / scale, height / scale, -width, -height, width, height)
break
}
let dataUrl = canvas.toDataURL('image/jpeg', this.cropperConfig.quality)
self.callback(dataUrl)
self.isShow = false
},
getFocalPoint(point0, point1) {
return {
x: (point0.pageX + point1.pageX) / 2,
y: (point0.pageY + point1.pageY) / 2
}
},
touchStart(event) {
var fingerCount = event.touches.length
if (fingerCount) {
// 记录触摸初始位置
let touchEvent = event.touches[0]
this.touchPos = {
x: touchEvent.clientX,
y: touchEvent.clientY
}
}
if (fingerCount >= 2) {
// 获取两点距离、中点位置;两点距离old/new=放大倍数;中点位置,缩放中心;
let point0 = event.touches[0]
let point1 = event.touches[1]
this.distance = getDinstance(point0, point1)
this.touchPos = this.getFocalPoint(point0, point1)
// 设置缩放倍数,
}
},
touchMove(event) {
// 根据触摸点位移,移动图片,重置触摸点位置
var fingerCount = event.touches.length
var touchEvent = event.touches[0]
if (fingerCount === 1) {
let distX = touchEvent.pageX - this.touchPos.x
let distY = touchEvent.pageY - this.touchPos.y
let newX = this.imageState.left - distX
let newY = this.imageState.top - distY
let scale = this.imageState.scale
// alert(scale)
let maxX = this.imageState.width * scale - this.cropBoxRect.width
let maxY = this.imageState.height * scale - this.cropBoxRect.height
this.imageState.left = newX < 0 ? 0 : (newX > maxX ? maxX : newX)
this.imageState.top = newY < 0 ? 0 : (newY > maxY ? maxY : newY)
this.touchPos.x = touchEvent.pageX
this.touchPos.y = touchEvent.pageY
} else if (fingerCount > 1) {
let point0 = event.touches[0]
let point1 = event.touches[1]
let distance = getDinstance(point0, point1)
let zoom = distance / this.distance
let scale = zoom * this.imageState.scale
let maxX = this.imageState.width * scale - this.cropBoxRect.width
let maxY = this.imageState.height * scale - this.cropBoxRect.height
let touchPos = this.getFocalPoint(point0, point1)
let newX = zoom * (this.imageState.left + touchPos.x) - touchPos.x
let newY = zoom * ((this.imageState.top - this.imgInitTop) + touchPos.y) - touchPos.y + this.imgInitTop
// 限制缩放
// 图片新位置:由中点位置确认;(新位置到中点)/(旧位置到中点)=(new scale)/(old scale)
// newLeft - touchPos.x = (distance / this.distance) * (oldLetf - touchPos.x)
// oldLeft = 0 - this.imageState.left
// oldTop = imgInitTop - this.imageState.top
this.distance = distance
if (scale < this.minScale) {
this.imageState.scale = this.minScale
} else {
this.imageState.scale = scale
this.imageState.left = newX < 0 ? 0 : (newX > maxX ? maxX : newX)
this.imageState.top = newY < 0 ? 0 : (newY > maxY ? maxY : newY)
}
this.touchPos = touchPos
}
}
}
}
</script>
<style lang="scss" scoped>
$themeColor:#409EFF;
.box {
display: flex;
position: relative;
}
.box-f1 {
flex: 1;
}
.box-ac {
align-items: center
}
.box-jc {
justify-content: center
}
.box-ver {
flex-direction: column
}
.cropper-page {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 10;
background-color: #fff;
overflow: hidden;
}
.cover {
color: #FFF;
font-size: .4rem;
background-color: rgba(0, 0, 0, 0.2);
}
.cropper-box {
// border: 1px dashed #FFF;
border: 2px dashed #FFF;
}
.cropper-img {
position: absolute;
z-index: -1;
}
input[type="file"] {
opacity: 0;
position: fixed;
top: -1000px;
left: -1000px;
}
.btn {
font-size: .6rem;
padding: .1rem .3rem;
border: .02rem solid;
color: #FFF;
border-radius: .4rem;
width:80px;
height:35px;
display: flex;
align-items: center;
justify-content: center;
background:#909399;
&.sure {
background: $themeColor;
}
}
</style>
3.简单使用。
<template>
<div>
<image-cropper ref="imageCropper" :cropperConfig="cropperConfig" :callback="loadImage"></image-cropper>
<button @click="selectFile()">打开</button>
<div>
<img v-if="img" :src="img" style="width:200px;height:200px;"/>
</div>
</div>
</template>
<script>
import imageCropper from '@/components/imageCropper'
export default {
name: 'Home',
components: {imageCropper},
data() {
return {
img:'',
cropperConfig: {
width: 1,
height: 1,
quality: 0.7,
maxWidth: 750
}
};
},
mounted() {
},
methods: {
selectFile () {
this.$refs.imageCropper.checkPhoto()
},
// 图片裁剪之后的回调
loadImage (data) {
// this.images.push(data)
console.log(data)
this.img=data;
},
},
};
</script>
<style lang="scss" scoped>
</style>
更多推荐
已为社区贡献41条内容
所有评论(0)