<template>
    <view class="container">
        <view 
            class="image-box" 
            :style="{
                backgroundImage: 'url('+ src +')',
                width: imageBoxWidth + 'px',
                height: imageBoxHeight + 'px',
                borderRadius: cropShape == 'rect' ? '' : '' 
            }">
            <view class="mask"></view>
            <view 
                class="cropping-box"
                @touchstart.stop="touchstart"
                @touchmove.stop="touchmove"
                :style="{
                    top: cropBoxY + 'px',
                    left: cropBoxX + 'px',
                    width: cropBoxWidth  + 'px',
                    height: cropBoxHeight + 'px',
                    backgroundImage: 'url('+ src +')',
                    backgroundSize: imageBoxWidth + 'px' + ' ' + imageBoxHeight + 'px',
                    backgroundPositionX: (-cropBoxX - 2) + 'px',
                    backgroundPositionY: (-cropBoxY - 2) + 'px',
                    borderRadius: cropShape == 'rect' ? '' : '50%' 
                }"
                >
                
                <!-- <view v-if="cropShape == 'rect' && !isFixedSize" class="zoom-handle-rect" data-body="handle"></view> -->
                <!-- <view v-if="cropShape == 'circular'" class="zoom-chandle-circular" data-body="handle"></view> -->
            </view>
        </view>

        <!-- <canvas class="canvas" canvas-id="canvas" id="canvas" :style="{width: canvasWidth + 'px', height: canvasHeight + 'px'}"></canvas> -->

        <view class="operation-area">
            <!-- <view class="ratio-area" v-if="cropShape == 'rect'">
                <view class="ratio-btn" @click="setRatio('full')">full</view>
                <view class="ratio-btn" @click="setRatio(item)" v-for="item in ratioGroup">{{item}}</view>
            </view> -->
            <view class="crop-area">
                <!-- <u--image :src="cropImgPath" mode="widthFix" shape="circle" width="100px"
            height="100px"></u--image> -->
            </view>
            <view class="action">
                <!-- <view shape="circle" hover-class="none" class="btn" @click="cancel">取消</view> -->
                <view shape="circle" hover-class="none" class="btn full" @click="cropping">继续</view>
            </view>
            <!-- <view class="bottom">
                <u-button size="mini" @click="cancel">取消</u-button>
                <u-button size="mini" type="primary" @click="cropping">裁剪</u-button>
            </view> -->
        </view>
    </view>
</template>
<script>

let startX, startY;
let boxX, boxY, boxWidth, boxHeight;
let imageOriginalWidth, imageOriginalHeight;
let imageZoomRatio;
let windowInfo;

