盒子模型

2019-10-11  本文已影响0人  田成力

js盒子模型

提供一些属性和方法用来描述当前盒子的样式的

client

clientWidth/clientHight

当前盒子可视区域的宽度和高度
可视区域:内容的宽高+padding
clientWidth=width+padding(left/right)
clientHight=height+padding(top/bottom)

和内容是否已出以及我们是否设置了overflow:hidden;没有关系
clientTopclientLeft
clientTop:盒子上边框的高度。
clientLeft:盒子左边框的宽度。
获取的结果就是border-width的值

通过js盒子模型属性获取的结果是不带单位的,而且只能是整数(他会自动四舍五入)
[图片上传失败...(image-44f587-1570785313950)]

获取当前页面一屏幕的宽度
document.documentElement.clientWidth||document.body.clientWidth

获取当前页面一屏幕的高度
document.documentElement.clientHeight||document.body.clientHeight

面试题:让一个盒子水平垂直居中?不知道盒子宽度和高度如何处理?

css:
知道盒子宽高时
[图片上传失败...(image-63d655-1570785313950)]
不知道盒子宽高时(不兼容ie低版本浏览器)
[图片上传失败...(image-57feda-1570785313950)]
使用css3的flex伸缩盒模型(不兼容)
[图片上传失败...(image-545a5c-1570785313950)]

js:获取当前盒子具体的left/top值
[图片上传失败...(image-e4c527-1570785313950)]

offset

offsetWidthoffsetHeight
在clientWidth和clientHeight的基础上加上盒子的边框即可
offsetWidth=width+padding(左右)+border(左右)=clientHeight+border(左右)
在真实项目中想获取一个盒子的宽度和高度,我们一般用offsetWidth而不是clientwidth,border也是盒子的一部分

offsetParent:参照物
offsetLeft:左偏移()
offsetTop:上偏移
offset系列(与溢出的内容无关)
偏移:
1.当前元素(边框以外)到参照物(边框以内)的距离
2.获取偏移量,当前元素不一定要设成定位元素。
3.当前元素找参照物的方式跟css里找参照物一样
4.默认的参照物是body,但实际上到窗口左边和上边的距离,body是文档的代理人,对body不要设置margin,float等属性
5.其他元素margin,float也会造成影响

scroll

scrollWidthscrollHeight

没有内容溢出的情况:获取的结果和clientWidth和clientHeight是一样的
有内容溢出的情况:真实内容的宽度或者高度(包含溢出的内容),加上左padding或者上padding。获取的结果是一个约等于值,每个浏览器由于对行高或者文字的渲染不一样,结果也是不一样的,是否设置了overflow对最后获取的结果也有影响
[图片上传失败...(image-cbc9b0-1570785313950)]
scrollLeft:横向滚动条卷出去的宽度
scrollTop:纵向滚动条卷出去的高度。
最大宽、高 等于= 整个文档(scrollwidth/height)宽、高,减去一屏的(clientwidth/height)宽、高
scrollTop=scrollheight-clientheight
scrollLeftscrollTop是13个js盒子模型相关属性里唯一两个可以赋值的属性,其他的11个属性只能获取不能赋值,

通过js盒模型属性获取值的特点

  • 1.若赋值是浮点数取得是整数部分,不会四舍五入
  • 2.13个js盒子模型获取的值都不带单位
  • 3.获取的结果都是复合样式值(好几个元素的样式组合在一起的值),如果只想获取单一样式值(例如只想获取padding)我们的盒子模型属性就操作不了了(这不能说没有用,真实项目中有时候我们就是需要获取组合的值来完成一些操作)

在js中获取元素具体的样式值

通过js盒子模型属性获取的结果都是盒子的组合样式值,不能直接获取某一个具体样式值,例如就想获得左padding
curEle.style.xxx
获取当前元素所有写在行内样式上的样式值
特殊:只有把样式写在行内样式上,才可以通过这种办法获取到(写在其他地方的样式获取不到)所以这种办法在真实项目中使用非常少。
window.getComputedStyle/currentStyle
只要当前元素在页面中显示出来我们就可以获取样式值,也就是获取所有经过浏览器计算过的样式
window.getComputedStyle:适用于标准浏览器,低版本IE浏览器不兼容,所以用curEle.currentStyle来获取需要的样式值。
[图片上传失败...(image-2ef0a6-1570785313950)]
[图片上传失败...(image-7fc29d-1570785313950)]
[图片上传失败...(image-a88a73-1570785313950)]
[图片上传失败...(image-daf800-1570785313950)]
[图片上传失败...(image-795616-1570785313950)]
[图片上传失败...(image-7a3dad-1570785313950)]
[图片上传失败...(image-5bba7a-1570785313950)]

