原生js实现 兼容常规pc、大屏、移动端 适配方案

1、设计稿

1)pc设计稿为19201080的可视化大屏,16:9比例设计
2)大屏设计稿3584
1152的可视化大屏,28:9比例设计
3)移动端设计稿 宽750的可视化大屏

2、适配不同屏幕

1)pc要兼容不同分辨率下的屏幕,注意这里说的是往下兼容 兼容1k以下的 不能出现滚动条 使用scale
2)大屏比例为28:9,在项目开发中,可以按照1680:540 达到28:9的效果 不能出现滚动条 使用rem
3)移动端兼容,以750为标准实现适配 使用rem

3、实现思路:

1)pc可以根据vw、vh去实现

<style scoped lang="scss">
@function vw($px) {
    @return ($px/1920) * 100vw;
}
body {
	width:vw(1920)
}
</<style>

问题:在echats中,当在小屏幕的时候,图表的字体会比ui稿上的大,这时候你又要把字体在js里面再进行一步转换

// 字体转换
function toFontSize(px){
    let vw = px / 1920;
    let htmlWidth = document.documentElement.clientWidth || document.body.clientWidth;
    return htmlWidth * vw
}

2)rem
rem (font size of the root element), 是 css3 的引入的一个大小单位。即相对于根元素的 font-size 值的大小。所谓根元素在网页里一般就是 html。

问题:在echats中,当在小屏幕的时候,图表的字体会比ui稿上的大,这时候你又要把字体在js里面再进行一步转换

3)缩放scale
浏览器body设置为设计稿宽高即1920*1080, 动态根据实际宽高对body的width,height进行缩放,从而实现内容缩放
采用scale方案,字体不受浏览器最小字体限制,可以自由绽放到该分辨率下对应比例

4)根据不同屏幕切换显示 不同页面
pc和大屏的页面布局结构一致,所以更换className去实现切换
移动端与pc、大屏的页面布局都不一致,所以根据js判断当前是否为移动设备进行显示切换

