vue仿京東放大鏡加商品縮略圖輪播組件

以下是最終的vue版本,光滑流暢,,99%還原京東放大鏡甚至更好

1.vue版本

<template>
  <div id="magnifier">
    <div
      class="small-box"
      @mouseover="smallBoxOver"
      @mousemove="smallBoxMove($event)"
      @mouseleave="smallLeave"
    >
      <img :src="theImg" />
      <span class="hover"></span>
    </div>
    <div class="thumbnail-box">
      <a class="btn btn-prev" @click="prev"></a>
      <a class="btn btn-next" @click="next"></a>

      <div class="list">
        <ul class="wrapper">
          <li
            class="item"
            v-for="(item, index) in pictureList"
            :key="index"
            @mouseover="chooseImg(item,index)"
            @mouseleave="leaveImg(index)"
            :class="activeIndex===index?'item-cur':''"
          >
            <img :src="item.url" />
          </li>
        </ul>
      </div>
    </div>
    <div class="big-box">
      <img :src="theImg" />
    </div>
  </div>
</template>

<script>
import $ from 'jquery'
import 'jquery'
export default {
  data() {
    return {
      theImg: '', // 當前選中的圖片
      activeIndex: 0,
      pictureList: [
        {
          url:
            'http://mp.ofweek.com/Upload/News/Img/member645/201711/17170046839337.jpg'
        },
        {
          url:
            'http://image.buy.ccb.com/merchant/201703/904919627/1522929521661_4.jpg'
        },
        {
          url:
            'http://image5.suning.cn/uimg/b2c/newcatentries/0070130691-000000000826244625_5_800x800.jpg'
        },
        {
          url:
            'http://img12.360buyimg.com/n5/s450x450_jfs/t9952/98/2269407420/279171/6137fe2f/59f28b2bN6959e086.jpg'
        },
        {
          url:
            'http://d.ifengimg.com/w600/p0.ifengimg.com/pmop/2017/1213/A4037864F6728F006B67AAEC51EC8A485F320FD2_size93_w1024_h734.jpeg'
        },
        {
          url:
            'http://d.ifengimg.com/w600/p0.ifengimg.com/pmop/2017/1213/A4037864F6728F006B67AAEC51EC8A485F320FD2_size93_w1024_h734.jpeg'
        }
      ],
      $elem: '',
      $smallBox: '',
      $smallBox_pic: '',
      $smallBox_mask: '',
      $thumbnailBox: '',
      $thumbnailBox_prev: '',
      $thumbnailBox_next: '',
      $thumbnailBox_wrapper: '',
      $thumbnailBox_item: '',
      $thumbnailBox_pic: '',
      $bigBox: '',
      $bigBox_pic: ''
    }
  },
  created() {
    this.theImg = this.pictureList[0].url
  },
  mounted() {
    this.initPreview()
  },
  methods: {
    initPreview() {
      this.$elem = $('#magnifier')
      this.$smallBox = this.$elem.find('.small-box')
      this.$smallBox_pic = this.$smallBox.find('img')
      this.$smallBox_mask = this.$smallBox.find('.hover')
      this.$thumbnailBox = this.$elem.find('.thumbnail-box')
      this.$thumbnailBox_prev = this.$thumbnailBox.find('.btn-prev')
      this.$thumbnailBox_next = this.$thumbnailBox.find('.btn-next')
      this.$thumbnailBox_wrapper = this.$thumbnailBox.find('.wrapper')
      this.$thumbnailBox_item = this.$thumbnailBox.find('.item')
      this.$thumbnailBox_pic = this.$thumbnailBox.find('img')
      this.$bigBox = this.$elem.find('.big-box')
      this.$bigBox_pic = this.$bigBox.find('img')
    },
    moveBigPic() {
      // 改變大圖
      let scaleX =
        this.$smallBox_mask.position().left /
        (this.$smallBox.width() - this.$smallBox_mask.width())
      let scaleY =
        this.$smallBox_mask.position().top /
        (this.$smallBox.height() - this.$smallBox_mask.height())
      let scroll_l = scaleX * (this.$bigBox_pic.width() - this.$bigBox.width())
      let scroll_t =
        scaleY * (this.$bigBox_pic.height() - this.$bigBox.height())
      this.$bigBox.stop(true)
      this.$bigBox.scrollLeft(scroll_l).scrollTop(scroll_t)
    },
    setMask() {
      // 設置 mask 寬高
      //   let mask_w =
      //     this.$smallBox.width() /
      //     (this.$bigBox_pic.width() / this.$bigBox.width()) /
      //     2.5
      //   let mask_h =
      //     this.$smallBox.height() /
      //     (this.$bigBox_pic.height() / this.$bigBox.height()) /
      //     2.5
      //   //   this.$smallBox_mask.stop(true)
      //   this.$smallBox_mask.css({ width: mask_w, height: mask_h })
      //   this.$smallBox_mask.css({ height: '121.5px', width: '121.5px' })
    },
    smallBoxOver() {
      this.$bigBox.show()
      this.$smallBox_mask.show()
      this.setMask()
      this.$smallBox.stop(true)
    },
    smallBoxMove(ev) {
      //   console.log('ev.clientX', ev.clientX)
      let oEvent = ev || window.event
      let offset_pos = {
        left:
          oEvent.clientX -
          this.$smallBox.offset().left -
          this.$smallBox_mask.width() / 2,
        top:
          oEvent.clientY -
          this.$smallBox.offset().top -
          this.$smallBox_mask.height() / 2 +
          $(window).scrollTop()
      }
      if (offset_pos.left < 0) {
        offset_pos.left = 0
      } else if (
        offset_pos.left >
        this.$smallBox.width() - this.$smallBox_mask.width()
      ) {
        offset_pos.left = this.$smallBox.width() - this.$smallBox_mask.width()
      }
      if (offset_pos.top < 0) {
        offset_pos.top = 0
      } else if (
        offset_pos.top >
        this.$smallBox.height() - this.$smallBox_mask.height()
      ) {
        offset_pos.top = this.$smallBox.height() - this.$smallBox_mask.height()
      }

      this.$smallBox_mask.css(offset_pos)
      //   this.$smallBox_mask.css({ height: '121.5px', width: '121.5px' })

      this.moveBigPic()
    },
    smallLeave() {
      this.$smallBox_mask.hide()
      this.$bigBox.hide()
    },
    prev() {
      this.$thumbnailBox_wrapper.animate({ marginLeft: 0 })
    },
    next() {
      let ov_pic = this.$thumbnailBox_item.length - 5
      let ov_dis = ov_pic * 78
      this.$thumbnailBox_wrapper.stop(true)
      if (ov_pic > 0) {
        this.$thumbnailBox_wrapper.animate({ marginLeft: -ov_dis })
      }
    },
    leaveImg(index) {},
    chooseImg(item, index) {
      this.theImg = item.url
      this.activeIndex = index
    }
  }
}
</script>