设置元素样式属性
加单位(符合加单位)
[图片上传失败...(image-f40e17-1570785313950)]
[图片上传失败...(image-7f8b17-1570785313950)]
[图片上传失败...(image-4f8bef-1570785313950)]
加单位(排除不需要加单位的)
[图片上传失败...(image-2ab4d4-1570785313950)]

批量给当前元素设置css样式
[图片上传失败...(image-9180c7-1570785313950)]
必须和setCss一起使用。

封装css属性

 var css = function () {
        var len = arguments.length;
        fn = getCss;
        len > 3 ? fn = setCss : (len === 2 && Object.prototype.toString.call(arguments[1]) === '[object Object]' ? fn = setGroupCss : null);
        return fn.apply(this.arguments);}

考虑兼容性方法

考虑兼容性方法:

try{}catch(e){};
判断属性的方式"getComeputedStyle"in window,window.getComeputedStyle
检测数据类型,instanceOf,
Object.prototype.tostring.call
检测浏览器的方式
/MSIE[6-8]\.0/.test(navigator.userAgent)

拖拽

原理
[图片上传失败...(image-d94834-1570785313950)]

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="../../reset.min.css">
    <style type="text/css">
        html, body {
            height: 500%;
            -webkit-user-select :none;
        }
        .dialogMark {
            position: fixed;
            top: 0;
            left: 0;
            z-index: 100;
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, .3);
        }
        .diaLogBox {
            /*控制盒子在中间我们最好在js中实现,经过精密的计算,计算出具体的top和left而不是模糊的百分比这样我们在js中通过*/
            width: 200px;
            position: fixed;
            height: 300px;
            background: #FFF;
            z-index: 101;
            overflow: hidden;
        }
        .diaLogBox h3 {
            position: relative;
            padding: 0 10px;
            height: 50px;
            line-height: 50px;
            background: #DDD;
            border-bottom: 1px solid #aaaaaa;
            cursor: move;
        }
        .diaLogBox h3 i {
            position: absolute;
            right: 10px;
            top: 50%;
            margin-top: -10px;
            width: 20px;
            height: 20px;
            line-height: 20px;
            text-align: center;
            font-size: 16px;
            color: #E01D20;
            font-style: normal;
            font-family: "Microsoft JhengHei";
            background: lightgoldenrodyellow;
        }
    </style>

</head>
<body>
<!--dialog:模态框-->

<div class="dialogMark"></div>
<div class="diaLogBox" id="diaLogBox">
    <h3 class="title">大力出奇迹
         <i class="closeBtn">X</i>
    </h3>
    <div class="con">

    </div>
</div>
<script>
    let dialogRender = (function () {
        let diaLogBox = document.getElementById('diaLogBox');
        let title = diaLogBox.getElementsByTagName('h3')[0];
         let closeBtn=diaLogBox.getElementsByTagName('i')[0];
        let winW = document.documentElement.clientWidth || document.body.clientWidth;
        let winH = document.documentElement.clientHeight || document.body.clientHeight;

        let maxL = winW - diaLogBox.offsetWidth;
        let maxT = winH - diaLogBox.offsetHeight;
        let Down = function (ev) {
            console.log(1);
            ev = ev || window.event;
            //记录鼠标起始位置&&盒子的起始位置
            this.strX = ev.clientX;
            this.strY = ev.clientY;
            this.strL = diaLogBox.offsetLeft;
            this.strT = diaLogBox.offsetTop;
            //谷歌下不兼容,用setCapture,releaseCapture解决鼠标焦点丢失问题
            if(this.setCapture){
                this.onmousemove=Move;
                this.onmouseup=Up;
                this.setCapture();
                return;
            }


            //按下代表拖拽开始,会有鼠标丢失的问题,
//            this.onmousemove=Move;
//            this.onmouseup=Up;
            //解决方法:
            //用document解决鼠标焦点丢失问题
            //let _this = this;
            document.onmousemove = (ev) => {
                Move.call(this,ev);
            };
            document.onmouseup = (ev) => {
                Up.call(this,ev);
            }
        };
        let Move = function (ev) {
//            console.log(this);
            ev = ev || window.event;
            let curL = ev.clientX - this.strX + this.strL;
            let curT = ev.clientY - this.strY + this.strT;

            console.log(curT, ev.clientY, this.strY, this.strT);
            //边界处理
            curL = curL < 0 ? 0 : (curL > maxL ? maxL : curL);
            curT = curT < 0 ? 0 : (curT > maxT ? maxT : curT);
            console.log(curT);
            diaLogBox.style.left = curL + 'px';
            diaLogBox.style.top = curT + 'px';

            console.log(diaLogBox.style.top);
        };
        let Up = function (ev) {
           //谷歌下不兼容,用setCapture,releaseCapture解决鼠标焦点丢失问题
            if(this.setCapture){
                this.onmousemove=null;
                this.onmouseup=null;
                this.releaseCapture();
                return;
            }
            //用document解决鼠标焦点丢失问题
            document.onmousemove = null;
            document.onmouseup = null;
        };
        
  closeBtn.onclick=function () {
            diaLogBox.style.display='none';
        };

        return {
            init: function () {
                //让盒子处于页面中间
                diaLogBox.style.left = maxL / 2 + 'px';
                diaLogBox.style.top = maxT / 2 + 'px';
                title.onmousedown = Down;
            }
        }
    })();
    dialogRender.init();

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

