数据可视化

文章探讨了HTML5的Canvas标签及其坐标系统,展示了如何绘制矩形和清除区域。同时,提到了Canvas与SVG的区别,SVG作为矢量图在缩放时不失真。文章还通过Echarts的示例说明了在Web开发中的数据可视化应用,并讨论了在Vue或React组件中使用Echarts的注意事项。最后,文章深入介绍了多种大屏适配方案,包括使用rem、vw单位和scale函数,以解决不同分辨率下页面布局的问题。

Canvans优缺点

在这里插入图片描述

基本使用

在这里插入图片描述
canvas 标签内部的内容是当前浏览器不兼容才会显示的
getContext(‘2d’)是用来获取上下文的api

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        canvas {
            background-color: rebeccapurple;
        }
    </style>S
</head>

<body>
    <canvas id="canvs" width="200px" height="200px">
        您的浏览器不兼容canvans
    </canvas>
    <script>
        var c = document.querySelector('#canvs')
        let ctx = c.getContext('2d')
        console.log(ctx)
    </script>
</body>

</html>

canvans的坐标系统

在这里插入图片描述

绘制矩形

在这里插入图片描述

使用

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        canvas {
            border: 1px solid red;
        }
    </style>
</head>

<body>
    <canvas id="canvs" width="200px" height="200px">
        您的浏览器不兼容canvans
    </canvas>
    <script>
        var c = document.querySelector('#canvs')
        let ctx = c.getContext('2d')
        //绘制矩形
        ctx.fillRect(0,0,100,100)
        //绘制边框
        ctx.strokeRect(100,100,10,10)
        //清除矩形
        ctx.clearRect(0,0,50,50)
    </script>
</body>

</html>

效果
在这里插入图片描述

svg与canvans的区别

svg缩放不会失真模糊,因为是矢量图,做适配的话用svg
在这里插入图片描述

Echarts

根据官网进行一个demo

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>

    </style>
</head>

<body>
    <div id="main" style="width: 600px;height:400px;"></div>
    <script src="https://cdn.jsdelivr.net/npm/echarts@5.4.1/dist/echarts.min.js"></script>
    <script type="text/javascript">
        // 基于准备好的dom,初始化echarts实例
        var myChart = echarts.init(document.getElementById('main'));

        // 指定图表的配置项和数据
        var option = {
            title: {
                text: 'ECharts 入门示例'
            },
            tooltip: {},
            legend: {
                data: ['销量']
            },
            xAxis: {
                data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子']
            },
            yAxis: {},
            series: [
                {
                    name: '销量',
                    type: 'bar',
                    data: [5, 20, 36, 10, 10, 20]
                }
            ]
        };

        // 使用刚指定的配置项和数据显示图表。
        myChart.setOption(option);
    </script>

</body>

</html>

如果说我们想在vue/react组件中使用,那么我们需要注意要等待组件实例渲染完成再操作dom。

Echarts的渲染原理

在这里插入图片描述
可以在echarts.init()中进行渲染器的切换

options配置

在这里插入图片描述
坐标系配置
在这里插入图片描述
折线图
在这里插入图片描述

大屏适配方案

背景

近期公司投放在展厅大屏中演示的大数据页面,出现了文字、图表、表格等多类组件显示错乱的情况。

目的

解决页面错乱问题,实现多种分辨率的大屏适配

大屏适配方案1 – rem + font-size

动态设置HTML根字体大小 和 body 字体大小,也就是说要在缩放时动态改变HTML根字体大小 和 body 字体大小
我们可以写一个flexible.js来完成,监听onresize 事件
flexible.js

