JS如何获取鼠标在一个标签中的坐标

鼠标的坐标系统太重要了。利用鼠标坐标,可以做好多事情,比如游戏中的鼠标跟随,网页中利用鼠标位置做特效等等。

鼠标坐标的获取,分为两种情况来讨论。

1. 只有一个标签,没有子标签的情况

这种情况最简单,利用事件对象 event 的 offsetX 和 offsetY 属性可以获取鼠标在该标签中的坐标。

问:为什么要用事件对象?

答:因为鼠标坐标的获取往往跟鼠标事件有关联。

举个例子:

<style>
        .box{
            width: 400px;
            height: 400px;
            background: #ccc;
            margin-left: auto;
            margin-right: auto;
        }
 </style>
<div class="box" id="box">
    这个是内容
</div>

<script>
    let box = document.getElementById("box");
    box.addEventListener("click",function(event){
        console.info( event.offsetX, event.offsetY );
    });
</script>

鼠标点 box 的任意位置,都会在控制台中输出对应的坐标。

例子嘛,可以做一个 canvas 绘图板。有兴趣的朋友可以试试。

我的一个课程视频,里就说了这个案例:https://v.huya.com/play/291503364.html

2. 包含子标签的情况

利用事件对象 event 的 offsetX,offsetY 属性,如果目标里面有子标签,得到的就是相对子标签的坐标。

这就尴尬了~

<style>
        .box{
            width: 400px;
            height: 400px;
            background: #ccc;
            margin-left: auto;
            margin-right: auto;
        }
        .small{
            width: 200px;
            background: #666666;
            height: 200px;
            margin-left: auto;
            margin-right: auto;
        }
</style>
<div class="box" id="box">
    <div class="small" id="small">

    </div>
</div>

<script>
    let box = document.getElementById("box");
    box.addEventListener("click",function(event){
        // 如果点在了子标签上,得到的是相对子标签的坐标。
        console.info( event.offsetX, event.offsetY );
    });
</script>

解决方法:

为了得到在 box 里的坐标,可以利用 box.getBoundingClientRect() 获取box 在窗口中的位置。利用鼠标在窗口中的坐标,减去 box 在窗口的坐标就可以了。
先看下这个  getBoundingClientRect() 是个什么。

<div class="box" id="box">
    <div class="small" id="small">

    </div>
</div>

<script>
    let box = document.getElementById("box");
    box.addEventListener("click",function(event){
        let sPos = box.getBoundingClientRect();
        console.info( sPos );
        console.info( sPos.x, sPos.y ); // 输出标签左上角在窗口的坐标。
    },true);
</script>

getBoundingClientRect   ,字面含义:获取客户端(client,特指浏览器)形成的矩形区域。它可以获取标签在浏览器窗口中的坐标,以及边界值。

鼠标的在浏览器窗口中的坐标很简单,就是事件对象 event 的 clientX 和 clientY 属性。

那么获取鼠标在指定标签中的方式就是:

let box = document.getElementById("box");
box.addEventListener("click",function(event){
    let sPos = box.getBoundingClientRect();
    // 输出鼠标在标签中的坐标
     console.info( event.clientX-sPos.x, event.clientY-sPos.y ); 
},true);

3. 封装成一个函数

 let getMousePostion = function(box,event){
        /*
        * 返回鼠标在某个标签里的坐标,数组
        * box: 某个标签对象
        * event: 事件对象
        * */
        let sPos = box.getBoundingClientRect();
        return  [ event.clientX-sPos.x, event.clientY-sPos.y ];
    };

经典案例1:按住鼠标推动翻转图片

 先看效果:为了减少体积,缩小图片,降低了画面质量。

在 div#box 里按住鼠标移动,可以控制图片翻转。