<style lang="less" scoped>
.thumbnail-box .btn-prev {
  left: 0;
  background: url(../../assets/img/fjd/images/btn_prev.png) no-repeat;
}
.thumbnail-box .btn-next {
  right: 0;
  background: url(../../assets/img/fjd/images/btn_next.png) no-repeat;
}

ul,
li {
  list-style: none;
}

#magnifier {
  position: relative;
  width: 450px;
}
.small-box {
  position: relative;
  width: 450px;
  height: 450px;
  margin-bottom: 20px;
  border: 1px solid #eee;
}
.small-box img {
  display: block;
  object-fit: fill;
  width: 100%;
  height: 100%;
}
.small-box .hover {
  display: none;
  position: absolute;
  left: 0;
  top: 0;
  width: 125px;
  height: 125px;
  border: 1px solid #aaa;
  background: #0099ff;
  opacity: 0.5;
  cursor: move;
}
.thumbnail-box {
  position: relative;
  width: 100%;
  height: 62px;
}
.thumbnail-box .btn {
  position: absolute;
  top: 50%;
  width: 22px;
  height: 32px;
  margin-top: -16px;
}

.thumbnail-box .list {
  overflow: hidden;
  width: 390px;
  margin: 0 auto;
  height: 58px;
}
.thumbnail-box .wrapper {
  width: 100000px;
}
.thumbnail-box .list .item {
  float: left;
  margin: 0 11.9px;
}
.thumbnail-box .list .item-cur {
}
.thumbnail-box .list .item img {
  border: 2px solid #fff;
  height: 50px;
  width: 50px;
}

