基于JavaScript实现图片放大镜功能

 更新时间:2023年06月28日 10:24:47   作者:jimojianghu  
在一些电商网站上,经常看到有商品图片被放大查看的功能,所以本文将使用前端技术实现一个简单的图片放大镜功能,希望能给大家带来一定的帮助

在一些电商网站上,经常看到有商品图片被放大查看的功能,包括另外一些图片展示站点,也有类似的功能。

如果我们想让图片能展示更多细节清晰的内容,实现这样一个放大镜功能,是非常划算的,既能使用小图显示满足大多数用户的查看需求,又能通过放大图片的方式显示更清晰内容。这样,一方面可以节省不必要的大图流量,又能满足对图片清晰度有要求的用户需求。

所以,本文将使用前端技术实现一个简单的图片放大镜功能,希望能给大家带来一定的帮助。

图片放大镜效果

我们可以先来看下图片放大镜最后的效果图:

如上图所示,

左边的小图方块内,就是需要放大的图片,上面有一个蒙层区域(可视作放大镜),只可以在小图范围内移动,该蒙层遮住的区域就代表图片需要放大的部分;

右边的大图方块内,展示的是蒙层部分放大后的清晰图像,这里本质上是显示的完整像素的图片、或者是比左边更大像素的高清图片。

左边蒙层的实时移动,在右边显示清晰图像,这就形成了一个图片放大镜的功能效果。

接下来,我们具体看看它的实现过程。

实现过程

一、设计UI界面

要实现放大镜功能,就要先设计好界面布局,从上面的效果图里看到,界面上分了两块:一个是原始的缩略小图区域;一个是放大后的预览大图区域。
在html中使用div来布局的话,如下所示:

<div id="el_EnlargeContainer" class="enlarge">
  <!--左边原始小图区域-->
  <div id="el_SmallContainer" class="small">
    <img id="el_SmallImage"/>
    <div id="el_maskEnarge" class="mask"></div>
  </div>
  <!--右边预览大图区域-->
  <div id="el_PreviewContainer" class="preview">
    <img id="el_PreviewImage"/>
  </div>
</div>

从以上html代码可知,

外层定义了一个 el_EnlargeContainer 的整个放大功能整体内容区域,里面有两个子元素:一个是缩略小图的div,包含一个img图片元素用于展示缩略图,还有一个蒙层的div元素;另外一个是预览大图区域,包含有放大后的大图img元素,这里加载的是原始大尺寸图。

主要样式设置

蒙层需要覆盖在缩略小图的上面,所以需要使用绝对定位方式,并且设置带透明度的颜色,鼠标样式也设置为 move,默认隐藏,具体的CSS样式如下所示:

.mask {
  position: absolute;
  top: 0;
  left: 0;
  background: rgba(255, 255, 0, 0.6);
  cursor: move;
  display: none;
}

预览大图区域样式类 preview,由于要显示在右侧区域,也可以使用绝对定位的方式,超出显示在小图区域的右边即可:

.preview {
  position: absolute;
  top: 0;
  left: 150px;
  /* ... */
}

其他的样式设置都较简单,根据布局方式一一展示即可,这里就先略过。

下面,我们需要做的是加载图片。

二、加载缩略小图

上面的代码中,我们只定义了img标签元素,并没有直接加载图片资源,这是由于我们做的是以动态加载图片的方式来实现这个放大镜功能。

当动态加载图片资源后,需要根据图片像素宽高,设置对应界面元素的大小和位置信息。

缩略小图作为首先需要主体展示的资源,我们需要先加载,并设置小图区域容器和图片的大小:

el_SmallImage.onload = () => {
  let { width, height } = el_SmallImage
  const smallScale = Math.min(SMALLSIZE / width, SMALLSIZE / height, 1)
  smallImgWidth = width * smallScale
  smallImgHeight = height * smallScale
  el_EnlargeContainer.style.width = el_SmallImage.style.width = smallImgWidth + 'px'
  el_EnlargeContainer.style.height = el_SmallImage.style.height = smallImgHeight + 'px'
  resolve(el_SmallImage)
}
el_SmallImage.src = imgSrc

以上代码,加载缩略小图后,获取到图片的宽高数据,然后相应的计算。其中 SMALLSIZE 是预先定义的一个常量,表示小图区域的一个固定尺寸大小,可根据需要自定义取值,通过该值计算缩略图的缩放比例——缩略图依据该固定尺寸,计算合适的宽高比例进行展示。

注意,这里设置的是整个放大镜的整体内容区域 el_EnlargeContainer 的大小,就是小图展示的大小,而预览放大的图片是浮在右侧的,并不被包含在这块区域内。

这时候的缩略图,就是我们网站要稳定展示的图片信息,作为用户初始浏览的内容,如下图:

一般电商网站上,使用轮播图切换的方式,展示缩略图片信息。

