Files
cashier_app/uni_modules/lime-clipper/components/l-clipper/l-clipper.vue
2025-12-03 10:13:55 +08:00

1075 lines
25 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="lime-clipper" :class="{open: value}" disable-scroll :style="'z-index: ' + zIndex + ';' + customStyle">
<view class="lime-clipper-mask" @touchstart.stop.prevent="clipTouchStart"
@touchmove.stop.prevent="clipTouchMove" @touchend.stop.prevent="clipTouchEnd">
<view class="lime-clipper__content" :style="clipStyle">
<view class="lime-clipper__edge" v-for="(item, index) in [0, 0, 0, 0]" :key="index"></view>
</view>
</view>
<image class="lime-clipper-image" @error="imageLoad" @load="imageLoad" @touchstart="imageTouchStart"
@touchmove="imageTouchMove" @touchend="imageTouchEnd" :src="image"
:mode="imageWidth == 'auto' ? 'widthFix' : 'scaleToFill'" v-if="image" :style="imageStyle" />
<canvas v-if="_canvasId" :canvas-id="_canvasId" :id="_canvasId" disable-scroll
:style="'width: ' + canvasWidth * scaleRatio + 'px; height:' + canvasHeight * scaleRatio + 'px;'"
class="lime-clipper-canvas"></canvas>
<view class="lime-clipper-tools">
<view class="lime-clipper-tools__btns">
<!-- <view v-if="isShowCancelBtn" @tap="cancel">
<slot name="cancel" v-if="$slots.cancel" />
<view v-else class="cancel">取消</view>
</view>
<view v-if="isShowPhotoBtn" @tap="uploadImage">
<slot name="photo" v-if="$slots.photo" />
<image v-else src="/uni_modules/lime-clipper/static/photo.svg" />
</view>
<view v-if="isShowRotateBtn" @tap="rotate">
<slot name="rotate" v-if="$slots.rotate" />
<image v-else src="/uni_modules/lime-clipper/static/rotate.svg" data-type="inverse" />
</view>
<view v-if="isShowConfirmBtn" @tap="confirm" >
<slot name="confirm" v-if="$slots.confirm" />
<view v-else class="confirm">确定</view>
</view> -->
<view v-if="isShowCancelBtn" @tap="cancel">
<slot name="cancel">
<text class="text cancel">取消</text>
</slot>
</view>
<view v-if="isShowPhotoBtn" @tap="uploadImage">
<slot name="photo">
<text class="text icon photo">&#xe76c;</text>
</slot>
</view>
<view v-if="isShowRotateBtn" @tap="rotate">
<slot name="rotate">
<text class="text icon rotate">&#xe76d;</text>
</slot>
</view>
<view v-if="isShowConfirmBtn" @tap="confirm">
<slot name="confirm">
<text class="text confirm" :style="{background: confirmBgColor}">确定</text>
</slot>
</view>
</view>
<slot></slot>
</view>
</view>
</template>
<script>
/**
* Clipper 图片裁剪组件
* @description 用于实现图片裁剪功能的交互式组件,支持缩放、旋转、比例锁定等高级功能
* @tutorial https://ext.dcloud.net.cn/plugin?name=lime-clipper
*
* @property {string} customStyle 自定义容器样式支持CSS字符串
* @property {number} zIndex]画布层级默认999
* @property {string} imageUrl 源图片地址(支持本地/网络路径)
* @property {'jpg' | 'png'} fileType 输出图片格式默认jpg
* @property {number} quality 图片压缩质量0-1默认0.8
* @property {number} width 裁剪区域默认宽度单位rpx
* @property {number} height 裁剪区域默认高度单位rpx
* @property {number} minWidth 最小裁剪宽度默认50px
* @property {number} maxWidth 最大裁剪宽度(默认:屏幕宽度)
* @property {number} destWidth 输出图片宽度(默认按裁剪尺寸)
* @property {number} destHeight 输出图片高度(默认按裁剪尺寸)
* @property {number} minHeight 最小裁剪高度默认50px
* @property {number} maxHeight 最大裁剪高度(默认:屏幕高度)
* @property {boolean} isLockWidth 锁定裁剪宽度(禁止调整)
* @property {boolean} isLockHeight 锁定裁剪高度(禁止调整)
* @property {boolean} isLockRatio 锁定宽高比默认false
* @property {number} scaleRatio 初始缩放比例默认1.0
* @property {number} minRatio 最小缩放比例默认0.5
* @property {number} maxRatio 最大缩放比例默认3.0
* @property {boolean} isDisableScale 禁用缩放功能
* @property {boolean} isDisableRotate 禁用旋转功能
* @property {boolean} isLimitMove 限制移动不超出图片范围
* @property {boolean} isShowPhotoBtn 显示相册选择按钮
* @property {boolean} isShowRotateBtn 显示旋转按钮
* @property {boolean} isShowConfirmBtn 显示确认按钮
* @property {boolean} isShowCancelBtn 显示取消按钮
* @property {number} rotateAngle 初始旋转角度(单位度)
* @property {any} source 自定义图片源(预留扩展)
* @property {string} confirmBgColor 确认按钮背景色
* @property {string} canvasId 画布唯一标识(多实例时必填)
* @event {Function} ready 准完成触发
* @event {Function} change 变化时触发
* @event {Function} rotate 旋转时触发
* @event {Function} cancel 取消时触发
* @event {Function} success 点击确定时成功生成图片后触发
*/
import {
determineDirection,
calcImageOffset,
calcImageScale,
calcImageSize,
calcPythagoreanTheorem,
clipTouchMoveOfCalculate,
imageTouchMoveOfCalcOffset,
} from './utils.js';
const cache = {}
export default {
name: 'lime-clipper',
props: {
value: {
type: Boolean,
default: true
},
// #ifdef MP-WEIXIN
type: {
type: String,
default: '2d'
},
// #endif
customStyle: {
type: String,
},
zIndex: {
type: Number,
default: 99
},
imageUrl: {
type: String
},
fileType: {
type: String,
default: 'png'
},
quality: {
type: Number,
default: 1
},
width: {
type: Number,
default: 400
},
height: {
type: Number,
default: 400
},
minWidth: {
type: Number,
default: 200
},
maxWidth: {
type: Number,
default: 600
},
destWidth: Number,
destHeight: Number,
minHeight: {
type: Number,
default: 200
},
maxHeight: {
type: Number,
default: 600
},
isLockWidth: {
type: Boolean,
default: false
},
isLockHeight: {
type: Boolean,
default: false
},
isLockRatio: {
type: Boolean,
default: true
},
scaleRatio: {
type: Number,
default: 1
},
minRatio: {
type: Number,
default: 0.5
},
maxRatio: {
type: Number,
default: 2
},
isDisableScale: {
type: Boolean,
default: false
},
isDisableRotate: {
type: Boolean,
default: false
},
isLimitMove: {
type: Boolean,
default: false
},
isShowPhotoBtn: {
type: Boolean,
default: true
},
isShowRotateBtn: {
type: Boolean,
default: true
},
isShowConfirmBtn: {
type: Boolean,
default: true
},
isShowCancelBtn: {
type: Boolean,
default: true
},
rotateAngle: {
type: Number,
default: 90
},
source: {
type: Object,
default: () => ({
album: '从相册中选择',
camera: '拍照',
// #ifdef MP-WEIXIN
message: '从微信中选择'
// #endif
})
},
confirmBgColor: {
type: String,
default: null
},
canvasId: {
type: String,
default: null
}
},
data() {
return {
canvasWidth: 0,
canvasHeight: 0,
clipX: 0,
clipY: 0,
clipWidth: 0,
clipHeight: 0,
animation: false,
imageWidth: 0,
imageHeight: 0,
imageTop: 0,
imageLeft: 0,
scale: 1,
angle: 0,
image: '',
imageInit: false,
sysinfo: {},
throttleTimer: null,
throttleFlag: true,
timeClipCenter: null,
flagClipTouch: false,
flagEndTouch: false,
clipStart: {},
animationTimer: null,
touchRelative: [{
x: 0,
y: 0
}],
hypotenuseLength: 0,
ctx: null,
// canvasId: 'lime-clipper'
};
},
computed: {
_canvasId() {
return this.canvasId ?? `l-clipper-${this._ ? this._.uid : this._uid}`
},
clipStyle() {
const {
clipWidth,
clipHeight,
clipY,
clipX,
animation
} = this
return `
width: ${clipWidth}px;
height:${clipHeight}px;
transition-property: ${animation ? '' : 'background'};
left: ${clipX}px;
top: ${clipY}px
`
},
imageStyle() {
const {
imageWidth,
imageHeight,
imageLeft,
imageTop,
animation,
scale,
angle
} = this
return `
width: ${imageWidth ? imageWidth + 'px' : 'auto'};
height: ${imageHeight ? imageHeight + 'px' : 'auto'};
transform: translate3d(${imageLeft - imageWidth / 2}px, ${imageTop - imageHeight / 2}px, 0) scale(${scale}) rotate(${angle}deg);
transition-duration: ${animation ? 0.35 : 0}s
`
},
clipSize() {
const {
clipWidth,
clipHeight
} = this;
return {
clipWidth,
clipHeight
};
},
clipPoint() {
const {
clipY,
clipX
} = this;
return {
clipY,
clipX
};
}
},
watch: {
value(val) {
if (!val) {
this.animation = 0
this.angle = 0
} else {
if (this.imageUrl) {
const {
imageWidth,
imageHeight,
imageLeft,
imageTop,
scale,
clipX,
clipY,
clipWidth,
clipHeight,
path
} = cache?.[this.imageUrl] || {}
if (path != this.image) {
this.image = this.imageUrl;
} else {
this.setDiffData({
imageWidth,
imageHeight,
imageLeft,
imageTop,
scale,
clipX,
clipY,
clipWidth,
clipHeight
})
}
}
}
},
imageUrl(url) {
this.image = url
},
image: {
handler: async function(url) {
this.getImageInfo(url)
},
// immediate: true,
},
clipSize({
widthVal,
heightVal
}) {
let {
minWidth,
minHeight
} = this;
minWidth = uni.upx2px(minWidth);
minHeight = uni.upx2px(minHeight);
if (widthVal < minWidth) {
this.setDiffData({
clipWidth: minWidth
})
}
if (heightVal < minHeight) {
this.setDiffData({
clipHeight: minHeight
})
}
this.calcClipSize();
},
angle(val) {
this.animation = this.imageInit;
this.moveStop();
const {
isLimitMove
} = this;
if (isLimitMove && val % 90) {
this.setDiffData({
angle: Math.round(val / 90) * 90
})
}
this.imgMarginDetectionScale();
},
animation(val) {
clearTimeout(this.animationTimer);
if (val) {
let animationTimer = setTimeout(() => {
this.setDiffData({
animation: false
})
}, 260);
this.setDiffData({
animationTimer
})
this.animationTimer = animationTimer;
}
},
isLimitMove(val) {
if (val) {
if (this.angle % 90) {
this.setDiffData({
angle: Math.round(this.angle / 90) * 90
})
}
this.imgMarginDetectionScale();
}
},
clipPoint() {
this.cutDetectionPosition();
},
width(width, oWidth) {
if (width !== oWidth) {
this.setDiffData({
clipWidth: uni.upx2px(width) //width / 2
})
}
},
height(height, oHeight) {
if (height !== oHeight) {
this.setDiffData({
clipHeight: uni.upx2px(height) //height / 2
})
}
}
},
mounted() {
const sysinfo = uni.getSystemInfoSync();
this.sysinfo = sysinfo;
this.setClipInfo();
this.image = this.imageUrl || this.image
this.setClipCenter();
this.calcClipSize();
this.cutDetectionPosition();
},
methods: {
setDiffData(data) {
Object.keys(data).forEach(key => {
if (this[key] !== data[key]) {
this[key] = data[key];
}
});
},
getImageInfo(url) {
if (!url) return;
if (this.value) {
uni.showLoading({
title: '请稍候...',
mask: true
});
}
this.imageInit = false
uni.getImageInfo({
src: url,
success: res => {
if (['right', 'left'].includes(res.orientation)) {
this.imgComputeSize(res.height, res.width);
} else {
this.imgComputeSize(res.width, res.height);
}
this.image = res.path;
if (this.isLimitMove) {
this.imgMarginDetectionScale();
this.$emit('ready', res);
}
const {
imageWidth,
imageHeight,
imageLeft,
imageTop,
scale,
clipX,
clipY,
clipWidth,
clipHeight
} = this
cache[url] = Object.assign(res, {
imageWidth,
imageHeight,
imageLeft,
imageTop,
scale,
clipX,
clipY,
clipWidth,
clipHeight
});
},
fail: (err) => {
this.imgComputeSize();
if (this.isLimitMove) {
this.imgMarginDetectionScale();
}
}
});
},
setClipInfo() {
const {
width,
height,
sysinfo,
_canvasId
} = this;
const clipWidth = width / 2;
const clipHeight = height / 2;
const clipY = (sysinfo.windowHeight - clipHeight) / 2;
const clipX = (sysinfo.windowWidth - clipWidth) / 2;
const imageLeft = sysinfo.windowWidth / 2;
const imageTop = sysinfo.windowHeight / 2;
this.ctx = uni.createCanvasContext(_canvasId, this);
this.clipWidth = clipWidth;
this.clipHeight = clipHeight;
this.clipX = clipX;
this.clipY = clipY;
this.canvasHeight = clipHeight;
this.canvasWidth = clipWidth;
this.imageLeft = imageLeft;
this.imageTop = imageTop;
},
setClipCenter() {
const {
sysInfo,
clipHeight,
clipWidth,
imageTop,
imageLeft
} = this;
let sys = sysInfo || uni.getSystemInfoSync();
let clipY = (sys.windowHeight - clipHeight) * 0.5;
let clipX = (sys.windowWidth - clipWidth) * 0.5;
this.imageTop = imageTop - this.clipY + clipY;
this.imageLeft = imageLeft - this.clipX + clipX;
this.clipY = clipY;
this.clipX = clipX;
},
calcClipSize() {
const {
clipHeight,
clipWidth,
sysinfo,
clipX,
clipY
} = this;
if (clipWidth > sysinfo.windowWidth) {
this.setDiffData({
clipWidth: sysinfo.windowWidth
})
} else if (clipWidth + clipX > sysinfo.windowWidth) {
this.setDiffData({
clipX: sysinfo.windowWidth - clipX
})
}
if (clipHeight > sysinfo.windowHeight) {
this.setDiffData({
clipHeight: sysinfo.windowHeight
})
} else if (clipHeight + clipY > sysinfo.windowHeight) {
this.clipY = sysinfo.windowHeight - clipY;
this.setDiffData({
clipY: sysinfo.windowHeight - clipY
})
}
},
cutDetectionPosition() {
const {
clipX,
clipY,
sysinfo,
clipHeight,
clipWidth
} = this;
let cutDetectionPositionTop = () => {
if (clipY < 0) {
this.setDiffData({
clipY: 0
})
}
if (clipY > sysinfo.windowHeight - clipHeight) {
this.setDiffData({
clipY: sysinfo.windowHeight - clipHeight
})
}
};
let cutDetectionPositionLeft = () => {
if (clipX < 0) {
this.setDiffData({
clipX: 0
})
}
if (clipX > sysinfo.windowWidth - clipWidth) {
this.setDiffData({
clipX: sysinfo.windowWidth - clipWidth
})
}
};
if (clipY === null && clipX === null) {
let newClipY = (sysinfo.windowHeight - clipHeight) * 0.5;
let newClipX = (sysinfo.windowWidth - clipWidth) * 0.5;
this.setDiffData({
clipX: newClipX,
clipY: newClipY
})
} else if (clipY !== null && clipX !== null) {
cutDetectionPositionTop();
cutDetectionPositionLeft();
} else if (clipY !== null && clipX === null) {
cutDetectionPositionTop();
this.setDiffData({
clipX: (sysinfo.windowWidth - clipWidth) / 2
})
} else if (clipY === null && clipX !== null) {
cutDetectionPositionLeft();
this.setDiffData({
clipY: (sysinfo.windowHeight - clipHeight) / 2
})
}
},
imgComputeSize(width, height) {
const {
imageWidth,
imageHeight
} = calcImageSize(width, height, this);
this.imageWidth = imageWidth;
this.imageHeight = imageHeight;
},
imgMarginDetectionScale(scale) {
if (!this.isLimitMove) return;
const currentScale = calcImageScale(this, scale);
this.imgMarginDetectionPosition(currentScale);
},
imgMarginDetectionPosition(scale) {
if (!this.isLimitMove) return;
const {
scale: currentScale,
left,
top
} = calcImageOffset(this, scale);
this.setDiffData({
imageLeft: left,
imageTop: top,
scale: currentScale
})
},
throttle() {
this.setDiffData({
throttleFlag: true
})
},
moveDuring() {
clearTimeout(this.timeClipCenter);
},
moveStop() {
clearTimeout(this.timeClipCenter);
const timeClipCenter = setTimeout(() => {
if (!this.animation) {
this.setDiffData({
imageInit: true,
animation: true,
})
}
this.setClipCenter();
}, 800);
this.setDiffData({
timeClipCenter
})
},
clipTouchStart(e) {
// #ifdef H5
e.preventDefault()
// #endif
if (!this.image) {
uni.showToast({
title: '请选择图片',
icon: 'none'
});
return;
}
const currentX = e.touches[0].clientX;
const currentY = e.touches[0].clientY;
const {
clipX,
clipY,
clipWidth,
clipHeight
} = this;
const corner = determineDirection(clipX, clipY, clipWidth, clipHeight, currentX, currentY);
this.moveDuring();
if (!corner) {
return
}
this.clipStart = {
width: clipWidth,
height: clipHeight,
x: currentX,
y: currentY,
clipY,
clipX,
corner
};
this.flagClipTouch = true;
this.flagEndTouch = true;
},
clipTouchMove(e) {
// #ifdef H5
e.stopPropagation()
e.preventDefault()
// #endif
if (!this.image) {
uni.showToast({
title: '请选择图片',
icon: 'none'
});
return;
}
// 只针对单指点击做处理
if (e.touches.length !== 1) {
return;
}
const {
flagClipTouch,
throttleFlag
} = this;
if (flagClipTouch && throttleFlag) {
const {
isLockRatio,
isLockHeight,
isLockWidth
} = this;
if (isLockRatio && (isLockWidth || isLockHeight)) return;
this.setDiffData({
throttleFlag: false
})
this.throttle();
const clipData = clipTouchMoveOfCalculate(this, e);
if (clipData) {
const {
width,
height,
clipX,
clipY
} = clipData;
if (!isLockWidth && !isLockHeight) {
this.setDiffData({
clipWidth: width,
clipHeight: height,
clipX,
clipY
})
} else if (!isLockWidth) {
this.setDiffData({
clipWidth: width,
clipX
})
} else if (!isLockHeight) {
this.setDiffData({
clipHeight: height,
clipY
})
}
this.imgMarginDetectionScale();
}
}
},
clipTouchEnd() {
this.moveStop();
this.flagClipTouch = false;
},
imageTouchStart(e) {
// #ifdef H5
e.preventDefault()
// #endif
this.flagEndTouch = false;
const {
imageLeft,
imageTop
} = this;
const clientXForLeft = e.touches[0].clientX;
const clientYForLeft = e.touches[0].clientY;
let touchRelative = [];
if (e.touches.length === 1) {
touchRelative[0] = {
x: clientXForLeft - imageLeft,
y: clientYForLeft - imageTop
};
this.touchRelative = touchRelative;
} else {
const clientXForRight = e.touches[1].clientX;
const clientYForRight = e.touches[1].clientY;
let width = Math.abs(clientXForLeft - clientXForRight);
let height = Math.abs(clientYForLeft - clientYForRight);
const hypotenuseLength = calcPythagoreanTheorem(width, height);
touchRelative = [{
x: clientXForLeft - imageLeft,
y: clientYForLeft - imageTop
},
{
x: clientXForRight - imageLeft,
y: clientYForRight - imageTop
}
];
this.touchRelative = touchRelative;
this.hypotenuseLength = hypotenuseLength;
}
},
imageTouchMove(e) {
// #ifdef H5
e.preventDefault()
// #endif
const {
flagEndTouch,
throttleFlag
} = this;
if (flagEndTouch || !throttleFlag) return;
const clientXForLeft = e.touches[0].clientX;
const clientYForLeft = e.touches[0].clientY;
this.setDiffData({
throttleFlag: false
})
this.throttle();
this.moveDuring();
if (e.touches.length === 1) {
const {
left: imageLeft,
top: imageTop
} = imageTouchMoveOfCalcOffset(this, clientXForLeft, clientYForLeft);
this.setDiffData({
imageLeft,
imageTop
})
this.imgMarginDetectionPosition();
} else {
const clientXForRight = e.touches[1].clientX;
const clientYForRight = e.touches[1].clientY;
let width = Math.abs(clientXForLeft - clientXForRight),
height = Math.abs(clientYForLeft - clientYForRight),
hypotenuse = calcPythagoreanTheorem(width, height),
scale = this.scale * (hypotenuse / this.hypotenuseLength);
if (this.isDisableScale) {
scale = 1;
} else {
scale = scale <= this.minRatio ? this.minRatio : scale;
scale = scale >= this.maxRatio ? this.maxRatio : scale;
this.$emit('change', {
width: this.imageWidth * scale,
height: this.imageHeight * scale
});
}
this.imgMarginDetectionScale(scale);
this.hypotenuseLength = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2));
this.scale = scale;
}
},
imageTouchEnd() {
this.setDiffData({
flagEndTouch: true
})
this.moveStop();
},
uploadImage() {
const itemList = Object.entries(this.source)
const sizeType = ['original', 'compressed']
const success = ({
tempFilePaths: a,
tempFiles: b
}) => {
this.image = a ? a[0] : b[0].path
};
const _uploadImage = (type) => {
if (type !== 'message') {
uni.chooseImage({
count: 1,
sizeType,
sourceType: [type],
success
});
}
// #ifdef MP-WEIXIN
if (type == 'message') {
wx.chooseMessageFile({
count: 1,
type: 'image',
success
})
}
// #endif
}
if (itemList.length > 1) {
uni.showActionSheet({
itemList: itemList.map(v => v[1]),
success: ({
tapIndex: i
}) => {
_uploadImage(itemList[i][0])
}
})
} else {
_uploadImage(itemList[0][0])
}
},
imageReset() {
const sys = this.sysinfo || uni.getSystemInfoSync();
this.moveStop()
this.scale = 1;
this.angle = 0;
this.imageTop = sys.windowHeight / 2;
this.imageLeft = sys.windowWidth / 2;
},
imageLoad(e) {
this.imageReset();
uni.hideLoading();
this.$emit('ready', e.detail);
},
rotate(event) {
if (this.isDisableRotate) return;
if (!this.image) {
uni.showToast({
title: '请选择图片',
icon: 'none'
});
return;
}
const {
rotateAngle
} = this;
const originAngle = this.angle
const type = event.currentTarget.dataset.type;
if (type === 'along') {
this.angle = originAngle + rotateAngle
} else {
this.angle = originAngle - rotateAngle
}
this.$emit('rotate', this.angle);
},
confirm() {
if (!this.image) {
uni.showToast({
title: '请选择图片',
icon: 'none'
});
return;
}
uni.showLoading({
title: '加载中'
});
const {
canvasHeight,
canvasWidth,
clipHeight,
clipWidth,
scale,
ctx,
imageLeft,
imageTop,
clipX,
clipY,
angle,
scaleRatio: dpr,
image,
quality,
fileType,
type: imageType,
_canvasId
} = this;
const draw = () => {
const imageWidth = this.imageWidth * scale * dpr;
const imageHeight = this.imageHeight * scale * dpr;
const xpos = imageLeft - clipX;
const ypos = imageTop - clipY;
// const ctx = uni.createCanvasContext(_canvasId, this);
ctx.translate(xpos * dpr, ypos * dpr);
ctx.rotate((angle * Math.PI) / 180);
ctx.drawImage(image, -imageWidth / 2, -imageHeight / 2, imageWidth, imageHeight);
ctx.draw(false, () => {
const width = clipWidth * dpr
const height = clipHeight * dpr
let params = {
x: 0,
y: 0,
width,
height,
destWidth: this.destWidth || width,
destHeight: this.destHeight || height,
canvasId: _canvasId,
fileType,
quality,
success: (res) => {
// 钉钉小程序
data.url = res.tempFilePath || res.filePath;
uni.hideLoading();
this.$emit('success', data);
this.$emit('input', false)
},
fail: (error) => {
console.error('error', error)
this.$emit('fail', error);
this.$emit('input', false)
}
};
let data = {
url: '',
width,
height
};
uni.canvasToTempFilePath(params, this)
});
};
if (canvasWidth !== clipWidth || canvasHeight !== clipHeight) {
this.canvasWidth = clipWidth;
this.canvasHeight = clipHeight;
ctx.draw();
this.$nextTick(() => {
setTimeout(() => {
draw();
}, 100);
})
} else {
draw();
}
},
cancel() {
this.$emit('cancel', false)
this.$emit('input', false)
},
}
};
</script>
<style lang="scss">
@import './index';
</style>