4、简单实现代码
<!DOCTYPE html>
<html>
    <head><meta name="viewport" content="width=device-width,initial-scale=1.0,maixmum-scale=1.0,minimum-scale=1.0,user-scalable=no"></head>
    <body>
        <!-- 大屏 + pc 页面 -->
        <div class="pc" id="main">
            <div class="column">
                <div class="bk"></div>
                <div class="bk"></div>
                <div class="bk"></div>
            </div>
            <div class="column">
                <div class="big-bk"></div>
                <div class="big-bk"></div>
            </div>
            <div class="column">
                <div class="bk"></div>
                <div class="bk"></div>
                <div class="bk"></div>
            </div>
        </div>
        <!-- 移动端页面 -->
        <div class="mobile">
            <div class="column">
                <div class="bk"></div>
                <div class="bk"></div>
                <div class="bk"></div>
                <div class="bk"></div>
            </div>
        </div>
    </body>

    <script>
        var bodyStyle = document.createElement('style')  
        var docWidth,docHeight;        
        var designWidth,designHeight;

        // 屏幕缩放实现
        function refreshScale(){
            bodyStyle.innerHTML=`body{width:${designWidth}px; height:${designHeight}px!important;}`
            document.documentElement.firstElementChild.appendChild(bodyStyle)
            document.getElementById('main').style='display:flex'
            document.getElementsByClassName('mobile')[0].style='display:none'
            
            var widthRatio = docWidth / designWidth,
                heightRatio = docHeight / designHeight;
            document.body.style = `transform:scale(${widthRatio},${heightRatio});transform-origin:left top;`;
            // 应对浏览器全屏切换前后窗口因短暂滚动条问题出现未占满情况
            setTimeout(function(){
                var lateWidth= document.documentElement.clientWidth,
                    lateHeight = document.documentElement.clientHeight;
                if( lateWidth === docWidth ) return;

                widthRatio = lateWidth / designWidth
                heightRatio = lateHeight / designHeight
                document.body.style = "transform:scale(" + widthRatio + "," + heightRatio + ");transform-origin:left top;"
            },0)
        }

        // 清除scale
        function clearScale(){
            // 清除pc样式
            bodyStyle.innerHTML=``
            document.documentElement.firstElementChild.appendChild(bodyStyle)
            document.body.style="transform:none;transform-origin:none"
        }

        // 初始化
        function init(){    
            // 获取当前屏幕可视区域大小
            docWidth = document.documentElement.clientWidth; 
            docHeight = document.documentElement.clientHeight;        
            // 判断是否是移动设备
            if(/Android|webOS|iPhone|iPad|iPod|BlackBerry|Windows Phone/i.test(navigator.userAgent)){              
                mobilePage();
            }else{ 
                let mainClass =  document.getElementById('main').classList;    
                if(docWidth == 1680 || docWidth == 3584){ // 模拟大屏
                    designWidth = docWidth;
                    designHeight = docWidth / 28 *9;
                    mainClass.add('large');
                    mainClass.remove('pc');                
                    largePage();
                }else{  // pc
                    designWidth = 1920;
                    designHeight = 1080;
                    mainClass.add('pc');
                    mainClass.remove('large');                   
                    refreshScale()
                }            
            }
        }

        // 大屏设置 rem 函数
        function setRem (designSize) {          
            // 基准大小
            baseSize = 100;
            let basePc = baseSize / designSize; // 表示1680的设计图,使用100PX的默认值
            let vW = window.innerWidth; // 当前窗口的宽度
            
            let rem = vW * basePc; // 以默认比例值乘以当前窗口宽度,得到该宽度下的相应font-size值
            document.documentElement.style.fontSize =  rem + "px";
        }

        // 大屏页面
        function largePage(){
            clearScale();
            document.getElementById('main').style='display:flex'
            document.getElementsByClassName('mobile')[0].style='display:none'
            // 大屏 设置 rem 函数
            let designSize = 1680;
            setRem(designSize);
        }

        // 移动端页面
        function mobilePage(){
            clearScale()
            // 是移动设备 展示移动设备页
            document.getElementById('main').style='display:none'
            document.getElementsByClassName('mobile')[0].style='display:flex'
            // mobile 设置 rem 函数
            let designSize = 750;
            setRem(designSize);
        }
        
        // 初始化
        init();

        // 监听前进/后退以及load事件触发
        window.addEventListener("pageshow", function (e) {
            if (e.persisted) { // 浏览器后退的时候重新计算
                init()
            }
        }, false);

        // 监听屏幕缩放
        window.addEventListener("resize",function(){
            init()
        }, false);
    </script>
</html>

<style>
    html {
        width: 100%;
        height: 100%;
    }
    body{      
        margin:0px;
        transform: translate3d(0,0,0)  
    }
    /* pc */
    .pc {
        width: 1860px;
        height: 1020px;
        display: flex;
        flex-direction: row;
        justify-content: space-between;
        padding:30px;
    }
    .pc .column {
        display: flex;
        flex-direction: column;
        justify-content: space-between;
    }
    .pc .bk {
        width: 450px;
        height: 350px;
        border: #000 solid 1px;
        margin-top: 30px;
    }

    .bk:first-child{
        margin-top: 0px;
    }
    .pc .big-bk {
        width: 850px;
        height: 550px;
        border: #000 solid 1px;
        margin: 30px 30px 0px 30px;
    }

    .big-bk:first-child {
        margin-top: 0px;
    }

    /* 移动端 */
    .mobile {
        display: flex;
        flex-direction: column;
        align-items: center;
    }
    .mobile .bk {
        width: 6.9rem;
        height: 2rem;
        border: #000 solid 0.01rem;
        margin-top: 0.3rem;
    }

    /* 大屏 */
    .large {
        width: 16.2rem;
        height: 4.6rem;
        display: flex;
        flex-direction: row;
        justify-content: space-between;
        padding:0.3rem;
    }

    .large .column {
        display: flex;
        flex-direction: column;
        justify-content: space-between;
    }
    .large .bk {
        width: 4.5rem;
        height: 1.5rem;
        border: #000 solid 1px;
        margin-top: 0.3rem;
    }
    .large .big-bk {
        width: 6.5rem;
        height: 2.5rem;
        border: #000 solid 1px;
        margin: 0.3rem 0.3rem 0rem 0.3rem;
    }
</style>

pc兼容 参考:https://blog.csdn.net/sophie_u/article/details/109582687

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值