100%经典文章: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);

素材图: 

经典案例4:滑块拖动

<style>
        *{
            margin: 0;
            padding: 0;
        }
        .vol{
            width: 200px;
            margin-left: auto;
            margin-right: auto;
            height: 20px;
            padding-top: 10px;
            position: relative;
            background: #ccc;
        }
        .volJd{
            width: 100%;
            height: 10px;
            background: #858585;
        }
        .volJdColor{
            height: 10px;
            width: 100%;
            background: #731700;
        }
        .volBlock{
            position: absolute;
            width:20px;
            height: 20px;
            background: #4e1200;
            border-radius: 100%;
            left:100%;
            margin-left: -10px;
            top:50%;
            margin-top: -10px;
        }
        .text{
            text-align: center;
        }
    </style>

<div class="text" id="text">
    100%
</div>
<div class="vol">
    <div class="volJd" id="vol">
        <div class="volJdColor" id="volJdColor"></div>
        <div class="volBlock" id="volBlock"></div>
    </div>
</div>

<script>
        let text = document.getElementById("text");

        let vol = document.getElementById("vol");
        let volJdColor = document.getElementById("volJdColor");
        let volBlock = document.getElementById("volBlock");

        let getBfb = function(event){
            let x = event.clientX ;  // 鼠标在窗口中的x位置
            let volX = vol.getBoundingClientRect().x ;  // 标签距离窗口左边缘位置
            let disX = x - volX ;   // 鼠标到标签左边的距离。可能为负数,也可能超过 vol 的宽度。

            disX = Math.max(0,disX);   // dis 与 0 的最大值,防止dis的值小于 0 。
            disX = Math.min(200,disX); // dis 与 200 的最小值,防止 dis 的值大于200,也就是 vol的宽度。

            return  disX / 200 ;  // 返回 0-1 之间的小数
        };

        let setVol = function( event ){
           let  bfb =  Math.floor( getBfb(event)*10000)/100;  // 鼠标坐标相对vol 宽度的百分比
            volJdColor.style.width =  bfb +"%";
            volBlock.style.left = bfb+"%";
            text.innerHTML = bfb+"%"  ;
        };

        vol.addEventListener("mousedown",function(){
            document.addEventListener("mousemove",setVol);
        });
        document.addEventListener("mouseup",function(){
            document.removeEventListener("mousemove",setVol);
        });
       
</script>

觉得好的点个赞呗~~

 

 

 

  • 7
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值