.thumbnail-box .list .item-cur img {
  border: 2px solid #e53e41;
}
.big-box {
  display: none;
  overflow: hidden;
  position: absolute;
  left: 451px;
  top: 0;
  width: 540px;
  height: 540px;
  border: 1px solid #e4e4e4;
  z-index: 999;
}
.big-box img {
  display: block;
}
</style>

2. JQ版本

<template>
  <div id="magnifier">
    <!-- <div class="small-box" @mouseover="smallBoxOver" @mousemove="smallBoxMove"> -->
    <div class="small-box">
      <img :src="theImg" />
      <span class="hover"></span>
    </div>
    <div class="thumbnail-box">
      <!-- <a href="javascript:;" class="btn btn-prev" @click="prev"></a>
      <a href="javascript:;" class="btn btn-next" @click="next"></a>-->
      <a href="javascript:;" class="btn btn-prev"></a>
      <a href="javascript:;" class="btn btn-next"></a>
      <div class="list">
        <ul class="wrapper">
          <!-- <li class="item item-cur" v-for="(item, index) in pictureList" :key="index">
              <img :src="item.url" />
          </li>-->
          <!-- <li
              class="item"
              v-for="(item, index) in pictureList"
              :key="index"
              @mouseover="itemMouseOver"
          ></li>-->
          <li
            class="item"
            v-for="(item, index) in pictureList"
            :key="index"
            @mouseenter="chooseImg(item)"
          >
            <img :src="item.url" />
          </li>
        </ul>
      </div>
    </div>

    <!-- 縮略圖容器 -->
    <div class="carousel" style="display:none;">
      <!-- 左箭頭 -->
      <div class="left_arrow arrow" @click="leftArrowClick"></div>
      <!-- 縮略圖展示盒子 -->
      <div class="show_box">
        <ul class="picture_container" ref="middlePicture">
          <li
            class="picture_item"
            @mouseover="tabPicture(item)"
            v-for="(item, index) in pictureList"
            :key="index"
          >
            <img :src="item.url" class="small_img" alt />
          </li>
        </ul>
      </div>
      <!-- 向右箭頭 -->
      <div class="right_arrow arrow" @click="rightArrowClick"></div>
    </div>
    <div class="big-box">
      <img :src="theImg" />
    </div>
  </div>
</template>

<script>
import $ from 'jquery'
import jQuery from 'jquery'
import 'jquery'
import '../ProductPreview/fjd/magnifier'

export default {
  data() {
    return {
      theImg: '', // 當前選中的圖片
      pictureList: [
        {
          url:
            'http://mp.ofweek.com/Upload/News/Img/member645/201711/17170046839337.jpg'
        },
        {
          url:
            'http://image.buy.ccb.com/merchant/201703/904919627/1522929521661_4.jpg'
        },
        {
          url:
            'http://image5.suning.cn/uimg/b2c/newcatentries/0070130691-000000000826244625_5_800x800.jpg'
        },
        {
          url:
            'http://img12.360buyimg.com/n5/s450x450_jfs/t9952/98/2269407420/279171/6137fe2f/59f28b2bN6959e086.jpg'
        },
        {
          url:
            'http://d.ifengimg.com/w600/p0.ifengimg.com/pmop/2017/1213/A4037864F6728F006B67AAEC51EC8A485F320FD2_size93_w1024_h734.jpeg'
        },
        {
          url:
            'http://d.ifengimg.com/w600/p0.ifengimg.com/pmop/2017/1213/A4037864F6728F006B67AAEC51EC8A485F320FD2_size93_w1024_h734.jpeg'
        }
      ]
      // $elem: '',
      // $smallBox: '',
      // $smallBox_pic: '',
      // $smallBox_mask: '',
      // $thumbnailBox: '',
      // $thumbnailBox_prev: '',
      // $thumbnailBox_next: '',
      // $thumbnailBox_wrapper: '',
      // $thumbnailBox_item: '',
      // $thumbnailBox_pic: '',
      // $bigBox: '',
      // $bigBox_pic: ''
    }
  },
  created() {
    this.theImg = this.pictureList[0].url
  },
  mounted() {},
  methods: {
    chooseImg(item) {
      this.theImg = item.url
    },
    // 切換圖片
    tabPicture(item) {
      this.middleImg = item.url
    },
    // 點擊左邊箭頭
    leftArrowClick() {
      if (this.middleLeft < 0) {
        // 每次向右平移一個圖片盒子的寬度
        this.middleLeft += this.itemWidth
        $('.picture_container').animate(
          {
            left: this.middleLeft
          },
          500
        )
      }
    },
    // 點擊右邊箭頭
    rightArrowClick() {
      // 每次向左平移一個盒子的寬度,最多移動的寬度爲(圖片數組長度-4)*每張縮略圖的寬度
      if (this.middleLeft > -this.itemWidth * (this.pictureList.length - 4)) {
        this.middleLeft -= this.itemWidth
        $('.picture_container').animate(
          {
            left: this.middleLeft
          },
          500
        )
      }
      console.log(this.middleLeft)
    }
  }
}
</script>

