1.商品详情-图片放大镜

image.png

1.1左侧遮罩的鼠标跟随效果

1.1.1准备待移动的遮罩容器

  1. <div class="middle" ref="target">
  2. <img :src="images[currIndex]" alt="">
  3. + <div class="layer"></div>
  4. </div>
  1. .middle {
  2. width: 400px;
  3. height: 400px;
  4. + position: relative;
  5. + cursor: move;
  6. + .layer {
  7. + width: 200px;
  8. + height: 200px;
  9. + background: rgba(0,0,0,.2);
  10. + left: 0;
  11. + top: 0;
  12. + position: absolute;
  13. + }
  14. }

1.1.2鼠标跟随
在@vueuse中,有一个工具方法:useMouseInElement

  1. // 导入 useMouseInElement
  2. import { useMouseInElement } from '@vueuse/core'
  3. setup(){
  4. // 以哪个元素为基准,计算鼠标的位置
  5. const target = ref(null)
  6. const { elementX, elementY, isOutside } = useMouseInElement(target)
  7. return { currIndex, target, elementX, elementY, isOutside }
  8. }
  1. 测试:{{elementX}}, {{elementY}}, {{isOutside}}
  2. <div class="middle" ref="target">

1.2计算相对位置

image.png

  1. setup() {
  2. const target = ref(null)
  3. const { elementX, elementY, isOutside } = useMouseInElement(target)
  4. const layerStyle = reactive({ top: '0px', left: '0px'})
  5. watch([elementX,
  6. elementY,
  7. isOutside], () => {
  8. // top, left 用来确定绝对定位下 遮罩元素 的位置
  9. let top = elementY.value - 100
  10. let left = elementX.value - 100
  11. // 给遮罩元素赋值位置
  12. layerStyle.top = top + 'px'
  13. layerStyle.left = left + 'px'
  14. })
  15. return {
  16. target,
  17. elementX,
  18. elementY,
  19. isOutside,
  20. layerStyle
  21. }
  22. }

使用

  1. <div class="middle" ref="target">
  2. <img :src="images[currIndex]" alt="">
  3. <!-- 放大镜遮罩 -->
  4. <div class="layer" :style="layerStyle"></div>
  5. </div>

1.3位置计算修正

image.png

  1. // 遮罩元素的位置不能移出 中图 所在范围
  2. if (top > 200) top = 200
  3. if (top < 0) top = 0
  4. if (left > 200) left = 200
  5. if (left < 0) left = 0

1.4右侧放大效果

  1. <div class='goods-image'>
  2. + <div class="large" :style="{backgroundImage: `url(${images[currIndex]})`}"></div>
  3. <!-- 中图 -->
  4. <div class="middle" ref="target"> 省略其他...</div>
  5. <!-- 小图 -->
  6. <ul class="small">省略其他...</ul>
  7. </div>

样式

  1. .goods-image {
  2. width: 480px;
  3. height: 400px;
  4. position: relative;
  5. display: flex;
  6. + z-index: 500;
  7. + .large {
  8. + position: absolute;
  9. + top: 0;
  10. + left: 412px;
  11. + width: 400px;
  12. + height: 400px;
  13. + box-shadow: 0 0 10px rgba(0,0,0,0.1);
  14. + background-repeat: no-repeat;
  15. + background-size: 800px 800px;
  16. + background-color: #f8f8f8;
  17. + }

3.5为啥可以放大?

放大两倍:
图片本身是800 800; div是400 400; background-size:800px 800px


3.6移动放大区域

修改:background-position-x,background-position-y

  1. import { reactive, ref, watch } from 'vue'
  2. import { useMouseInElement } from '@vueuse/core'
  1. const target = ref(null)
  2. const { elementX, elementY, isOutside } = useMouseInElement(target)
  3. const layerStyle = reactive({
  4. top: '0px',
  5. left: '0px'
  6. })
  7. const largeStyle = reactive({
  8. 'background-position-x': '0px',
  9. 'background-position-y': '0px'
  10. })
  11. watch([elementX,
  12. elementY,
  13. isOutside], () => {
  14. // 省略其他...
  15. // 给大图设置background-position的值,以移动位置的效果
  16. largeStyle['background-position-x'] = -2 * left + 'px'
  17. largeStyle['background-position-y'] = -2 * top + 'px'
  18. })
  19. return {
  20. // 省略其他...
  21. largeStyle
  22. }

在setup中返回largeStyle,模板使用它

  1. <div class="large" :style="{backgroundImage:`url(${images[currIndex]})`},...largeStyle}"></div>
  2. <div class="middle" ref="target">
  3. <img :src="images[currIndex]" alt="">
  4. <div class="layer" :style="layerStyle"></div>
  5. </div>

3.7鼠标进入显示,移出隐藏

image.png
useMouseInElement就已经返回一个响应式数据isOutSide,它就可以表示当前鼠标是否进入,离开了元素。
注意取反!!!

  1. <!-- 放大镜的图片位置 -->
  2. <div v-show="!isOutside" class="large" :style="{backgroundImage: `url(${images[curIdx]})`, ...bgPosition}"></div>
  3. <!-- 左边的大图 -->
  4. <div class="middle" ref="target">
  5. <img :src="images[curIdx]" alt="">
  6. <!-- 放大镜的遮罩层 -->
  7. <div v-show="!isOutside" class="layer" :style="layerStyle"></div>
  8. </div>