2024-09-26 11:41:20 +08:00
|
|
|
|
<template>
|
|
|
|
|
|
<view class="image-cropper" catchtouchmove="_preventTouchMove">
|
|
|
|
|
|
<view class="main" id="main_bc" @touchend="_cutTouchEnd" @touchstart="_cutTouchStart" @touchmove="_cutTouchMove">
|
|
|
|
|
|
<view class="content">
|
|
|
|
|
|
<view class="content_top bg_gray {{_flag_bright? '':'bg_black'}}"
|
|
|
|
|
|
style="height:{{cut_top}}px;transition-property:{{_cut_animation?'':'background'}}"></view>
|
|
|
|
|
|
<view class="content_middle" style="height:{{height}}px;">
|
|
|
|
|
|
<view class="content_middle_left bg_gray {{_flag_bright? '':'bg_black'}}"
|
|
|
|
|
|
style="width:{{cut_left}}px;transition-property:{{_cut_animation?'':'background'}}"></view>
|
|
|
|
|
|
<view class="content_middle_middle"
|
|
|
|
|
|
style="width:{{width}}px;height:{{height}}px;transition-duration: .3s;transition-property:{{_cut_animation?'':'background'}};">
|
|
|
|
|
|
<view class="border border-top-left" style="background: {{borderColor}}"></view>
|
|
|
|
|
|
<view class="border border-top-right" style="background: {{borderColor}}"></view>
|
|
|
|
|
|
<view class="border border-right-top" style="background: {{borderColor}}"></view>
|
|
|
|
|
|
<view class="border border-right-bottom" style="background: {{borderColor}}"></view>
|
|
|
|
|
|
<view class="border border-bottom-right" style="background: {{borderColor}}"></view>
|
|
|
|
|
|
<view class="border border-bottom-left" style="background: {{borderColor}}"></view>
|
|
|
|
|
|
<view class="border border-left-bottom" style="background: {{borderColor}}"></view>
|
|
|
|
|
|
<view class="border border-left-top" style="background: {{borderColor}}"></view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="content_middle_right bg_gray {{_flag_bright? '':'bg_black'}}"
|
|
|
|
|
|
style="transition-property:{{_cut_animation?'':'background'}}"></view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="content_bottom bg_gray {{_flag_bright?'':'bg_black'}}"
|
|
|
|
|
|
style="transition-property:{{_cut_animation?'':'background'}}"></view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<image @load="imageLoad" bindtouchstart="_start" bindtouchmove="_move" bindtouchend="_end"
|
|
|
|
|
|
style="width:{{img_width ? img_width + 'px' : 'auto'}};height:{{img_height ? img_height + 'px' : 'auto'}};top:{{tanTop}};left:{{tanLeft}};transform:translate3d({{tanTop=='50%'?'-'+tanTop:_img_left-img_width/2+'px'}},{{tanLeft=='50%'?'-'+tanLeft:_img_top-img_height/2+'px'}},0) scale({{scale}}) rotate({{angle}}deg);transition-duration:{{_cut_animation?.4:0}}s;"
|
|
|
|
|
|
class="img"
|
|
|
|
|
|
:src="imgSrc"></image>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<canvas canvas-id="image-cropper" disable-scroll="true"
|
|
|
|
|
|
style="width:{{_canvas_width * export_scale}}px;height:{{_canvas_height * export_scale}}px;left:{{canvas_left}}px;top:{{canvas_top}}px"
|
|
|
|
|
|
class="image-cropper-canvas"></canvas>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="main-box">
|
|
|
|
|
|
<view class="main-cancel ~flo_l ~font_30 ~text-center" @tap.stop="chooseimage">选择图片</view>
|
|
|
|
|
|
<view class="main-save ~flo_r ~font_30 ~text-center" @tap.stop="saveUpdate">确定</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<chooseImageTips :chooseShow.sync="chooseShow" @hideCut.user="hideCut" @imgSrcCut.user="imgSrcCut"></chooseImageTips>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
|
|
|
import wepy from '@wepy/core'
|
|
|
|
|
|
wepy.component({
|
|
|
|
|
|
// config = {
|
|
|
|
|
|
// component: true
|
|
|
|
|
|
// }
|
|
|
|
|
|
// components = {chooseImageTips}
|
|
|
|
|
|
props: {
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 图片路径
|
|
|
|
|
|
*/
|
|
|
|
|
|
imgSrc: {
|
|
|
|
|
|
type: String
|
|
|
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 裁剪框颜色
|
|
|
|
|
|
*/
|
|
|
|
|
|
borderColor: {
|
|
|
|
|
|
type: String,
|
|
|
|
|
|
default: 'white'
|
|
|
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 裁剪框高度
|
|
|
|
|
|
*/
|
|
|
|
|
|
height: {
|
|
|
|
|
|
type: Number,
|
|
|
|
|
|
default: 200
|
|
|
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 裁剪框宽度
|
|
|
|
|
|
*/
|
|
|
|
|
|
width: {
|
|
|
|
|
|
type: Number,
|
|
|
|
|
|
default: 200
|
|
|
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 裁剪框最小尺寸
|
|
|
|
|
|
*/
|
|
|
|
|
|
min_width: {
|
|
|
|
|
|
type: Number,
|
|
|
|
|
|
default: 100
|
|
|
|
|
|
},
|
|
|
|
|
|
min_height: {
|
|
|
|
|
|
type: Number,
|
|
|
|
|
|
default: 100
|
|
|
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 裁剪框最大尺寸
|
|
|
|
|
|
*/
|
|
|
|
|
|
max_width: {
|
|
|
|
|
|
type: Number,
|
|
|
|
|
|
default: 300
|
|
|
|
|
|
},
|
|
|
|
|
|
'max_height': {
|
|
|
|
|
|
type: Number,
|
|
|
|
|
|
default: 300
|
|
|
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 裁剪框禁止拖动
|
|
|
|
|
|
*/
|
|
|
|
|
|
disable_width: {
|
|
|
|
|
|
type: Boolean,
|
|
|
|
|
|
default: false
|
|
|
|
|
|
},
|
|
|
|
|
|
disable_height: {
|
|
|
|
|
|
type: Boolean,
|
|
|
|
|
|
default: false
|
|
|
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 锁定裁剪框比例
|
|
|
|
|
|
*/
|
|
|
|
|
|
disable_ratio: {
|
|
|
|
|
|
type: Boolean,
|
|
|
|
|
|
default: false
|
|
|
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 生成的图片尺寸相对剪裁框的比例
|
|
|
|
|
|
*/
|
|
|
|
|
|
export_scale: {
|
|
|
|
|
|
type: Number,
|
|
|
|
|
|
default: 1
|
|
|
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 生成的图片质量0-1
|
|
|
|
|
|
*/
|
|
|
|
|
|
quality: {
|
|
|
|
|
|
type: Number,
|
|
|
|
|
|
default: 0
|
|
|
|
|
|
},
|
|
|
|
|
|
cut_top: {
|
|
|
|
|
|
type: Number,
|
|
|
|
|
|
default: 212
|
|
|
|
|
|
},
|
|
|
|
|
|
cut_left: {
|
|
|
|
|
|
type: Number,
|
|
|
|
|
|
default: 37
|
|
|
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
|
|
|
* canvas上边距(不设置默认不显示)
|
|
|
|
|
|
*/
|
|
|
|
|
|
canvas_top: {
|
|
|
|
|
|
type: Number,
|
|
|
|
|
|
default: null
|
|
|
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
|
|
|
* canvas左边距(不设置默认不显示)
|
|
|
|
|
|
*/
|
|
|
|
|
|
canvas_left: {
|
|
|
|
|
|
type: Number,
|
|
|
|
|
|
default: null
|
|
|
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 图片宽度
|
|
|
|
|
|
*/
|
|
|
|
|
|
img_width: {
|
|
|
|
|
|
type: Number,
|
|
|
|
|
|
default: null
|
|
|
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 图片高度
|
|
|
|
|
|
*/
|
|
|
|
|
|
img_height: {
|
|
|
|
|
|
type: Number,
|
|
|
|
|
|
default: null
|
|
|
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 图片缩放比
|
|
|
|
|
|
*/
|
|
|
|
|
|
scale: {
|
|
|
|
|
|
type: Number,
|
|
|
|
|
|
default: 1
|
|
|
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 图片旋转角度
|
|
|
|
|
|
*/
|
|
|
|
|
|
angle: {
|
|
|
|
|
|
type: Number,
|
|
|
|
|
|
default: 0
|
|
|
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 判断是否是新图片
|
|
|
|
|
|
*/
|
|
|
|
|
|
newPic: {
|
|
|
|
|
|
type: Number,
|
|
|
|
|
|
default: 0
|
|
|
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 最小缩放比
|
|
|
|
|
|
*/
|
|
|
|
|
|
min_scale: {
|
|
|
|
|
|
type: Number,
|
|
|
|
|
|
default: 0.5
|
|
|
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 最大缩放比
|
|
|
|
|
|
*/
|
|
|
|
|
|
max_scale: {
|
|
|
|
|
|
type: Number,
|
|
|
|
|
|
default: 2
|
|
|
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 是否禁用旋转
|
|
|
|
|
|
*/
|
|
|
|
|
|
disable_rotate: {
|
|
|
|
|
|
type: Boolean,
|
|
|
|
|
|
default: false
|
|
|
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 是否限制移动范围(剪裁框只能在图片内)
|
|
|
|
|
|
*/
|
|
|
|
|
|
limit_move: {
|
|
|
|
|
|
type: Boolean,
|
|
|
|
|
|
default: 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, // 图片左边距
|
|
|
|
|
|
chooseShow: false,
|
|
|
|
|
|
tanTop: '50%',
|
|
|
|
|
|
tanLeft: '50%'
|
|
|
|
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
watch: {
|
|
|
|
|
|
// 监听截取框宽高变化
|
|
|
|
|
|
width(newV, oldV) {
|
|
|
|
|
|
if (newV < this.min_width) {
|
|
|
|
|
|
this.width = this.min_width
|
|
|
|
|
|
}
|
|
|
|
|
|
this._computeCutSize()
|
|
|
|
|
|
},
|
|
|
|
|
|
height(newV, oldV) {
|
|
|
|
|
|
if (newV < this.min_height) {
|
|
|
|
|
|
this.height = this.min_height
|
|
|
|
|
|
}
|
|
|
|
|
|
this._computeCutSize()
|
|
|
|
|
|
},
|
|
|
|
|
|
angle(newV, oldV) {
|
|
|
|
|
|
// 停止居中裁剪框,继续修改图片位置
|
|
|
|
|
|
this._moveStop()
|
|
|
|
|
|
if (this.limit_move) {
|
|
|
|
|
|
if (this.angle % 90) {
|
|
|
|
|
|
this.angle = Math.round(this.angle / 90) * 90
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
_cut_animation(newV, oldV) {
|
|
|
|
|
|
// 开启过渡300毫秒之后自动关闭
|
|
|
|
|
|
clearTimeout(this._cut_animation_time)
|
|
|
|
|
|
if (newV) {
|
|
|
|
|
|
this._cut_animation_time = setTimeout(() => {
|
|
|
|
|
|
this._cut_animation = false
|
|
|
|
|
|
}, 300)
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
limit_move(newV) {
|
|
|
|
|
|
if (newV) {
|
|
|
|
|
|
if (this.angle % 90) {
|
|
|
|
|
|
this.angle = Math.round(this.angle / 90) * 90
|
|
|
|
|
|
}
|
|
|
|
|
|
this._imgMarginDetectionScale()
|
|
|
|
|
|
!this._canvas_overflow && this._draw()
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
canvas_top() {
|
|
|
|
|
|
this._canvasDetectionPosition()
|
|
|
|
|
|
},
|
|
|
|
|
|
canvas_left() {
|
|
|
|
|
|
this._canvasDetectionPosition()
|
|
|
|
|
|
},
|
|
|
|
|
|
imgSrc(e) {
|
|
|
|
|
|
this.pushImg()
|
|
|
|
|
|
},
|
|
|
|
|
|
cut_top() {
|
|
|
|
|
|
this._cutDetectionPosition()
|
|
|
|
|
|
if (this.limit_move) {
|
|
|
|
|
|
!this._canvas_overflow && this._draw()
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
cut_left() {
|
|
|
|
|
|
this._cutDetectionPosition()
|
|
|
|
|
|
if (this.limit_move) {
|
|
|
|
|
|
!this._canvas_overflow && this._draw()
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
ready() {
|
|
|
|
|
|
this.info = wx.getSystemInfoSync()
|
|
|
|
|
|
this.INIT_IMGWIDTH = this.img_width
|
|
|
|
|
|
this.INIT_IMGHEIGHT = this.img_height
|
|
|
|
|
|
this._canvas_height = this.height
|
|
|
|
|
|
this._canvas_width = this.width
|
|
|
|
|
|
console.log('--9988')
|
|
|
|
|
|
this._initCanvas()
|
|
|
|
|
|
this.imgSrc && (this.imgSrc = this.imgSrc)
|
|
|
|
|
|
// 根据开发者设置的图片目标尺寸计算实际尺寸
|
|
|
|
|
|
this._initImageSize()
|
|
|
|
|
|
// 设置裁剪框大小>设置图片尺寸>绘制canvas
|
|
|
|
|
|
this._computeCutSize()
|
|
|
|
|
|
// 检查裁剪框是否在范围内
|
|
|
|
|
|
this._cutDetectionPosition()
|
|
|
|
|
|
// 检查canvas是否在范围内
|
|
|
|
|
|
this._canvasDetectionPosition()
|
|
|
|
|
|
this.setCutCenter()
|
|
|
|
|
|
this.$emit('load', {
|
|
|
|
|
|
cropper: this
|
|
|
|
|
|
})
|
|
|
|
|
|
},
|
|
|
|
|
|
// 渲染
|
|
|
|
|
|
methods: {
|
|
|
|
|
|
_draw(callback) {
|
|
|
|
|
|
console.log(this.imgSrc)
|
2024-09-29 11:01:17 +08:00
|
|
|
|
if (!this.imgSrc || !this.ctx) return
|
2024-09-26 11:41:20 +08:00
|
|
|
|
let draw = () => {
|
|
|
|
|
|
// 图片实际大小
|
|
|
|
|
|
let img_width = this.img_width * this.scale * this.export_scale
|
|
|
|
|
|
let img_height = this.img_height * this.scale * this.export_scale
|
|
|
|
|
|
// canvas和图片的相对距离
|
|
|
|
|
|
var xpos = this._img_left - this.cut_left
|
|
|
|
|
|
var ypos = this._img_top - this.cut_top
|
|
|
|
|
|
// 旋转画布
|
|
|
|
|
|
this.ctx.translate(xpos * this.export_scale, ypos * this.export_scale)
|
|
|
|
|
|
this.ctx.rotate(this.angle * Math.PI / 180)
|
|
|
|
|
|
this.ctx.drawImage(this.imgSrc, -img_width / 2, -img_height / 2, img_width, img_height)
|
|
|
|
|
|
this.ctx.draw(false, () => {
|
|
|
|
|
|
callback && callback()
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
console.log(this.ctx, 'this.ctx=333')
|
2024-09-29 11:01:17 +08:00
|
|
|
|
if (this.ctx && (this.ctx.width != this.width || this.ctx.height != this.height)) {
|
2024-09-26 11:41:20 +08:00
|
|
|
|
// 优化拖动裁剪框,所以必须把宽高设置放在离用户触发渲染最近的地方
|
|
|
|
|
|
this._canvas_height = this.height
|
|
|
|
|
|
this._canvas_width = this.width
|
|
|
|
|
|
draw()
|
|
|
|
|
|
this._canvas_height = this.height
|
|
|
|
|
|
this._canvas_width = this.width
|
|
|
|
|
|
} else {
|
|
|
|
|
|
draw()
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
chooseimage() {
|
|
|
|
|
|
let vm = this
|
|
|
|
|
|
vm.chooseShow = true
|
|
|
|
|
|
vm.newPic = 1
|
|
|
|
|
|
// wx.chooseImage({
|
|
|
|
|
|
// count: 1,
|
|
|
|
|
|
// // sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有
|
|
|
|
|
|
// sizeType: ['compressed'], // 可以指定是原图还是压缩图,默认二者都有
|
|
|
|
|
|
// sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有
|
|
|
|
|
|
// success: (res) => {
|
|
|
|
|
|
// vm.imgSrc = res.tempFilePaths[0]
|
|
|
|
|
|
// console.log(vm.imgSrc)
|
|
|
|
|
|
// }
|
|
|
|
|
|
// })
|
|
|
|
|
|
},
|
|
|
|
|
|
async saveUpdate(event) {
|
|
|
|
|
|
// 生成图片并回调
|
|
|
|
|
|
await this._initCanvas()
|
|
|
|
|
|
let vm = this
|
|
|
|
|
|
console.log(this.imgSrc, '//')
|
|
|
|
|
|
if (!this.imgSrc) return
|
|
|
|
|
|
if (vm.newPic == 0) {
|
|
|
|
|
|
console.log('222')
|
|
|
|
|
|
vm.$emit('saveCut', {
|
|
|
|
|
|
url: this.imgSrc
|
|
|
|
|
|
})
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
let draw = () => {
|
|
|
|
|
|
// 图片实际大小
|
|
|
|
|
|
let img_width = this.img_width * this.scale * this.export_scale
|
|
|
|
|
|
let img_height = this.img_height * this.scale * this.export_scale
|
|
|
|
|
|
// canvas和图片的相对距离
|
|
|
|
|
|
var xpos = this._img_left - this.cut_left
|
|
|
|
|
|
var ypos = this._img_top - this.cut_top
|
|
|
|
|
|
// 旋转画布
|
|
|
|
|
|
vm.ctx.translate(xpos * vm.export_scale, ypos * vm.export_scale)
|
|
|
|
|
|
vm.ctx.rotate(this.angle * Math.PI / 180)
|
|
|
|
|
|
vm.ctx.drawImage(vm.imgSrc, -img_width / 2, -img_height / 2, img_width, img_height)
|
|
|
|
|
|
console.log(vm.ctx, '333')
|
|
|
|
|
|
vm.ctx.draw(false, () => {
|
|
|
|
|
|
console.log('444')
|
|
|
|
|
|
wx.canvasToTempFilePath({
|
|
|
|
|
|
width: vm.width * vm.export_scale,
|
|
|
|
|
|
height: Math.round(vm.height * vm.export_scale),
|
|
|
|
|
|
destWidth: vm.width * vm.export_scale,
|
|
|
|
|
|
destHeight: Math.round(vm.height) * vm.export_scale,
|
|
|
|
|
|
fileType: 'png',
|
|
|
|
|
|
quality: vm.quality,
|
|
|
|
|
|
canvasId: vm.el,
|
|
|
|
|
|
success: (res) => {
|
|
|
|
|
|
console.log(res.tempFilePath, '///')
|
|
|
|
|
|
vm.$emit('saveCut', {
|
|
|
|
|
|
url: res.tempFilePath,
|
|
|
|
|
|
width: vm.width * vm.export_scale,
|
|
|
|
|
|
height: vm.height * vm.export_scale
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
}, vm.$wx)
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
if (vm.ctx.width != vm.width || vm.ctx.height != vm.height) {
|
|
|
|
|
|
// 优化拖动裁剪框,所以必须把宽高设置放在离用户触发渲染最近的地方
|
|
|
|
|
|
vm._canvas_height = vm.height
|
|
|
|
|
|
vm._canvas_width = vm.width
|
|
|
|
|
|
draw()
|
|
|
|
|
|
vm._canvas_height = vm.height
|
|
|
|
|
|
vm._canvas_width = vm.width
|
|
|
|
|
|
} else {
|
|
|
|
|
|
draw()
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
_preventTouchMove(event) {
|
|
|
|
|
|
},
|
|
|
|
|
|
// 裁剪框处理
|
|
|
|
|
|
_cutTouchMove(e) {
|
|
|
|
|
|
if (this._flag_cut_touch && this.MOVE_THROTTLE_FLAG) {
|
|
|
|
|
|
// if (this.disable_ratio && (this.disable_width || this.disable_height)) return
|
|
|
|
|
|
// 节流
|
|
|
|
|
|
this.MOVE_THROTTLE_FLAG = false
|
|
|
|
|
|
this._move_throttle()
|
|
|
|
|
|
let width = this.width,
|
|
|
|
|
|
height = this.height,
|
|
|
|
|
|
cut_top = this.cut_top,
|
|
|
|
|
|
cut_left = this.cut_left,
|
|
|
|
|
|
size_correct = () => {
|
|
|
|
|
|
width = width <= this.max_width ? width >= this.min_width ? width : this.min_width : this.max_width
|
|
|
|
|
|
height = height <= this.max_height ? height >= this.min_height ? height : this.min_height : this.max_height
|
|
|
|
|
|
},
|
|
|
|
|
|
size_inspect = () => {
|
|
|
|
|
|
if ((width > this.max_width || width < this.min_width || height > this.max_height || height < this.min_height) && this.disable_ratio) {
|
|
|
|
|
|
size_correct()
|
|
|
|
|
|
return false
|
|
|
|
|
|
} else {
|
|
|
|
|
|
size_correct()
|
|
|
|
|
|
return true
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
height = this.CUT_START.height + ((this.CUT_START.corner > 1 && this.CUT_START.corner < 4 ? 1 : -1) * (this.CUT_START.y - e.touches[0].clientY))
|
|
|
|
|
|
switch (this.CUT_START.corner) {
|
|
|
|
|
|
case 1:
|
|
|
|
|
|
width = this.CUT_START.width + this.CUT_START.x - e.touches[0].clientX
|
|
|
|
|
|
if (this.disable_ratio) {
|
|
|
|
|
|
height = width / (this.width / this.height)
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!size_inspect()) return
|
|
|
|
|
|
cut_left = this.CUT_START.cut_left - (width - this.CUT_START.width)
|
|
|
|
|
|
break
|
|
|
|
|
|
case 2:
|
|
|
|
|
|
width = this.CUT_START.width + this.CUT_START.x - e.touches[0].clientX
|
|
|
|
|
|
if (this.disable_ratio) {
|
|
|
|
|
|
height = width / (this.width / this.height)
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!size_inspect()) return
|
|
|
|
|
|
cut_top = this.CUT_START.cut_top - (height - this.CUT_START.height)
|
|
|
|
|
|
cut_left = this.CUT_START.cut_left - (width - this.CUT_START.width)
|
|
|
|
|
|
break
|
|
|
|
|
|
case 3:
|
|
|
|
|
|
width = this.CUT_START.width - this.CUT_START.x + e.touches[0].clientX
|
|
|
|
|
|
if (this.disable_ratio) {
|
|
|
|
|
|
height = width / (this.width / this.height)
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!size_inspect()) return
|
|
|
|
|
|
cut_top = this.CUT_START.cut_top - (height - this.CUT_START.height)
|
|
|
|
|
|
break
|
|
|
|
|
|
case 4:
|
|
|
|
|
|
width = this.CUT_START.width - this.CUT_START.x + e.touches[0].clientX
|
|
|
|
|
|
if (this.disable_ratio) {
|
|
|
|
|
|
height = width / (this.width / this.height)
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!size_inspect()) return
|
|
|
|
|
|
break
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!this.disable_width && !this.disable_height) {
|
|
|
|
|
|
this.width = width
|
|
|
|
|
|
this.cut_left = cut_left
|
|
|
|
|
|
this.height = height
|
|
|
|
|
|
this.cut_top = cut_top
|
|
|
|
|
|
} else if (!this.disable_width) {
|
|
|
|
|
|
this.width = width
|
|
|
|
|
|
this.cut_left = cut_left
|
|
|
|
|
|
} else if (!this.disable_height) {
|
|
|
|
|
|
this.height = height
|
|
|
|
|
|
this.cut_top = cut_top
|
|
|
|
|
|
}
|
|
|
|
|
|
this._imgMarginDetectionScale()
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
_cutTouchStart(e) {
|
|
|
|
|
|
let currentX = e.touches[0].clientX
|
|
|
|
|
|
let currentY = e.touches[0].clientY
|
|
|
|
|
|
let cutbox_top4 = this.cut_top + this.height - 30
|
|
|
|
|
|
let cutbox_bottom4 = this.cut_top + this.height + 20
|
|
|
|
|
|
let cutbox_left4 = this.cut_left + this.width - 30
|
|
|
|
|
|
let cutbox_right4 = this.cut_left + this.width + 30
|
|
|
|
|
|
|
|
|
|
|
|
let cutbox_top3 = this.cut_top - 30
|
|
|
|
|
|
let cutbox_bottom3 = this.cut_top + 30
|
|
|
|
|
|
let cutbox_left3 = this.cut_left + this.width - 30
|
|
|
|
|
|
let cutbox_right3 = this.cut_left + this.width + 30
|
|
|
|
|
|
|
|
|
|
|
|
let cutbox_top2 = this.cut_top - 30
|
|
|
|
|
|
let cutbox_bottom2 = this.cut_top + 30
|
|
|
|
|
|
let cutbox_left2 = this.cut_left - 30
|
|
|
|
|
|
let cutbox_right2 = this.cut_left + 30
|
|
|
|
|
|
|
|
|
|
|
|
let cutbox_top1 = this.cut_top + this.height - 30
|
|
|
|
|
|
let cutbox_bottom1 = this.cut_top + this.height + 30
|
|
|
|
|
|
let cutbox_left1 = this.cut_left - 30
|
|
|
|
|
|
let cutbox_right1 = this.cut_left + 30
|
|
|
|
|
|
if (currentX > cutbox_left4 && currentX < cutbox_right4 && currentY > cutbox_top4 && currentY < cutbox_bottom4) {
|
|
|
|
|
|
this._moveDuring()
|
|
|
|
|
|
this._flag_cut_touch = true
|
|
|
|
|
|
this._flag_img_endtouch = true
|
|
|
|
|
|
this.CUT_START = {
|
|
|
|
|
|
width: this.width,
|
|
|
|
|
|
height: this.height,
|
|
|
|
|
|
x: currentX,
|
|
|
|
|
|
y: currentY,
|
|
|
|
|
|
corner: 4
|
|
|
|
|
|
}
|
|
|
|
|
|
} else if (currentX > cutbox_left3 && currentX < cutbox_right3 && currentY > cutbox_top3 && currentY < cutbox_bottom3) {
|
|
|
|
|
|
this._moveDuring()
|
|
|
|
|
|
this._flag_cut_touch = true
|
|
|
|
|
|
this._flag_img_endtouch = true
|
|
|
|
|
|
this.CUT_START = {
|
|
|
|
|
|
width: this.width,
|
|
|
|
|
|
height: this.height,
|
|
|
|
|
|
x: currentX,
|
|
|
|
|
|
y: currentY,
|
|
|
|
|
|
cut_top: this.cut_top,
|
|
|
|
|
|
cut_left: this.cut_left,
|
|
|
|
|
|
corner: 3
|
|
|
|
|
|
}
|
|
|
|
|
|
} else if (currentX > cutbox_left2 && currentX < cutbox_right2 && currentY > cutbox_top2 && currentY < cutbox_bottom2) {
|
|
|
|
|
|
this._moveDuring()
|
|
|
|
|
|
this._flag_cut_touch = true
|
|
|
|
|
|
this._flag_img_endtouch = true
|
|
|
|
|
|
this.CUT_START = {
|
|
|
|
|
|
width: this.width,
|
|
|
|
|
|
height: this.height,
|
|
|
|
|
|
cut_top: this.cut_top,
|
|
|
|
|
|
cut_left: this.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._flag_cut_touch = true
|
|
|
|
|
|
this._flag_img_endtouch = true
|
|
|
|
|
|
this.CUT_START = {
|
|
|
|
|
|
width: this.width,
|
|
|
|
|
|
height: this.height,
|
|
|
|
|
|
cut_top: this.cut_top,
|
|
|
|
|
|
cut_left: this.cut_left,
|
|
|
|
|
|
x: currentX,
|
|
|
|
|
|
y: currentY,
|
|
|
|
|
|
corner: 1
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
_cutTouchEnd(e) {
|
|
|
|
|
|
this._moveStop()
|
|
|
|
|
|
this._flag_cut_touch = false
|
|
|
|
|
|
// console.log(e,'_cutTouchEnd;;;')
|
|
|
|
|
|
},
|
|
|
|
|
|
// 点击中间剪裁框处理
|
|
|
|
|
|
_click(event) {
|
|
|
|
|
|
console.log(event)
|
|
|
|
|
|
if (!this.imgSrc) {
|
|
|
|
|
|
// 调起上传
|
|
|
|
|
|
this.chooseimage()
|
|
|
|
|
|
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.cut_left && x <= (this.cut_left + this.width)) && (y >= this.cut_top && y <= (this.cut_top + this.height))) {
|
|
|
|
|
|
// 生成图片并回调
|
|
|
|
|
|
wx.canvasToTempFilePath({
|
|
|
|
|
|
width: this.width * this.export_scale,
|
|
|
|
|
|
height: Math.round(this.height * this.export_scale),
|
|
|
|
|
|
destWidth: this.width * this.export_scale,
|
|
|
|
|
|
destHeight: Math.round(this.height) * this.export_scale,
|
|
|
|
|
|
fileType: 'png',
|
|
|
|
|
|
quality: this.quality,
|
|
|
|
|
|
canvasId: this.el,
|
|
|
|
|
|
success: (res) => {
|
|
|
|
|
|
this.$emit('tapcut', {
|
|
|
|
|
|
url: res.tempFilePath,
|
|
|
|
|
|
width: this.width * this.export_scale,
|
|
|
|
|
|
height: this.height * this.export_scale
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
}, this.$wx)
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
imageLoad(e) {
|
|
|
|
|
|
this.$emit('imageload', this.imageObject)
|
|
|
|
|
|
wx.hideLoading() // 重置图片角度、缩放、位置
|
|
|
|
|
|
this.imgReset()
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
}, 100)
|
|
|
|
|
|
},
|
|
|
|
|
|
// 开始触摸
|
|
|
|
|
|
_start(event) {
|
|
|
|
|
|
this._flag_img_endtouch = false
|
|
|
|
|
|
if (event.touches.length == 1) {
|
|
|
|
|
|
// 单指拖动
|
|
|
|
|
|
this._touch_img_relative[0] = {
|
|
|
|
|
|
x: (event.touches[0].clientX - this._img_left),
|
|
|
|
|
|
y: (event.touches[0].clientY - this._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._touch_img_relative = [{
|
|
|
|
|
|
x: (event.touches[0].clientX - this._img_left),
|
|
|
|
|
|
y: (event.touches[0].clientY - this._img_top)
|
|
|
|
|
|
}, {
|
|
|
|
|
|
x: (event.touches[1].clientX - this._img_left),
|
|
|
|
|
|
y: (event.touches[1].clientY - this._img_top)
|
|
|
|
|
|
}]
|
|
|
|
|
|
this._hypotenuse_length = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2))
|
|
|
|
|
|
}
|
|
|
|
|
|
!this._canvas_overflow && this._draw()
|
|
|
|
|
|
},
|
|
|
|
|
|
_move(event) {
|
|
|
|
|
|
// console.log('asssssss',event)
|
|
|
|
|
|
if (this._flag_img_endtouch || !this.MOVE_THROTTLE_FLAG) return
|
|
|
|
|
|
this.MOVE_THROTTLE_FLAG = false
|
|
|
|
|
|
this._move_throttle()
|
|
|
|
|
|
this._moveDuring()
|
|
|
|
|
|
if (event.touches.length == 1) {
|
|
|
|
|
|
// 单指拖动
|
|
|
|
|
|
let left = (event.touches[0].clientX - this._touch_img_relative[0].x),
|
|
|
|
|
|
top = (event.touches[0].clientY - this._touch_img_relative[0].y)
|
|
|
|
|
|
// 图像边缘检测,防止截取到空白
|
|
|
|
|
|
this._img_left = left
|
|
|
|
|
|
this._img_top = top
|
|
|
|
|
|
this._imgMarginDetectionPosition()
|
|
|
|
|
|
this._img_left = this._img_left
|
|
|
|
|
|
this._img_top = this._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.scale * (hypotenuse / this._hypotenuse_length),
|
|
|
|
|
|
current_deg = 0
|
|
|
|
|
|
scale = scale <= this.min_scale ? this.min_scale : scale
|
|
|
|
|
|
scale = scale >= this.max_scale ? this.max_scale : scale
|
|
|
|
|
|
// 图像边缘检测,防止截取到空白
|
|
|
|
|
|
this.scale = scale
|
|
|
|
|
|
this._imgMarginDetectionScale()
|
|
|
|
|
|
// 双指旋转(如果没禁用旋转)
|
|
|
|
|
|
let _touch_img_relative = [{
|
|
|
|
|
|
x: (event.touches[0].clientX - this._img_left),
|
|
|
|
|
|
y: (event.touches[0].clientY - this._img_top)
|
|
|
|
|
|
}, {
|
|
|
|
|
|
x: (event.touches[1].clientX - this._img_left),
|
|
|
|
|
|
y: (event.touches[1].clientY - this._img_top)
|
|
|
|
|
|
}]
|
|
|
|
|
|
if (!this.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._touch_img_relative[0].y, this._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._touch_img_relative[1].y, this._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._touch_img_relative = _touch_img_relative
|
|
|
|
|
|
this._hypotenuse_length = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2))
|
|
|
|
|
|
|
|
|
|
|
|
this.angle = this.angle + current_deg
|
|
|
|
|
|
this.scale = this.scale
|
|
|
|
|
|
}
|
|
|
|
|
|
!this._canvas_overflow && this._draw()
|
|
|
|
|
|
},
|
|
|
|
|
|
// 结束操作
|
|
|
|
|
|
_end(event) {
|
|
|
|
|
|
this._flag_img_endtouch = true
|
|
|
|
|
|
this._moveStop()
|
|
|
|
|
|
// console.log(event)
|
|
|
|
|
|
},
|
|
|
|
|
|
hideCut(e) {
|
|
|
|
|
|
this.chooseShow = e.chooseShow
|
|
|
|
|
|
},
|
|
|
|
|
|
imgSrcCut(e) {
|
|
|
|
|
|
this.imgSrc = e.imgSrc
|
|
|
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 上传图片
|
|
|
|
|
|
*/
|
|
|
|
|
|
upload() {
|
|
|
|
|
|
let that = this
|
|
|
|
|
|
wx.chooseImage({
|
|
|
|
|
|
count: 1,
|
|
|
|
|
|
sizeType: ['original', 'compressed'],
|
|
|
|
|
|
sourceType: ['album', 'camera'],
|
|
|
|
|
|
success(res) {
|
|
|
|
|
|
const tempFilePaths = res.tempFilePaths[0]
|
|
|
|
|
|
console.log('Img Temp Paths: ' + tempFilePaths)
|
|
|
|
|
|
that.pushImg(tempFilePaths)
|
|
|
|
|
|
wx.showLoading({
|
|
|
|
|
|
title: '加载中...'
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 返回图片信息
|
|
|
|
|
|
*/
|
|
|
|
|
|
getImg(getCallback) {
|
|
|
|
|
|
this._draw(() => {
|
|
|
|
|
|
wx.canvasToTempFilePath({
|
|
|
|
|
|
width: this.width * this.export_scale,
|
|
|
|
|
|
height: Math.round(this.height * this.export_scale),
|
|
|
|
|
|
destWidth: this.width * this.export_scale,
|
|
|
|
|
|
destHeight: Math.round(this.height) * this.export_scale,
|
|
|
|
|
|
fileType: 'png',
|
|
|
|
|
|
quality: this.quality,
|
|
|
|
|
|
canvasId: this.el,
|
|
|
|
|
|
success: (res) => {
|
|
|
|
|
|
getCallback({
|
|
|
|
|
|
url: res.tempFilePath,
|
|
|
|
|
|
width: this.width * this.export_scale,
|
|
|
|
|
|
height: this.height * this.export_scale
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
}, this)
|
|
|
|
|
|
})
|
|
|
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 设置图片动画
|
|
|
|
|
|
* {
|
|
|
|
|
|
* x:10,//图片在原有基础上向下移动10px
|
|
|
|
|
|
* y:10,//图片在原有基础上向右移动10px
|
|
|
|
|
|
* angle:10,//图片在原有基础上旋转10deg
|
|
|
|
|
|
* scale:0.5,//图片在原有基础上增加0.5倍
|
|
|
|
|
|
* }
|
|
|
|
|
|
*/
|
|
|
|
|
|
setTransform(transform) {
|
|
|
|
|
|
if (!transform) return
|
|
|
|
|
|
if (!this.disable_rotate) {
|
|
|
|
|
|
this.angle = transform.angle ? this.angle + transform.angle : this.angle
|
|
|
|
|
|
}
|
|
|
|
|
|
var scale = this.scale
|
|
|
|
|
|
if (transform.scale) {
|
|
|
|
|
|
scale = this.scale + transform.scale
|
|
|
|
|
|
scale = scale <= this.min_scale ? this.min_scale : scale
|
|
|
|
|
|
scale = scale >= this.max_scale ? this.max_scale : scale
|
|
|
|
|
|
}
|
|
|
|
|
|
this.scale = scale
|
|
|
|
|
|
let cutX = this.cut_left
|
|
|
|
|
|
let cutY = this.cut_top
|
|
|
|
|
|
if (transform.cutX) {
|
|
|
|
|
|
this.cut_left = cutX + transform.cutX
|
|
|
|
|
|
}
|
|
|
|
|
|
if (transform.cutY) {
|
|
|
|
|
|
this.cut_top = cutY + transform.cutY
|
|
|
|
|
|
}
|
|
|
|
|
|
this._img_top = transform.y ? this._img_top + transform.y : this._img_top
|
|
|
|
|
|
this._img_left = transform.x ? this._img_left + transform.x : this._img_left
|
|
|
|
|
|
// 图像边缘检测,防止截取到空白
|
|
|
|
|
|
this._imgMarginDetectionScale()
|
|
|
|
|
|
// 停止居中裁剪框,继续修改图片位置
|
|
|
|
|
|
this._moveDuring()
|
|
|
|
|
|
this.scale = this.scale
|
|
|
|
|
|
this._img_top = this._img_top
|
|
|
|
|
|
this._img_left = this._img_left
|
|
|
|
|
|
|
|
|
|
|
|
!this._canvas_overflow && this._draw()
|
|
|
|
|
|
// 可以居中裁剪框了
|
|
|
|
|
|
this._moveStop()// 结束操作
|
|
|
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 设置剪裁框尺寸
|
|
|
|
|
|
*/
|
|
|
|
|
|
setCutSize(w, h) {
|
|
|
|
|
|
this.width = w
|
|
|
|
|
|
this.height = h
|
|
|
|
|
|
this._computeCutSize()
|
|
|
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 设置剪裁框和图片居中
|
|
|
|
|
|
*/
|
|
|
|
|
|
setCutCenter() {
|
|
|
|
|
|
let cut_top = (this.info.windowHeight - this.height) * 0.5
|
|
|
|
|
|
let cut_left = (this.info.windowWidth - this.width) * 0.5
|
|
|
|
|
|
// 顺序不能变
|
|
|
|
|
|
this._img_top = this._img_top - this.cut_top + cut_top
|
|
|
|
|
|
this.cut_top = cut_top
|
|
|
|
|
|
this._img_left = this._img_left - this.cut_left + cut_left
|
|
|
|
|
|
this.cut_left = cut_left
|
|
|
|
|
|
},
|
|
|
|
|
|
_setCutCenter() {
|
|
|
|
|
|
let cut_top = (this.info.windowHeight - this.height) * 0.5
|
|
|
|
|
|
let cut_left = (this.info.windowWidth - this.width) * 0.5
|
|
|
|
|
|
this.cut_top = cut_top
|
|
|
|
|
|
this.cut_left = cut_left
|
|
|
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 设置剪裁框宽度-即将废弃
|
|
|
|
|
|
*/
|
|
|
|
|
|
setWidth(width) {
|
|
|
|
|
|
this.width = width
|
|
|
|
|
|
this._computeCutSize()
|
|
|
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 设置剪裁框高度-即将废弃
|
|
|
|
|
|
*/
|
|
|
|
|
|
setHeight(height) {
|
|
|
|
|
|
this.height = height
|
|
|
|
|
|
this._computeCutSize()
|
|
|
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 是否锁定旋转
|
|
|
|
|
|
*/
|
|
|
|
|
|
setDisableRotate(value) {
|
|
|
|
|
|
this.disable_rotate = value
|
|
|
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 是否限制移动
|
|
|
|
|
|
*/
|
|
|
|
|
|
setLimitMove(value) {
|
|
|
|
|
|
this._cut_animation = true
|
|
|
|
|
|
this.limit_move = !!value
|
|
|
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 初始化图片,包括位置、大小、旋转角度
|
|
|
|
|
|
*/
|
|
|
|
|
|
imgReset() {
|
|
|
|
|
|
this.scale = 1
|
|
|
|
|
|
this.angle = 0
|
|
|
|
|
|
this.tanLeft = 0
|
|
|
|
|
|
this.tanTop = 0
|
|
|
|
|
|
this._img_top = wx.getSystemInfoSync().windowHeight / 2
|
|
|
|
|
|
this._img_left = wx.getSystemInfoSync().windowWidth / 2
|
|
|
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 加载(更换)图片
|
|
|
|
|
|
*/
|
|
|
|
|
|
pushImg(src) {
|
|
|
|
|
|
console.log('pushing img: ' + src)
|
|
|
|
|
|
if (src) {
|
|
|
|
|
|
this.imgSrc = src
|
|
|
|
|
|
// 发现是手动赋值直接返回,交给watch处理
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
wx.getImageInfo({
|
|
|
|
|
|
src: this.imgSrc,
|
|
|
|
|
|
success: (res) => {
|
|
|
|
|
|
console.log('----------------------', res)
|
|
|
|
|
|
this.imageObject = res
|
|
|
|
|
|
// 图片非本地路径需要换成本地路径
|
|
|
|
|
|
if (this.imgSrc.search(/tmp/) == -1) {
|
|
|
|
|
|
this.imgSrc = res.path
|
|
|
|
|
|
}
|
|
|
|
|
|
// 计算最后图片尺寸
|
|
|
|
|
|
this._imgComputeSize()
|
|
|
|
|
|
if (this.limit_move) {
|
|
|
|
|
|
// 限制移动,不留空白处理
|
|
|
|
|
|
this._imgMarginDetectionScale()
|
|
|
|
|
|
}
|
|
|
|
|
|
this._draw()
|
|
|
|
|
|
},
|
|
|
|
|
|
fail: (err) => {
|
|
|
|
|
|
this.imgSrc = ''
|
|
|
|
|
|
console.log(err)
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 设置图片放大缩小
|
|
|
|
|
|
*/
|
|
|
|
|
|
setScale(scale) {
|
|
|
|
|
|
if (!scale) return
|
|
|
|
|
|
this.scale = scale
|
|
|
|
|
|
!this._canvas_overflow && this._draw()
|
|
|
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 设置图片旋转角度
|
|
|
|
|
|
*/
|
|
|
|
|
|
setAngle(angle) {
|
|
|
|
|
|
if (!angle) return
|
|
|
|
|
|
this._cut_animation = true
|
|
|
|
|
|
this.angle = angle
|
|
|
|
|
|
this._imgMarginDetectionScale()
|
|
|
|
|
|
!this._canvas_overflow && this._draw()
|
|
|
|
|
|
},
|
|
|
|
|
|
_initCanvas() {
|
|
|
|
|
|
// 初始化canvas
|
|
|
|
|
|
// if (!this.ctx) {
|
|
|
|
|
|
let vm = this
|
|
|
|
|
|
this.ctx = wx.createCanvasContext('image-cropper', this.$wx)
|
|
|
|
|
|
console.log(this.ctx, '=====')
|
|
|
|
|
|
// }
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 根据开发者设置的图片目标尺寸计算实际尺寸
|
|
|
|
|
|
*/
|
|
|
|
|
|
_initImageSize() {
|
|
|
|
|
|
// 处理宽高特殊单位 %>px
|
|
|
|
|
|
if (this.INIT_IMGWIDTH && typeof this.INIT_IMGWIDTH === 'string' && this.INIT_IMGWIDTH.indexOf('%') != -1) {
|
|
|
|
|
|
let width = this.INIT_IMGWIDTH.replace('%', '')
|
|
|
|
|
|
this.INIT_IMGWIDTH = this.img_width = this.info.windowWidth / 100 * width
|
|
|
|
|
|
}
|
|
|
|
|
|
if (this.INIT_IMGHEIGHT && typeof this.INIT_IMGHEIGHT === 'string' && this.INIT_IMGHEIGHT.indexOf('%') != -1) {
|
|
|
|
|
|
let height = this.img_height.replace('%', '')
|
|
|
|
|
|
this.INIT_IMGHEIGHT = this.img_height = this.info.windowHeight / 100 * height
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 检测剪裁框位置是否在允许的范围内(屏幕内)
|
|
|
|
|
|
*/
|
|
|
|
|
|
_cutDetectionPosition() {
|
|
|
|
|
|
let _cutDetectionPositionTop = () => {
|
|
|
|
|
|
// 检测上边距是否在范围内
|
|
|
|
|
|
if (this.cut_top < 0) {
|
|
|
|
|
|
this.cut_top = 0
|
|
|
|
|
|
}
|
|
|
|
|
|
if (this.cut_top > this.info.windowHeight - this.height) {
|
|
|
|
|
|
this.cut_top = this.info.windowHeight - this.height
|
|
|
|
|
|
}
|
|
|
|
|
|
}, _cutDetectionPositionLeft = () => {
|
|
|
|
|
|
// 检测左边距是否在范围内
|
|
|
|
|
|
if (this.cut_left < 0) {
|
|
|
|
|
|
this.cut_left = 0
|
|
|
|
|
|
}
|
|
|
|
|
|
if (this.cut_left > this.info.windowWidth - this.width) {
|
|
|
|
|
|
this.cut_left = this.info.windowWidth - this.width
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
// 裁剪框坐标处理(如果只写一个参数则另一个默认为0,都不写默认居中)
|
|
|
|
|
|
if (this.cut_top == null && this.cut_left == null) {
|
|
|
|
|
|
this._setCutCenter()
|
|
|
|
|
|
} else if (this.cut_top != null && this.cut_left != null) {
|
|
|
|
|
|
_cutDetectionPositionTop()
|
|
|
|
|
|
_cutDetectionPositionLeft()
|
|
|
|
|
|
} else if (this.cut_top != null && this.cut_left == null) {
|
|
|
|
|
|
_cutDetectionPositionTop()
|
|
|
|
|
|
this.cut_left = (this.info.windowWidth - this.width) / 2
|
|
|
|
|
|
} else if (this.cut_top == null && this.cut_left != null) {
|
|
|
|
|
|
_cutDetectionPositionLeft()
|
|
|
|
|
|
this.cut_top = (this.info.windowHeight - this.height) / 2
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 检测canvas位置是否在允许的范围内(屏幕内)如果在屏幕外则不开启实时渲染
|
|
|
|
|
|
* 如果只写一个参数则另一个默认为0,都不写默认超出屏幕外
|
|
|
|
|
|
*/
|
|
|
|
|
|
_canvasDetectionPosition() {
|
|
|
|
|
|
if (this.canvas_top == null && this.canvas_left == null) {
|
|
|
|
|
|
this._canvas_overflow = false
|
|
|
|
|
|
this.canvas_top = -5000
|
|
|
|
|
|
this.canvas_left = -5000
|
|
|
|
|
|
} else if (this.canvas_top != null && this.canvas_left != null) {
|
|
|
|
|
|
if (this.canvas_top < -this.height || this.canvas_top > this.info.windowHeight) {
|
|
|
|
|
|
this._canvas_overflow = true
|
|
|
|
|
|
} else {
|
|
|
|
|
|
this._canvas_overflow = false
|
|
|
|
|
|
}
|
|
|
|
|
|
} else if (this.canvas_top != null && this.canvas_left == null) {
|
|
|
|
|
|
this.canvas_left = 0
|
|
|
|
|
|
} else if (this.canvas_top == null && this.canvas_left != null) {
|
|
|
|
|
|
this.canvas_top = 0
|
|
|
|
|
|
if (this.canvas_left < -this.width || this.canvas_left > this.info.windowWidth) {
|
|
|
|
|
|
this._canvas_overflow = true
|
|
|
|
|
|
} else {
|
|
|
|
|
|
this._canvas_overflow = false
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 图片边缘检测-位置
|
|
|
|
|
|
*/
|
|
|
|
|
|
_imgMarginDetectionPosition(scale) {
|
|
|
|
|
|
if (!this.limit_move) return
|
|
|
|
|
|
let left = this._img_left
|
|
|
|
|
|
let top = this._img_top
|
|
|
|
|
|
var scaleV2 = scale || this.scale
|
|
|
|
|
|
let img_width = this.img_width
|
|
|
|
|
|
let img_height = this.img_height
|
|
|
|
|
|
if (this.angle / 90 % 2) {
|
|
|
|
|
|
img_width = this.img_height
|
|
|
|
|
|
img_height = this.img_width
|
|
|
|
|
|
}
|
|
|
|
|
|
left = this.cut_left + img_width * scaleV2 / 2 >= left ? left : this.cut_left + img_width * scaleV2 / 2
|
|
|
|
|
|
left = this.cut_left + this.width - img_width * scaleV2 / 2 <= left ? left : this.cut_left + this.width - img_width * scaleV2 / 2
|
|
|
|
|
|
top = this.cut_top + img_height * scaleV2 / 2 >= top ? top : this.cut_top + img_height * scaleV2 / 2
|
|
|
|
|
|
top = this.cut_top + this.height - img_height * scaleV2 / 2 <= top ? top : this.cut_top + this.height - img_height * scaleV2 / 2
|
|
|
|
|
|
this._img_left = left
|
|
|
|
|
|
this._img_top = top
|
|
|
|
|
|
this.scale = scaleV2
|
|
|
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 图片边缘检测-缩放
|
|
|
|
|
|
*/
|
|
|
|
|
|
_imgMarginDetectionScale() {
|
|
|
|
|
|
if (!this.limit_move) return
|
|
|
|
|
|
let scale = this.scale
|
|
|
|
|
|
let img_width = this.img_width
|
|
|
|
|
|
let img_height = this.img_height
|
|
|
|
|
|
if (this.angle / 90 % 2) {
|
|
|
|
|
|
img_width = this.img_height
|
|
|
|
|
|
img_height = this.img_width
|
|
|
|
|
|
}
|
|
|
|
|
|
if (img_width * scale < this.width) {
|
|
|
|
|
|
scale = this.width / img_width
|
|
|
|
|
|
}
|
|
|
|
|
|
if (img_height * scale < this.height) {
|
|
|
|
|
|
scale = Math.max(scale, this.height / img_height)
|
|
|
|
|
|
}
|
|
|
|
|
|
this._imgMarginDetectionPosition(scale)
|
|
|
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 计算图片尺寸
|
|
|
|
|
|
*/
|
|
|
|
|
|
_imgComputeSize() {
|
|
|
|
|
|
let img_width = this.img_width,
|
|
|
|
|
|
img_height = this.img_height
|
|
|
|
|
|
if (!this.INIT_IMGHEIGHT && !this.INIT_IMGWIDTH) {
|
|
|
|
|
|
// 默认按图片最小边 = 对应裁剪框尺寸
|
|
|
|
|
|
img_width = this.imageObject.width
|
|
|
|
|
|
img_height = this.imageObject.height
|
|
|
|
|
|
if (img_width / img_height > this.width / this.height) {
|
|
|
|
|
|
img_height = this.height
|
|
|
|
|
|
img_width = this.imageObject.width / this.imageObject.height * img_height
|
|
|
|
|
|
} else {
|
|
|
|
|
|
img_width = this.width
|
|
|
|
|
|
img_height = this.imageObject.height / this.imageObject.width * img_width
|
|
|
|
|
|
}
|
|
|
|
|
|
} else if (this.INIT_IMGHEIGHT && !this.INIT_IMGWIDTH) {
|
|
|
|
|
|
img_width = this.imageObject.width / this.imageObject.height * this.INIT_IMGHEIGHT
|
|
|
|
|
|
} else if (!this.INIT_IMGHEIGHT && this.INIT_IMGWIDTH) {
|
|
|
|
|
|
img_height = this.imageObject.height / this.imageObject.width * this.INIT_IMGWIDTH
|
|
|
|
|
|
}
|
|
|
|
|
|
console.log(img_width)
|
|
|
|
|
|
console.log(img_height)
|
|
|
|
|
|
this.img_width = img_width
|
|
|
|
|
|
this.img_height = img_height
|
|
|
|
|
|
},
|
|
|
|
|
|
// 改变截取框大小
|
|
|
|
|
|
_computeCutSize() {
|
|
|
|
|
|
if (this.width > this.info.windowWidth) {
|
|
|
|
|
|
this.width = his.info.windowWidth
|
|
|
|
|
|
} else if (this.width + this.cut_left > this.info.windowWidth) {
|
|
|
|
|
|
this.cut_left = this.info.windowWidth - this.cut_left
|
|
|
|
|
|
}
|
|
|
|
|
|
if (this.height > this.info.windowHeight) {
|
|
|
|
|
|
this.height = this.info.windowHeight
|
|
|
|
|
|
} else if (this.height + this.cut_top > this.info.windowHeight) {
|
|
|
|
|
|
this.cut_top = this.info.windowHeight - this.cut_top
|
|
|
|
|
|
}
|
|
|
|
|
|
!this._canvas_overflow && this._draw()
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
_move_throttle() {
|
|
|
|
|
|
// 安卓需要节流
|
|
|
|
|
|
if (this.info.platform == 'android') {
|
|
|
|
|
|
clearTimeout(this.MOVE_THROTTLE)
|
|
|
|
|
|
this.MOVE_THROTTLE = setTimeout(() => {
|
|
|
|
|
|
this.MOVE_THROTTLE_FLAG = true
|
|
|
|
|
|
}, 1000 / 40)
|
|
|
|
|
|
return this.MOVE_THROTTLE_FLAG
|
|
|
|
|
|
} else {
|
|
|
|
|
|
this.MOVE_THROTTLE_FLAG = true
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// 停止移动时需要做的操作
|
|
|
|
|
|
_moveStop() {
|
|
|
|
|
|
// 清空之前的自动居中延迟函数并添加最新的
|
|
|
|
|
|
clearTimeout(this.TIME_CUT_CENTER)
|
|
|
|
|
|
this.TIME_CUT_CENTER = setTimeout(() => {
|
|
|
|
|
|
// 动画启动
|
|
|
|
|
|
if (!this._cut_animation) {
|
|
|
|
|
|
this._cut_animation = true
|
|
|
|
|
|
}
|
|
|
|
|
|
this.setCutCenter()
|
|
|
|
|
|
}, 1000)
|
|
|
|
|
|
// 清空之前的背景变化延迟函数并添加最新的
|
|
|
|
|
|
clearTimeout(this.TIME_BG)
|
|
|
|
|
|
this.TIME_BG = setTimeout(() => {
|
|
|
|
|
|
if (this._flag_bright) {
|
|
|
|
|
|
this._flag_bright = false
|
|
|
|
|
|
}
|
|
|
|
|
|
}, 2000)
|
|
|
|
|
|
},
|
|
|
|
|
|
// 移动中
|
|
|
|
|
|
_moveDuring() {
|
|
|
|
|
|
// 清空之前的自动居中延迟函数
|
|
|
|
|
|
clearTimeout(this.TIME_CUT_CENTER)
|
|
|
|
|
|
// 清空之前的背景变化延迟函数
|
|
|
|
|
|
clearTimeout(this.TIME_BG)
|
|
|
|
|
|
// 高亮背景
|
|
|
|
|
|
if (!this._flag_bright) {
|
|
|
|
|
|
this._flag_bright = true
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
</script>
|
|
|
|
|
|
<style lang="less">
|
|
|
|
|
|
.main-box{
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
height: 10vh;
|
|
|
|
|
|
position: fixed;
|
|
|
|
|
|
bottom: 0;
|
|
|
|
|
|
left: 0;
|
|
|
|
|
|
z-index: 999999;
|
|
|
|
|
|
padding: 0 10vw;
|
|
|
|
|
|
.main-cancel,.main-save{
|
|
|
|
|
|
background: #d1d1d1;
|
|
|
|
|
|
padding: 8rpx 0;
|
|
|
|
|
|
width: 200rpx;
|
|
|
|
|
|
border-radius: 6rpx;
|
|
|
|
|
|
color: #D92553;
|
|
|
|
|
|
}
|
|
|
|
|
|
.main-save{
|
|
|
|
|
|
color: white;
|
|
|
|
|
|
background: #D92553;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
.image-cropper{
|
|
|
|
|
|
background:rgba(14, 13, 13,.8);
|
|
|
|
|
|
position: fixed;
|
|
|
|
|
|
top:0;
|
|
|
|
|
|
left:0;
|
|
|
|
|
|
width:100vw;
|
|
|
|
|
|
height:100vh;
|
|
|
|
|
|
z-index: 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
.main{
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
width:100vw;
|
|
|
|
|
|
height:100vh;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
}
|
|
|
|
|
|
.content{
|
|
|
|
|
|
z-index: 9;
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
width:100vw;
|
|
|
|
|
|
height:100vh;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction:column;
|
|
|
|
|
|
pointer-events:none;
|
|
|
|
|
|
}
|
|
|
|
|
|
.bg_black{
|
|
|
|
|
|
background: rgba(0, 0, 0, 0.8)!important;
|
|
|
|
|
|
}
|
|
|
|
|
|
.bg_gray{
|
|
|
|
|
|
background: rgba(0, 0, 0, 0.45);
|
|
|
|
|
|
transition-duration: .35s;
|
|
|
|
|
|
}
|
|
|
|
|
|
.content>.content_top{
|
|
|
|
|
|
pointer-events:none;
|
|
|
|
|
|
}
|
|
|
|
|
|
.content>.content_middle{
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
height: 200px;
|
|
|
|
|
|
width:100%;
|
|
|
|
|
|
}
|
|
|
|
|
|
.content_middle_middle{
|
|
|
|
|
|
width:200px;
|
|
|
|
|
|
box-sizing:border-box;
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
transition-duration: .3s;
|
|
|
|
|
|
}
|
|
|
|
|
|
.content_middle_right{
|
|
|
|
|
|
flex: auto;
|
|
|
|
|
|
}
|
|
|
|
|
|
.content>.content_bottom{
|
|
|
|
|
|
flex: auto;
|
|
|
|
|
|
}
|
|
|
|
|
|
.image-cropper .img{
|
|
|
|
|
|
z-index: 2;
|
|
|
|
|
|
top:0;
|
|
|
|
|
|
left:0;
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
border:none;
|
|
|
|
|
|
width:100%;
|
|
|
|
|
|
backface-visibility: hidden;
|
|
|
|
|
|
transform-origin:center;
|
|
|
|
|
|
}
|
|
|
|
|
|
.image-cropper-canvas{
|
|
|
|
|
|
position: fixed;
|
|
|
|
|
|
background: white;
|
|
|
|
|
|
width:150px;
|
|
|
|
|
|
height:150px;
|
|
|
|
|
|
z-index: 10;
|
|
|
|
|
|
top:-200%;
|
|
|
|
|
|
pointer-events:none;
|
|
|
|
|
|
}
|
|
|
|
|
|
.border{
|
|
|
|
|
|
background: white;
|
|
|
|
|
|
pointer-events:auto;
|
|
|
|
|
|
position:absolute;
|
|
|
|
|
|
}
|
|
|
|
|
|
.border-top-left{
|
|
|
|
|
|
left:-2.5px;
|
|
|
|
|
|
top:-2.5px;
|
|
|
|
|
|
height:2.5px;
|
|
|
|
|
|
width:33rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
.border-top-right{
|
|
|
|
|
|
right:-2.5px;
|
|
|
|
|
|
top:-2.5px;
|
|
|
|
|
|
height:2.5px;
|
|
|
|
|
|
width:33rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
.border-right-top{
|
|
|
|
|
|
top:-1px;
|
|
|
|
|
|
width:2.5px;
|
|
|
|
|
|
height:30rpx;
|
|
|
|
|
|
right:-2.5px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.border-right-bottom{
|
|
|
|
|
|
width:2.5px;
|
|
|
|
|
|
height:30rpx;
|
|
|
|
|
|
right:-2.5px;
|
|
|
|
|
|
bottom:-1px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.border-bottom-left{
|
|
|
|
|
|
height:2.5px;
|
|
|
|
|
|
width:33rpx;
|
|
|
|
|
|
bottom:-2.5px;
|
|
|
|
|
|
left:-2.5px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.border-bottom-right{
|
|
|
|
|
|
height:2.5px;
|
|
|
|
|
|
width:33rpx;
|
|
|
|
|
|
bottom:-2.5px;
|
|
|
|
|
|
right:-2.5px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.border-left-top{
|
|
|
|
|
|
top:-1px;
|
|
|
|
|
|
width:2.5px;
|
|
|
|
|
|
height:30rpx;
|
|
|
|
|
|
left:-2.5px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.border-left-bottom{
|
|
|
|
|
|
width:2.5px;
|
|
|
|
|
|
height:30rpx;
|
|
|
|
|
|
left:-2.5px;
|
|
|
|
|
|
bottom:-1px;
|
|
|
|
|
|
}
|
|
|
|
|
|
</style>
|
|
|
|
|
|
<config>
|
|
|
|
|
|
{
|
|
|
|
|
|
usingComponents: {
|
|
|
|
|
|
chooseImageTips: '~@/components/chooseImageTips',
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
</config>
|