美文网首页
iview vue图片预览插件

iview vue图片预览插件

作者: skyfiring | 来源:发表于2020-01-07 10:12 被阅读0次

    引自:laii7/vue查看图片插件,略作修改,添加了缩放旋转功能。若未使用iview组件,请将ImageViewer.vue中图标Icon换掉,以免报错。

    1. 目录结构 image.png
    2. 代码如下
    // config.js,可以根据个人需求进行设置以下选项
    export default {
        canClickModalHide: false,         //控制是否点击遮罩层关闭
        closeButtonVisible: true,         //控制关闭按钮是否可见,若设置为false则canClickModalHide必定为true
        modalOpacity: 0.5,                //控制遮罩层的透明度(0-1之间的number类型)
        controlButtonVisible: true,       //控制按钮是否可见
    }
    
    // ImageViewer.vue
    <template>
        <div v-if="visible" @click="hideImage">
            <div class="see-image" :style="{ backgroundColor:background }">
                <img v-drag="greet" 
                    id="drag" 
                    class="image" 
                    :src="currentImg" 
                    @wheel.prevent="wheel"
                    ref="user_image"/>
            </div>
            <div class="close" v-show="closeButtonVisible">
                <Icon @click="close" type="md-close-circle" :size="40" class="close-icon" />
            </div>
            <div class="control" v-show="controlButtonVisible">
                <Icon @click.stop="scaleImage('add')" type="ios-add-circle-outline" :size="24" class="control-icon" />
                <Icon @click.stop="scaleImage('remove')" type="ios-remove-circle-outline" :size="24" class="control-icon" />
                <Icon @click.stop="rotateImage('left')" type="md-undo" :size="24" class="control-icon" />
                <Icon @click.stop="rotateImage('right')" type="md-redo" :size="24" class="control-icon" />
            </div>
        </div>
    </template>
    
    <script>
        import config from './config'
        const {modalOpacity, canClickModalHide, controlButtonVisible, closeButtonVisible} = config;
        export default {
            data() {
                return {
                    currentImg: '',
                    visible: false,
                    background: modalOpacity > 1 || modalOpacity <= 0 || typeof modalOpacity !== "number" ? null : 'rgba(0,0,0,' + modalOpacity + ')',
                    controlButtonVisible,
                    closeButtonVisible,
                    rotateDeg: 0,
                }
            },
            methods: {
                close() {
                    this.clearImg();
                },
                //接受传来的位置数据,并将数据绑定给data下的val
                greet(val) {
                    this.val = val;
                },
                //点击图片之外区域隐藏图片
                hideImage(e) {
                    if (!this.visible || (!canClickModalHide && closeButtonVisible)) return;
                    document.addEventListener('click', (e) => {
                        if (e.target.nodeName !== 'IMG' && e.target.nodeName !== 'BUTTON') {
                            this.clearImg();
                        }
                    });
                },
                //旋转图片
                rotateImage(direction) {
                    if(direction === 'left'){
                        this.rotateDeg -= 90;
                    }else{
                        this.rotateDeg += 90;
                    }
                    this.$refs.user_image.style.transform = `rotate(${this.rotateDeg}deg)`;
                    this.$refs.user_image.style.transition = '.3s';
                },
                // 按钮缩放图片
                scaleImage(scale){
                    if(scale === 'add'){
                        this.$refs.user_image.style.transform = this.$refs.user_image.style.transform + ' scale(1.1)';
                    }else{
                        this.$refs.user_image.style.transform = this.$refs.user_image.style.transform + ' scale(0.9)';
                    }
                },
                // 滚轮缩放图片
                wheel(e) {
                    if (e.wheelDelta) {  //判断浏览器IE,谷歌滑轮事件
                        if (e.wheelDelta > 0) { //当滑轮向上滚动时
                            this.$refs.user_image.style.transform = this.$refs.user_image.style.transform + ' scale(1.1)';
                        }
                        if (e.wheelDelta < 0) { //当滑轮向下滚动时
                            this.$refs.user_image.style.transform = this.$refs.user_image.style.transform + ' scale(0.9)';
                        }
                    } else if (e.deltaY) {  //Firefox滑轮事件
                        if (e.deltaY < 0) { //当滑轮向上滚动时
                            this.$refs.user_image.style.transform = this.$refs.user_image.style.transform + ' scale(1.1)';
                        }
                        if (e.deltaY > 0) { //当滑轮向下滚动时
                            this.$refs.user_image.style.transform = this.$refs.user_image.style.transform + ' scale(0.9)';
                        }
                    }
                },
                //当图片隐藏时候的回调
                clearImg() {
                    this.visible = false;
                    this.rotateDeg = 0;
                    document.removeEventListener('click', null);
                    setTimeout(() => {
                        if (this.$refs.user_image) {
                            this.$refs.user_image.style.transform = 'rotate(0deg)';
                            this.$refs.user_image.style.left = '';
                            this.$refs.user_image.style.top = '';
                        }
                    }, 100)
                },
            }
        }
    </script>
    
    <style scoped>
        .see-image {
            width: 100%;
            z-index: 9999;
            background: rgba(0, 0, 0, .3);
            height: 100%;
            position: fixed;
            top: 0;
            left: 0;
            display: flex;
            justify-content: center;
            align-items: center;
            animation: .25s showAimation ease;
        }
        @keyframes showAimation {
            from {
                opacity: .3;
            }
            to {
                opacity: 1;
            }
        }
        .image {
            max-width: 400px;
            min-width: 150px;
            position: absolute;
        }
        .close {
            position: absolute;
            right: 40px;
            top: 40px;
            height: 40px;
            width: 40px;
            color: #515a6e;
            border-radius: 50%;
            display: flex;
            justify-content: center;
            align-items: center;
            transition: .3s;
            z-index: 10000;
        }
        .close:hover {
            transform: rotate(90deg);
            color: #17233d;
        }
        .close img {
            width: 40px;
            height: 40px;
        }
        .close-icon {
            cursor: pointer;
        }
        .control {
            width: 180px;
            height: 48px;
            line-height: 48px;
            margin-left: -90px;
            background: #606266;
            border-radius: 50%;
            position: absolute;
            bottom: 40px;
            left: 50%;
            color: #fff;
            border-color: #fff;
            border-radius: 24px;
            display: flex;
            justify-content: center;
            align-items: center;
            z-index: 10000;
        }
        .control-icon {
            margin: 0 6px;
            cursor: pointer;
        }
    </style>
    
    // index.js
    import ImageViewerComponent from './ImageViewer'
    const ImageViewer = {}
    ImageViewer.install = Vue => {
        const ImageViewerConstructor = Vue.extend(ImageViewerComponent);
        const instance = new ImageViewerConstructor();
        instance.$mount(document.createElement('div'))
        document.body.appendChild(instance.$el)
        //自定义拖动
        Vue.directive('drag',
            function (el, binding) {
                instance.isShowImageDialog = true;
                let oDiv = el;   //当前元素
                oDiv.onmousedown = function (e) {
                    if (e.button === 2) return;
                    e.preventDefault();
                    let bw = document.body.clientWidth;
                    let bh = document.body.clientHeight;
                    //鼠标按下,计算当前元素距离可视区的距离
                    let disX = e.clientX - oDiv.offsetLeft;
                    let disY = e.clientY - oDiv.offsetTop;
                    document.onmousemove = function (e) {
                        //通过事件委托,计算移动的距离
                        let l = 0, t = 0;
                        // 拖动边界
                        if (e.clientX >= bw) {
                            l = bw - disX;
                        } else if (e.clientX <= 0) {
                            {
                                l =0- disX;
                            }
                        } else {
                            l = e.clientX - disX;
                        }
                        if (e.clientY >= bh) {
                            t = bh - disY;
                        }else if(e.clientY <= 0) {
                            t =0- disY;
                        }
                        else {
                            t = e.clientY - disY;
                        }
                        //移动当前元素
                        oDiv.style.left = l + 'px';
                        oDiv.style.top = t + 'px';
                        //将此时的位置传出去
                        binding.value({x: e.pageX, y: e.pageY})
                    };
                    // 事件移除
                    document.onmouseup = function (e) {
                        document.onmousemove = null;
                        document.onmouseup = null;
                    };
                };
            }
        );
        // 挂载触发方法
        Vue.prototype.$imageViewer = (e) => {
            instance.currentImg = e.currentTarget.currentSrc;
            instance.visible = true;
        }
    }
    export default ImageViewer;
    
    3. 使用
    // vue项目的main.js文件中引用,注意由于组件中用到了ivew相关组件,请放在iview之后引用
    
    import imageViewer from '@/components/vue-imageViewer-master' // 图片查看
    Vue.use(imageViewer);
    
    // 组件中直接添加 @click="$imageViewer" 即可
    <img :src="url" @click="$imageViewer">
    
    4. 效果图 image.png

    相关文章

      网友评论

          本文标题:iview vue图片预览插件

          本文链接:https://www.haomeiwen.com/subject/hqcractx.html