<style lang="less" scoped>
.thumbnail-box .btn-prev {
  left: 0;
  background: url(../../assets/img/fjd/images/btn_prev.png) no-repeat;
}
.thumbnail-box .btn-next {
  right: 0;
  background: url(../../assets/img/fjd/images/btn_next.png) no-repeat;
}

ul,
li {
  list-style: none;
}

#magnifier {
  position: relative;
  width: 450px;
}
.small-box {
  position: relative;
  width: 450px;
  height: 450px;
  margin-bottom: 20px;
  border: 1px solid #eee;
}
.small-box img {
  display: block;
  object-fit: fill;
  width: 100%;
  height: 100%;
}
.small-box .hover {
  display: none;
  position: absolute;
  left: 0;
  top: 0;
  width: 200px;
  height: 200px;
  border: 1px solid #aaa;
  background: #0099ff;
  opacity: 0.5;
  cursor: move;
}
.thumbnail-box {
  position: relative;
  width: 100%;
  height: 62px;
}
.thumbnail-box .btn {
  position: absolute;
  top: 50%;
  width: 22px;
  height: 32px;
  margin-top: -16px;
}

.thumbnail-box .list {
  overflow: hidden;
  width: 390px;
  margin: 0 auto;
  height: 58px;
}
.thumbnail-box .wrapper {
  width: 100000px;
}
.thumbnail-box .list .item {
  float: left;
  margin: 0 11.9px;
}
.thumbnail-box .list .item-cur {
}
.thumbnail-box .list .item img {
  border: 2px solid #fff;
  height: 50px;
  width: 50px;
}
.thumbnail-box .list .item-cur img {
  border: 2px solid #e53e41;
}
.big-box {
  display: none;
  overflow: hidden;
  position: absolute;
  left: 451px;
  top: 0;
  width: 540px;
  height: 540px;
  border: 1px solid #e4e4e4;
  z-index: 999;
}
.big-box img {
  display: block;
}
</style>

magnifier.js 