export default {
    name:'imageCropping',
    props: {
        src: {
            type: String,
        },
        ratioGroup: {
            type: Array,
            default(){
                return []
            }
        },
        isFixedSize: {
            type: Boolean,
            default:false
        },
        cropShape: {
            type: String,
            default: 'circular'  // 'rect' , 'circular' 
        }
	},
    data() {
        return {
            imageBoxWidth: 0,
            imageBoxHeight: 0,
            cropBoxX: 0,
            cropBoxY: 0,
            cropBoxWidth: 0, 
            cropBoxHeight: 0,
            // move: 移动 , zoom: 缩放
            mode: '',
            cropSize: 100,
            cropImgPath: ''
        }
    },
    mounted(){
        this.getImageInfo();
    },
    
    methods:{
        // 获取图片尺寸
        getImageInfo() {
            windowInfo = uni.getWindowInfo();
            if (this.src) {
                uni.getImageInfo({
                    src: this.src,
                    success: (res) => {
                        console.log("图片尺寸信息", res);
                        imageOriginalWidth = res.width;
                        imageOriginalHeight = res.height;

                        let widthZoomRatio = imageOriginalWidth / windowInfo.windowWidth;
                        let heightZoomRatio = imageOriginalHeight / windowInfo.windowHeight;
                        imageZoomRatio = widthZoomRatio > heightZoomRatio ? widthZoomRatio : heightZoomRatio;

                        this.imageBoxWidth = (imageOriginalWidth / imageZoomRatio);
                        this.imageBoxHeight = (imageOriginalHeight / imageZoomRatio);
                        this.setRatio('1:1');
                    },
                    fail: (error) => {
                        console.log("error", error);
                    }
                })
            }
            
        },
        touchstart(event){
            startX = event.touches[0].clientX;
            startY = event.touches[0].clientY;
            
            if(event.target.dataset.body == "handle"){
                this.mode = 'zoom';
                boxWidth = this.cropBoxWidth;
                boxHeight = this.cropBoxHeight;
            }else {
                this.mode = 'move';
                boxX = this.cropBoxX;
                boxY = this.cropBoxY;
            }
        },
        touchmove(event){
            let distanceX = event.touches[0].clientX - startX;
            let distanceY = event.touches[0].clientY - startY;

            let x = boxX + distanceX;
            let y = boxY + distanceY;
            let width = boxWidth + distanceX;
            let height = boxHeight + distanceY;

            let maxX = this.imageBoxWidth-this.cropBoxWidth;
            let maxY = this.imageBoxHeight-this.cropBoxHeight;
            let maxWidth = this.imageBoxWidth-this.cropBoxX;
            let maxHeight = this.imageBoxHeight-this.cropBoxY;

            switch (this.mode) {
                case 'move':
                    this.cropBoxX = x < 0 ? 0 : (x > maxX ? maxX : x);
                    this.cropBoxY = y < 0 ? 0 : (y > maxY ? maxY : y);
                    break;
                case 'zoom':
                    if(this.cropShape == 'rect'){
                        this.cropBoxWidth = width > maxWidth ? maxWidth : width;
                        this.cropBoxHeight = height > maxHeight ? maxHeight : height;
                    }else{
                        this.cropBoxHeight = height > maxHeight ? maxHeight : height;
                        this.cropBoxWidth = height > maxHeight ? maxHeight : height;
                    }
                    break;
            }
        },
        setRatio(ratio){
            if(ratio == 'full'){
                this.cropBoxWidth = this.imageBoxWidth;
                this.cropBoxHeight = this.imageBoxHeight;
                this.cropBoxX = 0;
                this.cropBoxY = 0;
            }else{
                let x = ratio.split(':')[0];
                let y = ratio.split(':')[1];
                let r1 = (x/y);
                let r2 = (y/x);
                
                if(this.imageBoxWidth < this.imageBoxHeight){
                    console.log("盒子宽度小于盒子高度");
                    let size = this.imageBoxWidth;
                    if(size / r1 > this.imageBoxHeight){
                        size = this.imageBoxHeight;
                        this.cropBoxWidth = (size / r2) - this.cropSize;
                        this.cropBoxHeight = size - this.cropSize;
                        this.cropBoxX = this.cropSize / 2;
                        this.cropBoxY = (this.imageBoxWidth - this.imageBoxWidth) / 2;
                    }else{
                        this.cropBoxWidth = size - this.cropSize;
                        this.cropBoxHeight = (size / r1) - this.cropSize;
                        this.cropBoxX = this.cropSize / 2;
                        this.cropBoxY = (this.imageBoxHeight - this.cropBoxHeight) / 2;
                    }
                }else{
                    let size = this.imageBoxHeight;
                    if(size / r1 > this.imageBoxWidth){
                        size = this.imageBoxWidth;
                        this.cropBoxWidth = size - this.cropSize;
                        this.cropBoxHeight = (size / r2) - this.cropSize;
                        this.cropBoxX = ((this.imageBoxWidth - this.cropBoxWidth) / 2);
                        this.cropBoxY = ((this.imageBoxHeight - this.cropBoxHeight) / 2);
                    }else{
                        this.cropBoxWidth =( size / r1) - this.cropSize;
                        this.cropBoxHeight = size - this.cropSize;
                        this.cropBoxX = ((this.imageBoxWidth - this.cropBoxWidth) / 2);
                        this.cropBoxY = ((this.imageBoxWidth - this.cropBoxWidth) / 2);
                    }
                }
            }
            
        },
        async cropping(){
            let x = this.cropBoxX * imageZoomRatio;
            let y = this.cropBoxY * imageZoomRatio;
            let w = this.cropBoxWidth * imageZoomRatio;
            let h = this.cropBoxHeight * imageZoomRatio;

            // 方式2： 
            const canvas = uni.createOffscreenCanvas({type: '2d',width: w, height: h});
            const context = canvas.getContext('2d');
            context.fillStyle = '#fff'; // 设置绘制后的填充颜色
            context.globalCompositeOperation = 'source-over';
            const image = canvas.createImage();
            await new Promise((resolve,reject) => {
                image.onload = resolve
                image.onerror = reject
                image.src = this.src; 
                image.backgroundColor = 'red'
                // image.src = "https://pic4.ntimg.cn/file/20191225/30544261_221404258307_1.jpg"; 
            })
            context.clearRect(0, 0, w, h);
            if(this.cropShape == 'circular'){
                context.beginPath();
                context.arc(w/2,h/2,w/2,0,Math.PI * 2);
                context.fill();
                context.clip();
                context.clip();
            }
            context.drawImage(image,x,y,w,h,0, 0, w, h);
            
            const DataURL = canvas.toDataURL();
            
            const fs = wx.getFileSystemManager();
            let tempFilePath = `${wx.env.USER_DATA_PATH}/` + new Date().getTime() + '.png'
            fs.writeFile({
                filePath: tempFilePath,
                data: DataURL.replace('data:image/png;base64,',''),
                encoding: 'base64',
                success: res => {
                    this.$emit('completed',{
                        tempFilePath
                    });
                    this.cropImgPath = tempFilePath;
                },
                fail(res) {
                    console.error(res)
                }
            })

            // 方式一：
            // const context = uni.createCanvasContext('canvas', this)
            // context.drawImage(this.src,x,y,w,h,0, 0, w, h)
            // context.draw(false, ()=>{
            //     console.log(123);
            //     uni.canvasToTempFilePath({
            //         canvas: context,
            //         success: function(res) {
            //             console.log(res)
            //         },
            //         complete: function(res){
            //             console.log(res)
            //         }
            //     },this)
            // })
            
        },
        yuantu(){
            this.$emit('completed',{
                tempFilePath: this.src
            })
        },
        cancel(){
            this.$emit('cancel')
        }
    }
}