(function flexible(window, document) {
  var docEl = document.documentElement;
  var dpr = window.devicePixelRatio || 1;
  console.log(dpr)
  function setBodyFontSize() {
    if (document.body) {
      // 1.body 字体大小默认为 16px
      document.body.style.fontSize = 16 * dpr + "px";
    } else {
      document.addEventListener("DOMContentLoaded", setBodyFontSize);
    }
  }
  setBodyFontSize();

  // 这里默认平均分成 10 等分(适用移动端)
  function setRemUnit() {
    // 2.这里改成了24,将网页分成 24 等份,这样每个 1rem 对应的为 80px
    // 3.为什么要分成 24份 ? 目的是让缩放的细腻度更小,比如 0.1rem -> 8px
    var rem = docEl.clientWidth / 24;
    docEl.style.fontSize = rem + "px";
  }

  setRemUnit();

  window.addEventListener("resize", setRemUnit);
  window.addEventListener("pageshow", function (e) {
    if (e.persisted) {
      setRemUnit();
    }
  });

  if (dpr >= 2) {
    var fakeBody = document.createElement("body");
    var testElement = document.createElement("div");
    testElement.style.border = ".5px solid transparent";
    fakeBody.appendChild(testElement);
    docEl.appendChild(fakeBody);
    if (testElement.offsetHeight === 1) {
      docEl.classList.add("hairlines");
    }
    docEl.removeChild(fakeBody);
  }
})(window, document);

假如你的大屏是1920px宽度
 将设计稿的宽(1920)平均分成 24 等份, 每一份为 80px。
 HTML字体大小就设置为 80 px,即1rem = 80px, 24rem = 1920px
 body字体大小设置为 16px。
安装 cssrem 插件, root font size 设置为 80px。这个是px单位转rem的参考值
进入插件设置安装设计稿修改
在这里插入图片描述

 接着就可以按照 1920px * 1080px 的设计稿愉快开发,此时的页面已经是响应式,并且宽高比不变。
我们将代码中的px手动改为rem即可,比如li的字体大小,div的宽高,这些改完后我们进行页面的缩放发现字体大小与宽高都会等比例缩放了
demo

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Document</title>
  <style>

    body {
      margin: 0;
      padding: 0;
    }

    ul {
      margin: 0;
      padding: 0;
    }

    body {
      width: 24rem;
      height: 13.5rem;
      box-sizing: border-box;
      background-color: rgba(255, 0, 0, 0.1);
      border: 3px solid rebeccapurple;
    }

    ul {
      display: flex;
      flex-direction: row;
      flex-wrap: wrap;
      list-style: none;
      width: 100%;
      height: 100%;
    }

    li {
      width: 33.333%;
      height: 50%;
      box-sizing: border-box;
      border: 3px solid green;
      font-size: 0.375rem;
    }
  </style>
</head>

<body>
  <ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
    <li>6</li>
  </ul>

  <script src="../js/lib_flexible.js"></script>
</body>

</html>

大屏适配方案2 - vw

◼ 直接使用vw单位。
 屏幕的宽默认为 100vw,那么100vw = 1920px, 1vw = 19.2px 。
 安装 cssrem 插件, body的宽高(1920px * 1080px)直接把px单位转vw单位
在这里插入图片描述
 接着就可以按照 1920px * 1080px 的设计稿愉快开发,此时的页面已经是响应式,并宽高比不变。
demo

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      body,
      ul {
        margin: 0;
        padding: 0;
      }
      body {
        width: 100vw;
        height: 56.25vw;
        box-sizing: border-box;
        border: 2px solid red;
        background-color: rgba(255, 0, 0, 0.1);
      }

      ul {
        display: flex;
        flex-direction: row;
        flex-wrap: wrap;
        list-style: none;
        width: 100%;
        height: 100%;
      }

      li {
        width: 33.333%;
        height: 50%;
        box-sizing: border-box;
        border: 3px solid green;
        font-size: 1.5625vw;
      }
    </style>
  </head>
  <body>
    <ul>
      <li>1</li>
      <li>2</li>
      <li>3</li>
      <li>4</li>
      <li>5</li>
      <li>6</li>
    </ul>
  </body>
</html>

大屏适配方案3(推荐) - scale

