类似淘宝的放大镜 vue

组件页面封装

<template>
    <div class="img-zoom" >
        <div class="img-box">
            <div class="box"
                :style="minImgBoxStyle"
                @mouseleave="mouseLeave"
                @mouseenter="mouseEnter"
                @mousemove="mousemove($event)">
                <!--原始照片-小照片-->
                <img class="zoom-img"
                    fit="contain" ref="minImg" :src="finalMinIMGsrc"
                    @load="imgload"/>
                <!--探测块-->
                <div v-show="show" class="areaMark" 
                :style="areaMarkStyle"></div>
            </div>
            <div class="thumb-list">
                <div class="thumb-item" 
                    v-for="(imgItem , imgIndex) in imgList" 
                    :key="imgIndex"
                    @click="imgChange(imgItem,imgIndex)"
                    :class="imgIndex == activeIndex ? 'active':''">
                    <img :src="imgItem" alt="" sizes="" srcset="">
                </div>
            </div>
        </div>
        <div class="maxImgBox" 
            :style="maxImgBoxStyle" 
            v-show="show">
            <!--放大后的照片-->
            <img 
                :style="maxImgStyle" fit="contain" 
                :src="finalMaxIMGsrc"/>
        </div>
        
    </div>
</template>
<script>

export default {
    props: {
        index: {
            type: Number,
            default: 0
        },
        scale: {
            type: Number,
            default: 2
        },
        imgList:{
            type: Array,
            default: []
        }
    },
    data() {
        return {
            show: false,
            finalMinIMGsrc: '',
            finalMaxIMGsrc: '',
            minIMGsrc: '',
            imgBoxWidth: 0,
            imgBoxHeight: 0,
            areaWidth: 0,
            areaHeight: 0,
            areaMarkStyle: {},
            minImgBoxStyle: {
                cursor: 'move'
            },
            minImgStyle: {},
            maxImgBoxStyle: {},
            maxImgStyle: {
                position: 'absolute',
            },
            activeIndex: 0,
        }
    },
    watch: {
        'minIMGsrc'() {
            this.init()
        },
        'maxIMGsrc'() {
            this.init()
        },
    },
    mounted() {
        this.imgChange(this.imgList[0],0);
    },
    methods: {
        init() {
            window.addEventListener('resize', this.imgboxStyleLoad, true);
            this.$nextTick(() => {
                this.imgboxStyleLoad();
            });
        },
        imgboxStyleLoad(){
            this.finalMinIMGsrc = this.minIMGsrc;
            this.finalMaxIMGsrc = this.minIMGsrc;
            this.$nextTick(() => {
                setTimeout(() => {
                    this.imgBoxWidth = this.$refs.minImg.width;
                    this.imgBoxHeight = this.$refs.minImg.height;
                    this.imgload();
                    this.$set(this.minImgStyle, 'width', this.imgBoxWidth + 'px')
                    this.$set(this.minImgStyle, 'height', this.imgBoxHeight + 'px')
                    this.$set(this.maxImgStyle, 'width', this.imgBoxWidth + 'px')
                    this.$set(this.maxImgStyle, 'height', this.imgBoxHeight + 'px')
                    this.$set(this.maxImgBoxStyle, 'width', this.imgBoxWidth + 'px')
                    this.$set(this.maxImgBoxStyle, 'height', this.imgBoxHeight + 'px')
                    let index = this.index +1;
                    if(index % 4 == 0){
                        this.$set(this.maxImgBoxStyle, 'left','-'+ this.imgBoxWidth + 'px');
                    } else{
                        this.$set(this.maxImgBoxStyle, 'left', this.imgBoxWidth + 'px');
                    }

                    this.areaWidth = this.imgBoxWidth / this.scale;
                    this.areaHeight = this.imgBoxHeight / this.scale;
                    this.$set(this.areaMarkStyle, 'width', this.areaWidth + 'px')
                    this.$set(this.areaMarkStyle, 'height', this.areaHeight + 'px')
                    this.$set(this.maxImgStyle, 'transform', 'scale(' + this.scale + ')')
                    // console.log(this.maxImgBoxStyle,'放大图片盒子样式')
                    // console.log(this.maxImgStyle,'放大图片样式')
                }, 300);
            })
        },
        imgload(){
            this.$nextTick(() => {
                this.imgBoxWidth = this.$refs.minImg.width;
                this.imgBoxHeight = this.$refs.minImg.height;
                // console.log(this.imgBoxWidth,this.imgBoxHeight,'img高度load')
            })
        },
        mouseEnter() {
            this.show = true
        },
        mouseLeave() {
            this.show = false
        },
        mousemove(e) {
            // 获取文档顶端与屏幕顶部之间的距离
            // scrollTop指的是“元素中的内容”超出“元素上边界”的那部分的高度
            let documentScrollTop = document.documentElement.scrollTop || document.body.scrollTop;
            // 获取鼠标相对于屏幕的坐标
            let mouseClientX = e.clientX
            let mouseClientY = e.clientY
            // 获取小照片相对于屏幕位置信息
            // getBoundingClientRect()用于获得页面中某个元素的左,上,右和下分别相对浏览器视窗的位置。
            let minImgPosition = this.$refs.minImg.getBoundingClientRect();
            let minImgX = minImgPosition.left;
            let minImgY = minImgPosition.top;
            // 计算出探测块相对于小图片的坐标
            let areaLeft = mouseClientX - minImgX - this.areaWidth / 2
            let areaTop = mouseClientY - minImgY - this.areaHeight / 2
            if (documentScrollTop > 0) {
                areaTop = documentScrollTop + areaTop
            }
            let minLeft = 0
            let maxLeft = this.imgBoxWidth - this.areaWidth
            let minTop = 0
            let maxTop = this.imgBoxHeight - this.areaHeight
            // 禁止探测块移出小图片
            if (areaLeft < minLeft) {
                areaLeft = minLeft
            }
            if (areaLeft > maxLeft) {
                areaLeft = maxLeft
            }
            if (areaTop < minTop) {
                areaTop = minTop
            }
            if (areaTop > maxTop) {
                areaTop = maxTop
            }
            // 更新探测块的坐标
            this.$set(this.areaMarkStyle, 'left', areaLeft + 'px')
            this.$set(this.areaMarkStyle, 'top', areaTop + 'px')
            // 更新放大后照片的坐标
            this.$set(this.maxImgStyle, 'top', (this.scale - 1) * this.imgBoxHeight / 2 - areaTop * this.scale + 'px')
            this.$set(this.maxImgStyle, 'left', (this.scale - 1) * this.imgBoxWidth / 2 - areaLeft * this.scale + 'px')
        },
        imgChange(imgItem,imgIndex){
            this.activeIndex = imgIndex;
            this.minIMGsrc = imgItem;
            this.finalMinIMGsrc = imgItem;
            this.init();
        }
    },
    beforeDestroy() {
        window.removeEventListener('resize', this.imgboxStyleLoad, true)
    },
}
</script>
<style lang="scss" scoped>

</style>

页面引入组件

<imgZoom  :index="0" :imgList="imgList" :scale="3" ></imgZoom>
//data数据
 imgList: [require('./../../assets/images/ambitus01.jpg'),require('./../../assets/images/ambitus02.jpg'),require('./../../assets/images/ambitus03.jpg')]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值