vue仿京东放大镜加商品缩略图轮播组件
以下是最终的vue版本,光滑流畅,体验感非常好,99%还原京东放大镜甚至更好1.vue版本<template><div id="magnifier"><divclass="small-box"@mouseover="smallBoxOver"@mousemove="smallBoxMove($event)"@mouseleave="smallLeave"><
·
以下是最终的vue版本,光滑流畅,99%还原京东放大镜甚至更好,不会出现多次操作会变卡的问题
1.vue版本
6/23日更新,处理图片尺寸过小无法通过拖动实现放大移动效果的问题
7/18日更新,关于视频处理,不需要引入视频的小伙伴可以注释掉代码中关于视频插件的部分
//安装 视频插件
npm install vue-video-player
//main.js全局注册
import VideoPlayer from 'vue-video-player'
import 'video.js/dist/video-js.css'
Vue.use(VideoPlayer)
<template>
<div id="magnifier" class="preview">
<div
class="small-box"
@mouseover="smallBoxOver"
@mousemove="smallBoxMove($event)"
@mouseleave="smallLeave"
>
<VideoPlayer v-if="isShowVideo" class="videoPlayer" :video="videoObj"></VideoPlayer>
<img :src="theImg" v-else />
<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" />
</li>
</ul>
</div>
</div>
<div class="big-box">
<img :src="theImg" />
</div>
</div>
</template>
<script>
import $ from 'jquery'
import 'jquery'
import VideoPlayer from '@/components/video/video'
// import VideoPlayer from '@/components/video/simpleVideo'
export default {
data() {
return {
theImg: '', // 当前选中的图片
activeIndex: 0,
isShowVideo: false,
goodVideo: '',
videoObj: {
type: 'video/mp4',
src: require('../../assets/video/jabil.mp4')
},
pictureList: [
'http://mp.ofweek.com/Upload/News/Img/member645/201711/17170046839337.jpg',
'http://image.buy.ccb.com/merchant/201703/904919627/1522929521661_4.jpg',
'http://image5.suning.cn/uimg/b2c/newcatentries/0070130691-000000000826244625_5_800x800.jpg',
'http://img12.360buyimg.com/n5/s450x450_jfs/t9952/98/2269407420/279171/6137fe2f/59f28b2bN6959e086.jpg',
'http://d.ifengimg.com/w600/p0.ifengimg.com/pmop/2017/1213/A4037864F6728F006B67AAEC51EC8A485F320FD2_size93_w1024_h734.jpeg',
'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: ''
}
},
components: {
VideoPlayer
},
props: {
imageArr: {
type: [Array, Object],
default: () => []
}
},
created() {
this.theImg = this.imageArr[0]
},
mounted() {
this.initPreview()
},
methods: {
playVideo() {
this.isShowVideo = true
},
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
this.activeIndex = index
}
}
}
</script>
<style lang="less" scoped>
/deep/ .vjs_video_3-dimensions.vjs-fluid {
padding-top: 100% !important;
}
.videoPlayer {
height: 100%;
width: 100%;
}
.thumbnail-box {
position: relative;
width: 100%;
height: 62px;
.btn-prev {
left: 0;
background: url(../../assets/img/fjd/images/btn_prev.png) no-repeat;
}
.btn-next {
right: 0;
background: url(../../assets/img/fjd/images/btn_next.png) no-repeat;
}
.btn {
position: absolute;
top: 50%;
width: 22px;
height: 32px;
margin-top: -16px;
}
.list {
overflow: hidden;
width: 390px;
margin: 0 auto;
height: 58px;
}
.wrapper {
width: 100000px;
}
.list .item {
float: left;
margin: 0 11.9px;
img {
border: 2px solid #fff;
height: 50px;
width: 50px;
}
}
.list .item-cur img {
border: 2px solid #e53e41;
}
}
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;
img {
display: block;
object-fit: fill;
width: 100%;
height: 100%;
}
.hover {
display: none;
position: absolute;
left: 0;
top: 0;
width: 125px;
height: 125px;
border: 1px solid #aaa;
background: #0099ff;
opacity: 0.5;
cursor: move;
}
}
.big-box {
display: none;
overflow: hidden;
position: absolute;
left: 451px;
top: 0;
width: 540px;
height: 540px;
border: 1px solid #e4e4e4;
z-index: 999;
img {
display: block;
height: 128%;
}
}
.preview {
.preview-btn {
position: absolute;
z-index: 5;
bottom: 62px;
left: 0;
width: 100%;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
justify-content: center;
text-align: center;
li {
display: inline-block;
margin: 0 5px;
vertical-align: text-top;
}
.video-icon {
cursor: pointer;
display: inline-block;
z-index: 999;
width: 50px;
height: 50px;
background: url(//static.360buyimg.com/item/unite/1.0.101/components/default/preview/i/main-circles.png)
0 -55px no-repeat;
}
.video-icon:hover {
background: url(//static.360buyimg.com/item/unite/1.0.101/components/default/preview/i/main-circles.png) -55px -55px
no-repeat;
}
}
}
</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"
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
更多推荐
已为社区贡献19条内容
所有评论(0)