为什么不直接用offsetLeft

来源:4-7 video-javascript(4)

夜魇丶

2019-11-28 20:57:12

<!doctype html>
<html>
<head>
    <meta charset="utf-8">
    <title></title>
    <style type="text/css">
*{margin: 0;padding: 0;list-style: none;}
.outerNode{width: 540px;height: 332px;position: absolute;left: 50%;top: 50%;margin: -166px 0 0 -270px;box-shadow: 0 0 4px #5b606d;}  
.outerNode .videoNode{
    width: 540px;height: 305px;float: left;
    background: black;
}     
.outerNode .controlsNode{
    width: 540px;height: 27px;float: left;background: url(images/ctrs_bg.gif) repeat-x;
}

.outerNode .controlsNode .playNode{
    float: left;width: 15px;height: 17px;margin: 6px 0 0 14px;
    background: url(images/playNode.png) no-repeat;cursor: pointer;
}
.outerNode .controlsNode .pauseNode{
    float: left;width: 15px;height: 17px;margin: 6px 0 0 14px;
    background: url(images/pause.png) no-repeat;cursor: pointer;
}


.outerNode .controlsNode .loadNode{width: 267px;height: 10px;margin: 9px 0 0 14px;float: left;background: url(images/load_bg.png) repeat-x;position: relative;}
.outerNode .controlsNode .loadNode .lineNode{
    width: 0%;height: 7px;position: absolute;left: 0;top: 1px;
    background: url(images/line_bg.png) repeat-x;

}
.outerNode .controlsNode .loadNode .lineNode .lineRight{
    width: 2px;height: 100%;position: absolute;right: 0;top: 0;
    background: url(images/line_r_bg.png) no-repeat;
}

.outerNode .controlsNode .loadNode .loadLeft{
    height: 100%;width:3px ;position: absolute;left: 0;top: 0;
    background: url(images/left_bg.png) no-repeat;z-index: 4;
}
.outerNode .controlsNode .loadNode .loadRight{
    height: 100%;width:3px ;position: absolute;right: 0;top: 0;
    background: url(images/right_bg.png) no-repeat;
}
.outerNode .controlsNode .loadNode .crlNode{width: 17px;height: 17px;background: url(images/crl_bg.png);position: absolute;left: -8.5px;top: -3.5px;cursor: pointer;z-index: 5;}

.outerNode .controlsNode .timeNode{
    float: left;width: 75px;height: 10px;margin: 9px 0 0 9px;
}
.outerNode .controlsNode .timeNode span{font-size:10px;float: left;line-height: 10px;color: white; }
.outerNode .controlsNode .volumeNode{
    width: 17px;height: 16px;float: left;margin: 5px 0 0 6px;
    background: url(images/volume_bg.png);
}
.outerNode .controlsNode .volumeLine{
    height: 8px;width: 61px;float: left;margin: 10px 0 0 4px;
    background: url(images/volumeLine_bg.png) repeat-x;position: relative;
}
.outerNode .controlsNode .volumeLine .v_left{
    width: 3px;height:100%;position: absolute;left: 0;top: 0;background: url(images/v_left.png) no-repeat;
}
.outerNode .controlsNode .volumeLine .v_right{
    width: 3px;height:100%;position: absolute;right: 0;top: 0;background: url(images/v_right.png) no-repeat;
}
.outerNode .controlsNode .volumeLine .v_DragNode{width: 15px;height: 13px;position: absolute;left: -2.5px;top: -3.5px;background: url(images/vo_d.png) no-repeat;cursor: pointer;}
.outerNode .controlsNode .fullNode{
    width:15px;height:17px;float: left;margin: 6px 0 0 35px;
    background: url(images/full_bg.png) no-repeat;cursor: pointer;
    transition: 0.7s;
}
.outerNode .controlsNode .fullNode:hover{
    background: url(images/full_hover_bg.png) no-repeat;
}

    </style>

</head>
<body>
    <!-- 最外层的元素 -->
    <div class='outerNode'>
        <!-- video元素 -->
        <video class='videoNode' src='data/imooc.mp4' poster="data/poster.jpg"></video>
        <!-- 控制器的元素 -->
        <div class='controlsNode'>
            <!-- 控制播放暂停的按钮 -->
            <div class='playNode'></div>
            <!-- video的进度条 -->
            <div class='loadNode'>
                <div class='loadLeft'></div>
                <div class='loadRight'></div>
                <!-- 拖动进度条的按钮 -->
                <div class='crlNode'></div>
                <!-- 真正的进度条 -->
                <div class='lineNode'>
                    <div class='lineRight'></div>
                </div>
            </div>
            <!-- 时间的元素 -->
            <div class='timeNode'>
                <span class='now'>00:00</span>
                <span> - </span>
                <span class='all'>4:30</span>
            </div>
            <!-- 声音的标志 -->
            <div class='volumeNode'></div>
            <!-- 声音的条 -->
            <div class='volumeLine'>
                <div class='v_left'></div>
                <div class='v_right'></div>
                <div class='v_DragNode'></div>
            </div>
            <!-- 全屏的按钮 -->
            <div class='fullNode'></div>
        </div>
    </div>
<script type="text/javascript">
    var playNode = document.getElementsByClassName('playNode')[0];
    var videoNode = document.getElementsByClassName('videoNode')[0];
    var fullNode = document.querySelector('.fullNode');
    var nowNode = document.querySelector('.now');
    var allNode = document.querySelector('.all');
    var lineNode = document.querySelector('.lineNode');
    var crlNode = document.querySelector('.crlNode');
    // console.log(lineNode);

    var playBln = true;
    playNode.onclick = function(){
        //传统的通过布尔值去改变classname的方法
        playBln = !playBln;
        if(playBln == false){
            this.className = 'pauseNode';
            videoNode.play();
            // playBln = false;
        }else{
            this.className = 'playNode';
            videoNode.pause();
            // playBln = true;
        }
    };

    fullNode.onclick = function(){
        if(videoNode.webkitRequestFullscreen){
            videoNode.webkitRequestFullscreen();
        } else if(videoNode.mozRequestFullScreen){
            videoNode.mozRequestFullScreen();    
        } else {
            videoNode.requestFullscreen();
        }
    };

    videoNode.addEventListener('canplay',function(){
        var needTime = parseInt(videoNode.duration);
        var second = needTime % 60;
        var minue = parseInt(needTime / 60);
        var totaltime = toDou(minue) + ":" + toDou(second);
        allNode.innerHTML = totaltime;
        // console.log(total);
    });

    function toDou(time){
        return time < 10 ? "0" + time : time;
    }

    videoNode.addEventListener('timeupdate',function(){
        // console.log(videoNode.currentTime/videoNode.duration * 100);
        lineNode.style.width = (videoNode.currentTime/videoNode.duration) * 100 + '%';
        crlNode.style.left = lineNode.offsetWidth - 8.5 + 'px';
        var needTime = parseInt(videoNode.currentTime);
        var second = needTime % 60;
        var minue = parseInt(needTime / 60);
        var totaltime = toDou(minue) + ":" + toDou(second);
        nowNode.innerHTML = totaltime;
        // console.log(total);
    });

    // 拖拽进度条按钮
    crlNode.onmousedown = function(e){
        var ev = e || event;
        var l = ev.clientX - this.offsetLeft;
        // console.log('ev.clientX=' + ev.clientX);
        // console.log('l=' + l);
        document.onmousemove = function(e){
            var ev = e || event;
            var needX = ev.clientX - l;
            // console.log('needX=' + this.needX);
            console.log('crlNode.offsetLeft=' + crlNode.offsetLeft);
            needX = needX < -8.5 ? -8.5 : needX;
            console.log('needX=' + needX);
            crlNode.style.left = needX + 'px';
        };
        document.onmouseup = function(e){
            document.onmousemove = document.onmouseup = null;
        }
    }

</script>
</body>
</html>


我看了其它同学的回答还是没想明白。我打印出来两个之间的数值都差不多。

1. 有一个很重要的地方就是offsetLeft究竟是距离父元素的距离还是距离浏览器视口左侧的距离。

http://img.mukewang.com/climg/5ddf7fa60908f86608540080.jpg

http://img.mukewang.com/climg/5ddf7fbb096f10fc08550092.jpg


2. 我看得非常懵…=

var l = ev.clientX - this.offsetLeft;

var needX = ev.clientX - l;

单看这两个式子,needX的值应该和this.offsetLeft值相等吧。我为什么要那么费力去求needX的值。

http://img.mukewang.com/climg/5ddf823b0997ad4802760182.jpg

3. 我拖动鼠标的同时offsetLeft值应该也会变化,我把变化后的值赋给crlNode.style.left为什么不行。

var needX = ev.clientX - l; (因为这里ev.clientX - l 和 this.offsetLeft 相等,所以我才有了下面的考虑)

crlNode.style.left = needX + 'px';

这么写可以。

但是

crlNode.style.left = crlNode.offsetLeft + 'px';
这么写不行。


4. 和第三问类似。

我上面也解释到,这两个式子的取值应该是一样的。因为鼠标的距离减去父元素距离浏览器视口左侧的距离就是那个视频进度点与父元素的距离。所以我得出了下面的式子。

var needX = ev.clientX - l;

crlNode.style.left = needX + 'px';


var needX = crlNode.offsetLeft;
crlNode.style.left = crlNode.offsetLeft + 'px';

第一个式子结果可以拖动,第二个不能拖动。我想不明白,难道是因为ev.clientX的值会因为鼠标的移动实时变化,而offsetLeft不会因为视频控制点的变化而实时变化吗?


表达的很啰唆…也不知道老师能不能看不明白,辛苦解答。

写回答

1回答

好帮手慕慕子

2019-11-29

同学你好,对于你的问题解答如下:

  1. 计算当前元素距离有定位属性(static除外)的先辈元素的距离,如果所有的先辈元素都没有设置定位属性,那么计算的就是当前元素距离窗口左侧的距离。

    示例:

    http://img.mukewang.com/climg/5de07fbc099107d809380889.jpg

    打印结果:给grand设置了相对定位,那么,此时打印son.offsetLeft就是距离先辈元素的距离

    http://img.mukewang.com/climg/5de07fd009ecd19701300028.jpg

    如果都不设置定位

    http://img.mukewang.com/climg/5de07fed0911b82b04060557.jpg

    打印结果:  先辈元素没有定位属性,那么offset计算的就是距离窗口左侧的距离

    http://img.mukewang.com/climg/5de0804209809f1301000032.jpg

  2. 第一个是在鼠标按下的时候,获取按钮此时距离最左侧的距离, needX表示定位的left值, 也就是按钮移动的距离, 在鼠标移动的过程中clientX值是变化的。可以参考下图注释理解:

    http://img.mukewang.com/climg/5de0816709b45e2f10520447.jpg

  3. 从第二问的解答中,可以看出来,ev.clientX - l 和 this.offsetLeft是不相等的。

    var l = ev.clientX-this.offsetLeft获取的是鼠标点击那一瞬间的值(可以理解为初始值)

    var needX = ev.clinetX - l 表示的是鼠标移动过程中的值,ev.client是不断改变的

    所以你直接写crlNode.style.left = crlNode.offsetLeft + 'px'的值是不可以的

  4. 我们要明白,只有按钮的位置改变了,才可以获取到改变后的offsetLeft值, 这里如果通过crlNode.offsetLeft直接设置按钮的left值,按钮没有发生移动,offsetLeft就是一个固定的值,所以不可以这样写。

    结合第二条和第三条的解答去理解,需要在鼠标的移动过程中,通过鼠标距离窗口左侧的距离减去初始值,才可以设置按钮的left值,让按钮的位置发生改变

如果帮助到了你,欢迎采纳,祝学习愉快~


1

0 学习 · 6815 问题

查看课程