jquery实现放大镜效果

1,793 阅读2分钟

电商平台通常有一种类似放大镜的效果,用来查看商品的细节,我们现在就是要模仿这种效果。

  1. 效果一
    外部放大

原理:这种放大说白了就是一张大图和一张小图,滑块在小图上滑动,通过计算获取滑块相对于整张图的位置,而滑块与大图的显示区域是成比例的,根据比例关系将大图的位置也调整到响应的位置,这里对大图位置的处理可以绝对定位,也可用背景图片定位,总之是要在一个较小的区域里显示一张大图的一部分。

以下使用jquery的实现,我采用的是背景图片定位。

HTML

<div id="glass">
  <div class="left">
    <div class="move-box"></div>
  </div>
  <div class="right"></div>
</div>

css

body, div {
  margin: 0;
  padding: 0;
}

#glass {
  height: 1000px;
}
.left {
  margin-left: 50px;
  margin-top: 50px;
  width: 400px;
  height: 225px;
  position: relative;
  background-color: #8b8b8b;
  background: url(../assets/images/sky_small.png) no-repeat;
  float: left;
}
.move-box {
  width: 100px;
  height: 56px;
  position: absolute;
  background-color: rgb(0, 0, 0, .5);
}
.right {
  width: 600px;
  height: 338px;
  background-color: #8b8b8b;
  background-image: url(../assets/images/sky-big.jpg);
  background-repeat: no-repeat;
  display: none;
  float: left;
  margin-left: 2px;
}

jquery

var $glass = $('#glass')
var $left = $glass.find('.left'), $right = $glass.find('.right')
var $moveBox = $glass.find('.move-box')

var moveBoxW = $moveBox.width(), moveBoxH = $moveBox.height()
var leftBoxW = $left.width(), leftBoxH = $left.height()
var rightBoxW = $right.width(), rightBoxH = $right.height()

var leftBoxX = $left.offset().left, leftBoxY = $left.offset().top

var scaleW = leftBoxW / moveBoxW, scaleH = leftBoxH / moveBoxH
var imgWidth = rightBoxW * scaleW, imgHeight = rightBoxH * scaleH

var imgSize = $right.css('background-size', imgWidth + 'px ' + imgHeight + 'px')
// 小图的mousemove事件
$left.mousemove(function (e) {
  var x = e.offsetX, y = e.offsetY
  var left = x - moveBoxW / 2, top = y - moveBoxH / 2
  if (left < 0) {
    left = 0
  }
  if (left > leftBoxW - moveBoxW) {
    left = leftBoxW - moveBoxW
  }
  if (top < 0) {
    top = 0
  }
  if (top > leftBoxH - moveBoxH) {
    top = leftBoxH - moveBoxH
  }
  
  $moveBox.css({left: left + 'px', top: top + 'px'})
  imgMove($right, left, top)
}).hover(function () {
  $right.css('display', 'block')
}, function () {
  $right.css('display', 'none')
})
// 滑块的mousemove事件
$moveBox.mousemove(function (e) {
  e.stopPropagation()
  var x = e.pageX, y = e.pageY
  var left = x - leftBoxX - moveBoxW / 2, top = y - leftBoxY - moveBoxH / 2
  if (left < 0) {
    left = 0
  }
  if (left > leftBoxW - moveBoxW) {
    left = leftBoxW - moveBoxW
  }
  if (top < 0) {
    top = 0
  }
  if (top > leftBoxH - moveBoxH) {
    top = leftBoxH - moveBoxH
  }
  
  $moveBox.css({left: left + 'px', top: top + 'px'})
  imgMove($right, left, top)
})
// 大图位置计算
var imgMove = function (ele, left, top) {
  var x = -rightBoxW / moveBoxW * left + 'px', y = -rightBoxH / moveBoxH * top + 'px'
  ele.css('background-position', x + ' ' + y)
}

  1. 效果2
    原图放大

这种放大方式看似在原图上放大,其实原理也是一样,只是现在大图跟着滑块在移动,同样通过滑块相对于小图的位置移动大图。

这里大图移动的位置,不能单纯的靠滑块拖动的位置计算,因为滑块的覆盖区域无法完全显示大图的该区域,因此这里需要以鼠标位置为基准调整大图位置,然后为了将图片显示在滑块中间位置,还需要根据滑块的宽高调整大图的位置。

以下是使用query实现,我采用的是背景图片定位法。

HTML

<div id="glass-two">
  <div class="lens"></div>
</div>

css

#glass-two {
  width: 600px;
  height: 338px;
  position: relative;
  background: url(../assets/images/sky-middle.png) no-repeat;
}
.lens {
  width: 100px;
  height: 100px;
  position: absolute;
  border-radius: 50%;
  background-image: url(../assets/images/sky-big.jpg);
  background-repeat: no-repeat;
  border: 1px solid #000;
  box-sizing: border-box;
}

jquery

var $glassTwo = $('#glass-two')
var $lens = $('.lens')

var glassTwoW = $glassTwo.width(), glassTowH = $glassTwo.height()
var lensW = $lens.width(), lensH = $lens.height()

var glassTowX = $glassTwo.offset().left, glassTowY = $glassTwo.offset().top

var imgWidth = 2000, imgHeight = 1225
$lens.css('background-size', `${imgWidth}px ${imgHeight}px`)

var scaleW = imgWidth / glassTwoW, scaleH = imgHeight / glassTowH

$glassTwo.mousemove(function (e) {
  var x = e.offsetX, y = e.offsetY
  var left = x - lensW / 2, top = y - lensH / 2
  if (left < 0) {
    left = 0
  }
  if (top < 0) {
    top = 0
  }
  if (left > glassTwoW - lensW) {
    left = glassTwoW - lensW
  }
  if (top > glassTowH - lensH) {
    top = glassTowH - lensH
  }

  $lens.css({left: left + 'px', top: top + 'px'})
  imgMove($lens, {W: imgWidth, H: imgHeight}, x, y)
})

$lens.mousemove(function (e) {
  e.stopPropagation()
  var x = e.pageX, y = e.pageY
  var pointX = x - glassTowX, pointY = y - glassTowY
  var left = pointX - lensW / 2, top = pointY - lensH / 2
  if (left < 0) {
    left = 0
  }
  if (top < 0) {
    top = 0
  }
  if (left > glassTwoW - lensW) {
    left = glassTwoW - lensW
  }
  if (top > glassTowH - lensH) {
    top = glassTowH - lensH
  }
  $lens.css({left: left + 'px', top: top + 'px'})
  imgMove($lens, {W: imgWidth, H: imgHeight}, pointX, pointY)
})

var imgMove = function ($moveBox, imgSize, left, top) {
  var moveBoxW = $moveBox.width(), moveBoxH = $moveBox.height()
  var x = -(scaleW * left - moveBoxW / 2), y = -(scaleH * top - moveBoxH / 2)
  if (x > 0) {
    x = 0
  }
  if (y > 0) {
    y = 0
  }
  if (x < -(imgSize.W - moveBoxW)) {
    x = -(imgSize.W - moveBoxW)
  }
  if (y < -(imgSize.H - moveBoxH)) {
    y = -(imgSize.H - moveBoxH)
  }
  $moveBox.css('background-position', `${x}px ${y}px`)
}