从上图可见,只展示了缩略图片,放大后的预览大图还没涉及到,是因为我们可以在监听事件里进行加载,有利于节省图片加载流量。

三、缩略图事件监听

接下来,我们需要处理缩略小图的事件监听,实现加载预览大图、蒙层移动的效果。

根据上面的html布局,我们在缩略小图的外部容器 el_SmallContainer 上添加鼠标事件,主要是 onmouseenteronmouseleaveonmousemove 三个事件。

onmouseenter 事件,当鼠标进入到页面展示的缩略图上时进行处理,这时需要做两件事:一是加载预览大图的原始图像,二是显示蒙层和预览大图的完整内容区域。

el_SmallContainer.onmouseenter = async () => {
  // 加载预览大图原始图
  if (loadPreviewImage === null) {
    loadPreviewImage = await setPreviewImage(previewImgUrl)
  }
  // 显示蒙层和预览大图区域
  el_maskEnarge.style.display = 'block'
  el_PreviewContainer.style.display = 'block'
}

以上代码,就是鼠标进入事件的处理,其中有加载并设置预览大图的原始数据信息,具体代码如下所示:

let { width, height } = el_PreviewImage
let previewScale = Math.min(PREVIEWSIZE / width, PREVIEWSIZE / height, 1)
el_PreviewContainer.style.width = width * previewScale + 'px'
el_PreviewContainer.style.height = height * previewScale + 'px'
el_PreviewContainer.style.left = (smallImgWidth + 10) + 'px'
el_maskEnarge.style.width = smallImgWidth * previewScale + 'px'
el_maskEnarge.style.height = smallImgHeight * previewScale + 'px'

以上代码,用于加载预览大图,这时能获取到图片的原始宽高数据,其中 PREVIEWSIZE 也是预先定义的常量,表示预览大图区域的一个固定尺寸大小。大图宽高与PREVIEWSIZE尺寸计算出对应的缩放比,用于计算实际展示区域的尺寸。

el_PreviewContainer 预览大图容器内容需要定位在右侧区域,设置 left 样式属性。

另外,蒙层的大小也得设置,蒙层大小是在缩略小图区域展示的,但要使用预览大图的缩放比,这样才能得到准确的蒙层内容用于在右侧放大区域呈现放大效果。

onmouseleave 事件比较简单,当鼠标离开缩略图内容区域的时候,就隐藏蒙层和预览大图区域,放大镜效果隐藏:

el_SmallContainer.onmouseleave = () => {
  el_maskEnarge.style.display = 'none'
  el_PreviewContainer.style.display = 'none'
}

定义了放大镜的显示和隐藏事件后,就应该处理移动的效果了,移动实现实时放大,使用到 onmousemove 鼠标事件。

四、实现放大

鼠标移动也是在缩略小图内容区域,对 el_SmallContainer 元素进行事件监听:

el_SmallContainer.onmousemove = (event) => {
  // ...
}

在该事件中,我们需要处理以下几件事:

获取鼠标移动的位置信息

let x = event.pageX - el_EnlargeContainer.offsetLeft - el_maskEnarge.offsetWidth / 2
let y = event.pageY - el_EnlargeContainer.offsetTop - el_maskEnarge.offsetHeight / 2

以上代码里,读取了蒙层的offset数据,是为了移动时,能够让鼠标显示在蒙层的中心位置。

限制蒙层移动的范围,不能超出缩略小图内容区域

const xMax = el_SmallContainer.offsetWidth - el_maskEnarge.offsetWidth
x = x < 0 ? 0 : (x > xMax ? xMax : x)
const yMax = el_SmallContainer.offsetHeight - el_maskEnarge.offsetHeight
y = y < 0 ? 0 : (y > yMax ? yMax : y)

更新蒙层的位置信息,实时移动蒙层元素

el_maskEnarge.style.left = x + 'px'
el_maskEnarge.style.top = y + 'px'

设置预览大图显示的位置信息

const rate = el_PreviewImage.offsetWidth / el_SmallContainer.offsetWidth
el_PreviewImage.style.marginTop = -(rate * y) + 'px'
el_PreviewImage.style.marginLeft = -(rate * x) + 'px'

以上代码,是在一定的内容区域里,加载一张完整原始尺寸的大图,但多余的部分先隐藏 overflow: hidden;。然后计算缩略小图和预览大图的比值,右侧的预览大图等比例移动,通过使用 marginTopmarginLeft 属性设置定位的方式来移动。注意,这里处理的 el_PreviewImage 原始大图元素。 数据取负值,是相对于初始加载时候左上角的值。

总结

至此,一个可以非固定尺寸、动态加载图片的放大镜功能就基本完成了。

动态加载图片,可以不用考虑图片的像素宽高,任意尺寸的图片都可以完整放大,缩略小图和预览大图也可以是同一张图片。

另外,就是放大镜的内容显示区域,是根据不同图片的比例进行动态计算的,尺寸大小可变,但能够通过常量设定,控制在一定范围内。

