数据大屏适配方案 (scale)

296 阅读6分钟

数据大屏适配方案 (scale)

目录

[TOC]

  • 大屏之关键-前期的自适应适配

  • 根据 ui 稿绘制图表,调细节

而解决了适配问题后,后面就只是一个慢工出细活,耗时间的事情了。

适配方案分析

看了网上的各种方案,目前大家采用的大概有 2 种👇

方案实现方式优点缺点
vm vh1.按照设计稿的尺寸,将 px 按比例计算转为 vwvh1.可以动态计算图表的宽高,字体等,灵活性较高 2.当屏幕比例跟 ui 稿不一致时,不会出现两边留白情况1.每个图表都需要单独做字体、间距、位移的适配,比较麻烦
scale1.通过 scale 属性,根据屏幕大小,对图表进行整体的等比缩放1.代码量少,适配简单 2.一次处理后不需要在各个图表中再去单独适配1.因为是根据 ui 稿等比缩放,当大屏跟 ui 稿的比例不一样时,会出现周边留白情况  2.当缩放比例过大时候,字体会有一点点模糊,就一点点  3.当缩放比例过大时候,事件热区会偏移。

vw vh

什么是vw和vh

  • vw和vh他们是一个相对单位(类似em和rem)

vw是:viewport width 视口宽度单位
vh是: viewport height 视口高度单位

  • 相对视口的尺寸计算

1vw=1/100视口宽度
1vh=1/100视口高度
eg:当前屏幕视口是375像素,1vw就是3.75像素

vw和百分比的区别是什么?

百分比是相对父元素来说的
vw和vh是相对于当前视口来说的

vw怎么使用

如何还原设计稿?
前提:我们设计稿按照iphone678来设计,有个盒子是50*50像素的,如何使用vw呢?
分析:

②那么1vw是多少像素呢
375/100=3.75px
③我们的目标是做少像素?
50 50
④ 那么,50是多少个vw?
50/3.75=13.33vw

实现思路

按照设计稿的尺寸,将 px 按比例计算转为 vwvh ,转换公式如下

假设设计稿尺寸为 1920*1080(做之前一定问清楚 ui 设计稿的尺寸)

即:
网页宽度=1920px
网页高度=1080px

我们都知道
网页宽度=100vw
网页宽度=100vh

所以,在 1920px*1080px 的屏幕分辨率下

1920px = 100vw

1080px = 100vh

这样一来,以一个宽 100px 和 100px 的 div 来说,其所占的宽高,以 vw 和 vh 为单位,计算方式如下:

vwDiv = 100 / (1920 / 100vw)
vhDiv = 100 / (1080 / 100vh)

所以,就在 1920*1080 的屏幕分辨率下,计算出了单个 div 的宽高

当屏幕放大或者缩小时,div 还是以 vw 和 vh 作为宽高的,就会自动适应不同分辨率的屏幕

案例

<!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>
        * {
            margin: 0;
            padding: 0;
        }
 
        .box {
            width:100vw;
            height:100vh;
            background: orange;
        }
        .top{
            width: 5.2vw;
            height: 9.26vh;
            background: red;
            margin-left: 2.6vw;
        }
 
        .bottom{
            width: 5.2vw;
            height: 9.26vh;
            background: skyblue; 
            margin-left: 2.6vw;
            margin-top:9.26vh;
        }
    
    </style>
</head>
 
<body>
    <div class="box">
        <div class="top">数据大屏幕</div>
        <div class="bottom">hahaha </div>
    </div>
</body>
 
</html>
<script>
    //vw|vh:新增单位 ->IE8
</script>

scale方案

我们整个大屏的尺寸设置和设计图一样,只是通过css的scale放大缩小属性,来控制实际展示的大小。

通过监听浏览器窗口的大小,来改变scale的比例,从而实现数据大屏适配。(百度、网易等大数据适配的解决方案均是这个)

scale()方法

