echarts自适应、响应式(媒体查询、适配rem)

1,523 阅读2分钟

echarts自适应、响应式(适配rem)

 本文正在参加「金石计划」

响应式:能够适配不同的设备,比如:PC、平板、手机。
自适应:能够适配不同分辨率的界面,比如1920像素,500像素。
echarts自适应:拖动窗口时候,图表和图表内字体适配窗口大小。
接下来介绍两种方法,大家自行选择。

1.方法一:配合媒体查询

  • 样式
  • tip: 媒体查询的顺序必须从大的像素写到小的像素,因为他们的优先级是一样的,后面的代码覆盖前面的代码。如果反过来写,就达不到效果了。
<style>  
#main {  
    width: 800px;  
    height: 400px;  
}  
/* 这里的意思是当屏幕宽度最大为750px的时候,触发这个样式 */
@media screen and (max-width: 750px) {  
    #main {  
        width: 400px;  
        height: 400px;  
    }  
}  
/* 这里的意思是当屏幕宽度最大为550px的时候,触发这个样式 */
@media screen and (max-width: 550px) {  
    #main {  
        width: 200px;  
        height: 400px;  
    }  
}  
</style>
  • HTML和JS代码,下面使用的是饼图的option配置,去官网随便复制一个也可以。
<div id="main" class="header">header</div>

<script type="text/javascript">
    var myChart = echarts.init(document.getElementById('main'));
    var option = {  
        tooltip: {  
            trigger: 'item'  
        },  
        legend: {  
            top: '5%',  
            left: 'center',  
            textStyle: {  
                fontSize: 15  
            }  
        },  
        series: [  
        {  
            top: '20rem',  
            name: 'Access From',  
            type: 'pie',  
            radius: ['50%', '70%'],  
            avoidLabelOverlap: false,  
            itemStyle: {  
                borderRadius: 10,  
                borderColor: '#fff',  
                borderWidth: 2  
            },  
        label: {  
            show: false,  
            position: 'center'  
        },  
        emphasis: {  
            label: {  
                show: true,  
                fontSize: 40,  
                fontWeight: 'bold'  
            }  
        },  
        labelLine: {  
            show: false  
        },  
        data: [  
            {value: 1048, name: 'Search Engine'},  
            {value: 735, name: 'Direct'},  
            {value: 580, name: 'Email'},  
            {value: 484, name: 'Union Ads'},  
            {value: 300, name: 'Video Ads'}  
        ]  
      }  
    ]  
};
    // 使用刚指定的配置项和数据显示图表。  
    myChart.setOption(option);
    
    // 关键代码
    let timer;  
    function debounce(fn, delay) {  
        if (timer) clearTimeout(timer);  
        timer = setTimeout(() => {  
            fn()  
        }, delay)  
    }  
  
    window.addEventListener('resize', function () {  
    debounce(myChart.resize, 300)  
    })
</script>

  • 下面对关键代码进行解释,第一个是简介版本:如果没有学习过防抖函数,可以使用第一个。第二个是优化后的代码,因为窗口变化会一直触发resize函数,所以使用防抖函数可以优化性能。
  • echart自带resize函数。作用 : 重新刷新画布的函数,改变图表尺寸,在容器大小发生改变时需要手动调用。
  1. 简洁版:
    //简洁版
    window.addEventListener('resize', function () {  
        myChart.resize()
    })
  1. 优化版
    // 关键代码
    let timer;  
    function debounce(fn, delay) {  
        if (timer) clearTimeout(timer);  
        timer = setTimeout(() => {  
            fn()  
        }, delay)  
    }  
  
    window.addEventListener('resize', function () {  
        debounce(myChart.resize, 300)  
    })
  • 1400px下的图 image.png
  • 700px下的图 image.png
  • 500px下的图 image.png

方法二: 手动更改不同的样式(rem)

  • 样式
