<template>
|
<view class="picture-cut" :class="{'picture-cut-show':isShow}">
|
|
<!-- :style="{width:choosePictureWidth+'px',height:choosePictureHeight+'px',top:choosePictureTop+'px',left:choosePictureLeft+'px'}" -->
|
<view class="select-box" :style="{width: '70%', height: '250px', top:choosePictureTop+'px',left: '15%'}">
|
<view class="horn">
|
<!-- <view class="lt" data-drag="leftTop" @touchstart.stop="dragStart" @touchmove.stop.prevent="dragMove" ></view>
|
<view class="rt" data-drag="topTight" @touchstart.stop="dragStart" @touchmove.stop.prevent="dragMove" ></view>
|
<view class="rb" data-drag="rightBottom" @touchstart.stop="dragStart" @touchmove.stop.prevent="dragMove"></view>
|
<view class="lb" data-drag="bottomLeft" @touchstart.stop="dragStart" @touchmove.stop.prevent="dragMove"></view> -->
|
</view>
|
</view>
|
|
|
<movable-area class="picture-area" :style="{width:areaWidth+'px',height:areaHeight+'px',top:areaHeightTop+'px',left:areaWidthLeft+'px'}">
|
<movable-view class="picture-view" :style="{width:img_width/img_scaling+'px',height:img_height/img_scaling+'px'}"
|
direction="all" :x="offsetX" :y="offsetY" scale="true" :scale-min="scaleMin" @change="movableChange" @scale="movableScale">
|
<image :style="{width:img_width/img_scaling+'px',height:img_height/img_scaling+'px'}" :src="pictureSrc"></image>
|
</movable-view>
|
</movable-area>
|
<view class="area-bottom">
|
<view class="area-bottom-box">
|
<view @click="cancelArea">取消</view>
|
<!-- <view @click="changeImg">换个图片</view> -->
|
<view @click="createImg">完成</view>
|
</view>
|
|
</view>
|
<canvas canvas-id="picture-canvas" :style="'position:absolute;border: 1px solid red; width:'+canvasWidth+'px;height:'+canvasHeight+'px;top:-9999px;left:-9999px;'" class="canvas-view"></canvas>
|
</view>
|
</template>
|
|
<script>
|
|
let tailorSize = 240; // 需要截取的尺寸240x240px,此变量要和样式中的240px和120px相对应,120px为此变量的一半,若要修改成其他值一定要一一对应
|
let tailorWidth = 0;
|
let tailorHeight = 0;
|
let newOffsetX = 0; // 拖动缩放完成后的X轴偏移量
|
let newOffsetY = 0; // 拖动缩放完成后的Y轴偏移量
|
let T_PAGE_X, // 手移动的时候x的位置
|
T_PAGE_Y, // 手移动的时候Y的位置
|
area_x,
|
area_y
|
let [choosePictureMinWidth,choosePictureMinHeight] = [50,50];
|
export default {
|
name: "tly-picture-cut",
|
props: {
|
// 图片路径
|
pictureSrc: {
|
type: String,
|
required: true
|
}
|
},
|
data() {
|
return {
|
offsetX: 0, // 图像初始化的X轴偏移量
|
offsetY: 0, // 图像初始化的Y轴偏移量
|
img_width: 0, // 图片真实宽度
|
img_height: 0, // 图片真实高度
|
img_scaling: 1, //图片初始化缩放比例
|
scale: 1, // 拖动缩放完成后的图片缩放比例
|
scaleMin: 0.5, // 最小缩放值
|
isShow: false,
|
choosePictureWidth:0,
|
choosePictureHeight:0,
|
choosePictureTop:0,
|
choosePictureLeft:0,
|
chooseVisible:0.5,
|
areaWidth:0,
|
areaHeight:0,
|
movableViewTop:0,
|
movableViewLeft:0,
|
areaWidthLeft:0,
|
areaHeightTop:0,
|
canvasWidth:0,
|
canvasHeight:0,
|
|
};
|
},
|
watch: {
|
pictureSrc() {
|
this.getImgInfo();
|
}
|
},
|
methods: {
|
changeImg(){
|
this.$emit('changeImg')
|
},
|
cancelArea(){
|
this.hidePop();
|
},
|
// 设置大小的时候触发的touchStart事件
|
dragStart(e) {
|
T_PAGE_X = e.touches[0].pageX
|
T_PAGE_Y = e.touches[0].pageY
|
},
|
|
// 设置大小的时候触发的touchMove事件
|
dragMove(e) {
|
var _this = this
|
var dragType = e.target.dataset.drag
|
var dragLengthX = (T_PAGE_X - e.touches[0].pageX);
|
var dragLengthY = (T_PAGE_Y - e.touches[0].pageY);
|
switch (dragType) {
|
case 'leftTop':
|
this.choosePictureWidth += dragLengthX;
|
this.choosePictureLeft -= dragLengthX;
|
this.choosePictureTop -= dragLengthY;
|
this.choosePictureHeight += dragLengthY;
|
this.canvasY -= dragLengthY
|
this.canvasX -= dragLengthX
|
break;
|
case 'topTight':
|
this.choosePictureWidth -= dragLengthX;
|
this.choosePictureHeight += dragLengthY;
|
this.choosePictureTop -= dragLengthY;
|
this.canvasY -= dragLengthY
|
break;
|
case 'bottomLeft':
|
this.choosePictureWidth += dragLengthX;
|
this.choosePictureLeft -= dragLengthX;
|
this.choosePictureHeight -= dragLengthY;
|
this.canvasX -= dragLengthX
|
|
break;
|
case 'rightBottom':
|
this.choosePictureWidth -= dragLengthX;
|
this.choosePictureHeight -= dragLengthY;
|
break;
|
default:
|
break;
|
}
|
T_PAGE_Y -= dragLengthY;
|
T_PAGE_X -= dragLengthX;
|
},
|
// 显示组件
|
showPop() {
|
this.isShow = true;
|
},
|
// 隐藏组件
|
hidePop() {
|
this.isShow = false;
|
},
|
// 初始化图片
|
getImgInfo() {
|
uni.getImageInfo({
|
src: this.pictureSrc,
|
success: (res) => {
|
|
// 屏幕可用宽高
|
let sysInfo = uni.getSystemInfoSync();
|
let windowWidth = sysInfo.windowWidth;
|
let windowHeight = sysInfo.windowHeight;
|
// 图片宽高
|
// 等比缩放
|
this.img_width = windowWidth*0.8;
|
this.img_height = res.height*(this.img_width/res.width);
|
this.canvasWidth = this.img_width;
|
this.canvasHeight = this.img_height;
|
//截图宽
|
this.choosePictureWidth = this.img_width*this.chooseVisible;
|
//截图高
|
this.choosePictureHeight = this.img_height*this.chooseVisible;
|
|
this.canvasX = (this.img_width - this.choosePictureWidth) /2;
|
this.canvasY = (this.img_height - this.choosePictureHeight) /2;
|
area_x = this.canvasX ;
|
area_y = this.canvasY ;
|
this.choosePictureTop = windowHeight/2-this.choosePictureHeight/2;
|
this.choosePictureLeft = windowWidth/2-this.choosePictureWidth/2;
|
// 计算初始缩放比和最小缩放值
|
if (this.img_width < this.choosePictureWidth || this.img_height < this.choosePictureHeight) { // 当图片宽或高小于240px时
|
let count = this.img_width <= this.img_height ? this.img_width : this.img_height;
|
let check = this.choosePictureWidth <= this.choosePictureHeight ? this.choosePictureWidth : this.choosePictureHeight;
|
this.img_scaling = count / check;
|
this.scaleMin = 1;
|
} else if (this.img_width > windowWidth && this.img_width <= this.img_height) { // 当图片宽度大于屏幕宽度并且图片宽度小于图片高度时
|
this.img_scaling = this.img_width / windowWidth;
|
this.scaleMin = tailorSize / windowWidth;
|
} else {
|
this.img_scaling = 1;
|
//this.img_scaling = count / check;
|
let count = this.img_width <= this.img_height ? this.img_width : this.img_height;
|
let check = this.choosePictureWidth <= this.choosePictureHeight ? this.choosePictureWidth : this.choosePictureHeight;
|
this.scaleMin = check / count;
|
}
|
//外块宽高
|
this.areaWidth = this.choosePictureWidth*3;
|
this.areaHeight = this.choosePictureHeight*3;
|
//外块偏移量
|
this.areaHeightTop = -((this.areaHeight - windowHeight)/2);
|
this.areaWidthLeft = -((this.areaWidth - windowWidth)/2);
|
|
this.offsetX = this.areaWidth/2-(this.img_width/this.img_scaling)/2;
|
this.offsetY = this.areaHeight/2-(this.img_height/this.img_scaling)/2;
|
|
// 获取新的偏移量
|
newOffsetX = this.offsetX;
|
newOffsetY = this.offsetY;
|
}
|
})
|
},
|
// 计算拖动偏移量
|
movableChange(e) {
|
|
this.canvasX = this.canvasX-(e.detail.x-area_x);
|
area_x = e.detail.x;
|
this.canvasY = this.canvasY-(e.detail.y-area_y)
|
if(this.canvasY<0){
|
this.canvasY = 0;
|
}
|
area_y = e.detail.y;
|
|
},
|
// 计算缩放比例和偏移量
|
movableScale(e) {
|
newOffsetX = e.detail.x
|
newOffsetY = e.detail.y
|
this.canvasWidth = this.canvasWidth*e.detail.scale;
|
this.canvasHeight = this.canvasHeight*e.detail.scale;
|
this.scale = e.detail.scale;
|
},
|
// 截取图片
|
createImg() {
|
var that = this;
|
let ctx = uni.createCanvasContext("picture-canvas",this);
|
ctx.drawImage(this.pictureSrc, 0, 0, this.img_width*this.scale,this.img_height*this.scale );
|
// ctx.draw();
|
ctx.draw(false, () => {
|
|
uni.canvasToTempFilePath({
|
x: this.canvasX,
|
y: this.canvasY,
|
width: this.choosePictureWidth,
|
height: this.choosePictureHeight,
|
destWidth: this.choosePictureWidth,
|
destHeight: this.choosePictureHeight,
|
quality: 0.9,
|
canvasId: 'picture-canvas',
|
success: function (res) {
|
|
//#ifdef H5
|
that.hidePop();
|
that.$emit("createImg",res.tempFilePath)
|
//#endif
|
//#ifdef MP-WEIXIN || APP
|
uni.getFileSystemManager().readFile({
|
filePath: res.tempFilePath,
|
encoding: 'base64',
|
success: res => {
|
let base64 = 'data:image/png;base64,' + res.data;
|
|
that.hidePop();
|
that.$emit("createImg",base64)
|
}
|
})
|
//#endif
|
|
|
}
|
},this);
|
|
|
|
});
|
}
|
}
|
}
|
</script>
|
|
<style>
|
.picture-cut {
|
position: fixed;
|
top: 0;
|
left: 0;
|
bottom: 0;
|
right: 0;
|
width: 100%;
|
height: 100%;
|
|
z-index: 999999;
|
|
transform: translateX(100%);
|
transition: all 200ms ease;
|
visibility: hidden;
|
}
|
|
.picture-cut-show {
|
transform: translateY(0) !important;
|
visibility: visible;
|
|
|
}
|
|
/* 拖动域的位置和大小 */
|
.picture-cut .picture-area {
|
|
position: absolute;
|
/* 使其居中定位 */
|
|
|
|
}
|
|
/* 拖动控件的大小 */
|
.picture-area {
|
|
pointer-events: none;
|
z-index: 998;
|
|
}
|
|
.picture-view {
|
|
pointer-events: auto;
|
|
}
|
|
/* 中间选择框的大小,本意是视觉上模拟拖动域 */
|
.select-box {
|
|
position: absolute;
|
/* top: calc(50% - 120px);
|
left: calc(50% - 120px); */
|
/* width: 240px;
|
height: 240px; */
|
box-sizing: border-box;
|
/* border-radius: 50%; */
|
|
|
box-shadow: 0px 0px 0px 2005px rgba(0, 0, 0, 0.7) ;
|
z-index: 999;
|
pointer-events: none;
|
/* min-width: 50px;
|
min-height: 50px; */
|
}
|
.horn{
|
position: absolute;
|
width: 100%;
|
height: 100%;
|
/* border:1rpx solid #ff0000; */
|
|
}
|
.horn>view{
|
width: 15px;
|
height: 15px;
|
position:absolute;
|
}
|
.horn .lt{
|
pointer-events: auto;
|
/* border-top: 3px solid #ff0000;
|
border-left: 3px solid #ff0000; */
|
left: -4px;
|
top: -4px;
|
}
|
.horn .rt{
|
pointer-events: auto;
|
/* border-top: 3px solid #ff0000;
|
border-right: 3px solid #ff0000; */
|
right: -2px;
|
top: -2px;
|
}
|
.horn .rb{
|
pointer-events: auto;
|
/* border-bottom:3px solid #ff0000;
|
border-right: 3px solid #ff0000; */
|
right: -2px;
|
bottom: -2px;
|
}
|
.horn .lb{
|
pointer-events: auto;
|
/* border-bottom:3px solid #ff0000;
|
border-left: 3px solid #ff0000; */
|
left: -2px;
|
bottom: -2px;
|
}
|
.area-bottom{
|
position: absolute;
|
width:100%;
|
height:75px;
|
|
bottom: 0;
|
z-index:999;
|
box-shadow: 0 -8px 12px -5px #ffffff;
|
background-color: rgba(66, 66, 66, 0.4);
|
}
|
.area-bottom-box{
|
|
display: flex;
|
justify-content: space-between;
|
width:86%;
|
height:50px;
|
line-height: 60px;
|
color:#FFFFFF;
|
margin:0 auto;
|
}
|
.button-view {
|
position: absolute;
|
bottom: 20px;
|
right: 20px;
|
width: 60px;
|
background-color: #007AFF;
|
font-size: 14px;
|
color: #FFFFFF;
|
z-index:101;
|
}
|
|
/* 画布大小,画布大小就是截取的原始大小 */
|
.canvas-view {
|
position: absolute;
|
/* visibility: hidden; */
|
}
|
</style>
|