缩放,指的是“缩小”和“放大”。在CSS3中,我们可以使用scale()方法来将元素根据中心原点进行缩放。

跟translate()方法一样,缩放scale()方法也有3种情况:

(1)scaleX(x):元素仅水平方向缩放(X轴缩放);

(2)scaleY(y):元素仅垂直方向缩放(Y轴缩放);

(3)scale(x,y):元素水平方向和垂直方向同时缩放(X轴和Y轴同时缩放);

1、scaleX(x)

语法:transform:scaleX(x)

说明:x表示元素沿着水平方向(X轴)缩放的倍数,如果大于1就代表放大;如果小于1就代表缩小。 大家想想倍数是怎样一个概念就很好理解了。

2、scaleY(y)

语法: transform:scaleY(y)

说明: y表示元素沿着垂直方向(Y轴)缩放的倍数,如果大于1就代表放大;如果小于1就代表缩小。

3、scale(x,y)

语法:transform:scale(x,y)

说明:x表示元素沿着水平方向(X轴)缩放的倍数,y表示元素沿着垂直方向(Y轴)缩放的倍数。

注意,Y是一个可选参数,如果没有设置Y值,则表示X、Y两个方向的缩放倍数是一样的(同时放大相同倍数)。

css3 transform

当谈到网页设计和用户界面的时候,CSS3 Transform是一个非常强大且灵活的工具。它提供了一种改变元素在2D和3D空间中位置、旋转、缩放和倾斜的方式,为开发者创造出更为吸引人的用户体验。

1. 基本转换属性
1.1 位移(Translate)

通过 translate 属性,我们可以改变元素在水平和垂直方向上的位置。例如:

.element {
  transform: translate(50px, 30px);
}

上述代码将元素向右移动50像素,向下移动30像素。

1.2 旋转(Rotate)

使用 rotate 属性可以实现元素的旋转效果。例如:

.element {
  transform: rotate(45deg);
}

这将使元素顺时针旋转45度。

1.3 缩放(Scale)

通过 scale 属性,我们可以实现元素的缩放效果。例如:

.element {
  transform: scale(1.5);
}

这会将元素放大1.5倍。

1.4 倾斜(Skew)

skew 属性用于倾斜元素。例如:

.element {
  transform: skew(30deg, 20deg);
}

这将使元素在水平方向倾斜30度,在垂直方向倾斜20度。

2. 3D转换

CSS3 Transform还支持在三维空间中进行转换,通过使用 rotateXrotateYrotateZ 等属性,可以创建更为复杂的动画效果。

.element {
  transform: rotateX(45deg) rotateY(45deg);
}

这将使元素绕X轴和Y轴同时旋转45度。

3. 过渡效果

结合CSS3 Transform和过渡效果,我们可以创建平滑的动画效果。通过 transition 属性,我们可以指定过渡的持续时间、延迟时间以及过渡效果的类型。

.element {
  transition: transform 0.3s ease-in-out;
}
 
.element:hover {
  transform: scale(1.2);
}

上述代码表示在0.3秒内以缓慢进出的方式将元素放大1.2倍,实现了在鼠标悬停时的过渡效果。

4. 实际应用

CSS3 Transform在实际应用中有着广泛的用途,比如创建响应式的用户界面、实现页面切换动画、以及设计独特的交互元素。通过巧妙地运用这些转换属性,开发者能够提升用户体验,使页面更为生动有趣。

案例

<!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>
        * {
            margin: 0;
            padding: 0;
        }
 
        .container {
            width: 100vw;
            height: 100vh;
            background: url(./bg.png) no-repeat;
            background-size: cover;
        }
 
        .box {
            position: fixed;
            width: 1920px;
            height: 1080px;
            background: red;
            transform-origin: left top;
            left: 50%;
            top: 50%;
        }
 
        .top {
            width: 100px;
            height: 100px;
            background: hotpink;
            margin-left: 50px;
        }
 
        .bottom {
            width: 100px;
            height: 100px;
            background: skyblue;
            margin-left: 50px;
            margin-top: 100px;
        }
    </style>