html {  
    font-size: 10px;  
}  
#box {  
    font-size: 10px;  
    display: flex;  
    border: 1px solid black;  
    height: 8rem;  
    width: 8rem;  
    flex-direction: column;  
    overflow: hidden;  
    margin: 50px auto;  
}  
.header {  
    font-size: 2rem;  
    width: 100%;  
    height: 100%;  
    margin: 0 auto;  
}

  • html和js
  • tip : 需要导入flexible.js包
<div id="box">  
    <div id="main" class="header">header</div>  
</div>

// 导入flexible.js的代码
<script src="http://g.tbcdn.cn/mtb/lib-flexible/0.3.4/??flexible_css.js,flexible.js"></script>

<script type="text/javascript">  
/* 这个函数作用:默认我们在1920px像素下的设计图,然后传入你想要的像素(res参数)。*/
/* 比如我们在1920px下的设计图需要12px的字体,那么我们调用这个参数传入12即可。*/
/* 如果我们在3840px下,需要展示出以上1920px下12px的字体,那么clientWidth就获取到当前屏幕大小,*/ 
/* 比如是clientWidth = 3840px,然后res * fontSize = 12 * 2 = 24,我们看到的大小就会等倍数放大。 */
/* 就能够达到不同分辨率下,相同的视觉效果 */
function fontSizeFn(res) {  
    const clientWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;  
    if (!clientWidth) return;  
    let fontSize = clientWidth / 1920;  
    return res * fontSize;  
}  
  
// 基于准备好的dom,初始化echarts实例  
var myChart = echarts.init(document.getElementById('main'));  
  
// 指定图表的配置项和数据  
// 这里对某些需要有变化的数据进行适配,调用fontSizeFn方法。
var option = {  
    tooltip: {  
        trigger: 'item'  
    },  
    legend: {  
        top: '5%',  
        left: 'center',  
        itemWidth: fontSizeFn(32),  
        itemHeight: fontSizeFn(32),  
        itemGap: fontSizeFn(30),  
    },  
    series: [  
    {  
            name: 'Access From',  
            type: 'pie',  
            radius: [fontSizeFn(70), fontSizeFn(180)],  
            avoidLabelOverlap: false,  
            itemStyle: {  
            borderRadius: 10,  
            borderColor: '#fff',  
            borderWidth: 2  
        },  
            label: {  
                show: false,  
                position: 'center'  
            },  
            emphasis: {  
                label: {  
                    show: true,  
                    fontSize: 40,  
                    fontWeight: 'bold'  
                }  
            },  
            labelLine: {  
                show: false  
            },  
            data: [  
                {value: 1048, name: 'Search Engine'},  
                {value: 735, name: 'Direct'},  
                {value: 580, name: 'Email'},  
                {value: 484, name: 'Union Ads'},  
                {value: 300, name: 'Video Ads'}  
            ]  
        }  
    ]  
};  
   
myChart.setOption(option);  
  
// 关键代码  
window.addEventListener('resize', function () {  
    refreshChart(myChart)  
},false)  

// 这里必须clear一下,然后再resize,然后再setOption,不然图不会发生变化。
// 这里为什么需要重新为某些参数赋值?
// 因为如果直接setOption的话,不把option.series[0].radius这些参数进行重新赋值的话,图表就不会发生变化。
// 当我们的屏幕尺寸发生变化的时候,需要重新调用fontSizeFn方法去计算当前的大小。
// 如果不重新设置,那么参数就是屏幕变化前的大小
function refreshChart(chart) {  
    chart.clear()  
    chart.resize()  
    option.series[0].radius = [fontSizeFn(70), fontSizeFn(180)]  
    option.legend.itemWidth = fontSizeFn(32)  
    option.legend.itemHeight = fontSizeFn(32)  
    option.legend.itemGap = fontSizeFn(30)  
    chart.setOption(option)
}  
</script>
  • 效果展示 image.png
image.png

缺点:

  1. 分辨率太大的话,图会和上面的legend重叠
  2. 分辨率太小的话,图会变小

总结: 第一个方法比较合适一点,第二个方法感觉比较难选择一个合适的参数。