feat: 首次提交
This commit is contained in:
282
components/firstui/fui-image-cropper/bindingx.js
Normal file
282
components/firstui/fui-image-cropper/bindingx.js
Normal file
@ -0,0 +1,282 @@
|
||||
// 本文件由FirstUI授权予新疆天衡创新研究院有限公司(手机号:18 614 0 72 5 49,身份证尾号:5A07X5)专用,请尊重知识产权,勿私下传播,违者追究法律责任。
|
||||
// #ifdef APP-NVUE
|
||||
const animation = uni.requireNativePlugin('animation');
|
||||
export default {
|
||||
watch: {
|
||||
width(val) {
|
||||
this.canvasWidth = Number(val);
|
||||
},
|
||||
height(val) {
|
||||
this.canvasHeight = Number(val);
|
||||
},
|
||||
changeval(val) {
|
||||
this.$nextTick(() => {
|
||||
setTimeout(() => {
|
||||
this.valsChange(val)
|
||||
}, 50)
|
||||
})
|
||||
},
|
||||
src(val) {
|
||||
this.$nextTick(() => {
|
||||
if (val) {
|
||||
setTimeout(() => {
|
||||
this.ref = this.getEl(this.$refs['fui_cropper_img'])
|
||||
this.realRef = this.getEl(this.$refs['fui_cropper_real'])
|
||||
}, 50)
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
touchRelative: [{
|
||||
x: 0,
|
||||
y: 0
|
||||
}],
|
||||
hypotenuseLength: 0,
|
||||
flagEndTouch: false,
|
||||
canvasWidth: 0,
|
||||
canvasHeight: 0
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.ref = null;
|
||||
this.realRef = null;
|
||||
this.canvasWidth = Number(this.width);
|
||||
this.canvasHeight = Number(this.height);
|
||||
},
|
||||
methods: {
|
||||
cutDetectionPosition() {
|
||||
var windowHeight = this.windowHeight,
|
||||
windowWidth = this.windowWidth;
|
||||
|
||||
var cutDetectionPositionTop = () => {
|
||||
if (this.cutY < 0) {
|
||||
this.cutY = 0;
|
||||
}
|
||||
if (this.cutY > windowHeight - this.canvasHeight) {
|
||||
this.cutY = windowHeight - this.canvasHeight;
|
||||
}
|
||||
}
|
||||
|
||||
var cutDetectionPositionLeft = () => {
|
||||
if (this.cutX < 0) {
|
||||
this.cutX = 0;
|
||||
}
|
||||
if (this.cutX > windowWidth - this.canvasWidth) {
|
||||
this.cutX = windowWidth - this.canvasWidth;
|
||||
}
|
||||
}
|
||||
if (this.cutY == null && this.cutX == null) {
|
||||
var cutY = (windowHeight - this.canvasHeight) * 0.5;
|
||||
var cutX = (windowWidth - this.canvasWidth) * 0.5;
|
||||
this.cutY = cutY;
|
||||
this.cutX = cutX;
|
||||
} else if (this.cutY != null && this.cutX != null) {
|
||||
cutDetectionPositionTop();
|
||||
cutDetectionPositionLeft();
|
||||
} else if (this.cutY != null && this.cutX == null) {
|
||||
cutDetectionPositionTop();
|
||||
this.cutX = (windowWidth - this.canvasWidth) / 2;
|
||||
} else if (this.cutY == null && this.cutX != null) {
|
||||
cutDetectionPositionLeft();
|
||||
this.cutY = (windowHeight - this.canvasHeight) / 2;
|
||||
}
|
||||
},
|
||||
imgMarginDetectionPosition(scale, delay) {
|
||||
var left = this.imgLeft;
|
||||
var top = this.imgTop;
|
||||
scale = 1 // scale || this.scale;
|
||||
var imgWidth = this.imgWidth;
|
||||
var imgHeight = this.imgHeight;
|
||||
if ((this.angle / 90) % 2) {
|
||||
imgWidth = this.imgHeight;
|
||||
imgHeight = this.imgWidth;
|
||||
}
|
||||
left = this.cutX + (imgWidth * scale) / 2 >= left ? left : this.cutX + (imgWidth * scale) / 2;
|
||||
left = this.cutX + this.canvasWidth - (imgWidth * scale) / 2 <= left ? left : this.cutX + this.canvasWidth -
|
||||
(imgWidth * scale) / 2;
|
||||
top = this.cutY + (imgHeight * scale) / 2 >= top ? top : this.cutY + (imgHeight * scale) / 2;
|
||||
top = this.cutY + this.canvasHeight - (imgHeight * scale) / 2 <= top ? top : this.cutY + this.canvasHeight -
|
||||
(imgHeight * scale) / 2;
|
||||
|
||||
this.imgLeft = left;
|
||||
this.imgTop = top;
|
||||
this.scale = scale;
|
||||
if (!delay || delay === 'undefined') {
|
||||
this._animation()
|
||||
}
|
||||
},
|
||||
imgMarginDetectionScale(scale, delay) {
|
||||
scale = 1 //scale || this.scale;
|
||||
var imgWidth = this.imgWidth;
|
||||
var imgHeight = this.imgHeight;
|
||||
if ((this.angle / 90) % 2) {
|
||||
imgWidth = this.imgHeight;
|
||||
imgHeight = this.imgWidth;
|
||||
}
|
||||
if (imgWidth * scale < this.canvasWidth) {
|
||||
scale = this.canvasWidth / imgWidth;
|
||||
}
|
||||
if (imgHeight * scale < this.canvasHeight) {
|
||||
scale = Math.max(scale, this.canvasHeight / imgHeight);
|
||||
}
|
||||
this.imgMarginDetectionPosition(scale, delay);
|
||||
},
|
||||
computeCutSize() {
|
||||
if (this.canvasWidth > this.windowWidth) {
|
||||
this.canvasWidth = this.windowWidth;
|
||||
} else if (this.canvasWidth + this.cutX > this.windowWidth) {
|
||||
this.cutX = this.windowWidth - this.cutX;
|
||||
}
|
||||
if (this.canvasHeight > this.windowHeight) {
|
||||
this.canvasHeight = this.windowHeight;
|
||||
} else if (this.canvasHeight + this.cutY > this.windowHeight) {
|
||||
this.cutY = this.windowHeight - this.cutY;
|
||||
}
|
||||
},
|
||||
setCutCenter() {
|
||||
var cutY = (this.windowHeight - this.canvasHeight) * 0.5;
|
||||
var cutX = (this.windowWidth - this.canvasWidth) * 0.5;
|
||||
this.imgTop = this.imgTop - this.cutY + cutY;
|
||||
this.cutY = cutY;
|
||||
this.imgLeft = this.imgLeft - this.cutX + cutX;
|
||||
this.cutX = cutX;
|
||||
this.cutDetectionPosition()
|
||||
this._animation()
|
||||
},
|
||||
imageReset() {
|
||||
this.scale = 1;
|
||||
this.angle = 0;
|
||||
this._animation()
|
||||
},
|
||||
getEl(el) {
|
||||
return el.ref || el[0].ref;
|
||||
},
|
||||
_animation() {
|
||||
if (!this.ref || !this.realRef) return
|
||||
var x = this.imgLeft - this.imgWidth / 2;
|
||||
var y = this.imgTop - this.imgHeight / 2;
|
||||
animation.transition(this.realRef, {
|
||||
styles: {
|
||||
//暂时去除缩放功能,此功能后期做优化再放出使用
|
||||
// transform: `translate(${x}px,${y}px) scale(${this.scale}) rotate(${this.angle}deg)`
|
||||
transform: `translate(${x}px,${y}px) rotate(${this.angle}deg)`
|
||||
},
|
||||
duration: this.ani ? 250 : 0,
|
||||
timingFunction: 'linear',
|
||||
needLayout: false,
|
||||
delay: 0
|
||||
});
|
||||
animation.transition(this.ref, {
|
||||
styles: {
|
||||
transform: `translate(${x}px,${y}px) rotate(${this.angle}deg)`
|
||||
},
|
||||
duration: this.ani ? 250 : 0,
|
||||
timingFunction: 'linear',
|
||||
needLayout: false,
|
||||
delay: 0
|
||||
});
|
||||
},
|
||||
touchstart(e) {
|
||||
var touch = e.touches || e.changedTouches
|
||||
this.flagEndTouch = false;
|
||||
//暂时放弃双指操作,待后期优化
|
||||
if (touch.length == 1 && true) {
|
||||
this.touchRelative[0] = {
|
||||
x: touch[0].screenX - this.imgLeft,
|
||||
y: touch[0].screenY - this.imgTop
|
||||
};
|
||||
} else {
|
||||
var width = Math.abs(touch[0].screenX - touch[1].screenX);
|
||||
var height = Math.abs(touch[0].screenY - touch[1].screenY);
|
||||
this.touchRelative = [{
|
||||
x: touch[0].screenX - this.imgLeft,
|
||||
y: touch[0].screenY - this.imgTop
|
||||
},
|
||||
{
|
||||
x: touch[1].screenX - this.imgLeft,
|
||||
y: touch[1].screenY - this.imgTop
|
||||
}
|
||||
];
|
||||
this.hypotenuseLength = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2));
|
||||
}
|
||||
},
|
||||
touchmove(e) {
|
||||
var touch = e.touches || e.changedTouches
|
||||
if (this.flagEndTouch || touch.length > 1 || !this.src) return;
|
||||
this.moveDuring();
|
||||
//暂时放弃双指操作,待后期优化
|
||||
if (touch.length == 1 && true) {
|
||||
var left = touch[0].screenX - this.touchRelative[0].x,
|
||||
top = touch[0].screenY - this.touchRelative[0].y;
|
||||
this.imgLeft = left;
|
||||
this.imgTop = top;
|
||||
this._animation()
|
||||
this.imgMarginDetectionPosition();
|
||||
} else {
|
||||
var width = Math.abs(touch[0].screenX - touch[1].screenX),
|
||||
height = Math.abs(touch[0].screenY - touch[1].screenY),
|
||||
hypotenuse = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2)),
|
||||
scale = this.scale * (hypotenuse / this.hypotenuseLength),
|
||||
current_deg = 0;
|
||||
scale = scale <= 0.5 ? 0.5 : scale;
|
||||
scale = scale >= 2 ? 2 : scale;
|
||||
this.imgMarginDetectionScale(scale, true);
|
||||
var touchRelative = [{
|
||||
x: touch[0].screenX - this.imgLeft,
|
||||
y: touch[0].screenY - this.imgTop
|
||||
},
|
||||
{
|
||||
x: touch[1].screenX - this.imgLeft,
|
||||
y: touch[1].screenY - this.imgTop
|
||||
}
|
||||
];
|
||||
this.touchRelative = touchRelative;
|
||||
this.hypotenuseLength = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2));
|
||||
this.angle = this.angle + current_deg;
|
||||
this._animation()
|
||||
}
|
||||
},
|
||||
touchend(e) {
|
||||
this.flagEndTouch = true;
|
||||
this.moveStop();
|
||||
},
|
||||
valsChange(val) {
|
||||
if (val) {
|
||||
var params = val.split('_')
|
||||
var type = Number(params[0])
|
||||
if (type == 3) {
|
||||
this._animation()
|
||||
}
|
||||
switch (type) {
|
||||
case 1:
|
||||
this.setCutCenter();
|
||||
this.computeCutSize();
|
||||
this.cutDetectionPosition();
|
||||
break;
|
||||
case 2:
|
||||
this.setCutCenter();
|
||||
break;
|
||||
case 3:
|
||||
this.imgMarginDetectionScale()
|
||||
break;
|
||||
case 4:
|
||||
this.imageReset();
|
||||
break;
|
||||
case 5:
|
||||
this.setCutCenter();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// #endif
|
||||
|
||||
// #ifndef APP-NVUE
|
||||
export default {}
|
||||
// #endif
|
677
components/firstui/fui-image-cropper/fui-image-cropper.vue
Normal file
677
components/firstui/fui-image-cropper/fui-image-cropper.vue
Normal file
@ -0,0 +1,677 @@
|
||||
<!--本文件由FirstUI授权予新疆天衡创新研究院有限公司(手机号: 1 861 4 0 72 549,身份证尾号:5A07X5)专用,请尊重知识产权,勿私下传播,违者追究法律责任。-->
|
||||
<template>
|
||||
<view class="fui-image__cropper" @touchmove.stop.prevent="stop">
|
||||
<!-- #ifdef APP-VUE || MP-WEIXIN || H5 -->
|
||||
<image @touchstart="handler.touchstart" @touchmove="handler.touchmove" @touchend="handler.touchend"
|
||||
@mousedown="handler.mousedown" class="fui-cropper__img"
|
||||
:class="{'fui-cropper__img-hidden':!src || !initVal}" :src="src"
|
||||
:style="{width: (imgWidth ? imgWidth : width) + 'px',height: imgHeight ? imgHeight + 'px' : 'auto',transitionDuration: ani ?'0.25s' : '0s'}"
|
||||
mode="widthFix">
|
||||
</image>
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef APP-NVUE -->
|
||||
<image ref="fui_cropper_img" class="fui-cropper__img" :src="src"
|
||||
:style="{width: (imgWidth ? imgWidth : width) + 'px',height: imgHeight ? imgHeight + 'px' : 'auto'}"
|
||||
mode="widthFix">
|
||||
</image>
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef APP-PLUS || MP-WEIXIN || H5 -->
|
||||
<image @touchstart="touchstart" @touchmove="touchmove" @touchend="touchend" class="fui-cropper__img"
|
||||
:class="{'fui-cropper__img-hidden':!src || !initVal}" :src="src"
|
||||
:style="{width: (imgWidth ? imgWidth : width) + 'px',height: imgHeight ? imgHeight + 'px' : 'auto',transitionDuration: ani ?'0.25s' : '0s',transform:getTransform}"
|
||||
mode="widthFix">
|
||||
</image>
|
||||
<!-- #endif -->
|
||||
|
||||
<!-- #ifdef APP-NVUE -->
|
||||
<view class="fui-cropper__mask">
|
||||
<view class="fui-cropper__top" :style="{height:(windowHeight-canvasHeight)/2+'px'}"></view>
|
||||
<view class="fui-cropper__left" :style="{width:(windowWidth-canvasWidth)/2+'px',height:height+'px'}"></view>
|
||||
<view class="fui-cropper__right" :style="{width:(windowWidth-canvasWidth)/2+'px',height:height+'px'}">
|
||||
</view>
|
||||
<view class="fui-cropper__bottom" :style="{height:(windowHeight-canvasHeight)/2+'px'}"></view>
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef APP-NVUE -->
|
||||
<view class="fui-cropper__mask"
|
||||
:style="{ width: width + 'px', height: height + 'px', borderRadius: round ? '50%' : '0' }">
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef APP-VUE || MP-WEIXIN || H5-->
|
||||
<view class="fui-cropper__border" :change:prop="handler.valsChange" :prop="changeval"
|
||||
:data-width="width" :data-height="height" :data-windowHeight="windowHeight"
|
||||
:data-windowWidth="windowWidth" :data-imgWidth="imgWidth" :data-imgHeight="imgHeight"
|
||||
:data-imgTop="imgTop" :data-angle="angle"
|
||||
:style="{ borderRadius: round ? '50%' : '0',borderColor:borderColor}"></view>
|
||||
<!-- #endif -->
|
||||
|
||||
<!-- #ifdef APP-NVUE -->
|
||||
<view class="fui-cropper__border"
|
||||
:style="{width:width+'px',height:height+'px', borderRadius: round ? canvasWidth/2+'px' : '0',borderColor:borderColor}">
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
|
||||
<!-- #ifndef APP-PLUS || MP-WEIXIN || H5 -->
|
||||
<view class="fui-cropper__border" :style="{ borderRadius: round ? '50%' : '0',borderColor:borderColor}">
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
|
||||
<!-- #ifdef APP-NVUE -->
|
||||
<view class="fui-cropper__real-el"
|
||||
:style="{width: (imgWidth ? imgWidth : width) + 'px',height: imgHeight ? imgHeight + 'px' : 'auto'}"
|
||||
@touchstart="touchstart" @touchmove="touchmove" @touchend="touchend" ref="fui_cropper_real"></view>
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
|
||||
<!-- #ifndef APP-NVUE -->
|
||||
<canvas canvas-id="fui_image_cropper" id="fui_image_cropper" :disable-scroll="true"
|
||||
:style="{ width: nWidth * nScaleRatio + 'px', height: nWidth * nScaleRatio + 'px' }"
|
||||
class="fui-cropper__canvas"></canvas>
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<!-- #ifdef APP-VUE || MP-WEIXIN || H5-->
|
||||
<script src="./index.wxs" module="handler" lang="wxs"></script>
|
||||
<!-- #endif -->
|
||||
|
||||
<script>
|
||||
import mpjs from './mpjs.js'
|
||||
import bindingx from './bindingx.js'
|
||||
export default {
|
||||
name: "fui-image-cropper",
|
||||
mixins: [mpjs, bindingx],
|
||||
props: {
|
||||
src: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
//裁剪框高度 px
|
||||
height: {
|
||||
type: [Number, String],
|
||||
default: 280
|
||||
},
|
||||
//裁剪框宽度 px
|
||||
width: {
|
||||
type: [Number, String],
|
||||
default: 280
|
||||
},
|
||||
//是否为圆形裁剪框
|
||||
round: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
borderColor: {
|
||||
type: String,
|
||||
default: '#B2B2B2'
|
||||
},
|
||||
// #ifndef MP-QQ
|
||||
scaleRatio: {
|
||||
type: [Number, String],
|
||||
default: 2
|
||||
},
|
||||
// #endif
|
||||
// #ifdef MP-QQ
|
||||
scaleRatio: {
|
||||
type: [Number, String],
|
||||
default: 3
|
||||
},
|
||||
// #endif
|
||||
//图片的质量,取值范围为 (0, 1],不在范围内时当作1.0处理
|
||||
quality: {
|
||||
type: Number,
|
||||
default: 0.8
|
||||
},
|
||||
fileType: {
|
||||
type: String,
|
||||
default: 'png'
|
||||
},
|
||||
//是否为网络图片
|
||||
network: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
src(val) {
|
||||
this.initVal && this.handleImage(val)
|
||||
},
|
||||
ani(val) {
|
||||
clearTimeout(this.aniTimer);
|
||||
if (val) {
|
||||
this.aniTimer = setTimeout(() => {
|
||||
this.ani = false;
|
||||
}, 220);
|
||||
}
|
||||
},
|
||||
scaleRatio(val) {
|
||||
this.nScaleRatio = Number(val) || 2
|
||||
},
|
||||
width(val) {
|
||||
this.nWidth = Number(val) || 280
|
||||
},
|
||||
height(val) {
|
||||
this.nHeight = Number(val) || 280
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
windowHeight: 600,
|
||||
windowWidth: 400,
|
||||
cutX: 0,
|
||||
cutY: 0,
|
||||
imgWidth: 0,
|
||||
imgHeight: 0,
|
||||
scale: 1,
|
||||
angle: 0,
|
||||
ani: false,
|
||||
imgTop: 0,
|
||||
imgLeft: 0,
|
||||
changeval: '',
|
||||
initVal: false,
|
||||
naturalWidth: 0,
|
||||
naturalHeight: 0,
|
||||
picturePath: '',
|
||||
rotateAngle: 0,
|
||||
nScaleRatio: 2,
|
||||
nWidth: 280,
|
||||
nHeight: 280
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.cutTimer = null;
|
||||
this.aniTimer = null;
|
||||
this.ctx = null;
|
||||
this.nScaleRatio = Number(this.scaleRatio) || 2
|
||||
this.nWidth = Number(this.width) || 280
|
||||
this.nHeight = Number(this.height) || 280
|
||||
},
|
||||
mounted() {
|
||||
let sys = uni.getSystemInfoSync();
|
||||
this.windowHeight = sys.windowHeight
|
||||
this.windowWidth = sys.windowWidth
|
||||
this.imgTop = sys.windowHeight / 2;
|
||||
this.imgLeft = sys.windowWidth / 2;
|
||||
this.$nextTick(() => {
|
||||
// #ifndef APP-NVUE
|
||||
this.ctx = uni.createCanvasContext('fui_image_cropper', this);
|
||||
// #endif
|
||||
setTimeout(() => {
|
||||
this.changeval = `1_${this.getRandom()}`;
|
||||
this.initVal = true
|
||||
setTimeout(() => {
|
||||
this.src && this.handleImage(this.src)
|
||||
}, 50);
|
||||
}, 220);
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
stop() {},
|
||||
getRandom() {
|
||||
return Math.ceil(Math.random() * 10e5).toString(36)
|
||||
},
|
||||
loading() {
|
||||
uni.showLoading({
|
||||
// #ifndef MP-ALIPAY
|
||||
mask: true,
|
||||
// #endif
|
||||
title: '请稍候...'
|
||||
});
|
||||
},
|
||||
reset() {
|
||||
this.scale = 1;
|
||||
this.angle = 0;
|
||||
let sys = uni.getSystemInfoSync();
|
||||
this.imgTop = sys.windowHeight / 2;
|
||||
this.imgLeft = sys.windowWidth / 2;
|
||||
this.changeval = `4_${this.getRandom()}`;
|
||||
},
|
||||
calcSize(width, height) {
|
||||
let imgWidth = width,
|
||||
imgHeight = height;
|
||||
if (imgWidth > 0 && imgHeight > 0) {
|
||||
if (imgWidth / imgHeight > this.nWidth / this.nHeight) {
|
||||
imgHeight = this.nHeight;
|
||||
imgWidth = (width / height) * imgHeight;
|
||||
} else {
|
||||
imgWidth = this.nWidth;
|
||||
imgHeight = (height / width) * imgWidth;
|
||||
}
|
||||
} else {
|
||||
imgWidth = uni.getSystemInfoSync().windowWidth;
|
||||
imgHeight = 0;
|
||||
}
|
||||
this.imgWidth = imgWidth;
|
||||
this.imgHeight = imgHeight;
|
||||
this.changeval = `2_${this.getRandom()}`;
|
||||
uni.hideLoading()
|
||||
},
|
||||
// #ifdef APP-NVUE
|
||||
async compressImage(url, width, height, orientation) {
|
||||
let imgUrl = url;
|
||||
if (this.network) {
|
||||
imgUrl = await this.getLocalImage(url);
|
||||
if (!imgUrl) {
|
||||
this.toast('网络图片处理失败~');
|
||||
return;
|
||||
}
|
||||
}
|
||||
let defaultAngle = {
|
||||
up: 0,
|
||||
down: 180,
|
||||
left: 270,
|
||||
right: 90
|
||||
} [orientation] || 0;
|
||||
let f_dst = `_documents/${this.getRandom()}.jpg`;
|
||||
plus.zip.compressImage({
|
||||
src: imgUrl,
|
||||
dst: f_dst,
|
||||
overwrite: true,
|
||||
rotate: defaultAngle,
|
||||
format: 'jpg'
|
||||
},
|
||||
i => {
|
||||
this.picturePath = i.target;
|
||||
this.calcSize(width, height);
|
||||
this.changeval = `3_${this.getRandom()}`;
|
||||
},
|
||||
e => {
|
||||
this.picturePath = imgUrl;
|
||||
this.calcSize(width, height);
|
||||
this.changeval = `3_${this.getRandom()}`;
|
||||
}
|
||||
);
|
||||
},
|
||||
// #endif
|
||||
handleImage(src) {
|
||||
this.reset();
|
||||
this.loading();
|
||||
uni.getImageInfo({
|
||||
src: src,
|
||||
success: res => {
|
||||
let width = res.width;
|
||||
let height = res.height;
|
||||
this.naturalWidth = width;
|
||||
this.naturalHeight = height;
|
||||
let orientation = res.orientation;
|
||||
if (orientation && orientation != 'up') {
|
||||
//宽高传值颠倒
|
||||
width = orientation == 'down' ? res.width : res.height;
|
||||
height = orientation == 'down' ? res.height : res.width;
|
||||
//此处需要测试,可能导致裁剪出错
|
||||
// #ifdef APP-NVUE
|
||||
this.compressImage(src, width, height, orientation);
|
||||
// #endif
|
||||
} else {
|
||||
// #ifdef APP-NVUE
|
||||
this.calcSize(width, height);
|
||||
this.changeval = `3_${this.getRandom()}`;
|
||||
// #endif
|
||||
}
|
||||
|
||||
// #ifndef APP-NVUE
|
||||
this.calcSize(width, height);
|
||||
this.changeval = `3_${this.getRandom()}`;
|
||||
// #endif
|
||||
},
|
||||
fail: err => {
|
||||
this.calcSize(0, 0);
|
||||
this.changeval = `3_${this.getRandom()}`;
|
||||
}
|
||||
});
|
||||
},
|
||||
change(e) {
|
||||
this.cutX = e.cutX || 0;
|
||||
this.cutY = e.cutY || 0;
|
||||
this.imgWidth = e.imgWidth || this.imgWidth;
|
||||
this.imgHeight = e.imgHeight || this.imgHeight;
|
||||
this.scale = e.scale || 1;
|
||||
this.angle = e.angle || 0;
|
||||
this.imgTop = e.imgTop || 0;
|
||||
this.imgLeft = e.imgLeft || 0;
|
||||
},
|
||||
async getLocalImage(src) {
|
||||
return await new Promise((resolve, reject) => {
|
||||
uni.downloadFile({
|
||||
url: src,
|
||||
success: res => {
|
||||
resolve(res.tempFilePath);
|
||||
},
|
||||
fail: res => {
|
||||
reject(false);
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
moveStop() {
|
||||
clearTimeout(this.cutTimer);
|
||||
this.cutTimer = setTimeout(() => {
|
||||
this.changeval = `5_${this.getRandom()}`;
|
||||
}, 600);
|
||||
},
|
||||
moveDuring() {
|
||||
clearTimeout(this.cutTimer);
|
||||
},
|
||||
rotate() {
|
||||
if (!this.src) {
|
||||
this.toast('请选择要裁剪的图片!')
|
||||
return;
|
||||
}
|
||||
this.ani = true;
|
||||
let angle = this.angle + 90;
|
||||
if (angle % 90) {
|
||||
angle = Math.round(angle / 90) * 90;
|
||||
}
|
||||
this.angle = angle
|
||||
this.moveStop();
|
||||
this.changeval = `3_${this.getRandom()}`;
|
||||
},
|
||||
toast(text) {
|
||||
uni.showToast({
|
||||
title: text,
|
||||
icon: 'none'
|
||||
});
|
||||
},
|
||||
// #ifdef APP-NVUE
|
||||
getImageByNvue(callback) {
|
||||
let getCutImg = async () => {
|
||||
let imgUrl = this.picturePath || this.src;
|
||||
if (this.network) {
|
||||
imgUrl = await this.getLocalImage(this.src);
|
||||
if (!imgUrl) {
|
||||
this.toast('网络图片处理失败~');
|
||||
return;
|
||||
}
|
||||
}
|
||||
let f_dst = `_documents/${this.getRandom()}.${this.fileType}`;
|
||||
let multiple = Math.round(this.angle / 90);
|
||||
let angle = 0,
|
||||
x = 0,
|
||||
y = 0,
|
||||
left = 0,
|
||||
top = 0,
|
||||
clipHeight = 0,
|
||||
clipWidth = 0;
|
||||
let sys = uni.getSystemInfoSync();
|
||||
let isAndroid = sys.platform.toLocaleLowerCase() == 'android';
|
||||
|
||||
if (multiple % 2 == 0) {
|
||||
angle = this.angle % 360 == 0 || this.angle == 0 ? 0 : 180;
|
||||
if (!isAndroid || (isAndroid && angle == 0)) {
|
||||
x = this.imgLeft - (this.imgWidth * this.scale) / 2;
|
||||
y = this.imgTop - (this.imgHeight * this.scale) / 2;
|
||||
left = (((this.cutX - x) / this.imgWidth / this.scale) * 100).toFixed(2);
|
||||
top = (((this.cutY - y) / this.imgHeight / this.scale) * 100).toFixed(2);
|
||||
clipWidth = ((this.canvasWidth / this.imgWidth / this.scale) * 100).toFixed(2);
|
||||
clipHeight = ((this.canvasHeight / this.imgHeight / this.scale) * 100).toFixed(2);
|
||||
} else {
|
||||
x = this.imgLeft - (this.imgWidth * this.scale) / 2;
|
||||
y = this.imgTop - (this.imgHeight * this.scale) / 2;
|
||||
left = (((this.imgWidth * this.scale - (this.cutX - x) - this.canvasWidth) / this
|
||||
.imgWidth / this.scale) * 100).toFixed(2);
|
||||
top = (((this.imgHeight * this.scale - (this.cutY - y) - this.canvasHeight) / this
|
||||
.imgHeight / this.scale) * 100).toFixed(2);
|
||||
clipWidth = ((this.canvasWidth / this.imgWidth / this.scale) * 100).toFixed(2);
|
||||
clipHeight = ((this.canvasHeight / this.imgHeight / this.scale) * 100).toFixed(2);
|
||||
}
|
||||
} else {
|
||||
angle = this.angle % 270 == 0 ? 270 : 90;
|
||||
if (isAndroid) {
|
||||
if (angle == 90) {
|
||||
x = this.imgLeft - (this.imgHeight * this.scale) / 2;
|
||||
y = this.imgTop - (this.imgWidth * this.scale) / 2;
|
||||
top = (((this.imgHeight * this.scale - (this.cutX - x) - this.canvasHeight) / this
|
||||
.imgHeight / this.scale) * 100).toFixed(2);
|
||||
left = (((this.imgWidth * this.scale - (this.cutY - y) - this.canvasWidth) / this
|
||||
.imgWidth / this.scale) * 100).toFixed(2);
|
||||
clipHeight = ((this.canvasWidth / this.imgHeight / this.scale) * 100).toFixed(2);
|
||||
clipWidth = ((this.canvasHeight / this.imgWidth / this.scale) * 100).toFixed(2);
|
||||
} else {
|
||||
x = this.imgLeft - (this.imgHeight * this.scale) / 2;
|
||||
y = this.imgTop - (this.imgWidth * this.scale) / 2;
|
||||
top = (((this.cutX - x) / this.imgHeight / this.scale) * 100).toFixed(2);
|
||||
left = (((this.cutY - y) / this.imgWidth / this.scale) * 100).toFixed(2);
|
||||
clipHeight = ((this.canvasWidth / this.imgHeight / this.scale) * 100).toFixed(2);
|
||||
clipWidth = ((this.canvasHeight / this.imgWidth / this.scale) * 100).toFixed(2);
|
||||
}
|
||||
} else {
|
||||
x = this.imgLeft - (this.imgHeight * this.scale) / 2;
|
||||
y = this.imgTop - (this.imgWidth * this.scale) / 2;
|
||||
left = (((this.cutX - x) / this.imgHeight / this.scale) * 100).toFixed(2);
|
||||
top = (((this.cutY - y) / this.imgWidth / this.scale) * 100).toFixed(2);
|
||||
clipWidth = ((this.canvasWidth / this.imgHeight / this.scale) * 100).toFixed(2);
|
||||
clipHeight = ((this.canvasHeight / this.imgWidth / this.scale) * 100).toFixed(2);
|
||||
}
|
||||
}
|
||||
let width = (this.imgWidth < this.naturalWidth ? this.naturalWidth : this.imgWidth) * this
|
||||
.scale;
|
||||
let height = (this.imgHeight < this.naturalHeight ? this.naturalHeight : this.imgHeight) * this
|
||||
.scale;
|
||||
width = `${width}px`;
|
||||
height = `${height}px`;
|
||||
left = Number(left) <= 0 ? 0 : left;
|
||||
top = Number(top) <= 0 ? 0 : top;
|
||||
plus.zip.compressImage({
|
||||
src: imgUrl,
|
||||
dst: f_dst,
|
||||
quality: this.quality * 100,
|
||||
overwrite: true,
|
||||
format: this.fileType,
|
||||
width: width,
|
||||
height: height,
|
||||
rotate: angle,
|
||||
clip: {
|
||||
top: `${top}%`,
|
||||
left: `${left}%`,
|
||||
width: `${clipWidth}%`,
|
||||
height: `${clipHeight}%`
|
||||
}
|
||||
},
|
||||
i => {
|
||||
uni.hideLoading();
|
||||
callback && callback(i.target)
|
||||
},
|
||||
e => {
|
||||
console.log(e);
|
||||
uni.hideLoading();
|
||||
this.toast('图片裁剪失败,请稍候再试~');
|
||||
}
|
||||
);
|
||||
};
|
||||
setTimeout(() => {
|
||||
getCutImg();
|
||||
}, 20);
|
||||
},
|
||||
// #endif
|
||||
//裁剪
|
||||
cutting(callback) {
|
||||
if (!this.src) {
|
||||
this.toast('请选择要裁剪的图片!')
|
||||
return;
|
||||
}
|
||||
this.loading();
|
||||
// #ifdef APP-NVUE
|
||||
this.getImageByNvue(callback)
|
||||
// #endif
|
||||
|
||||
// #ifndef APP-NVUE
|
||||
let draw = async () => {
|
||||
let imgWidth = this.imgWidth * this.scale * this.nScaleRatio;
|
||||
let imgHeight = this.imgHeight * this.scale * this.nScaleRatio;
|
||||
let xpos = this.imgLeft - this.cutX;
|
||||
let ypos = this.imgTop - this.cutY;
|
||||
this.ctx.translate(xpos * this.nScaleRatio, ypos * this.nScaleRatio);
|
||||
this.ctx.rotate((this.angle * Math.PI) / 180);
|
||||
let src = this.src;
|
||||
// #ifdef APP-PLUS || MP
|
||||
if (this.network) {
|
||||
src = await this.getLocalImage(this.src);
|
||||
}
|
||||
// #endif
|
||||
this.ctx.drawImage(src, -imgWidth / 2, -imgHeight / 2, imgWidth, imgHeight);
|
||||
this.ctx.draw(false, () => {
|
||||
let params = {
|
||||
width: this.nWidth * this.nScaleRatio,
|
||||
height: Math.round(this.nHeight * this.nScaleRatio),
|
||||
// #ifdef MP-QQ
|
||||
destWidth: this.nWidth * this.nScaleRatio * 2,
|
||||
destHeight: Math.round(this.nHeight) * this.nScaleRatio * 2,
|
||||
// #endif
|
||||
|
||||
// #ifndef MP-QQ
|
||||
destWidth: this.nWidth * this.nScaleRatio,
|
||||
destHeight: Math.round(this.nHeight) * this.nScaleRatio,
|
||||
// #endif
|
||||
fileType: this.fileType,
|
||||
quality: this.quality
|
||||
};
|
||||
setTimeout(() => {
|
||||
// #ifdef MP-ALIPAY
|
||||
this.ctx.toTempFilePath({
|
||||
...params,
|
||||
success: res => {
|
||||
uni.hideLoading();
|
||||
this.ctx.rotate(((360 - this.angle % 360) * Math
|
||||
.PI) / 180);
|
||||
this.ctx.translate(-xpos * this.nScaleRatio, -
|
||||
ypos * this.nScaleRatio);
|
||||
this.ctx.clearRect(0, 0, this.nWidth * this
|
||||
.nScaleRatio, this.nHeight * this
|
||||
.nScaleRatio);
|
||||
this.ctx.draw();
|
||||
callback && callback(res.apFilePath)
|
||||
}
|
||||
});
|
||||
// #endif
|
||||
|
||||
// #ifndef MP-ALIPAY
|
||||
uni.canvasToTempFilePath({
|
||||
...params,
|
||||
canvasId: 'fui_image_cropper',
|
||||
success: res => {
|
||||
uni.hideLoading();
|
||||
callback && callback(res.tempFilePath)
|
||||
},
|
||||
fail(err) {
|
||||
console.log(err);
|
||||
}
|
||||
},
|
||||
this
|
||||
);
|
||||
// #endif
|
||||
}, 80)
|
||||
});
|
||||
};
|
||||
draw();
|
||||
// #endif
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.fui-image__cropper {
|
||||
background: rgba(0, 0, 0, 0.6);
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.fui-cropper__img,
|
||||
.fui-cropper__real-el {
|
||||
/* #ifndef APP-NVUE */
|
||||
backface-visibility: hidden;
|
||||
/* #endif */
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 2;
|
||||
transform-origin: center;
|
||||
}
|
||||
|
||||
/* #ifndef APP-NVUE */
|
||||
.fui-cropper__img-hidden {
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
/* #endif */
|
||||
.fui-cropper__mask {
|
||||
position: fixed;
|
||||
z-index: 4;
|
||||
/* #ifndef APP-NVUE */
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
border: 3000px solid rgba(0, 0, 0, 0.5);
|
||||
pointer-events: none;
|
||||
/* #endif */
|
||||
|
||||
/* #ifdef APP-NVUE */
|
||||
border-style: solid;
|
||||
border-color: rgba(0, 0, 0, 0.5);
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.fui-cropper__border {
|
||||
/* #ifndef APP-NVUE */
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
box-sizing: border-box;
|
||||
pointer-events: none;
|
||||
/* #endif */
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
}
|
||||
|
||||
/* #ifndef APP-NVUE */
|
||||
.fui-cropper__canvas {
|
||||
position: fixed;
|
||||
left: -3000px;
|
||||
top: -3000px;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* #endif */
|
||||
|
||||
/* #ifdef APP-NVUE */
|
||||
.fui-cropper__top {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
.fui-cropper__left {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
.fui-cropper__right {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
.fui-cropper__bottom {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
/* #endif */
|
||||
</style>
|
342
components/firstui/fui-image-cropper/index.wxs
Normal file
342
components/firstui/fui-image-cropper/index.wxs
Normal file
@ -0,0 +1,342 @@
|
||||
// 本文件由FirstUI授权予新疆天衡创新研究院有限公司(手机号:18 614 072 549,身份证尾号:5A07X5)专用,请尊重知识产权,勿私下传播,违者追究法律责任。
|
||||
function isPC() {
|
||||
if (typeof navigator !== 'object') return false;
|
||||
var userAgentInfo = navigator.userAgent;
|
||||
var Agents = ["Android", "iPhone", "SymbianOS", "Windows Phone", "iPad", "iPod"];
|
||||
var flag = true;
|
||||
for (var v = 0; v < Agents.length - 1; v++) {
|
||||
if (userAgentInfo.indexOf(Agents[v]) > 0) {
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
var isH5 = false
|
||||
if (typeof window === 'object') isH5 = true
|
||||
var cropper = {
|
||||
cutX: 0,
|
||||
cutY: 0,
|
||||
touchRelative: [{
|
||||
x: 0,
|
||||
y: 0
|
||||
}],
|
||||
hypotenuseLength: 0,
|
||||
flagEndTouch: false,
|
||||
canvasWidth: 0,
|
||||
canvasHeight: 0,
|
||||
imgWidth: 0,
|
||||
imgHeight: 0,
|
||||
scale: 1,
|
||||
angle: 0,
|
||||
imgTop: 0,
|
||||
imgLeft: 0,
|
||||
windowHeight: 0,
|
||||
windowWidth: 0,
|
||||
init: true
|
||||
}
|
||||
|
||||
function touchstart(e, ins) {
|
||||
var touch = null
|
||||
if (isH5 && isPC()) {
|
||||
touch = [e];
|
||||
} else {
|
||||
touch = e.touches || e.changedTouches
|
||||
}
|
||||
cropper.flagEndTouch = false;
|
||||
if (touch.length == 1) {
|
||||
cropper.touchRelative[0] = {
|
||||
x: touch[0].pageX - cropper.imgLeft,
|
||||
y: touch[0].pageY - cropper.imgTop
|
||||
};
|
||||
} else {
|
||||
var width = Math.abs(touch[0].pageX - touch[1].pageX);
|
||||
var height = Math.abs(touch[0].pageY - touch[1].pageY);
|
||||
cropper.touchRelative = [{
|
||||
x: touch[0].pageX - cropper.imgLeft,
|
||||
y: touch[0].pageY - cropper.imgTop
|
||||
},
|
||||
{
|
||||
x: touch[1].pageX - cropper.imgLeft,
|
||||
y: touch[1].pageY - cropper.imgTop
|
||||
}
|
||||
];
|
||||
cropper.hypotenuseLength = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function moveDuring(ins) {
|
||||
if (!ins) return;
|
||||
ins.callMethod('moveDuring')
|
||||
}
|
||||
|
||||
function moveStop(ins) {
|
||||
if (!ins) return;
|
||||
ins.callMethod('moveStop')
|
||||
};
|
||||
|
||||
function setCutCenter(ins) {
|
||||
var cutY = (cropper.windowHeight - cropper.canvasHeight) * 0.5;
|
||||
var cutX = (cropper.windowWidth - cropper.canvasWidth) * 0.5;
|
||||
cropper.imgTop = cropper.imgTop - cropper.cutY + cutY;
|
||||
cropper.cutY = cutY;
|
||||
cropper.imgLeft = cropper.imgLeft - cropper.cutX + cutX;
|
||||
cropper.cutX = cutX;
|
||||
cutDetectionPosition(ins)
|
||||
imgTransform(ins)
|
||||
updateData(ins)
|
||||
}
|
||||
|
||||
function touchmove(e, ins) {
|
||||
if (e.preventDefault) {
|
||||
e.preventDefault()
|
||||
}
|
||||
var touch = null
|
||||
if (isH5 && isPC()) {
|
||||
touch = [e];
|
||||
} else {
|
||||
touch = e.touches || e.changedTouches
|
||||
}
|
||||
if (cropper.flagEndTouch) return;
|
||||
moveDuring(ins);
|
||||
if (touch.length == 1) {
|
||||
var left = touch[0].pageX - cropper.touchRelative[0].x,
|
||||
top = touch[0].pageY - cropper.touchRelative[0].y;
|
||||
cropper.imgLeft = left;
|
||||
cropper.imgTop = top;
|
||||
imgTransform(ins);
|
||||
imgMarginDetectionPosition(ins);
|
||||
} else {
|
||||
var res = e.instance.getDataset();
|
||||
var width = Math.abs(touch[0].pageX - touch[1].pageX),
|
||||
height = Math.abs(touch[0].pageY - touch[1].pageY),
|
||||
hypotenuse = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2)),
|
||||
scale = cropper.scale * (hypotenuse / cropper.hypotenuseLength),
|
||||
current_deg = 0;
|
||||
scale = scale <= 0.5 ? 0.5 : scale;
|
||||
scale = scale >= 2 ? 2 : scale;
|
||||
cropper.scale = scale;
|
||||
imgMarginDetectionScale(ins, true);
|
||||
var touchRelative = [{
|
||||
x: touch[0].pageX - cropper.imgLeft,
|
||||
y: touch[0].pageY - cropper.imgTop
|
||||
},
|
||||
{
|
||||
x: touch[1].pageX - cropper.imgLeft,
|
||||
y: touch[1].pageY - cropper.imgTop
|
||||
}
|
||||
];
|
||||
cropper.touchRelative = touchRelative;
|
||||
cropper.hypotenuseLength = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2));
|
||||
cropper.angle = cropper.angle + current_deg;
|
||||
imgTransform(ins);
|
||||
}
|
||||
}
|
||||
|
||||
function touchend(e, ins) {
|
||||
cropper.flagEndTouch = true;
|
||||
moveStop(ins);
|
||||
updateData(ins)
|
||||
}
|
||||
|
||||
function cutDetectionPosition(ins) {
|
||||
var windowHeight = cropper.windowHeight,
|
||||
windowWidth = cropper.windowWidth;
|
||||
|
||||
var cutDetectionPositionTop = function() {
|
||||
if (cropper.cutY < 0) {
|
||||
cropper.cutY = 0;
|
||||
}
|
||||
if (cropper.cutY > windowHeight - cropper.canvasHeight) {
|
||||
cropper.cutY = windowHeight - cropper.canvasHeight;
|
||||
}
|
||||
}
|
||||
|
||||
var cutDetectionPositionLeft = function() {
|
||||
if (cropper.cutX < 0) {
|
||||
cropper.cutX = 0;
|
||||
}
|
||||
if (cropper.cutX > windowWidth - cropper.canvasWidth) {
|
||||
cropper.cutX = windowWidth - cropper.canvasWidth;
|
||||
}
|
||||
}
|
||||
if (cropper.cutY == null && cropper.cutX == null) {
|
||||
var cutY = (windowHeight - cropper.canvasHeight) * 0.5;
|
||||
var cutX = (windowWidth - cropper.canvasWidth) * 0.5;
|
||||
cropper.cutY = cutY;
|
||||
cropper.cutX = cutX;
|
||||
} else if (cropper.cutY != null && cropper.cutX != null) {
|
||||
cutDetectionPositionTop();
|
||||
cutDetectionPositionLeft();
|
||||
} else if (cropper.cutY != null && cropper.cutX == null) {
|
||||
cutDetectionPositionTop();
|
||||
cropper.cutX = (windowWidth - cropper.canvasWidth) / 2;
|
||||
} else if (cropper.cutY == null && cropper.cutX != null) {
|
||||
cutDetectionPositionLeft();
|
||||
cropper.cutY = (windowHeight - cropper.canvasHeight) / 2;
|
||||
}
|
||||
}
|
||||
|
||||
function imgMarginDetectionScale(ins, delay) {
|
||||
var scale = cropper.scale;
|
||||
var imgWidth = cropper.imgWidth;
|
||||
var imgHeight = cropper.imgHeight;
|
||||
if ((cropper.angle / 90) % 2) {
|
||||
imgWidth = cropper.imgHeight;
|
||||
imgHeight = cropper.imgWidth;
|
||||
}
|
||||
if (imgWidth * scale < cropper.canvasWidth) {
|
||||
scale = cropper.canvasWidth / imgWidth;
|
||||
}
|
||||
if (imgHeight * scale < cropper.canvasHeight) {
|
||||
scale = Math.max(scale, cropper.canvasHeight / imgHeight);
|
||||
}
|
||||
imgMarginDetectionPosition(ins, scale, delay);
|
||||
}
|
||||
|
||||
function imgMarginDetectionPosition(ins, scale, delay) {
|
||||
var left = cropper.imgLeft;
|
||||
var top = cropper.imgTop;
|
||||
scale = scale || cropper.scale;
|
||||
var imgWidth = cropper.imgWidth;
|
||||
var imgHeight = cropper.imgHeight;
|
||||
if ((cropper.angle / 90) % 2) {
|
||||
imgWidth = cropper.imgHeight;
|
||||
imgHeight = cropper.imgWidth;
|
||||
}
|
||||
left = cropper.cutX + (imgWidth * scale) / 2 >= left ? left : cropper.cutX + (imgWidth * scale) / 2;
|
||||
left = cropper.cutX + cropper.canvasWidth - (imgWidth * scale) / 2 <= left ? left : cropper.cutX + cropper
|
||||
.canvasWidth -
|
||||
(imgWidth * scale) / 2;
|
||||
top = cropper.cutY + (imgHeight * scale) / 2 >= top ? top : cropper.cutY + (imgHeight * scale) / 2;
|
||||
top = cropper.cutY + cropper.canvasHeight - (imgHeight * scale) / 2 <= top ? top : cropper.cutY + cropper
|
||||
.canvasHeight -
|
||||
(imgHeight * scale) / 2;
|
||||
|
||||
cropper.imgLeft = left;
|
||||
cropper.imgTop = top;
|
||||
cropper.scale = scale;
|
||||
if (!delay || delay === 'null') {
|
||||
imgTransform(ins);
|
||||
}
|
||||
}
|
||||
|
||||
function computeCutSize(ins) {
|
||||
if (cropper.canvasWidth > cropper.windowWidth) {
|
||||
cropper.canvasWidth = cropper.windowWidth;
|
||||
} else if (cropper.canvasWidth + cropper.cutX > cropper.windowWidth) {
|
||||
cropper.cutX = cropper.windowWidth - cropper.cutX;
|
||||
}
|
||||
if (cropper.canvasHeight > cropper.windowHeight) {
|
||||
cropper.canvasHeight = cropper.windowHeight;
|
||||
} else if (cropper.canvasHeight + cropper.cutY > cropper.windowHeight) {
|
||||
cropper.cutY = cropper.windowHeight - cropper.cutY;
|
||||
}
|
||||
}
|
||||
|
||||
function imgTransform(ins) {
|
||||
var owner = ins.selectComponent('.fui-cropper__img')
|
||||
if (!owner) return
|
||||
var x = cropper.imgLeft - cropper.imgWidth / 2;
|
||||
var y = cropper.imgTop - cropper.imgHeight / 2;
|
||||
owner.setStyle({
|
||||
'transform': 'translate3d(' + x + 'px,' + y + 'px,0) scale(' + cropper.scale + ') rotate(' + cropper
|
||||
.angle + 'deg)'
|
||||
})
|
||||
}
|
||||
|
||||
function imageReset(ins) {
|
||||
cropper.scale = 1;
|
||||
cropper.angle = 0;
|
||||
imgTransform(ins);
|
||||
}
|
||||
|
||||
function updateData(ins) {
|
||||
if (!ins) return;
|
||||
ins.callMethod('change', {
|
||||
cutX: cropper.cutX,
|
||||
cutY: cropper.cutY,
|
||||
imgWidth: cropper.imgWidth,
|
||||
imgHeight: cropper.imgHeight,
|
||||
scale: cropper.scale,
|
||||
angle: cropper.angle,
|
||||
imgTop: cropper.imgTop,
|
||||
imgLeft: cropper.imgLeft
|
||||
})
|
||||
}
|
||||
|
||||
function valsChange(prop, oldProp, ownerInstance, ins) {
|
||||
if (prop && prop !== 'null' && ins) {
|
||||
var params = prop.split('_')
|
||||
var type = +params[0]
|
||||
var dataset = ins.getDataset();
|
||||
if (cropper.init || type == 4) {
|
||||
cropper.canvasWidth = +dataset.width;
|
||||
cropper.canvasHeight = +dataset.height;
|
||||
cropper.windowHeight = +dataset.windowheight;
|
||||
cropper.windowWidth = +dataset.windowwidth;
|
||||
cropper.imgTop = (+dataset.windowheight) / 2;
|
||||
cropper.imgLeft = (+dataset.windowwidth) / 2;
|
||||
cropper.imgWidth = +dataset.imgwidth;
|
||||
cropper.imgHeight = +dataset.imgheight;
|
||||
cropper.init = false
|
||||
} else if (type == 2 || type == 3) {
|
||||
cropper.imgTop = (+dataset.windowheight) / 2;
|
||||
cropper.imgLeft = (+dataset.windowwidth) / 2;
|
||||
cropper.imgWidth = +dataset.imgwidth;
|
||||
cropper.imgHeight = +dataset.imgheight;
|
||||
}
|
||||
cropper.angle = +dataset.angle;
|
||||
if (type == 3) {
|
||||
imgTransform(ownerInstance);
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case 1:
|
||||
setCutCenter(ownerInstance);
|
||||
computeCutSize(ownerInstance);
|
||||
cutDetectionPosition(ownerInstance);
|
||||
break;
|
||||
case 2:
|
||||
setCutCenter(ownerInstance);
|
||||
break;
|
||||
case 3:
|
||||
imgMarginDetectionScale(ownerInstance)
|
||||
break;
|
||||
case 4:
|
||||
imageReset(ownerInstance);
|
||||
break;
|
||||
case 5:
|
||||
setCutCenter(ownerInstance);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var movable = false;
|
||||
|
||||
function mousedown(e, ins) {
|
||||
if (!isH5 || !isPC()) return
|
||||
touchstart(e, ins)
|
||||
movable = true
|
||||
window.onmousemove = function(event) {
|
||||
if (!isH5 || !isPC() || !movable) return
|
||||
touchmove(event, ins, e)
|
||||
}
|
||||
window.onmouseup = function(event) {
|
||||
if (!isH5 || !isPC() || !movable) return
|
||||
touchend(event, ins, e)
|
||||
movable = false
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
touchstart: touchstart,
|
||||
touchmove: touchmove,
|
||||
touchend: touchend,
|
||||
valsChange: valsChange,
|
||||
mousedown: mousedown
|
||||
}
|
231
components/firstui/fui-image-cropper/mpjs.js
Normal file
231
components/firstui/fui-image-cropper/mpjs.js
Normal file
@ -0,0 +1,231 @@
|
||||
// 本文件由FirstUI授权予新疆天衡创新研究院有限公司(手机号: 18 614072 5 4 9,身份证尾号:5A07X5)专用,请尊重知识产权,勿私下传播,违者追究法律责任。
|
||||
// #ifndef APP-PLUS || MP-WEIXIN || H5
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
touchRelative: [{
|
||||
x: 0,
|
||||
y: 0
|
||||
}],
|
||||
hypotenuseLength: 0,
|
||||
flagEndTouch: false,
|
||||
canvasWidth: 0,
|
||||
canvasHeight: 0
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.canvasWidth = Number(this.width);
|
||||
this.canvasHeight = Number(this.height);
|
||||
},
|
||||
watch: {
|
||||
width(val) {
|
||||
this.canvasWidth = Number(val);
|
||||
},
|
||||
height(val) {
|
||||
this.canvasHeight = Number(val);
|
||||
},
|
||||
changeval(val) {
|
||||
this.valsChange(val)
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
getTransform: function() {
|
||||
return `translate3d(${this.imgLeft - this.imgWidth / 2}px,${this.imgTop - this.imgHeight / 2}px,0) scale(${this.scale}) rotate(${this.angle}deg)`;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
cutDetectionPosition() {
|
||||
var windowHeight = this.windowHeight,
|
||||
windowWidth = this.windowWidth;
|
||||
|
||||
var cutDetectionPositionTop = () => {
|
||||
if (this.cutY < 0) {
|
||||
this.cutY = 0;
|
||||
}
|
||||
if (this.cutY > windowHeight - this.canvasHeight) {
|
||||
this.cutY = windowHeight - this.canvasHeight;
|
||||
}
|
||||
}
|
||||
|
||||
var cutDetectionPositionLeft = () => {
|
||||
if (this.cutX < 0) {
|
||||
this.cutX = 0;
|
||||
}
|
||||
if (this.cutX > windowWidth - this.canvasWidth) {
|
||||
this.cutX = windowWidth - this.canvasWidth;
|
||||
}
|
||||
}
|
||||
if (this.cutY == null && this.cutX == null) {
|
||||
var cutY = (windowHeight - this.canvasHeight) * 0.5;
|
||||
var cutX = (windowWidth - this.canvasWidth) * 0.5;
|
||||
this.cutY = cutY;
|
||||
this.cutX = cutX;
|
||||
} else if (this.cutY != null && this.cutX != null) {
|
||||
cutDetectionPositionTop();
|
||||
cutDetectionPositionLeft();
|
||||
} else if (this.cutY != null && this.cutX == null) {
|
||||
cutDetectionPositionTop();
|
||||
this.cutX = (windowWidth - this.canvasWidth) / 2;
|
||||
} else if (this.cutY == null && this.cutX != null) {
|
||||
cutDetectionPositionLeft();
|
||||
this.cutY = (windowHeight - this.canvasHeight) / 2;
|
||||
}
|
||||
},
|
||||
imgMarginDetectionPosition(scale) {
|
||||
var left = this.imgLeft;
|
||||
var top = this.imgTop;
|
||||
scale = scale || this.scale;
|
||||
var imgWidth = this.imgWidth;
|
||||
var imgHeight = this.imgHeight;
|
||||
if ((this.angle / 90) % 2) {
|
||||
imgWidth = this.imgHeight;
|
||||
imgHeight = this.imgWidth;
|
||||
}
|
||||
left = this.cutX + (imgWidth * scale) / 2 >= left ? left : this.cutX + (imgWidth * scale) / 2;
|
||||
left = this.cutX + this.canvasWidth - (imgWidth * scale) / 2 <= left ? left : this.cutX + this.canvasWidth -
|
||||
(imgWidth * scale) / 2;
|
||||
top = this.cutY + (imgHeight * scale) / 2 >= top ? top : this.cutY + (imgHeight * scale) / 2;
|
||||
top = this.cutY + this.canvasHeight - (imgHeight * scale) / 2 <= top ? top : this.cutY + this.canvasHeight -
|
||||
(imgHeight * scale) / 2;
|
||||
|
||||
this.imgLeft = left;
|
||||
this.imgTop = top;
|
||||
this.scale = scale;
|
||||
},
|
||||
imgMarginDetectionScale(scale) {
|
||||
scale = scale || this.scale;
|
||||
var imgWidth = this.imgWidth;
|
||||
var imgHeight = this.imgHeight;
|
||||
if ((this.angle / 90) % 2) {
|
||||
imgWidth = this.imgHeight;
|
||||
imgHeight = this.imgWidth;
|
||||
}
|
||||
if (imgWidth * scale < this.canvasWidth) {
|
||||
scale = this.canvasWidth / imgWidth;
|
||||
}
|
||||
if (imgHeight * scale < this.canvasHeight) {
|
||||
scale = Math.max(scale, this.canvasHeight / imgHeight);
|
||||
}
|
||||
this.imgMarginDetectionPosition(scale);
|
||||
},
|
||||
computeCutSize() {
|
||||
if (this.canvasWidth > this.windowWidth) {
|
||||
this.canvasWidth = this.windowWidth;
|
||||
} else if (this.canvasWidth + this.cutX > this.windowWidth) {
|
||||
this.cutX = this.windowWidth - this.cutX;
|
||||
}
|
||||
if (this.canvasHeight > this.windowHeight) {
|
||||
this.canvasHeight = this.windowHeight;
|
||||
} else if (this.canvasHeight + this.cutY > this.windowHeight) {
|
||||
this.cutY = this.windowHeight - this.cutY;
|
||||
}
|
||||
},
|
||||
setCutCenter() {
|
||||
var cutY = (this.windowHeight - this.canvasHeight) * 0.5;
|
||||
var cutX = (this.windowWidth - this.canvasWidth) * 0.5;
|
||||
this.imgTop = this.imgTop - this.cutY + cutY;
|
||||
this.cutY = cutY;
|
||||
this.imgLeft = this.imgLeft - this.cutX + cutX;
|
||||
this.cutX = cutX;
|
||||
this.cutDetectionPosition()
|
||||
},
|
||||
imageReset() {
|
||||
this.scale = 1;
|
||||
this.angle = 0;
|
||||
},
|
||||
touchstart(e) {
|
||||
var touch = e.touches || e.changedTouches
|
||||
this.flagEndTouch = false;
|
||||
if (touch.length == 1) {
|
||||
this.touchRelative[0] = {
|
||||
x: touch[0].clientX - this.imgLeft,
|
||||
y: touch[0].clientY - this.imgTop
|
||||
};
|
||||
} else {
|
||||
var width = Math.abs(touch[0].clientX - touch[1].clientX);
|
||||
var height = Math.abs(touch[0].clientY - touch[1].clientY);
|
||||
this.touchRelative = [{
|
||||
x: touch[0].clientX - this.imgLeft,
|
||||
y: touch[0].clientY - this.imgTop
|
||||
},
|
||||
{
|
||||
x: touch[1].clientX - this.imgLeft,
|
||||
y: touch[1].clientY - this.imgTop
|
||||
}
|
||||
];
|
||||
this.hypotenuseLength = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2));
|
||||
}
|
||||
},
|
||||
touchmove(e) {
|
||||
var touch = e.touches || e.changedTouches
|
||||
if (this.flagEndTouch) return;
|
||||
this.moveDuring();
|
||||
if (touch.length == 1) {
|
||||
var left = touch[0].clientX - this.touchRelative[0].x,
|
||||
top = touch[0].clientY - this.touchRelative[0].y;
|
||||
this.imgLeft = left;
|
||||
this.imgTop = top;
|
||||
this.imgMarginDetectionPosition();
|
||||
} else {
|
||||
var width = Math.abs(touch[0].clientX - touch[1].clientX),
|
||||
height = Math.abs(touch[0].clientY - touch[1].clientY),
|
||||
hypotenuse = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2)),
|
||||
scale = this.scale * (hypotenuse / this.hypotenuseLength),
|
||||
current_deg = 0;
|
||||
scale = scale <= 0.5 ? 0.5 : scale;
|
||||
scale = scale >= 2 ? 2 : scale;
|
||||
this.imgMarginDetectionScale(scale);
|
||||
var touchRelative = [{
|
||||
x: touch[0].clientX - this.imgLeft,
|
||||
y: touch[0].clientY - this.imgTop
|
||||
},
|
||||
{
|
||||
x: touch[1].clientX - this.imgLeft,
|
||||
y: touch[1].clientY - this.imgTop
|
||||
}
|
||||
];
|
||||
this.touchRelative = touchRelative;
|
||||
this.hypotenuseLength = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2));
|
||||
this.angle = this.angle + current_deg;
|
||||
this.scale = this.scale;
|
||||
}
|
||||
},
|
||||
touchend(e) {
|
||||
this.flagEndTouch = true;
|
||||
this.moveStop();
|
||||
},
|
||||
valsChange(val) {
|
||||
if (val) {
|
||||
var params = val.split('_')
|
||||
var type = Number(params[0])
|
||||
switch (type) {
|
||||
case 1:
|
||||
this.setCutCenter();
|
||||
this.computeCutSize();
|
||||
this.cutDetectionPosition();
|
||||
break;
|
||||
case 2:
|
||||
this.setCutCenter();
|
||||
break;
|
||||
case 3:
|
||||
this.imgMarginDetectionScale()
|
||||
break;
|
||||
case 4:
|
||||
this.imageReset();
|
||||
break;
|
||||
case 5:
|
||||
this.setCutCenter();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// #endif
|
||||
|
||||
// #ifdef APP-PLUS|| MP-WEIXIN || H5
|
||||
export default {}
|
||||
// #endif
|
Reference in New Issue
Block a user