弹性盒子

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="../../reset.min.css">
    <style type="text/css">
        html, body {
            width: 100%;
            height: 100%;
            overflow: hidden;
        }
        #box {
            position: absolute;
            width: 200px;
            height: 200px;
            top: 100px;
            left: 100px;
            background: red;
            cursor: move;
        }
    </style>
</head>
<body>

<div id="box">
</div>
<script src="发布订阅subscribe.js"></script>
<script>
    let box = document.querySelector('#box');
    let subscribeDown = new Subscribe();
    let subscribeMove = new Subscribe();
    let subscribeUp = new Subscribe();
    let down = function (ev) {
        this.strX = ev.clientX;
        this.strY = ev.clientY;
        this.strT = this.offsetTop;
        this.strL = this.offsetLeft;
        //解决鼠标焦点丢失
        this.MOVE = move.bind(this);
        this.UP = up.bind(this);
        document.addEventListener('mousemove', this.MOVE);
        document.addEventListener('mouseup', this.UP);
        subscribeDown.fire(this, ev);
    };
    let move = function (ev) {
        this.curL = ev.clientX - this.strX + this.strL;
        this.curT = ev.clientY - this.strY + this.strT;
        this.style.left = this.curL + 'px';
        this.style.top = this.curT + 'px';
        subscribeMove.fire(this, ev)
    };
    let up = function (ev) {
        //抬起清除事件
        document.removeEventListener('mousemove', this.MOVE);
        document.removeEventListener('mouseup', this.UP);
        subscribeUp.fire(this, ev);
    };
    box.onmousedown = down;

    subscribeMove.add((curEle, ev) => {
        if (!curEle.lastFly) {
            curEle.lastFly = curEle.offsetLeft;
            curEle.speedFly = 0;
            return;
        }
        curEle.speedFly = curEle.offsetLeft - curEle.lastFly;
        curEle.lastFly = curEle.offsetLeft;

    });
    subscribeUp.add((curEle, ev) => {
        let minL = 0;
        let maxL = document.documentElement.clientWidth - curEle.offsetWidth;
        let speed = curEle.speedFly;
        let dir = 'right';
        speed < 0 ? dir = 'left' : null;
        speed = Math.abs(speed);
        curEle.flyTimer = setInterval(() => {

            if (speed < 0.5) {
                clearInterval(curEle.flyTimer);
                return;
            }
            speed *= 0.98;
            let curL = curEle.offsetLeft;
            if (dir === 'right') {
                if (curL >= maxL) {
                    curEle.style.left = maxL + 'px';
                    dir = 'left';
                    return;
                }
                curL += speed;
            } else {
                if (curL <= minL) {
                    curEle.style.left = minL + 'px';
                    dir = 'right';
                    return;
                }
                curL -= speed;
            }
            curEle.style.left = curL + 'px';

        }, 17);
    });
    subscribeDown.add((curEle, ev) => {
        clearInterval(curEle.flyTimer);
        curEle.speedFly = 0;
        clearInterval(curEle.dropTimer);

    });
    subscribeUp.add((curEle, ev) => {
        let speed = 9.8;
        let minT = 0;
        let maxT = document.documentElement.clientHeight - curEle.offsetHeight;
        flag = 0;
        curEle.dropTimer = setInterval(() => {
            if (flag > 1) {
                clearInterval(curEle.dropTimer);
                return;
            }
            speed += 9.8;
            speed *= 0.98;
            let curT = curEle.offsetTop;
            curT += speed;
            if (curT >= maxT) {
                curEle.style.top = maxT + 'px';
                speed *= -1;
                flag++;return;
            }
            if (curT <= minT) {
                curEle.style.top = minT + 'px';
                speed *= -1;
                return;

            }
            curEle.style.top = curT + 'px';
            flag = 0;

        }, 17);
    });
    
</script>
</body>
</html>

上一篇下一篇

猜你喜欢

热点阅读