Bootstrap

基于vue实现图片的放大,缩小,旋转,拖拽功能

项目中有一个功能需要一个弹窗查看图片,具有放大,缩小,旋转,拖拽功能。
1、html部分

<template>
    <!-- 查看图片放大组件 -->
    <div id="look-image" v-if="visible">
        <!-- 图片展示区 -->
        <div class="look-image-content">
            <div class="show-image">
                <img src="../assets/image/2.jpg" alt="" ref="img" :style="styleObj" @mousedown="start" @mouseup="stop" @mousemove="move">
            </div>
        </div>
        <!-- 底部按钮操作去 -->
        <div class="look-image-footer">
            <div class="enlargement" @click="magnify">
                <i class=""></i>
                <span>放大</span>
            </div>
            <div class="shrink" @click="shrink">
                <i class=""></i>
                <span>缩小</span>
            </div>
            <div class="rotate" @click="rotate">
                <i class=""></i>
                <span>旋转</span>
            </div>
            <div class="close" @click="close">
                <i class=""></i>
                <span>关闭</span>
            </div>
        </div>
    </div>
</template>

2、script部分

<script>
export default {
    name: "look-image",
    data() {
        return {
            multiples: 1,       // 放大或者缩小
            deg: 0,             // 旋转的角度
            styleObj: null,       // 拖拽时修改图片的样式
            isDrag: false,      // 是否开始拖拽
            startX: 0,          // 鼠标的点击X轴
            startY: 0,          // 鼠标的点击Y轴
            moveX: 0,           // 鼠标移动的X轴
            moveY: 0,            // 鼠标移动的Y轴
            endX: 0,
            endY: 0,
        }
    },
    props: {
        url: {                      // 图片链接
            type: String,
            default: ""
        },
        visible: {                  // 控制组件的显示与隐藏
            type: Boolean,
            default: false
        }
    },
    methods: {
        // 放大
        magnify() {
            if(this.multiples >= 10){
                return
            }
            this.multiples += 0.25;
            this.styleObj = `transform: scale(${this.multiples}) rotateZ(${this.deg}deg);left:${this.endX}px;top:${this.endY}px`;
        },
        // 缩小
        shrink() {
            if(this.multiples <= 0){
                return
            }
            this.multiples -= 0.25;
            this.styleObj = `transform: scale(${this.multiples}) rotateZ(${this.deg}deg);left:${this.endX}px;top:${this.endY}px`;
        },
        // 旋转
        rotate(){
            this.deg += 90;
            if(this.deg >= 360){
                this.deg = 0
            }
            this.styleObj = `transform: scale(${this.multiples}) rotateZ(${this.deg}deg);left:${this.endX}px;top:${this.endY}px`;
        },
        start(e) {
            // 当点击图片时,开始拖拽
            if (e.buttons) {
                this.isDrag = true;
                this.startX = e.clientX;
                this.startY = e.clientY;
                this.styleObj = `transform: scale(${this.multiples}) rotateZ(${this.deg}deg);left:${this.endX}px;top:${this.endY}px`;
            }
        },
        stop() {
            this.isDrag = false;
            this.styleObj = `transform: scale(${this.multiples}) rotateZ(${this.deg}deg);left:${this.endX}px;top:${this.endY}px`;
        },
        move(e) {
            // 当鼠标拖拽图片的时候,才计算移动距离
            // 移动图片相对于父元素的位置
            if(this.isDrag) {
           	    // 鼠标移动的距离
                this.moveX = e.clientX;
                this.moveY = e.clientY;
                // 相对页面的距离
                let x=this.moveX-this.startX;
                let y=this.moveY-this.startY;
                let img=document.querySelector("#look-image img");
                this.endX = img.offsetLeft+x;
                this.endY = img.offsetLeft+y; 
                this.styleObj=`left:${this.endX}px;top:${this.endY}px`;
                this.styleObj = `transform: scale(${this.multiples}) rotateZ(${this.deg}deg);left:${this.endX}px;top:${this.endY}px`;
                // 记录上次移动的距离
                this.startX=this.moveX;
                this.startY=this.moveY;
            }
        },
        close() {
            this.$emit("closeImage", false);
        }
    }
}
</script>

3、css部分

<style lang="less" scoped>
    #look-image {
        position: fixed;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        width: 858px;
        height: 768px;
        background-color: #fefefe;
        border-radius: 10px;
        border: 1px solid #c5c5c5;
        overflow: hidden;
        z-index: 99;
        .look-image-content {
            width: 100%;
            border-bottom: 1px solid #c5c5c5;
            .show-image {
                margin: 44px 148px 74px;
                height: 539px;
                width: 562px;
                position: relative;
                overflow: hidden;
                img {
                    width: 100%;
                    height: 100%;
                    position: absolute;
                    top: 0;
                    left: 0;
                }
            }
        }
        .look-image-footer {
            display: flex;
            height: 110px;
            line-height: 110px;
            >div {
                width: 25%;
                position: relative;
                &::after {
                    content: "";
                    position: absolute;
                    top: 0;
                    right: 0;
                    width: 1px;
                    height: 100%;
                    background-color: #c5c5c5;
                }
                &:last-child {
                    &::after {
                        display: none;
                    }
                }
            }
        }
    }
</style>
;