</script>
<style lang="scss" scoped>
.container{
    width: 100vw;
    height: 100vh;
    overflow: hidden;
    position: fixed;
    left: 0;
    top: 0;
    z-index: 99;
    display: flex;
    align-items: flex-start;
    justify-content: flex-start;
    background-color: #fff;

    .image-box{
        position: relative;
        background-size: contain;
        background-repeat: no-repeat;
        // filter: invert(1);
        z-index: 999;

        .mask{
            width: 100%;
            height: 100%;
            position: absolute;
            left: 0;
            top: 0;
            background-color: rgba(0, 0, 0, 0.4);
            z-index: 99;
            /* border-radius: 50%; */
            // backdrop-filter: blur(10px);
        }
        .cropping-box{
            position: absolute;
            border: 2px solid springgreen;
            box-sizing: border-box;
            z-index: 9999;

            // .zoom-handle-rect,
            // .zoom-chandle-circular{
            //     width: 10px;
            //     height: 10px;
            //     background-color: springgreen;
            //     border-radius: 50%;
            //     position: absolute;
            //     right: -6px;
            //     bottom: -6px;
            // }
            .zoom-chandle-circular{
                right: 50%;
                transform: translateX(5px);
            }
            
        }
    }
}
.operation-area{
    position: fixed;
    bottom: 0;
    z-index: 1;
    width: 100%;
    padding: 10rpx 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;

    .ratio-area{
        display: flex;
        align-items: center;
        justify-content: center;
        margin-bottom: 16rpx;
        .ratio-btn{
            display: inline-block;
            padding: 8rpx 20rpx;
            border: 2rpx solid white;
            color: white;
            margin: 0 10rpx;
            font-size: 12px;
        }
    }
    .bottom{
        height: 120rpx;
        width: 100%;
        display: flex;
        align-items: center;
        justify-content: center;
        button{
            display: inline-block;
            margin: 0 20rpx;
        }
    }
    .action {
			height: 120rpx;
			width: 100vw;
			position: fixed;
			bottom: 60rpx;
			left: 0;
			display: flex;
			justify-content: center;
			align-items: center;
			background: none;
			z-index: 9999;

			.btn {
				height: 89rpx;
				line-height: 89rpx;
				width: 266rpx;
				border: 4rpx solid #7F66E8;
				text-align: center;
				border-radius: 60rpx;
				font-family: OPPOSans;
				font-weight: bold;
				font-size: 36rpx;
				color: #7F66E8;

				&.full {
					background-color: #7F66E8;
					color: #FFFFFF;
					margin-left: 30rpx;
					font-weight: bold;
				}
			}


		}
    
}
.canvas{
    position: absolute;
    bottom: 0;
    left: 0;
    z-index: 1;
    border: 1px solid;
    // display: none;
}
</style>