效果图:
 
我写的是vue的组件形式,方便复用,图片的宽高,缩放的比例可以自己定义
magnifier.vue
<template>
<div class="magnify">
<!-- 左边产品图片区域 -->
<div class="left_contaner">
<div class="middle_img" @mouseover="boxMouseOver" @mouseleave="boxMouseLeave">
<!-- 产品图片 -->
<img :src="middleImg" alt="">
<!-- 阴影盒子 -->
<div class="shade" @mouseover="shadeMouseOver" @mousemove="shadeMouseMove" ref="shade" v-show="isShade"></div>
</div>
<!-- 缩略图容器 -->
<div class="carousel">
<!-- 左箭头 -->
<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>
<!-- 右边放大区域 -->
<div class="right_contanier" v-show="isBig">
<img :src="middleImg" ref="bigImg" class="big_img" alt="">
</div>
</div>
</template> <script>
import $ from 'jquery'
export default {
props: {
middleImgWidth: {
default: 350,
type: Number
}, // 产品图片宽
middleImgHeight: {
default: 400,
type: Number
}, // 产品图片高
thumbnailHeight: {
default: 100,
type: Number
}, // 缩略图容器高度
imgList: Array, // 图片数据
zoom: {
default: 2, // 缩略比例,放大比例
type: Number
}
},
data() {
return {
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'}
],
middleImg: '', // 中图图片地址
bigImg: '', // 大图图片地址
isShade: false, // 控制阴影显示与否
isBig: false, // 控制放大图显示与否
initX: 0, // 初始clientX值
initY: 0, // 初始clientY值
leftX: 0, // 初始定位left
topY: 0, // 初始定位top
middleLeft: 0, // 当前放置小图盒子的定位left值,
itemWidth: 80, // 缩略图每张的宽度
}
},
created() {
if (this.imgList && this.imgList.length) {
this.pictureList = this.imgList
}
this.middleImg = this.pictureList[0].url
// 计算缩略图的宽度,默认是显示4张图片,两边箭头的宽度和为50
this.itemWidth = (this.middleImgWidth-50) / 4
},
mounted() {
this.$nextTick(() => {
// 容器的高
const imgWidth = this.middleImgHeight + this.thumbnailHeight + 20
// 设置容器宽高
$('.magnify').css({
width: this.middleImgWidth,
height: imgWidth
})
// 设置产品图宽高
$('.middle_img').css({
width: this.middleImgWidth,
height: this.middleImgHeight
})
// 设置移动阴影图宽高
$('.middle_img .shade').css({
width: this.middleImgWidth/this.zoom,
height: this.middleImgHeight/this.zoom
})
// 设置缩略图容器高
$('.carousel').css({
height: this.thumbnailHeight
})
// 设置每个缩略图宽
$('.picture_item').css({
width: this.itemWidth
})
// 设置放大后图片容器的宽高,left
$('.right_contanier').css({
left: this.middleImgWidth,
width: imgWidth,
height: imgWidth
})
// 设置放大图片的宽高(图片的放大倍数)
$('.right_contanier .big_img').css({
width: imgWidth * this.zoom,
height: imgWidth * this.zoom
})
})
},
methods: {
// 产品图片鼠标移入事件,显示阴影,显示大图
boxMouseOver (e) {
console.log(9999, e)
e.preventDefault();
e.stopPropagation();
this.isShade = true
this.isBig = true
// 计算阴影的位置
let x = e.offsetX - $('.shade').width()/2
let y = e.offsetY - $('.shade').height()/2
let maxLeft = $('.middle_img').width() - $('.shade').width()
let maxTop = $('.middle_img').height() - $('.shade').height()
x = x <= 0 ? 0 : x
x = x >= maxLeft ? maxLeft : x
y = y <= 0 ? 0 : y
y = y >= maxTop ? maxTop : y
     $('.shade').css({
         left: x,
         top: y
        })
    },
// 鼠标在阴影移动
shadeMouseMove (e) {
e.preventDefault();
e.stopPropagation();
    //用页面x - 父盒子的offsetLeft - 父盒子的左边框宽度 标红的两个方法补在下面
    var x = this.getEventPage(e).pageX - $('.middle_img')[0].offsetParent.offsetLeft - $('.middle_img')[0].offsetParent.clientLeft;
    //用页面y - 父盒子的offsetTop - 父盒子的上边框宽度
    var y = this.getEventPage(e).pageY - $('.middle_img')[0].offsetParent.offsetTop - $('.middle_img')[0].offsetParent.clientTop;
    //让阴影的坐标居中
    x -= $('.shade').width() / 2;
    y -= $('.shade').height() / 2;
    // 移动边界限制
    let maxLeft = $('.middle_img').width() - $('.shade').width()
    let maxTop = $('.middle_img').height() - $('.shade').height()
    x = x <= 0 ? 0 : x
    x = x >= maxLeft ? maxLeft : x
    y = y <= 0 ? 0 : y
    y = y >= maxTop ? maxTop : y
    // 重新赋值当前的定位值
    $('.shade').css({
      left: x,
      top: y
    })
      // 计算出实时的大图的定位,首先计算出比例
// 比例为x:大图宽度/小图宽度 y: 大图高度/小图高度,将小图的定位乘以比例就是大图的定位
const xRate = $('.big_img').width() / $('.middle_img').width()
const yRate = $('.big_img').height() / $('.middle_img').height()
$('.big_img').css({
left: -x*xRate,
top: -y*yRate
})
// console.log(e, x, y, xRate, yRate, 66677)
},
// 鼠标移入阴影,去除自定义事件
shadeMouseOver (e) {
e.preventDefault();
e.stopPropagation();
// console.log(88888, e)
},
// 图片移出隐藏阴影和大图
boxMouseLeave (e) {
this.isShade = false
this.isBig = false
},
// 切换图片
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 scoped>
.magnify {
position: relative;
}
.left_contaner {
width: 100%;
height: 100%;
}
.left_contaner .middle_img {
border: 1px solid #ccc;
box-sizing: border-box;
position: relative;
}
.left_contaner .shade {
background-color: rgba( 135,206,235, .5);
position: absolute;
top: 0;
left: 0;
 cursor: move;
}
.left_contaner .middle_img img {
width: 100%;
height: 100%;
}
.left_contaner .carousel {
width: 100%;
margin-top: 20px;
display: -webkit-flex;
}
.left_contaner .carousel .show_box {
flex: 1;
overflow: hidden;
position: relative;
}
.left_contaner .carousel .arrow {
flex-basis: 25px;
cursor: pointer;
}
.left_contaner .carousel .left_arrow {
background: url('http://www.jq22.com/demo/jQuery-fdj201705051102/images/btn_prev.png') no-repeat;
background-position: center center;
}
.left_contaner .carousel .right_arrow {
background: url('http://www.jq22.com/demo/jQuery-fdj201705051102/images/btn_next.png') no-repeat;
background-position: center right;
}
.left_contaner .carousel .picture_container {
width: 200%;
height: 100%;
position: absolute;
overflow: hidden;
top: 0;
left: 0;
}
.left_contaner .picture_container .picture_item {
height: 100%;
float: left;
padding: 5px;
box-sizing: border-box;
}
.left_contaner .picture_container .picture_item:hover {
border: 2px solid #f2019f;
}
.left_contaner .picture_container .picture_item img {
width: 100%;
height: 100%;
}
.right_contanier {
overflow: hidden;
position: absolute;
top: 0;
border: 1px solid #ccc;
}
.right_contanier .big_img {
position: absolute;
top: 0px;
left: 0px;
}
</style>

之前漏了两个方法,补在下面,放在methods方法里就好了

/**
* 获取网页滚出去的距离(包括上面滚出去的部分和左边滚出去的部分)
* @returns {{scrollTop: (Number|number), scrollLeft: (Number|number)}}
*/
getPageScroll() {
return {
scrollTop: window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0,
scrollLeft: window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0
}
},
/**
* 获取事件对象点击的点,相对于文档左上角的坐标
* @param e
* @returns {{pageX: *, pageY: *}}
*/
getEventPage(e) {
return {
pageX: e.clientX + this.getPageScroll().scrollLeft,
pageY: e.clientY + this.getPageScroll().scrollTop
}
}
父组件引用
 
<template>
 <div id="app">
  <img alt="Vue logo" src="./assets/logo.png">
  <!-- 图片放大镜,需要自定义图片的宽高在这里传入,组件有设置默认的宽高,不传也可以 -->
  <magnifier></magnifier>
 </div>
</template>
<script>
// 引入放大镜组件
import Magnifier from './components/magnifier.vue'
import $ from 'jquery'
export default {
name: 'app',
components: {
 // 注册
 Magnifier
 }
}
 
 git-hup地址: https://github.com/shengbid/my-element  这个文件是平时练习的项目,里面还有一些我写的其他博客的源码,有需要可以下载看看

vue项目js实现图片放大镜功能的更多相关文章

  1. 原生JS实现图片放大镜插件

      前  言 我们大家经常逛各种电商类的网站,商品的细节就需要用到放大镜,这个大家一定不陌生,今天我们就做一个图片放大镜的插件,来看看图片是如何被放大的…… 先看一下我们要是实现的最终效果是怎么样的  ...

  2. Vue项目中添加锁屏功能

    0. 直接上 预览链接 Vue项目中添加锁屏功能 1. 实现思路 ( 1 ) 设置锁屏密码 ( 2 ) 密码存localStorage (本项目已经封装h5的sessionStorage和localS ...

  3. vue中图片放大镜功能

    仿淘宝详情页图片鼠标移过去可对图片放大显示在右侧 效果图如下图,此功能支持PC端与移动端 接下来进入代码实现环节: 先准备两张图片,一张小图片叫 '土味.jpg',大小160*91:一张大图片叫 ' ...

  4. js 图片放大镜功能

    原理:放置两张相同的图片,一张作为主图片(图片1),另一张作为用来裁剪并放大的图片(图片2)          鼠标移动时,计算鼠标在图片1的位置(距离图片1左上角的x,y距离),以此决定在图片2开始 ...

  5. javascript 实现图片放大镜功能

    淘宝上经常用到的一个功能是利用图片的放大镜功能来查看商品的细节 下面我们来实现这样一个功能吧,原理很简单: 实现一个可以随鼠标移动的虚框 在另外一个块中对应显示虚框中的内容 实现思路: 虚框用css中 ...

  6. vue项目如何实现剪切板功能--vue-clipboard2

    一.vue项目利用vue-clipboard2实现剪切板的功能 1.安装vue-clipboard2插件:cnpm install --save vue-clipboard2 2.main.js添加 ...

  7. 纯JS实现图片验证码功能并兼容IE6-8

    最近要搞一个图片验证码功能,但是又不想自己写后台代码.于是自己准备搞一个纯前端的验证码功能,于是网上搜索了一下,找到一个插件gVerify.js,简单好用,实现完美.不过后面接到说要兼容IE8,想想也 ...

  8. vue项目打包后图片路径问题

    当用vue-cli自动构建项目后,有两种运行方法,分别是: npm run dev : 提供一个开发的环境,自动热更新,资源使用绝对路径,所以可以正常看到背景图片. npm run build : 打 ...

  9. 在Vue项目中 选择图片并预览

    最近开始使用vue做项目 在这个过程中,碰到了大多数做前端肯定经历的一个问题,就是文件上传预览 花了点时间解决,因此分享一下预览功能的解决方案 页面: <div class="sele ...

随机推荐

  1. PHP mysql_num_rows() 函数 返回结果集中行的数目。

    定义和用法 mysql_num_rows() 函数返回结果集中行的数目. 语法 mysql_num_rows(data) 参数 描述 data 必需.结果集.该结果集从 mysql_query() 的 ...

  2. MySQL标准化、自动化部署

    机器标准化:服务器的硬件配置(CPU.硬盘.内存.RAID)要保持一致 目录标准化: mysql的安装目录,存放数据的目录.日志文件等,多台机器上配置要统一 参数标准化: 多台服务器上,存放的my.c ...

  3. PostgreSql 使用自定义序列(Sequence)向表插入数据

    最近公司使用到了PostgreSql,哈哈,这个SQL之前基本上没有用过,既然公司使用到了,那就学习一下吧,记一篇小笔记: 什么是PostgreSql:https://www.postgresql.o ...

  4. Consul 随记

    consul 包含多个组件,但是作为一个整体对外提供服务发现和服务配置工具: 提供的关键特性有: 服务发现:发现的是服务对应的IP地址和PORT端口号 健康检查:检查服务节点状态 Key/Value存 ...

  5. RegexBuddy 4.7.0 x64 评估试用到期,无限试用的办法

    http://www.cnblogs.com/inrg/p/6491043.html 最后对比发现,在注册表 HKEY_USERS 节点下存在一个用户的项,形如 "S-1-5-21-1609 ...

  6. centos7:ssh免密登陆设置

    1.使用root用户登录,进入到目录/root/.ssh 2.执行命令:ssh-keygen -t rsa 一路回车,完成后会在目录/root/.ssh下面生成文件 id_rsa和id_rsa.pub ...

  7. webdriervAPI(警告框处理)

    from  selenium  import  webdriver driver  =  webdriver.Chorme() driver.get("http://www.baidu.co ...

  8. Python3 Selenium自动化web测试 ==> 第十节 WebDriver高级应用 -- xpath语法

    学习目的: xpath定位是针对常规定位方法中,最有效的定位方式. 场景: 页面元素的定位. 正式步骤: step1:常规属性 示例UI 示例UI相关HTML代码 相关代码示例: #通过id定位 dr ...

  9. FFMPEG 常用命令行

    目录 1. 分离音视频 2. 解复用 3. 视频转码 4. 视频封装 5. 视频剪切 6. 视频录制 7.叠加水印 8.将MP3转换为PCM数据 9. 推送RTP流.接收RTP流并存为ts文件 10. ...

  10. 使用canal通过mysql复制协议从binlog实现热数据nosql缓存(1)

    binlog: mysql在运行过程中执行的DML(增删改)操作都会以二进制形式记录在binlog中 canal server: canal server作为从数据库(slave)向主数据库发送dum ...