在vue中关于鼠标滑动事件

如下图,想要做一个鼠标在图片滑动,网状框跟随鼠标一起移动。遇到了很奇怪的问题,图1是正常的样子,但是当我鼠标再次移动的时候,就变成了图2。如果连续移动的话,网状框就会闪动,说白了就是第1秒网状框会跟着鼠标走,但是下一秒网状框就会回到左上角。如图3

图1图1

图2图2

网状框和商品图片都在一个div里,父级有的相对定位,网状框子级用的绝对定位。而且就此我还打印了网状框的left值,如图3

图3图3

下面是代码

模板

<div 
    class="goods_description_pic"
    @mouseenter="showcheckeddetailelement=true"
    @mouseleave="showcheckeddetailelement=false"
    @mousemove="checkeddetailproduct($event)">
    <img :src="productinformation.productimg">
    <span
        v-show="showcheckeddetailelement"
        @mouseenter="showcheckeddetailelement=true"
        class="goods_description_detailed_see"
        :style="{ left: followcheckedx+'px', top: followcheckedy+'px'}"></span>
</div>

js

export default{
    data(){
        return {
            followcheckedx: 0,
            followcheckedy: 0
        }
    },
    methods: {
        checkeddetailproduct (e){
            // offsetX是鼠标相对于窗口的距离
            // e.clientX - e.offsetX 标签距浏览器左端的距离
            this.followcheckedx = e.offsetX - 75;
            this.followcheckedy = e.offsetY - 75;
            if(this.followcheckedx>=150){
                this.followcheckedx=150;
            }
            if(this.followcheckedy>=150){
                this.followcheckedy=150;
            }
            if(this.followcheckedx<0){
                this.followcheckedx=0;
            }
            if(this.followcheckedy<0){
                this.followcheckedy=0;
            }
            console.log('left:' + this.followcheckedx)
            }
    }
}

肯定是有哪个地方疏忽了,谢谢大家帮我看一下,咱们一起学习进步

主要的问题已经找到了,如果在最外层的div上面加上mousemove事件,那么就相当于在img和span上分别加了mousemove事件,他们就会根据鼠标在自己的元素上进行重新定位,从而导致了第一秒在这里,下一秒又在另一个地方的情况。

问题已经解决,谢谢各位大神帮忙,我会尝试另外几种方法

阅读 15.9k
5 个回答

e.offsetX 确定是相对于窗口的距离么?
应该是相对于鼠标位置元素上层父级定位为相对或绝对的元素距离 没找到就相对于body
感觉你这offsetX在 相对于网状框和相对于div盒子来回切换了 所以在变

offsetXoffsetY是鼠标相对于事件源元素的X,Y坐标
(事件源:当前操作的那个元素就是事件源)

而此时在div中的还有imgspan,都会成为事件源,它就GG了,不知道以哪个为参考。

怎么办~~!把@mousemove事件改为@mousemove.self,再把img删掉(此时鼠标事件只针对div,不删掉的话,鼠标移到img上不会触发div的鼠标事件),然后就会发现“正常”了

但是!这也是有缺陷的,当鼠标在遮罩上小幅度移动的时候,遮罩并不会跟着走,因为span(遮罩)也会阻止鼠标事件的触发!(大幅度移动的时候鼠标接触div,span才会跟过去)

所以~鼠标跟随移动还是使用下面这种方法吧,给你写了例子,仅供参考,边缘判断还需要你自己写一下哦,

<div class='box'
     ref='box'
     @mousemove="handleMousemove">
     <img src="xxx" />
     <span class='mask'
           :style="{left: isLeft, top: isTop}"></span>
</div>
    handleMousemove() {
      // 图片离body的距离
      const boxL = this.$refs.box.offsetLeft
      const boxT = this.$refs.box.offsetTop
      // 75为半透明遮罩高度(宽度)的一半(假设它为正方形)
      this.isLeft = event.clientX - boxL - 75 + 'px'
      this.isTop = event.clientY - boxT - 75 + 'px'
    }

另外,希望你能知其然也知其所以然~(* ̄︶ ̄)

修改后的表述有问题。mousemove 是冒泡的,所以相当于接收到不同 target 发送来的事件,所以当你使用 offsetX offsetY 这种跟元素相关的属性,定位就会变化。于是,浮层就跑掉了,然后鼠标又回到原始图片上面,定位恢复,浮层又回来。如此反复。

解决方案有两个:

  1. 使用 MouseEvent.x 这种元素无关的属性,配合 div.getBoundingClientRect() 计算位置
  2. 禁掉不想触发事件的元素,比如 <span>,方法参考下面
span {
  pointer-events: none;
}

关于 pointer-events

问题已经解决,我的思路是再单拉出来一个div,宽度和高度都与图片窗口div一样,鼠标移动事件在单拉出来的div上设置。代码如下

模板

<div 
    class="goods_description_pic"
    @mouseenter="showcheckeddetailelement=true"
    @mouseleave="showcheckeddetailelement=false">
    <img 
        class="productimg" 
        :src="productinformation.productimg">
        <span
            v-show="showcheckeddetailelement"
            @mouseenter="showcheckeddetailelement=true"
            class="goods_description_detailed_see"
            :style="{ left: followcheckedx+'px', top: followcheckedy+'px'}"></span>
        <div 
            class="detial_see_wrap"
            @mousemove="checkeddetailproduct($event)">
        </div>
</div>

js

methods: {
    checkeddetailproduct (e){
        this.followcheckedx = e.offsetX -75;
        this.followcheckedy = e.offsetY - 75;
        /* 边缘判断*/
        if(this.followcheckedx>=150){
            this.followcheckedx=150;
        }
        if(this.followcheckedy>=150){
            this.followcheckedy=150;
        }
        if(this.followcheckedx<0){
            this.followcheckedx=0;
        }
        if(this.followcheckedy<0){
            this.followcheckedy=0;
        }
    }
}
新手上路,请多包涵

这个是只能用到鼠标滑动,鼠标滑动适不适用

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题