图片放大镜功能的大部分代码都已在文章中列出来了,根据这些内容,还可以适当修改,更改成各种符合我们需求的插件。

固定尺寸

很多网站在处理放大镜功能上,使用的是固定尺寸缩略小图和预览大图的方式。

我们当然也可以处理固定尺寸,这个时候就需要特定尺寸的缩略小图和原始大图,直接设置元素的固定尺寸,缩略图也可以直接加载:

/* 放大镜区域的大小 */
.enlarge {
  /* ... */
  width: 150px;
  height: 150px;
}
/* 缩略小图的大小 */
.small img {
  width: 150px;
  height: 150px;
}
/* 蒙层大小 */
.mask {
  /* ... */
  width: 75px;
  height: 75px;
}
/* 预览大图区域的大小 */
.preview {
  /* ... */
  width: 300px;
  height: 300px;
}
<img id="el_SmallImage" src="chrome.png"/>

以上代码,通过css直接设置各区域的宽高大小,缩略图也是直接加载,如此处理,就不需要手动设定各元素的宽高。

同样可以在鼠标进入事件中加载原始大图,这个时候图片尺寸也是固定的。

其他事件处理,基本相同,这样就可以增加一个固定图像尺寸和固定界面尺寸的放大镜功能了。

到此这篇关于基于JavaScript实现图片放大镜功能的文章就介绍到这了,更多相关JavaScript图片放大镜内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • JS异步编程之generator与async/await语法糖详解

    JS异步编程之generator与async/await语法糖详解

    这篇文章主要为大家详细介绍了JS异步编程中generator与async/await语法糖的使用,文中的示例代码讲解详细,感兴趣的小伙伴可以学习一下
    2022-11-11
  • 解决JS无法调用Controller问题的方法

    解决JS无法调用Controller问题的方法

    这篇文章主要介绍了解决JS无法调用Controller问题的方法,需要的朋友可以参考下
    2015-12-12
  • 前端图片懒加载(lazyload)的实现方法(提高用户体验)

    前端图片懒加载(lazyload)的实现方法(提高用户体验)

    图片懒加载又称图片延时加载、惰性加载,即在用户需要使用图片的时候加载,这样可以减少请求,节省带宽,提高页面加载速度,相对的,也能减少服务器压力,下面通过本文给大家分享图片懒加载lazyload的实现方法,感兴趣的朋友一起看看吧
    2017-08-08
  • ES6顶层对象、global对象实例分析

    ES6顶层对象、global对象实例分析

    这篇文章主要介绍了ES6顶层对象、global对象,结合实例形式分析了ES6顶层对象与global对象的概念、原理、用法及相关操作注意事项,需要的朋友可以参考下
    2019-06-06
  • JavaScript & jQuery完美判断图片是否加载完毕

    JavaScript & jQuery完美判断图片是否加载完毕

    本文主要介绍了JavaScript & jQuery完美判断图片是否加载完毕的方法。具有一定的参考价值,下面跟着小编一起来看下吧
    2017-01-01
  • 使用原生JavaScript实现文字大小自适应的代码示例

    使用原生JavaScript实现文字大小自适应的代码示例

    在现代Web开发中,文字大小自适应是一种常见的需求,尤其是在响应式设计中,通过原生JavaScript实现文字大小的动态调整,可以确保内容在不同设备和屏幕尺寸下都能保持良好的可读性和视觉效果,本文将深入探讨如何使用原生JavaScript实现文字大小自适应,需要的朋友可以参考下
    2025-02-02
  • 浅述节点的创建及常见功能的实现

    浅述节点的创建及常见功能的实现

    本文主要对节点的创建及常见功能的实现方法进行介绍,希望会对大家学习javascript有所帮助,下面就跟小编一起来看下吧
    2016-12-12
  • uniapp实现全局变量的几种方式总结

    uniapp实现全局变量的几种方式总结

    这里说全局变量,着重指的是能够全局动态响应的情况,下面这篇文章主要给大家介绍了关于uniapp实现全局变量的几种方式,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-10-10
  • uniapp页面通讯讲解之uni.$emit、uni.$on、uni.$once和uni.$off

    uniapp页面通讯讲解之uni.$emit、uni.$on、uni.$once和uni.$off

    uni-app 是一个使用vue.js开发所有前端应用的框架,下面这篇文章主要给大家介绍了关于uniapp页面通讯之uni.$emit、uni.$on、uni.$once和uni.$off的相关资料,需要的朋友可以参考下
    2022-09-09
  • JS实现给对象动态添加属性的方法

    JS实现给对象动态添加属性的方法

    这篇文章主要介绍了JS实现给对象动态添加属性的方法,涉及JS属性的遍历、动态赋值及eval方法的简单使用技巧,需要的朋友可以参考下
    2017-01-01

最新评论