zoukankan      html  css  js  c++  java
  • vue 图片放大镜效果

    插件名称:vue-photo-zoom-pro

    https://github.com/Mater1996/vue-photo-zoom-pro

    效果图

     使用:

    <template>
      <div class="images">
        <img style=" 300px;" @click.stop="showBigPicture(url)" :src="url" alt="">
    
        <!-- 显示大图 -->
        <Modal v-model="pictureModal" width="960" footer-hide :closable="closable" class-name="vertical-center-modal">
          <photo-zoom :url="bigPictureUrl" :bigWidth="200" :scale="2"
            overlayStyle=" 100%;height: 600px;border-radius: 3px;"></photo-zoom>
        </Modal>
      </div>
    </template>
    <script>
      import PhotoZoom from '@/components/photo-zoom'
      export default {
        components: { PhotoZoom },
        data() {
          return {
            url:'http://pic1.win4000.com/wallpaper/2019-01-28/5c4ebd381fc8b.jpg',
            bigPictureUrl:'',
            pictureModal: false,
            closable: false,
          }
        },
        methods: {
          showBigPicture(url) {
            this.pictureModal = true;
            this.bigPictureUrl = url;
          },
        },
      }
    </script>

    代码中使用了iviewUI的Modal, 

    组件内容:

       ├── components              
       │   ├── photo-zoom  //放大镜组件
       │   │   ├── index.vue         
       │   │   └── vue-photo-zoom-pro.vue 

    index.vue:

    <template>
      <div style=" 100%;height: 100%">
        <vue-photo-zoom-pro :width="bigWidth" :url="url" :type="type" :scale="scale" :out-show="showType"
          :overlayStyle="overlayStyle">
        </vue-photo-zoom-pro>
      </div>
    </template>
    
    <script>
      import vuePhotoZoomPro from '@/components/photo-zoom/vue-photo-zoom-pro'
      export default {
        name: 'PicZoom',
        components: { vuePhotoZoomPro },
        data() {
          return {
            type: "square",
            showType: false,
          }
        },
        props: {
          url: {
            type: String,
            required: true,
            // default: require('@/assets/vehicle_img/blank_vehicle.jpg') 
          },
          bigWidth: {
            type: Number,
            required: true,
            default: 168
          },
          scale: {
            type: Number,
            required: true,
            default: 2
          },
          overlayStyle: {
            type: String,
            default: '100%;height:100%'
          }
        },
      }
    </script>

    vue-photo-zoom-pro.vue:

    <template>
      <div class="pic-img">
        <div class="img-container">
          <img ref="img" @load="imgLoaded" :src="url" :style="overlayStyle" @error="imgerrorfun" />
          <div class="overlay" @mousemove.stop="!moveEvent && mouseMove($event)"
            @mouseout.stop="!leaveEvent && mouseLeave($event)" :style="overlayStyle">
          </div>
          <div v-if="!hideZoom && imgLoadedFlag &&!hideSelector" :class="['img-selector', {'circle': type === 'circle'}]"
            :style="[imgSelectorStyle, imgSelectorSize, imgSelectorPosition, !outShow && imgBg, !outShow && imgBgSize, !outShow && imgBgPosition]">
            <slot></slot>
          </div>
          <div v-if="outShow" v-show="!hideOutShow" :class="['img-out-show', {'base-line': baseline}]"
            :style="[imgOutShowSize, imgOutShowPosition, imgBg, imgBgSize, imgBgPosition]">
            <div v-if="pointer" class="img-selector-point"></div>
          </div>
        </div>
      </div>
    
    </template>
    
    <script>
      export default {
        name: "vue-photo-zoom-pro",
        props: {
          url: {
            type: String,
          },
          highUrl: String,
           {
            type: Number,
            default: 168
          },
          type: {
            type: String,
            default: "square",
            validator: function (value) {
              return ["circle", "square"].indexOf(value) !== -1;
            }
          },
          selectorStyle: {
            type: Object,
            default() {
              return {};
            }
          },
          outShowStyle: {},
          scale: {
            type: Number,
            default: 3
          },
          moveEvent: {
            type: [Object, MouseEvent],
            default: null
          },
          leaveEvent: {
            type: [Object, MouseEvent],
            default: null
          },
          hideZoom: {
            type: Boolean,
            default: false
          },
          outShow: {
            type: Boolean,
            default: false
          },
          pointer: {
            type: Boolean,
            default: false
          },
          baseline: {
            type: Boolean,
            default: false
          },
          overlayStyle: {
            type: String,
            default: '100%;height:100%'
          },
        },
        data() {
          return {
            selector: {
               this.width,
              top: 0,
              left: 0,
              bgTop: 0,
              bgLeft: 0,
              rightBound: 0,
              bottomBound: 0,
              absoluteLeft: 0,
              absoluteTop: 0
            },
            imgInfo: {},
            $img: null,
            screenWidth: document.body.clientWidth,
            outShowInitTop: 0,
            outShowTop: 0,
            hideOutShow: true,
            imgLoadedFlag: false,
            hideSelector: false,
            timer: null
          };
        },
        watch: {
          moveEvent(e) {
            this.mouseMove(e);
          },
          leaveEvent(e) {
            this.mouseLeave(e);
          },
          url(n) {
            this.imgLoadedFlag = false;
            // let img = require('@/assets/vehicle_img/blank_vehicle.jpg')
            // if(n == img){
            //  this.outShow = false
            // }
          },
          width(n) {
            this.initSelectorProperty(n);
          },
          screenWidth(val) {
            if (!this.timer) {
              this.screenWidth = val;
              this.timer = setTimeout(() => {
                this.imgLoaded();
                clearTimeout(this.timer);
                this.timer = null;
              }, 400);
            }
          }
        },
        computed: {
          addWidth() {
            return !this.outShow ? (this.width / 2) * (1 - this.scale) : 0;
          },
          imgSelectorPosition() {
            let { top, left } = this.selector;
            return {
              top: `${top}px`,
              left: `${left}px`
            };
          },
          imgSelectorSize() {
            let width = this.selector.width;
            return {
               `${width}px`,
              height: `${width}px`
            };
          },
          imgSelectorStyle() {
            return this.selectorStyle;
          },
          imgOutShowSize() {
            let {
              scale,
              selector: { width }
            } = this;
            return {
               `${width * scale}px`,
              height: `${width * scale}px`
            };
          },
          imgOutShowPosition() {
            return {
              top: `${this.outShowTop}px`,
              right: `${-8}px`
            };
          },
          imgBg() {
            return {
              backgroundImage: `url(${this.highUrl || this.url})`
            };
          },
          imgBgSize() {
            let {
              scale,
              imgInfo: { height, width }
            } = this;
            return {
              backgroundSize: `${width * scale}px ${height * scale}px`
            };
          },
          imgBgPosition() {
            let { bgLeft, bgTop } = this.selector;
            return {
              backgroundPosition: `${bgLeft}px ${bgTop}px`
            };
          },
        },
        mounted() {
          this.$img = this.$refs["img"];
        },
        methods: {
          imgLoaded() {
            let imgInfo = this.$img.getBoundingClientRect();
            if (JSON.stringify(this.imgInfo) != JSON.stringify(imgInfo)) {
              this.imgInfo = imgInfo;
              this.initSelectorProperty(this.width);
              this.resetOutShowInitPosition();
            }
            if (!this.imgLoadedFlag) {
              this.imgLoadedFlag = true;
              this.$emit("created", imgInfo);
            }
          },
          mouseMove(e) {
            if (!this.hideZoom && this.imgLoadedFlag) {
              this.imgLoaded();
              const { pageX, pageY, clientY } = e;
              const { scale, selector, outShow, addWidth, outShowAutoScroll } = this;
              let { outShowInitTop } = this;
              const scrollTop = pageY - clientY;
              const { absoluteLeft, absoluteTop, rightBound, bottomBound } = selector;
              const x = pageX - absoluteLeft; // 选择器的x坐标 相对于图片
              const y = pageY - absoluteTop; // 选择器的y坐标
              if (outShow) {
                if (!outShowInitTop) {
                  outShowInitTop = this.outShowInitTop = scrollTop + this.imgInfo.top;
                }
                this.hideOutShow && (this.hideOutShow = false);
                this.outShowTop =
                  scrollTop > outShowInitTop ? scrollTop - outShowInitTop : 0;
              }
              this.hideSelector && (this.hideSelector = false);
              selector.top = y > 0 ? (y < bottomBound ? y : bottomBound) : 0;
              selector.left = x > 0 ? (x < rightBound ? x : rightBound) : 0;
              selector.bgLeft = addWidth - x * scale; // 选择器图片的坐标位置
              selector.bgTop = addWidth - y * scale;
            }
          },
          initSelectorProperty(selectorWidth) {
            const selectorHalfWidth = selectorWidth / 2;
            const selector = this.selector;
            const { width, height, left, top } = this.imgInfo;
            const { scrollLeft, scrollTop } = document.documentElement;
            selector.width = selectorWidth;
            selector.rightBound = width - selectorWidth;
            selector.bottomBound = height - selectorWidth;
            selector.absoluteLeft = left + selectorHalfWidth + scrollLeft;
            selector.absoluteTop = top + selectorHalfWidth + scrollTop;
          },
          mouseLeave() {
            this.hideSelector = true;
            if (this.outShow) {
              this.hideOutShow = true;
            }
          },
          reset() {
            Object.assign(this.selector, {
              top: 0,
              left: 0,
              bgLeft: 0,
              bgTop: 0
            });
            this.resetOutShowInitPosition();
          },
          resetOutShowInitPosition() {
            this.outShowInitTop = 0;
          },
          imgerrorfun(e) {
            // let img = require('@/assets/vehicle_img/blank_vehicle.jpg')
            // this.url = img
            // e.target.src = img
            // e.target.onerror= null
          }
        }
      };
    </script>
    
    <style scoped>
      .img-container { position: relative; }
      .overlay { cursor: crosshair; position: absolute; top: 0; left: 0; opacity: 0.5; z-index: 3; }
      .img-selector { position: absolute; cursor: crosshair; border: 1px solid rgba(0, 0, 0, 0.1); background-repeat: no-repeat; background-color: rgba(64, 64, 64, 0.6);}
      .img-selector.circle {border-radius: 50%;}
      .img-out-show {z-index: 5000;position: absolute;background-repeat: no-repeat;-webkit-background-size: cover;background-color: white;transform: translate(100%, 0);}
      .img-selector-point {position: absolute; 4px;height: 4px;top: 50%;left: 50%;transform: translate(-50%, -50%);background-color: black;}
      .img-out-show.base-line::after {position: absolute;box-sizing: border-box;content: ""; 1px;top: 0;bottom: 0;left: 50%;transform: translateX(-50%);}
      .img-out-show.base-line::before {position: absolute;box-sizing: border-box;content: "";height: 1px;border: 1px dashed rgba(0, 0, 0, 0.36);left: 0;right: 0;top: 50%;transform: translateY(-50%);}
    </style>
  • 相关阅读:
    LeetCode 225 Implement Stack using Queues 用队列实现栈
    LeetCode 232 Implement Queue using Stacks 两个栈实现队列
    LeetCode 583 Delete Operation for Two Strings 删除两个字符串的不同部分使两个字符串相同,求删除的步数
    LeetCode 230 Kth Smallest Element in a BST 二叉搜索树中的第K个元素
    LeetCode 236 Lowest Common Ancestor of a Binary Tree 二叉树两个子节点的最低公共父节点
    LeetCode 148 Sort List 链表上的归并排序和快速排序
    LeetCode 069 Sqrt(x) 求平方根
    webpack新版本4.12应用九(配置文件之模块(module))
    webpack新版本4.12应用九(配置文件之输出(output))
    webpack新版本4.12应用九(配置文件之入口和上下文(entry and context))
  • 原文地址:https://www.cnblogs.com/tuspring/p/11969363.html
Copyright © 2011-2022 走看看