city_card/vant/dist/cropper/image-cropper.js
2023-07-18 16:54:17 +08:00

1117 lines
47 KiB
JavaScript
Executable File
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.

Component({
properties: {
/**
* 图片路径
*/
'imgSrc': {
type: String
},
/**
* 裁剪框高度
*/
'height': {
type: Number,
value: 200
},
/**
* 裁剪框宽度
*/
'width': {
type: Number,
value: 200
},
/**
* 裁剪框最小尺寸
*/
'min_width': {
type: Number,
value: 100
},
'min_height': {
type: Number,
value: 100
},
/**
* 裁剪框最大尺寸
*/
'max_width': {
type: Number,
value: 300
},
'max_height': {
type: Number,
value: 300
},
/**
* 裁剪框禁止拖动
*/
'disable_width': {
type: Boolean,
value: false
},
'disable_height': {
type: Boolean,
value: false
},
/**
* 锁定裁剪框比例
*/
'disable_ratio': {
type: Boolean,
value: false
},
/**
* 生成的图片尺寸相对剪裁框的比例
*/
'export_scale': {
type: Number,
value: 3
},
/**
* 生成的图片质量0-1
*/
'quality': {
type: Number,
value: 1
},
'cut_top': {
type: Number,
value: null
},
'cut_left': {
type: Number,
value: null
},
/**
* canvas上边距不设置默认不显示
*/
'canvas_top': {
type: Number,
value: null
},
/**
* canvas左边距不设置默认不显示
*/
'canvas_left': {
type: Number,
value: null
},
/**
* 图片宽度
*/
'img_width': {
type: null,
value: null
},
/**
* 图片高度
*/
'img_height': {
type: null,
value: null
},
/**
* 图片缩放比
*/
'scale': {
type: Number,
value: 1
},
/**
* 图片旋转角度
*/
'angle': {
type: Number,
value: 0
},
/**
* 最小缩放比
*/
'min_scale': {
type: Number,
value: 0.5
},
/**
* 最大缩放比
*/
'max_scale': {
type: Number,
value: 2
},
/**
* 是否禁用旋转
*/
'disable_rotate': {
type: Boolean,
value: false
},
/**
* 是否限制移动范围(剪裁框只能在图片内)
*/
'limit_move': {
type: Boolean,
value: false
}
},
data: {
el: 'image-cropper', //暂时无用
info: wx.getSystemInfoSync(),
MOVE_THROTTLE: null, //触摸移动节流settimeout
MOVE_THROTTLE_FLAG: true, //节流标识
INIT_IMGWIDTH: 0, //图片设置尺寸,此值不变(记录最初设定的尺寸)
INIT_IMGHEIGHT: 0, //图片设置尺寸,此值不变(记录最初设定的尺寸)
TIME_BG: null, //背景变暗延时函数
TIME_CUT_CENTER: null,
_touch_img_relative: [{
x: 0,
y: 0
}], //鼠标和图片中心的相对位置
_flag_cut_touch: false, //是否是拖动裁剪框
_hypotenuse_length: 0, //双指触摸时斜边长度
_flag_img_endtouch: false, //是否结束触摸
_flag_bright: true, //背景是否亮
_canvas_overflow: true, //canvas缩略图是否在屏幕外面
_canvas_width: 200,
_canvas_height: 200,
origin_x: 0.5, //图片旋转中心
origin_y: 0.5, //图片旋转中心
_cut_animation: false, //是否开启图片和裁剪框过渡
_img_top: wx.getSystemInfoSync().windowHeight / 2, //图片上边距
_img_left: wx.getSystemInfoSync().windowWidth / 2, //图片左边距
watch: {
//监听截取框宽高变化
width(value, that) {
if (value < that.data.min_width) {
that.setData({
width: that.data.min_width
});
}
that._computeCutSize();
},
height(value, that) {
if (value < that.data.min_height) {
that.setData({
height: that.data.min_height
});
}
that._computeCutSize();
},
angle(value, that) {
//停止居中裁剪框,继续修改图片位置
that._moveStop();
if (that.data.limit_move) {
if (that.data.angle % 90) {
that.setData({
angle: Math.round(that.data.angle / 90) * 90
});
return;
}
}
},
_cut_animation(value, that) {
//开启过渡300毫秒之后自动关闭
clearTimeout(that.data._cut_animation_time);
if (value) {
that.data._cut_animation_time = setTimeout(() => {
that.setData({
_cut_animation: false
});
}, 300)
}
},
limit_move(value, that) {
if (value) {
if (that.data.angle % 90) {
that.setData({
angle: Math.round(that.data.angle / 90) * 90
});
}
that._imgMarginDetectionScale();
!that.data._canvas_overflow && that._draw();
}
},
canvas_top(value, that) {
that._canvasDetectionPosition();
},
canvas_left(value, that) {
that._canvasDetectionPosition();
},
imgSrc(value, that) {
that.pushImg();
},
cut_top(value, that) {
that._cutDetectionPosition();
if (that.data.limit_move) {
!that.data._canvas_overflow && that._draw();
}
},
cut_left(value, that) {
that._cutDetectionPosition();
if (that.data.limit_move) {
!that.data._canvas_overflow && that._draw();
}
}
}
},
attached() {
this.data.info = wx.getSystemInfoSync();
//启用数据监听
this._watcher();
this.data.INIT_IMGWIDTH = this.data.img_width;
this.data.INIT_IMGHEIGHT = this.data.img_height;
this.setData({
_canvas_height: this.data.height,
_canvas_width: this.data.width,
});
this._initCanvas();
this.data.imgSrc && (this.data.imgSrc = this.data.imgSrc);
//根据开发者设置的图片目标尺寸计算实际尺寸
this._initImageSize();
//设置裁剪框大小>设置图片尺寸>绘制canvas
this._computeCutSize();
//检查裁剪框是否在范围内
this._cutDetectionPosition();
//检查canvas是否在范围内
this._canvasDetectionPosition();
//初始化完成
this.triggerEvent('load', {
cropper: this
});
},
methods: {
/**
* 上传图片
*/
upload() {
let that = this;
wx.chooseImage({
count: 1,
sizeType: ['original', 'compressed'],
sourceType: ['album', 'camera'],
success(res) {
const tempFilePaths = res.tempFilePaths[0];
that.pushImg(tempFilePaths);
wx.showLoading({
title: '加载中...'
})
}
})
},
/**
* 返回图片信息
*/
getImg(getCallback) {
this._draw(() => {
wx.canvasToTempFilePath({
width: this.data.width * this.data.export_scale,
height: Math.round(this.data.height * this.data.export_scale),
destWidth: this.data.width * this.data.export_scale,
destHeight: Math.round(this.data.height) * this.data.export_scale,
fileType: 'png',
quality: this.data.quality,
canvasId: this.data.el,
success: (res) => {
getCallback({
url: res.tempFilePath,
width: this.data.width * this.data.export_scale,
height: this.data.height * this.data.export_scale
});
}
}, this)
});
},
/**
* 设置图片动画
* {
* x:10,//图片在原有基础上向下移动10px
* y:10,//图片在原有基础上向右移动10px
* angle:10,//图片在原有基础上旋转10deg
* scale:0.5,//图片在原有基础上增加0.5倍
* }
*/
setTransform(transform) {
if (!transform) return;
if (!this.data.disable_rotate) {
this.setData({
angle: transform.angle ? this.data.angle + transform.angle : this.data.angle
});
}
var scale = this.data.scale;
if (transform.scale) {
scale = this.data.scale + transform.scale;
scale = scale <= this.data.min_scale ? this.data.min_scale : scale;
scale = scale >= this.data.max_scale ? this.data.max_scale : scale;
}
this.data.scale = scale;
let cutX = this.data.cut_left;
let cutY = this.data.cut_top;
if (transform.cutX) {
this.setData({
cut_left: cutX + transform.cutX
});
this.data.watch.cut_left(null, this);
}
if (transform.cutY) {
this.setData({
cut_top: cutY + transform.cutY
});
this.data.watch.cut_top(null, this);
}
this.data._img_top = transform.y ? this.data._img_top + transform.y : this.data._img_top;
this.data._img_left = transform.x ? this.data._img_left + transform.x : this.data._img_left;
//图像边缘检测,防止截取到空白
this._imgMarginDetectionScale();
//停止居中裁剪框,继续修改图片位置
this._moveDuring();
this.setData({
scale: this.data.scale,
_img_top: this.data._img_top,
_img_left: this.data._img_left
});
!this.data._canvas_overflow && this._draw();
//可以居中裁剪框了
this._moveStop(); //结束操作
},
/**
* 设置剪裁框位置
*/
setCutXY(x, y) {
this.setData({
cut_top: y,
cut_left: x
});
},
/**
* 设置剪裁框尺寸
*/
setCutSize(w, h) {
this.setData({
width: w,
height: h
});
this._computeCutSize();
},
/**
* 设置剪裁框和图片居中
*/
setCutCenter() {
let cut_top = (this.data.info.windowHeight - this.data.height) * 0.5;
let cut_left = (this.data.info.windowWidth - this.data.width) * 0.5;
//顺序不能变
this.setData({
_img_top: this.data._img_top - this.data.cut_top + cut_top,
cut_top: cut_top, //截取的框上边距
_img_left: this.data._img_left - this.data.cut_left + cut_left,
cut_left: cut_left, //截取的框左边距
});
},
_setCutCenter() {
let cut_top = (this.data.info.windowHeight - this.data.height) * 0.5;
let cut_left = (this.data.info.windowWidth - this.data.width) * 0.5;
this.setData({
cut_top: cut_top, //截取的框上边距
cut_left: cut_left, //截取的框左边距
});
},
/**
* 设置剪裁框宽度-即将废弃
*/
setWidth(width) {
this.setData({
width: width
});
this._computeCutSize();
},
/**
* 设置剪裁框高度-即将废弃
*/
setHeight(height) {
this.setData({
height: height
});
this._computeCutSize();
},
/**
* 是否锁定旋转
*/
setDisableRotate(value) {
this.data.disable_rotate = value;
},
/**
* 是否限制移动
*/
setLimitMove(value) {
this.setData({
_cut_animation: true,
limit_move: !!value
});
},
/**
* 初始化图片,包括位置、大小、旋转角度
*/
imgReset() {
this.setData({
scale: 1,
angle: 0,
_img_top: wx.getSystemInfoSync().windowHeight / 2,
_img_left: wx.getSystemInfoSync().windowWidth / 2,
})
},
/**
* 加载(更换)图片
*/
pushImg(src) {
if (src) {
this.setData({
imgSrc: src
});
//发现是手动赋值直接返回交给watch处理
return;
}
// getImageInfo接口传入 src: '' 会导致内存泄漏
if (!this.data.imgSrc) return;
wx.getImageInfo({
src: this.data.imgSrc,
success: (res) => {
this.data.imageObject = res;
//图片非本地路径需要换成本地路径
if (this.data.imgSrc.search(/tmp/) == -1) {
this.setData({
imgSrc: res.path
});
}
//计算最后图片尺寸
this._imgComputeSize();
if (this.data.limit_move) {
//限制移动,不留空白处理
this._imgMarginDetectionScale();
}
this._draw();
},
fail: (err) => {
this.setData({
imgSrc: ''
});
}
});
},
imageLoad(e) {
setTimeout(() => {
this.triggerEvent('imageload', this.data.imageObject);
})
},
/**
* 设置图片放大缩小
*/
setScale(scale) {
if (!scale) return;
this.setData({
scale: scale
});
!this.data._canvas_overflow && this._draw();
},
/**
* 设置图片旋转角度
*/
setAngle(angle) {
if (!angle) return;
this.setData({
_cut_animation: true,
angle: angle
});
this._imgMarginDetectionScale();
!this.data._canvas_overflow && this._draw();
},
_initCanvas() {
//初始化canvas
if (!this.data.ctx) {
this.data.ctx = wx.createCanvasContext("image-cropper", this);
}
},
/**
* 根据开发者设置的图片目标尺寸计算实际尺寸
*/
_initImageSize() {
//处理宽高特殊单位 %>px
if (this.data.INIT_IMGWIDTH && typeof this.data.INIT_IMGWIDTH == "string" && this.data.INIT_IMGWIDTH.indexOf("%") != -1) {
let width = this.data.INIT_IMGWIDTH.replace("%", "");
this.data.INIT_IMGWIDTH = this.data.img_width = this.data.info.windowWidth / 100 * width;
}
if (this.data.INIT_IMGHEIGHT && typeof this.data.INIT_IMGHEIGHT == "string" && this.data.INIT_IMGHEIGHT.indexOf("%") != -1) {
let height = this.data.img_height.replace("%", "");
this.data.INIT_IMGHEIGHT = this.data.img_height = this.data.info.windowHeight / 100 * height;
}
},
/**
* 检测剪裁框位置是否在允许的范围内(屏幕内)
*/
_cutDetectionPosition() {
let _cutDetectionPositionTop = () => {
//检测上边距是否在范围内
if (this.data.cut_top < 0) {
this.setData({
cut_top: 0
});
}
if (this.data.cut_top > this.data.info.windowHeight - this.data.height) {
this.setData({
cut_top: this.data.info.windowHeight - this.data.height
});
}
},
_cutDetectionPositionLeft = () => {
//检测左边距是否在范围内
if (this.data.cut_left < 0) {
this.setData({
cut_left: 0
});
}
if (this.data.cut_left > this.data.info.windowWidth - this.data.width) {
this.setData({
cut_left: this.data.info.windowWidth - this.data.width
});
}
};
//裁剪框坐标处理如果只写一个参数则另一个默认为0都不写默认居中
if (this.data.cut_top == null && this.data.cut_left == null) {
this._setCutCenter();
} else if (this.data.cut_top != null && this.data.cut_left != null) {
_cutDetectionPositionTop();
_cutDetectionPositionLeft();
} else if (this.data.cut_top != null && this.data.cut_left == null) {
_cutDetectionPositionTop();
this.setData({
cut_left: (this.data.info.windowWidth - this.data.width) / 2
});
} else if (this.data.cut_top == null && this.data.cut_left != null) {
_cutDetectionPositionLeft();
this.setData({
cut_top: (this.data.info.windowHeight - this.data.height) / 2
});
}
},
/**
* 检测canvas位置是否在允许的范围内(屏幕内)如果在屏幕外则不开启实时渲染
* 如果只写一个参数则另一个默认为0都不写默认超出屏幕外
*/
_canvasDetectionPosition() {
if (this.data.canvas_top == null && this.data.canvas_left == null) {
this.data._canvas_overflow = false;
this.setData({
canvas_top: -5000,
canvas_left: -5000
});
} else if (this.data.canvas_top != null && this.data.canvas_left != null) {
if (this.data.canvas_top < -this.data.height || this.data.canvas_top > this.data.info.windowHeight) {
this.data._canvas_overflow = true;
} else {
this.data._canvas_overflow = false;
}
} else if (this.data.canvas_top != null && this.data.canvas_left == null) {
this.setData({
canvas_left: 0
});
} else if (this.data.canvas_top == null && this.data.canvas_left != null) {
this.setData({
canvas_top: 0
});
if (this.data.canvas_left < -this.data.width || this.data.canvas_left > this.data.info.windowWidth) {
this.data._canvas_overflow = true;
} else {
this.data._canvas_overflow = false;
}
}
},
/**
* 图片边缘检测-位置
*/
_imgMarginDetectionPosition(scale) {
if (!this.data.limit_move) return;
let left = this.data._img_left;
let top = this.data._img_top;
var scale = scale || this.data.scale;
let img_width = this.data.img_width;
let img_height = this.data.img_height;
if (this.data.angle / 90 % 2) {
img_width = this.data.img_height;
img_height = this.data.img_width;
}
left = this.data.cut_left + img_width * scale / 2 >= left ? left : this.data.cut_left + img_width * scale / 2;
left = this.data.cut_left + this.data.width - img_width * scale / 2 <= left ? left : this.data.cut_left + this.data.width - img_width * scale / 2;
top = this.data.cut_top + img_height * scale / 2 >= top ? top : this.data.cut_top + img_height * scale / 2;
top = this.data.cut_top + this.data.height - img_height * scale / 2 <= top ? top : this.data.cut_top + this.data.height - img_height * scale / 2;
this.setData({
_img_left: left,
_img_top: top,
scale: scale
})
},
/**
* 图片边缘检测-缩放
*/
_imgMarginDetectionScale() {
if (!this.data.limit_move) return;
let scale = this.data.scale;
let img_width = this.data.img_width;
let img_height = this.data.img_height;
if (this.data.angle / 90 % 2) {
img_width = this.data.img_height;
img_height = this.data.img_width;
}
if (img_width * scale < this.data.width) {
scale = this.data.width / img_width;
}
if (img_height * scale < this.data.height) {
scale = Math.max(scale, this.data.height / img_height);
}
this._imgMarginDetectionPosition(scale);
},
_setData(obj) {
let data = {};
for (var key in obj) {
if (this.data[key] != obj[key]) {
data[key] = obj[key];
}
}
this.setData(data);
return data;
},
/**
* 计算图片尺寸
*/
_imgComputeSize() {
let img_width = this.data.img_width,
img_height = this.data.img_height;
if (!this.data.INIT_IMGHEIGHT && !this.data.INIT_IMGWIDTH) {
//默认按图片最小边 = 对应裁剪框尺寸
img_width = this.data.imageObject.width;
img_height = this.data.imageObject.height;
if (img_width / img_height > this.data.width / this.data.height) {
img_height = this.data.height;
img_width = this.data.imageObject.width / this.data.imageObject.height * img_height;
} else {
img_width = this.data.width;
img_height = this.data.imageObject.height / this.data.imageObject.width * img_width;
}
} else if (this.data.INIT_IMGHEIGHT && !this.data.INIT_IMGWIDTH) {
img_width = this.data.imageObject.width / this.data.imageObject.height * this.data.INIT_IMGHEIGHT;
} else if (!this.data.INIT_IMGHEIGHT && this.data.INIT_IMGWIDTH) {
img_height = this.data.imageObject.height / this.data.imageObject.width * this.data.INIT_IMGWIDTH;
}
this.setData({
img_width: img_width,
img_height: img_height
});
},
//改变截取框大小
_computeCutSize() {
if (this.data.width > this.data.info.windowWidth) {
this.setData({
width: this.data.info.windowWidth,
});
} else if (this.data.width + this.data.cut_left > this.data.info.windowWidth) {
this.setData({
cut_left: this.data.info.windowWidth - this.data.cut_left,
});
};
if (this.data.height > this.data.info.windowHeight) {
this.setData({
height: this.data.info.windowHeight,
});
} else if (this.data.height + this.data.cut_top > this.data.info.windowHeight) {
this.setData({
cut_top: this.data.info.windowHeight - this.data.cut_top,
});
}!this.data._canvas_overflow && this._draw();
},
//开始触摸
_start(event) {
this.data._flag_img_endtouch = false;
if (event.touches.length == 1) {
//单指拖动
this.data._touch_img_relative[0] = {
x: (event.touches[0].clientX - this.data._img_left),
y: (event.touches[0].clientY - this.data._img_top)
}
} else {
//双指放大
let width = Math.abs(event.touches[0].clientX - event.touches[1].clientX);
let height = Math.abs(event.touches[0].clientY - event.touches[1].clientY);
this.data._touch_img_relative = [{
x: (event.touches[0].clientX - this.data._img_left),
y: (event.touches[0].clientY - this.data._img_top)
}, {
x: (event.touches[1].clientX - this.data._img_left),
y: (event.touches[1].clientY - this.data._img_top)
}];
this.data._hypotenuse_length = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2));
}!this.data._canvas_overflow && this._draw();
},
_move_throttle() {
//安卓需要节流
if (this.data.info.platform == 'android') {
clearTimeout(this.data.MOVE_THROTTLE);
this.data.MOVE_THROTTLE = setTimeout(() => {
this.data.MOVE_THROTTLE_FLAG = true;
}, 1000 / 40)
return this.data.MOVE_THROTTLE_FLAG;
} else {
this.data.MOVE_THROTTLE_FLAG = true;
}
},
_move(event) {
if (this.data._flag_img_endtouch || !this.data.MOVE_THROTTLE_FLAG) return;
this.data.MOVE_THROTTLE_FLAG = false;
this._move_throttle();
this._moveDuring();
if (event.touches.length == 1) {
//单指拖动
let left = (event.touches[0].clientX - this.data._touch_img_relative[0].x),
top = (event.touches[0].clientY - this.data._touch_img_relative[0].y);
//图像边缘检测,防止截取到空白
this.data._img_left = left;
this.data._img_top = top;
this._imgMarginDetectionPosition();
this.setData({
_img_left: this.data._img_left,
_img_top: this.data._img_top
});
} else {
//双指放大
let width = (Math.abs(event.touches[0].clientX - event.touches[1].clientX)),
height = (Math.abs(event.touches[0].clientY - event.touches[1].clientY)),
hypotenuse = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2)),
scale = this.data.scale * (hypotenuse / this.data._hypotenuse_length),
current_deg = 0;
scale = scale <= this.data.min_scale ? this.data.min_scale : scale;
scale = scale >= this.data.max_scale ? this.data.max_scale : scale;
//图像边缘检测,防止截取到空白
this.data.scale = scale;
this._imgMarginDetectionScale();
//双指旋转(如果没禁用旋转)
let _touch_img_relative = [{
x: (event.touches[0].clientX - this.data._img_left),
y: (event.touches[0].clientY - this.data._img_top)
}, {
x: (event.touches[1].clientX - this.data._img_left),
y: (event.touches[1].clientY - this.data._img_top)
}];
if (!this.data.disable_rotate) {
let first_atan = 180 / Math.PI * Math.atan2(_touch_img_relative[0].y, _touch_img_relative[0].x);
let first_atan_old = 180 / Math.PI * Math.atan2(this.data._touch_img_relative[0].y, this.data._touch_img_relative[0].x);
let second_atan = 180 / Math.PI * Math.atan2(_touch_img_relative[1].y, _touch_img_relative[1].x);
let second_atan_old = 180 / Math.PI * Math.atan2(this.data._touch_img_relative[1].y, this.data._touch_img_relative[1].x);
//当前旋转的角度
let first_deg = first_atan - first_atan_old,
second_deg = second_atan - second_atan_old;
if (first_deg != 0) {
current_deg = first_deg;
} else if (second_deg != 0) {
current_deg = second_deg;
}
}
this.data._touch_img_relative = _touch_img_relative;
this.data._hypotenuse_length = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2));
//更新视图
this.setData({
angle: this.data.angle + current_deg,
scale: this.data.scale
});
}!this.data._canvas_overflow && this._draw();
},
//结束操作
_end(event) {
this.data._flag_img_endtouch = true;
this._moveStop();
},
//点击中间剪裁框处理
_click(event) {
if (!this.data.imgSrc) {
//调起上传
this.upload();
return;
}
this._draw(() => {
let x = event.detail ? event.detail.x : event.touches[0].clientX;
let y = event.detail ? event.detail.y : event.touches[0].clientY;
if ((x >= this.data.cut_left && x <= (this.data.cut_left + this.data.width)) && (y >= this.data.cut_top && y <= (this.data.cut_top + this.data.height))) {
//生成图片并回调
wx.canvasToTempFilePath({
width: this.data.width * this.data.export_scale,
height: Math.round(this.data.height * this.data.export_scale),
destWidth: this.data.width * this.data.export_scale,
destHeight: Math.round(this.data.height) * this.data.export_scale,
fileType: 'png',
quality: this.data.quality,
canvasId: this.data.el,
success: (res) => {
this.triggerEvent('tapcut', {
url: res.tempFilePath,
width: this.data.width * this.data.export_scale,
height: this.data.height * this.data.export_scale
});
}
}, this)
}
});
},
//渲染
_draw(callback) {
if (!this.data.imgSrc) return;
let draw = () => {
//图片实际大小
let img_width = this.data.img_width * this.data.scale * this.data.export_scale;
let img_height = this.data.img_height * this.data.scale * this.data.export_scale;
//canvas和图片的相对距离
var xpos = this.data._img_left - this.data.cut_left;
var ypos = this.data._img_top - this.data.cut_top;
//旋转画布
this.data.ctx.translate(xpos * this.data.export_scale, ypos * this.data.export_scale);
this.data.ctx.rotate(this.data.angle * Math.PI / 180);
this.data.ctx.drawImage(this.data.imgSrc, -img_width / 2, -img_height / 2, img_width, img_height);
this.data.ctx.draw(false, () => {
callback && callback();
});
}
if (this.data.ctx.width != this.data.width || this.data.ctx.height != this.data.height) {
//优化拖动裁剪框,所以必须把宽高设置放在离用户触发渲染最近的地方
this.setData({
_canvas_height: this.data.height,
_canvas_width: this.data.width,
}, () => {
//延迟40毫秒防止点击过快出现拉伸或裁剪过多
setTimeout(() => {
draw();
}, 40);
});
} else {
draw();
}
},
//裁剪框处理
_cutTouchMove(e) {
if (this.data._flag_cut_touch && this.data.MOVE_THROTTLE_FLAG) {
if (this.data.disable_ratio && (this.data.disable_width || this.data.disable_height)) return;
//节流
this.data.MOVE_THROTTLE_FLAG = false;
this._move_throttle();
let width = this.data.width,
height = this.data.height,
cut_top = this.data.cut_top,
cut_left = this.data.cut_left,
size_correct = () => {
width = width <= this.data.max_width ? width >= this.data.min_width ? width : this.data.min_width : this.data.max_width;
height = height <= this.data.max_height ? height >= this.data.min_height ? height : this.data.min_height : this.data.max_height;
},
size_inspect = () => {
if ((width > this.data.max_width || width < this.data.min_width || height > this.data.max_height || height < this.data.min_height) && this.data.disable_ratio) {
size_correct();
return false;
} else {
size_correct();
return true;
}
};
height = this.data.CUT_START.height + ((this.data.CUT_START.corner > 1 && this.data.CUT_START.corner < 4 ? 1 : -1) * (this.data.CUT_START.y - e.touches[0].clientY));
switch (this.data.CUT_START.corner) {
case 1:
width = this.data.CUT_START.width + this.data.CUT_START.x - e.touches[0].clientX;
if (this.data.disable_ratio) {
height = width / (this.data.width / this.data.height)
}
if (!size_inspect()) return;
cut_left = this.data.CUT_START.cut_left - (width - this.data.CUT_START.width);
break
case 2:
width = this.data.CUT_START.width + this.data.CUT_START.x - e.touches[0].clientX;
if (this.data.disable_ratio) {
height = width / (this.data.width / this.data.height)
}
if (!size_inspect()) return;
cut_top = this.data.CUT_START.cut_top - (height - this.data.CUT_START.height)
cut_left = this.data.CUT_START.cut_left - (width - this.data.CUT_START.width)
break
case 3:
width = this.data.CUT_START.width - this.data.CUT_START.x + e.touches[0].clientX;
if (this.data.disable_ratio) {
height = width / (this.data.width / this.data.height)
}
if (!size_inspect()) return;
cut_top = this.data.CUT_START.cut_top - (height - this.data.CUT_START.height);
break
case 4:
width = this.data.CUT_START.width - this.data.CUT_START.x + e.touches[0].clientX;
if (this.data.disable_ratio) {
height = width / (this.data.width / this.data.height)
}
if (!size_inspect()) return;
break
}
if (!this.data.disable_width && !this.data.disable_height) {
this.setData({
width: width,
cut_left: cut_left,
height: height,
cut_top: cut_top,
})
} else if (!this.data.disable_width) {
this.setData({
width: width,
cut_left: cut_left
})
} else if (!this.data.disable_height) {
this.setData({
height: height,
cut_top: cut_top
})
}
this._imgMarginDetectionScale();
}
},
_cutTouchStart(e) {
let currentX = e.touches[0].clientX;
let currentY = e.touches[0].clientY;
let cutbox_top4 = this.data.cut_top + this.data.height - 30;
let cutbox_bottom4 = this.data.cut_top + this.data.height + 20;
let cutbox_left4 = this.data.cut_left + this.data.width - 30;
let cutbox_right4 = this.data.cut_left + this.data.width + 30;
let cutbox_top3 = this.data.cut_top - 30;
let cutbox_bottom3 = this.data.cut_top + 30;
let cutbox_left3 = this.data.cut_left + this.data.width - 30;
let cutbox_right3 = this.data.cut_left + this.data.width + 30;
let cutbox_top2 = this.data.cut_top - 30;
let cutbox_bottom2 = this.data.cut_top + 30;
let cutbox_left2 = this.data.cut_left - 30;
let cutbox_right2 = this.data.cut_left + 30;
let cutbox_top1 = this.data.cut_top + this.data.height - 30;
let cutbox_bottom1 = this.data.cut_top + this.data.height + 30;
let cutbox_left1 = this.data.cut_left - 30;
let cutbox_right1 = this.data.cut_left + 30;
if (currentX > cutbox_left4 && currentX < cutbox_right4 && currentY > cutbox_top4 && currentY < cutbox_bottom4) {
this._moveDuring();
this.data._flag_cut_touch = true;
this.data._flag_img_endtouch = true;
this.data.CUT_START = {
width: this.data.width,
height: this.data.height,
x: currentX,
y: currentY,
corner: 4
}
} else if (currentX > cutbox_left3 && currentX < cutbox_right3 && currentY > cutbox_top3 && currentY < cutbox_bottom3) {
this._moveDuring();
this.data._flag_cut_touch = true;
this.data._flag_img_endtouch = true;
this.data.CUT_START = {
width: this.data.width,
height: this.data.height,
x: currentX,
y: currentY,
cut_top: this.data.cut_top,
cut_left: this.data.cut_left,
corner: 3
}
} else if (currentX > cutbox_left2 && currentX < cutbox_right2 && currentY > cutbox_top2 && currentY < cutbox_bottom2) {
this._moveDuring();
this.data._flag_cut_touch = true;
this.data._flag_img_endtouch = true;
this.data.CUT_START = {
width: this.data.width,
height: this.data.height,
cut_top: this.data.cut_top,
cut_left: this.data.cut_left,
x: currentX,
y: currentY,
corner: 2
}
} else if (currentX > cutbox_left1 && currentX < cutbox_right1 && currentY > cutbox_top1 && currentY < cutbox_bottom1) {
this._moveDuring();
this.data._flag_cut_touch = true;
this.data._flag_img_endtouch = true;
this.data.CUT_START = {
width: this.data.width,
height: this.data.height,
cut_top: this.data.cut_top,
cut_left: this.data.cut_left,
x: currentX,
y: currentY,
corner: 1
}
}
},
_cutTouchEnd(e) {
this._moveStop();
this.data._flag_cut_touch = false;
},
//停止移动时需要做的操作
_moveStop() {
//清空之前的自动居中延迟函数并添加最新的
clearTimeout(this.data.TIME_CUT_CENTER);
this.data.TIME_CUT_CENTER = setTimeout(() => {
//动画启动
if (!this.data._cut_animation) {
this.setData({
_cut_animation: true
});
}
this.setCutCenter();
}, 1000)
//清空之前的背景变化延迟函数并添加最新的
clearTimeout(this.data.TIME_BG);
this.data.TIME_BG = setTimeout(() => {
if (this.data._flag_bright) {
this.setData({
_flag_bright: false
});
}
}, 2000)
},
//移动中
_moveDuring() {
//清空之前的自动居中延迟函数
clearTimeout(this.data.TIME_CUT_CENTER);
//清空之前的背景变化延迟函数
clearTimeout(this.data.TIME_BG);
//高亮背景
if (!this.data._flag_bright) {
this.setData({
_flag_bright: true
});
}
},
//监听器
_watcher() {
Object.keys(this.data).forEach(v => {
this._observe(this.data, v, this.data.watch[v]);
})
},
_observe(obj, key, watchFun) {
var val = obj[key];
Object.defineProperty(obj, key, {
configurable: true,
enumerable: true,
set: (value) => {
val = value;
watchFun && watchFun(val, this);
},
get() {
if (val && '_img_top|img_left||width|height|min_width|max_width|min_height|max_height|export_scale|cut_top|cut_left|canvas_top|canvas_left|img_width|img_height|scale|angle|min_scale|max_scale'.indexOf(key) != -1) {
let ret = parseFloat(parseFloat(val).toFixed(3));
if (typeof val == "string" && val.indexOf("%") != -1) {
ret += '%';
}
return ret;
}
return val;
}
})
},
_preventTouchMove() {}
}
})