</head>
 
<body>
    <div class="container">
        <!-- 数据展示的区域 -->
        <div class="box">
            <div class="top">我是祖国的</div>
            <div class="bottom">老花骨朵</div>
        </div>
    </div>
</body>
 
</html>
<script>
    //控制数据大屏放大与缩小
    let box = document.querySelector('.box');
    box.style.transform = `scale(${getScale()}) translate(-50%,-50%)`
    //计算缩放的比例啦
    function getScale(w = 1920, h = 1080) {
        const ww = window.innerWidth / w;
        const wh = window.innerHeight / h;
        return ww < wh ? ww : wh;
        //ww<wh情况: 1920/1920(ww)   1080/1080(wh)
        //ww>wh情况:1920/1920(ww)   1080/1080(wh)
    }
 
    window.onresize = () => {
        box.style.transform = `scale(${getScale()}) translate(-50%,-50%)`
    }
 
</script>

vue3中使用

<template>
  <div class="comtainer">
    <!-- 数据大屏内容区域 -->
    <div class="screen" ref="screen">
      <!-- 顶部 -->
      <div class="top"></div>
      <!-- 底部 -->
      <div class="bottom">
        <div class="left">左</div>
        <div class="center">中</div>
        <div class="right">右</div>
      </div>
    </div>
  </div>
</template>
 
<script setup lang="ts">
import { ref, onMounted } from "vue";
// 获取数据大屏展示内容盒子的dom元素
let screen = ref();
onMounted(() => {
  screen.value.style.transform = `scale(${getScale()}) translate(-50%,-50%)`;
});
// 定义大屏缩放比例
function getScale(w = 1920, h = 1080) {
  // 例子 原型搞为1920(4) 屏幕2269 (8)  放大缩小的比例 宽度
  const ww = window.innerWidth / w;
  // 例子 原型搞为1080(3) 屏幕2160 (6)  放大缩小的比例 高度
  const wh = window.innerHeight / h;
  // 函数返回宽度缩放比例ww和高度缩放比例wh中较小的那个值,这是因为它希望保持宽高比例不变,
  // 选择较小的比例来进行缩放,以确保整个内容可以在屏幕内完整显示。
  return ww < wh ? ww : wh;
  // ww宽度小于wh 高度:(视口宽度变小,视口高度变大)
}
// 监听窗口变化
window.onresize = () => {
  // scale(${getScale()}):这部分代码设置了缩放变换。
  // ${getScale()}是一个函数调用,它返回一个用于缩放的值。这个值将会替换${getScale()},从而生成类似scale(1.5)的字符串,其中1.5是实际的缩放比例。缩放可以让元素变大或变小。
  //translate(-50%,-50%):这部分代码设置了平移变换。它将元素水平和垂直方向分别平移到其自身宽度和高度的50%处。这通常用于将元素在其容器中水平和垂直居中对齐。
  // 先缩放完在把元素拽回去(因为scale缩放是以盒子中心点缩放的 css中改变了盒子位置及其中心点)
  screen.value.style.transform = `scale(${getScale()}) translate(-50%,-50%)`;
};
</script>
 
<style scoped lang="scss">
.comtainer {
  width: 100vw;
  height: 100vh;
  // no-repeat 表示不要重复平铺背景图像,即只显示一次,不会在水平和垂直方向重复。
  background: url(./images/bg.png) no-repeat;
  // cover 的意思是将背景图像等比例缩放,以覆盖整个元素的背景区域,确保背景图像完全覆盖并填充整个元素,无论元素的大小如何。
  background-size: cover;
  .screen {
    // 设置定位让基点位于屏设备中心点
    position: fixed;
    left: 50%;
    top: 50%;
    width: 1920px;
    height: 1080px;
    background-color: red;
    // 设置缩放基点为左上角 不能以盒子中心点
    transform-origin: left top;
  }
}
</style>