import jQuery from 'jquery'
import $ from 'jquery'
$(function() {
  $('#magnifier').magnifier()
})
;(function($, window, document, undefined) {
  let Magnifier = function(elem) {
    const self = this
    this.$elem = elem
    this.$smallBox = this.$elem.find('.small-box')
    this.$smallBox_pic = this.$smallBox.find('img')
    this.$smallBox_mask = this.$smallBox.find('.hover')
    this.$thumbnailBox = this.$elem.find('.thumbnail-box')
    this.$thumbnailBox_prev = this.$thumbnailBox.find('.btn-prev')
    this.$thumbnailBox_next = this.$thumbnailBox.find('.btn-next')
    this.$thumbnailBox_wrapper = this.$thumbnailBox.find('.wrapper')
    this.$thumbnailBox_item = this.$thumbnailBox.find('.item')
    this.$thumbnailBox_pic = this.$thumbnailBox.find('img')
    this.$bigBox = this.$elem.find('.big-box')
    this.$bigBox_pic = this.$bigBox.find('img')
  }

  Magnifier.prototype = {
    moveBigPic: function() {
      // 改變大圖
      let scaleX =
        this.$smallBox_mask.position().left /
        (this.$smallBox.width() - this.$smallBox_mask.width())
      let scaleY =
        this.$smallBox_mask.position().top /
        (this.$smallBox.height() - this.$smallBox_mask.height())
      let scroll_l = scaleX * (this.$bigBox_pic.width() - this.$bigBox.width())
      let scroll_t =
        scaleY * (this.$bigBox_pic.height() - this.$bigBox.height())
      this.$bigBox.stop(true)
      this.$bigBox.scrollLeft(scroll_l).scrollTop(scroll_t)
    },

    // changeSrouce: function(index, cur_src) {
    //   // 改變大小圖地址
    //   this.$smallBox_pic.attr('src', cur_src)
    //   this.$bigBox_pic.attr('src', 'images/big_' + (index + 1) + '.jpg')
    // },
    changeSrouce: function(index, cur_src) {
      // 改變大小圖地址
      // this.$smallBox_pic.attr('src', cur_src)
      // this.$bigBox_pic.attr('src', cur_src)
    },

    setMask: function() {
      // 設置 mask 寬高
      let mask_w =
        this.$smallBox.width() /
        (this.$bigBox_pic.width() / this.$bigBox.width()) /
        2.5
      let mask_h =
        this.$smallBox.height() /
        (this.$bigBox_pic.height() / this.$bigBox.height()) /
        2.5
      this.$smallBox_mask.stop(true)
      this.$smallBox_mask.css({ width: mask_w, height: mask_h })
    },

    inital: function() {
      // 初始化
      const self = this

      this.$thumbnailBox_next.click(function() {
        let ov_pic = self.$thumbnailBox_item.length - 5
        let ov_dis = ov_pic * 78
        self.$thumbnailBox_wrapper.stop(true)

        if (ov_pic > 0) {
          self.$thumbnailBox_wrapper.animate({ marginLeft: -ov_dis })
        }
      })

      this.$thumbnailBox_prev.click(function() {
        // self.$thumbnailBox_wrapper.stop(true)
        self.$thumbnailBox_wrapper.animate({ marginLeft: 0 })
      })

      this.$thumbnailBox_item.mouseover(function() {
        let cur_src = $(this).attr('data-src')

        self.$thumbnailBox_item.removeClass('item-cur')

        $(this).addClass('item-cur')

        // self.changeSrouce($(this).index(), cur_src)
      })

      this.$smallBox.hover(
        function() {
          self.$bigBox.show()
          self.$smallBox_mask.show()
          self.setMask()
          $(this).stop(true)
          $(this).mousemove(function(ev) {
            let oEvent = ev || window.event
            let offset_pos = {
              left:
                oEvent.clientX -
                $(this).offset().left -
                self.$smallBox_mask.width() / 2,
              top:
                oEvent.clientY -
                $(this).offset().top -
                self.$smallBox_mask.height() / 2 +
                $(window).scrollTop(),
            }

            if (offset_pos.left < 0) {
              offset_pos.left = 0
            } else if (
              offset_pos.left >
              $(this).width() - self.$smallBox_mask.width()
            ) {
              offset_pos.left = $(this).width() - self.$smallBox_mask.width()
            }
            if (offset_pos.top < 0) {
              offset_pos.top = 0
            } else if (
              offset_pos.top >
              $(this).height() - self.$smallBox_mask.height()
            ) {
              offset_pos.top = $(this).height() - self.$smallBox_mask.height()
            }

            self.$smallBox_mask.css(offset_pos)

            self.moveBigPic()
          })
        },
        function() {
          self.$smallBox_mask.hide()
          self.$bigBox.hide()
        }
      )
    },

    constructor: Magnifier,
  }

  $.fn.magnifier = function() {
    var magnifier = new Magnifier(this)

    return magnifier.inital()
  }
})(jQuery, window, document)

原html插件,純jq,學習用

鏈接:https://pan.baidu.com/s/16hEc-VtP--p_nZOdsMwi8w 
提取碼:ex37

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章