详细代码:不解释了,看注释。

 <style>
        .box{
            width: 800px;
            height: 600px;
            position: relative;
            margin-left: auto;
            margin-right: auto;
            background: #f2f2f2;
            perspective: 500px;
        }
        .img{
            width: 242px;
            height: 309px;
            overflow: hidden;
            position: absolute;
            left:50%;
            top:50%;
            margin-left: -121px;
            margin-top:-154.5px;
            transition:all 0.2s;
        }
 </style>

<div class="box" id="box">
    <div class="img" id="img">
        <img id="pic" src="../images/meinv.png" width="242" height="309" alt="">
    </div>
</div>

<script>
    // 找标签
    let box = document.getElementById("box"); // 标签范围
    let img = document.getElementById("img"); //  图片div
    let pic = document.getElementById("pic"); //  图片img
    // 极端情况,鼠标从 box 左边到右边的距离,就让图片翻转 180deg。
    let degreeNum = 180;
    // 开始的鼠标 x 位置。
    let startPos = 0;
    // 开始图片的翻转度。
    let startDeg = 0;
    // 鼠标移动控制的旋转度
    let xDeg = 0;
    // 获取鼠标坐标函数
    let getMousePostion = function(box,event){
        /*
        * 返回鼠标在某个标签里的坐标,数组
        * box: 某个标签的 id
        * event: 事件对象
        * */
        let sPos = box.getBoundingClientRect();
        return  [ event.clientX-sPos.x, event.clientY-sPos.y ];
    };
    // 鼠标移动事件处理
    let mouseMoveFun = function(event){
        let nowPos = getMousePostion(box,event)[0];
        let disX = nowPos - startPos ;
        // 鼠标控制的旋转度:鼠标移动距离 / box宽度 * 180
            xDeg = disX / box.offsetWidth * degreeNum;
        // 图片旋转:起始度+鼠标控制的旋转度
       img.style.transform = `rotateY(${startDeg+xDeg}deg)`;
    };

    // 鼠标按下事件:开始拖动
    box.addEventListener("mousedown",function(event){
        startPos = getMousePostion(box,event)[0]; // 按下那一瞬间的鼠标坐标
        box.addEventListener("mousemove",mouseMoveFun);
    });
    // 鼠标松开,取消鼠标移动事件,且重新设置图片旋转的起始度。
    box.addEventListener("mouseup",function(event){
        startDeg = startDeg+xDeg ;
        box.removeEventListener("mousemove",mouseMoveFun);
    });

    // 防止图片被鼠标拖拽
    pic.addEventListener("dragstart",function(event){
        event.preventDefault();
    });
</script>

经典案例2:鼠标滑动控制图片的倾斜度

鼠标在 div#box 里滑动,图片展示对应的倾斜度,不需要按住鼠标。

  <style>
        .box{
            width: 800px;
            height: 600px;
            position: relative;
            margin-left: auto;
            margin-right: auto;
            background: #f2f2f2;
            perspective: 500px;
        }
        .img{
            width: 242px;
            height: 309px;
            overflow: hidden;
            position: absolute;
            left:50%;
            top:50%;
            margin-left: -121px;
            margin-top:-154.5px;
            transition:all 0.2s;
        }

</style>

让图片在 -60deg 到 60deg 之间倾斜。
<div class="box" id="box">
    <div class="img" id="img">
        <img src="../images/meinv.png" width="242" height="309" alt="">
    </div>
</div>

<script>
    let box = document.getElementById("box");
    let img = document.getElementById("img");
    let boxCenter = [400,300];  //  box 中心点。
    let degreeNum = 60;  // 图片的倾斜度

    let getMousePostion = function(box,event){
        /*
        * 返回鼠标在某个标签里的坐标,数组
        * box: 某个标签的 id
        * event: 事件对象
        * */
        let sPos = box.getBoundingClientRect();
        return  [ event.clientX-sPos.x, event.clientY-sPos.y ];
    };
    box.addEventListener("mousemove",function(event){
        let mousePos = getMousePostion(box,event); // 获取鼠标在 box 里的坐标,数组。
        let disX = mousePos[0]-boxCenter[0];
        let disY = mousePos[1]-boxCenter[1];

        let xDeg = disX / boxCenter[0] * degreeNum;
        let yDeg = disY / boxCenter[1] * degreeNum;
        console.info( xDeg );
        img.style.transform = `rotateY(${xDeg}deg)  rotateX(${yDeg}deg)`;
    });
