vue裁剪 基于vue的图片裁剪+预览组件

本文介绍了基于Vue的图片裁剪组件的实现过程,包括组件的功能:默认展示底图、弹出裁剪功能、确认裁剪及取消操作。文章提到了在项目中寻找合适图片裁剪组件的挑战,并分享了经过改进的源码,提供了SelectBox.vue、CustomCropper.vue和Test.vue三个关键文件的说明。
摘要由CSDN通过智能技术生成

效果如下

默认展示一张底图

单击《重新选择》弹出图片裁剪功能

 

单击《确认》展示裁剪好的图片

单击《取消》取消裁剪操作

缘由

项目中多次需要用到图片裁剪功能,在试过几个控件都不理想之下,终于找到一个比较简单好用的组件,自己加以改进,要感谢此大神原文地址

改进后的源码

SelectBox.vue

<template>
    <div class="crop-wrap" @mousedown="wrapMouseDown">
        <div class="shadow-box" :style="recStyle">
            <img :src="img" class="shadow-img" :style="imgStyle">
        </div>
        <div class="crop-box" @mousedown="boxMouseDown" :class="showBox ? 'show': ''" :style="recStyle">
            <span class="drag-point point-lt" @mousedown="pointMouseDown('drag-lt', $event)"></span>
            <span class="drag-point point-lb" @mousedown="pointMouseDown('drag-lb', $event)"></span>
            <span class="drag-point point-rt" @mousedown="pointMouseDown('drag-rt', $event)"></span>
            <span class="drag-point point-rb" @mousedown="pointMouseDown('drag-rb', $event)"></span>
        </div>
    </div>
</template>

<script>
export default {
    props: {
        ratio: {},
        img: {},
        srcSize: {}
    },
    data() {
        return {
            rec: {
                w: 0, h: 0, l: 0, t: 0
            },
            pl: 0,
            pt: 0,
            action: '',
            actionPoint: {x: 0, y: 0},
            referPoint: {x: 0, y: 0},
            $rec: null
        };
    },
    computed: {
        showBox() {
            return this.rec.w && this.rec.h;
        },
        imgStyle() {
            return `width:${this.srcSize.w}px;height:${this.srcSize.h}px;top:${-this.rec.t}px;left:${-this.rec.l}px;`;
        },
        recStyle() {
            return `width:${this.rec.w}px;height:${this.rec.h}px;left:${this.rec.l}px;top:${this.rec.t}px;`;
        }
    },
    mounted() {
        window.addEventListener('mouseup', this.disableDrag);
        window.addEventListener('mousemove', this.updateRec);
    },
    beforeDestroy() {
        window.removeEventListener('mouseup', this.disableDrag);
        window.removeEventListener('mousemove', this.updateRec);
    },
    methods: {
        getLeft(el) {
            let left = el.offsetLeft;
            let parent = el.offsetParent;

            while (parent) {
                left += parent.offsetLeft;
                parent = parent.offsetParent;
            }
            return left;
        },
        getTop(el) {
            let top = el.offsetTop;
            let parent = el.offsetParent;

            while (parent) {
                top += parent.offsetTop;
                parent = parent.offsetParent;
            }
            return top;
        },
        initAction(name, x, y) {
            this.action = name;
            this.pl = this.getLeft(this.$el);
            this.pt = this.getTop(this.$el);
            this.actionPoint = {x, y};
            this.referPoint = {x: this.rec.l, y: this.rec.t};

            if (name === 'drag-lt') {
                this.referPoint = {x: this.rec.l + this.rec.w, y: this.rec.t + this.rec.h};
            } else if (name === 'drag-lb') {
                this.referPoint = {x: this.rec.l + this.rec.w, y: this.rec.t};
            } else if (name === 'drag-rt') {
                this.referPoint = {x: this.rec.l, y: this.rec.t + this.rec.h};
            } else if (name === 'drag-rb') {
                this.referPoint = {x: this.rec.l, y: this.rec.t};
            }
        },
        pointMouseDown(name, e) {
            this.initAction(name, e.pageX, e.pageY);
            e.stopPropagation();
        },
        boxMouseDown(e) {
            this.initAction('move', e.pageX, e.pageY);
            e.stopPropagation();
        },
        wrapMouseDown(e) {
            if (this.rec.w && this.rec.h) {
                return;
            }
            this.initAction('cross', e.pageX, e.pageY);
            this.rec = {
                w: 0,
                h: 0,
                l: e.pageX - this.pl,
                t: e.pageY - this.pt
            };
            e.stopPropagation();
        },
        disableDrag() {
            if (this.action) {
                this.action = '';
                this.$emit('selectEnd');
            }
        },
        clearRec() {
            this.action = '';
            this.rec = {w: 0, h: 0, l: 0, t: 0};
        },
        updateRec(e) {
            if (!this.action) {
                return;
            }

            const elWidth = this.$el.offsetWidth;
            const elHeight = this.$el.offsetHeight;
            const dx = e.pageX - this.actionPoint.x;
            const dy = e.pageY - this.actionPoint.y;
            const x = e.pageX;
            const y = e.pageY;
            let w = 0;
            let h = 0;
            let t = 0;
            let l = 0;

            if (dx === 0 && dy === 0) {
                return;
            }

            if (this.action === 'move') {
                t = dy + this.referPoint.y;
                l = dx + this.referPoint.x;

                if (t <= 0) {
                    t = 0;
                } else if (t + this.rec.h >= elHeight) {
                    t = elHeight - this.rec.h;
                }

                if (l <= 0) {
                    l = 0;
                } else if (l + this.rec.w >= elWidth) {
                    l = elWidth - this.rec.w;
                }

                this.rec.l = l;
                this.rec.t = t;
            } else if (this.action === 'cross') {
                if (dx > 0 && dy > 0) {
                    w = dx + this.rec.l >= elWidth ? elWidth - this.rec.l : dx;
                    h = w / this.ratio;

                    if (h + this.rec.t > elHeight) {
                        h = elHeight - this.rec.t;
                        w = h * this.ratio;
                    }
                    this.rec.w = w;
                    this.rec.h = h;
                } else if (dx > 0 && dy < 0) {
                    w = dx + this.referPoint.x >= elWidth ? elWidth - this.referPoint.x : dx;
                    h = w / this.ratio;

                    if (h >= this.referPoint.y) {
                        h = this.referPoint.y;
                        w = h * this.ratio;
                    }

                    this.rec.t = this.referPoint.y - h;
                    this.rec.w = w;
                    this.rec.h = h;
                } else if (dx < 0 && dy < 0) {
                    w = dx + this.referPoint.x <= 0 ? this.referPoint.x : -dx;
                    h = w / this.ratio;

                    if (h >= this.referPoint.y) {
                        h = this.referPoint.y;
                        w = h * this.ratio;
                    }

                    this.rec.t = this.referPoint.y - h;
                    this.rec.l = this.referPoint.x - w;
                    this.rec.w = w;
                    this.rec.h = h;
                } else if (dx < 0 && dy > 0) {
                    w = dx + this.referPoint.x <= 0 ? this.referPoint.x : -dx;
                    h = w / this.ratio;

                    if (h + this.referPoint.y >= elHeight) {
                        h = elHeight - this.referPoint.y;
                        w = h * this.ratio
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值