javascript技巧

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript技巧 > JavaScript图片放大镜

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

作者: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图片放大镜内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文