</script>

经典案例3:伪3D的banner

结合以上知识,可以做一个伪 3D 的banner。

原理:是利用鼠标距离banner 中点的位置,来控制各个元素的位移(translate)和倾斜度(rotateY)。

HTML标签:

<div class="banner"   id="banner">
    <img class="ren"  id="ren" src="images/renwu.png" width="281" height="430" alt="">
    <div class="text" id="text">WHITE MOUSE</div>
    <img class="bg"   id="bg" src="images/bannerbg.jpg" alt="">
</div>

CSS:各个元素重叠,所以 banner 相对定位,banner 里各个元素绝对定位。


    *{
        margin: 0;
        padding: 0;
    }
    .banner{
        width: 1200px;
        height: 430px;
        overflow: hidden;
        margin-left: auto;
        margin-right: auto;
        position: relative;
        transform-style: preserve-3d;  /* 3D 效果,写在容器上,把内部变成 3D 空间 */
        perspective: 500px;            /* 3D 透视,写在容器上 */
        background: #ccc;
    }
    .banner img{
        transition:all 0.2s;
    }
    .bg{
        transform: scale(1.1);
    }
    .ren{
        position: absolute;
        left:50%;
        top:50%;
        margin-left: -240px;
        margin-top: -214px;
        z-index: 2;
        transform: translateZ(50px);
    }
    .text{
        z-index: 1;
        width: 1200px;
        height: 200px;
        line-height: 150px;
        font-size: 150px;
        text-align: center;
        position: absolute;
        left:50%;
        top:50%;
        margin-left: -600px;
        margin-top: -100px;
        color: #fff;
        text-shadow: -10px 5px 0 rgba(0,0,0,0.5);
        transform: translateZ(20px);
    }
// 找标签
let banner = document.getElementById("banner");
let ren = document.getElementById("ren");
let text = document.getElementById("text");
let bg = document.getElementById("bg");
// 相关数据
let bannerCenter = [600,215];  // 中心点
let deg = 2;  // 元素最多倾斜 2 度。
let weizhi = [20,10,5]; // ren ,text ,bg。近中远,近点的内容移动距离大点。
// 获取鼠标坐标函数
let getMousePosition = function(box,event){
    let pos = box.getBoundingClientRect();
    return [ event.clientX - pos.x, event.clientY - pos.y ];
};

let moveFun = function(event){
    let mousePosX = getMousePosition(banner, event)[0];
    // 关键数据:鼠标跟中点的水平距离
    let disX = mousePosX - bannerCenter[0];
    // 关键数据:鼠标跟中点的水平距离 / banner宽度一半  。
    // 利用这个比例来计算各个元素的倾斜度和位移。
    let  weizhiBiLi= disX / bannerCenter[0];
    ren.style.transform = `translateZ(50px)  rotateY(${deg*weizhiBiLi}deg)    translateX(${weizhiBiLi*weizhi[0]}px)`;
    text.style.transform = `translateZ(20px) rotateY(${deg*weizhiBiLi}deg)    translateX(${weizhiBiLi*weizhi[1]}px)`;
    bg.style.transform   = `scale(1.1)       rotateY(${deg*weizhiBiLi}deg)    translateX(${weizhiBiLi*weizhi[2]}px)`;
};
// 添加监听事件
banner.addEventListener("mousemove",moveFun);

素材图: 

觉得好的点个赞呗~~

发布了86 篇原创文章 · 获赞 146 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/weixin_42703239/article/details/105001088