思路:
动态计算网页宽高比,决定是是否按照宽度的比率进行scale缩放。
demo
transform-origin: left top;代表设置缩放的原点为左上角

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Document</title>
  <style>
    body,
    ul {
      margin: 0;
      padding: 0;
    }

    body {
      position: relative;
      box-sizing: border-box;
      border: 2px solid red;
      background-color: rgba(255, 0, 0, 0.1);
      transform-origin: left top;
    }

    ul {
      display: flex;
      flex-direction: row;
      flex-wrap: wrap;
      list-style: none;
      width: 100%;
      height: 100%;
    }

    li {
      width: 33.333%;
      height: 50%;
      box-sizing: border-box;
      border: 3px solid green;
      font-size: 30px;
    }
  </style>
</head>

<body>
  <ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
    <li>6</li>
  </ul>

  <script>
    window.onload = function () {
      triggerScale();
      window.addEventListener("resize", function () {
        triggerScale();
      });
    };

    function triggerScale() {
      var targetX = 1920;
      var targetY = 1080;
      var targetRatio = 1920 / 1080;//宽高比率(16/9)
      // 获取html的宽度和高度(不包含滚动条)
      var currentX =
        document.documentElement.clientWidth || document.body.clientWidth;
      var currentY =
        document.documentElement.clientHeight || document.body.clientHeight;
      console.log(currentX, currentY)
      // 1.缩放比例  3840 / 2160 => 2
      var ratio = currentX / targetX;
      var currentRatio = currentX / currentY;
      var transformStr = "";
      //超宽屏,如果还是参照宽度缩放,那么高度会有问题,因为宽高已经不等比了
      if (currentRatio > targetRatio) {
        ratio = currentY / targetY;//参照高度缩放
        //除了缩放,还要进行居中
        transformStr = `width:${targetX}px;height:${targetY}px; transform:scale(${ratio}) translateX(-${targetX / 2
          }px); left:50%;`;
      } else {
        transformStr = `width:${targetX}px;height:${targetY}px; transform:scale(${ratio})`;
      }
      var bodyEl = document.querySelector("body");
      // 2.需要修改缩放的原点
      bodyEl.setAttribute("style", transformStr);
    }
  </script>
</body>

</html>

具体可以在app.vue的onMounted函数中通过节流执行这个函数
我们可以封装一个hook
useScalePage.js

import { onMounted, onUnmounted } from "vue";
import _ from "lodash";

export default function useScalePage() {
  let resizeChange = _.throttle(function () {
    triggerScale();
  }, 100);

  onMounted(function () {
    triggerScale();
    window.addEventListener("resize", resizeChange);
  });

  onUnmounted(function () {
    console.log("useScale onUnmounted");
    window.removeEventListener("resize", resizeChange);
  });

  function triggerScale(option = {}) {
    let targetX = option.targetX || 1920;
    let targetY = option.targetY || 1080;
    let targetRatio = option.targetRatio || 16 / 9;

    // 1.拿到当前屏幕的宽高
    let currentX =
      document.documentElement.clientWidth || document.body.clientWidth;
    let currentY =
      document.documentElement.clientHeight || document.body.clientHeight;

    // 2.计算缩放的比例
    let scaleRatio = currentX / targetX;

    // 当前的屏幕宽高比
    let currentRatio = currentX / currentY;
    if (currentRatio > targetRatio) {
      scaleRatio = currentY / targetY;
      // 3.设置缩放( 类似图片放大 )
      document.body.setAttribute(
        "style",
        `width:${targetX}px;height:${targetY}px;transform: scale(${scaleRatio})  translateX(-50%); left:50%`
      );
    } else {
      // 3.设置缩放( 类似图片放大 )
      document.body.setAttribute(
        "style",
        `width:${targetX}px;height:${targetY}px;transform: scale(${scaleRatio})`
      );
    }
  }
}

app.vue
在这里插入图片描述

三种适配方案的对比

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值