适配相关内容

106 阅读5分钟

前端适配问题

什么是前端适配?

我们希望在不同尺寸的设备下,页面可以自适应的展示或者进行等比例的缩放。从而在不同尺寸下,出现相似的结果。

像素分类

1.设备像素(物理像素): 设备屏幕的物理像素,在同一个设备上,它的物理像素都是固定的。 2.css像素(逻辑像素): 是为web开发者创造的,在CSS和javascript中使用的一个抽象的层。

dpr是指物理像素和css像素的比例。当dpr=1时,说明物理像素和css像素是1:1。此时一个物理像素等于一个css像素。当dpr=2时,说明物理像素是css像素的2倍,那么这时候4个物理像素为一个css像素

在pc端,css的一个像素往往都是对应电脑屏幕的一个物理像素,

在移动端,如iphone8,css像素为375px677px,dpr是2,设备像素是750px1354px。1个逻辑像素占4个物理像素 (4个物理像素来显示1个css逻辑像素)。

image-20220521094816569

什么是viewPort

MDN上说meta标签是:元素可提供有关页面的元信息(meta-information),比如针对搜索引擎和更新频度的描述和关键词。

  • 如果设置了 name 属性,meta 元素提供的是文档级别(document-level)的元数据,应用于整个页面。
  • 如果设置了 http-equiv 属性,meta 元素则是编译指令,提供的信息与类似命名的 HTTP 头部相同。
  • 如果设置了 charset 属性,meta 元素是一个字符集声明,告诉文档使用哪种字符编码。
  • 如果设置了 itemprop 属性,meta 元素提供用户定义的元数据。

viewPort是meta标签中name属性中的一个。指页面上用户可见区域。网页容器,用多大的空间来渲染页面。

<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">

这段代码的意思是将布局视口的宽度设置为设备宽度,初始缩放比例为1,最大缩放比例为1,用户不能缩放。

适配相关

第一种:使用lib-flexible 和 postcss-pxtorem

// main.js引入flexible和全局样式
// 移动端适配
import 'lib-flexible/flexible.js';
​
// 引入全局样式
import '@/assets/scss/index.scss';
// 配置不同,基础尺寸比例
// https://github.com/michael-ciniawsky/postcss-load-config
module.exports = {
  plugins: {
    autoprefixer: {
      overrideBrowserslist: ['Android 4.1', 'iOS 7.1', 'Chrome > 31', 'ff > 31', 'ie >= 8']
    },
    'postcss-pxtorem': {
      rootValue: 37.5,
      propList:['*'],
      selectorBlackList :['html'],
      minPixelValue :1.5,
      mediaQuery:false,
      exclude:'common',
    }
  }
}
​
// @mixin 指令允许我们定义一个可以在整个样式表中重复使用的样式。
// @include 指令可以将混入(mixin)引入到文档中。
@import './mixin.scss';
html {
  @include root-font-size();
}
​
// 清除浮动
@mixin clearfix {
  &:after {
    content: "";
    display: table;
    clear: both;
  }
}
// 多行隐藏
@mixin textoverflow($clamp:1) {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  -o-text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: $clamp;
  /*! autoprefixer: ignore next */
  -webkit-box-orient: vertical;
}
//flex box
@mixin flexbox($jc:space-between, $ai:center, $fd:row, $fw:nowrap) {
  display: flex;
  display: -webkit-flex;
  flex: 1;
  justify-content: $jc;
  -webkit-justify-content: $jc;
  align-items: $ai;
  -webkit-align-items: $ai;
  flex-direction: $fd;
  -webkit-flex-direction: $fd;
  flex-wrap: $fw;
  -webkit-flex-wrap: $fw;
}
​
​
/* 移动端页面设计稿宽度 */
$design-width: 750;
/* 移动端页面设计稿dpr基准值 */
$design-dpr: 2;
/* 将移动端页面分为10块 */
$blocks: 10;
/* 缩放所支持的设备最小宽度 */
$min-device-width: 320px;
/* 缩放所支持的设备最大宽度 */
$max-device-width: 750px;
​
/*
    rem与px对应关系,1rem代表html font-size值(为一块的宽度),$rem即为$px对应占多少块
​
        $px                    $rem
    -------------    ===    ------------
    $design-width              $blocks
*//* html根元素的font-size定义,简单地将页面分为$blocks块,方便计算 */
@mixin root-font-size() {
    font-size: 100vw / $blocks;
​
    body {
        @include container-min-width();
    }
​
    /* 最小宽度定义 */
    @media screen and (max-width: $min-device-width) {
        font-size: $min-device-width / $blocks;
    }
​
    /* 最大宽度定义 */
    &[data-content-max] {
        body[data-content-max] {
            @include container-max-width();
        }
​
        @media screen and (min-width: $max-device-width) {
            font-size: $max-device-width / $blocks;
        }
    }
}
​
/* 单位px转化为rem */
@function px2rem($px) {
    @return #{$px / $design-width * $blocks}rem;
}
​
/* 单位rem转化为px,可用于根据rem单位快速计算原px */
@function rem2px($rem) {
    @return #{$rem / $blocks * $design-width}px;
}
​
/**
 * 实现固定宽高比
 * @param  {string} $position: relative      定位方式
 * @param  {string} $width:    100%          容器宽度
 * @param  {string} $sub:      null          容器的目标子元素
 * @param  {number} $aspectX:  1             容器宽
 * @param  {number} $aspectY:  1             容器高
 */
@mixin aspect-ratio($position: relative,
    $width: 100%,
    $sub: null,
    $aspectX: 1,
    $aspectY: 1) {
    overflow: hidden;
    position: $position;
    padding-top: percentage($aspectY / $aspectX);
    width: $width;
    height: 0;
​
    @if $sub==null {
        $sub: "*";
    }
​
    &>#{$sub} {
        position: absolute;
        left: 0;
        top: 0;
        width: 100%;
        height: 100%;
    }
}
/* 设置容器拉伸的最小宽度 */
@mixin container-min-width() {
    margin-right: auto;
    margin-left: auto;
    min-width: $min-device-width;
}
​
/* 设置容器拉伸的最大宽度 */
@mixin container-max-width() {
    margin-right: auto;
    margin-left: auto;
    max-width: $max-device-width;
}
/* 设置字体大小,不使用rem单位, 根据dpr值分段调整 */
@mixin font-size($fontSize) {
    font-size: $fontSize / $design-dpr;
​
    [data-dpr="2"] & {
        font-size: $fontSize / $design-dpr * 2;
    }
​
    [data-dpr="3"] & {
        font-size: $fontSize / $design-dpr * 3;
    }
}
/* 清除浮动 */
@mixin clearfix {
    *zoom: 1;
​
    &:after {
        content: "";
        display: block;
        height: 0;
        visibility: hidden;
        clear: both;
    }
}
​
/*
*$line:超出显示几行省略号
*$substract:预留区域百分比
*/
@mixin text-overflow($line:1, $substract:0) {
    overflow: hidden;
    @if $line==1 {
        white-space: nowrap;
        text-overflow: ellipsis;
        width: 100% -$substract;
    }
    @else {
        display: -webkit-box;
        -webkit-line-clamp: $line;
        -webkit-box-orient: vertical;
    }
}
​
@mixin WH($Width:100%, $Height:100%) {
    width: $Width;
    height: $Height;
}

第二种:通过动态计算屏幕高度尺寸来设置html根目录下的fontSize大小

// 来自 https://github.com/amfe/lib-flexible/blob/2.0/index.js
(function flexible(window, document) {
  var docEl = document.documentElement;
  // 获取当前显示设备的物理像素分辨率与CSS像素分辨率之比;
  var dpr = window.devicePixelRatio || 1;
 
  //根据分辨率调整全局字体大小
  function setBodyFontSize() {
    // html已完成加载,则立即调整字体大小,否则等待html加载完成再调整字体大小
    if (document.body) {
      document.body.style.fontSize = 12 * dpr + "px";
    } else {
      // 监听DOMContentLoaded 事件——当初始的 HTML 文档被完全加载和解析完成之后触发,无需等待样式表
      document.addEventListener("DOMContentLoaded", setBodyFontSize);
    }
  }
  setBodyFontSize();
 
  // 根据屏幕宽度,重置1rem的长度为当前屏幕宽度的1/10
  function setRemUnit() {
    var rem = docEl.clientWidth / 10;
    // 1rem的值永远为根元素的字体大小,所以此处通过调整全局字体大小来重置rem
    docEl.style.fontSize = rem + "px";
  }
 
  setRemUnit();
 
  // 监听resize事件——屏幕大小发生变化时触发
  window.addEventListener("resize", setRemUnit);
  // 监听pageshow事件——显示页面时触发
  window.addEventListener("pageshow", function (e) {
    // 若是浏览器中点击后退时显示页面,则重置rem
    if (e.persisted) {
      setRemUnit();
    }
  });
 
  // 检测是否支持0.5px
  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);

echarts中字体设置

// 字体转换 px -> rem
export function fontChart(res) {
  let docEl = document.documentElement,
    clientWidth =
      window.innerWidth ||
      document.documentElement.clientWidth ||
      document.body.clientWidth;
  if (!clientWidth) return;
  // 此处的3840 为设计稿的宽度,记得修改!
  let fontSize = clientWidth / 1920;
  return res * fontSize;
}

第三种:通过scale设置

采用了css3的缩放transform: scale(X)属性。我们只要监听浏览器窗口大的小,同时控制变化的比例就可以了。

<template>
  <div
    class="ScreenAdapter"
    :style="style"
  >
    <slot />
  </div>
</template>
<script>
export default {
  name: '',
  //参数注入
  props: {
    width: {
      type: String,
      default: '1920' 
    },
    height: {
      type: String,
      default: '1080' 
    }
  },
  data() {
    return {
      style: {
        width: this.width + 'px',
        height: this.height + 'px',
        transform: 'scale(1) translate(-50%, -50%)'
      }
    }
  },
  mounted() {
    this.setScale()
    window.onresize = this.Debounce(this.setScale, 1000)
  },
  methods: {
    Debounce: (fn, t) => {
      const delay = t || 500
      let timer
      return function() {
        const args = arguments
        if (timer) {
          clearTimeout(timer)
        }
        const context = this
        timer = setTimeout(() => {
          timer = null
          fn.apply(context, args)
        }, delay)
      }
    },
    // 获取放大缩小比例
    getScale() {
      const w = window.innerWidth / this.width
      const h = window.innerHeight / this.height
      return [w,h];
    },
    // 设置比例
    setScale() {
      this.style.transform = 'scale(' + this.getScale()[0] + ','+ this.getScale()[1] + ') translate(-50%, -50%)'
      console.log('任你千变万化,我都不会影响性能')
    }
  }
}
</script>
<style lang="scss" scoped>
.ScreenAdapter {
  transform-origin: 0 0;
  position: absolute;
  left: 50%;
  top: 50%;
  transition: 0.3s;
  background: red;
}
</style>

数据可视化常用网站

Echarts : Documentation - Apache ECharts

Echarts :ppchart.com/#/

Make A Pie: Make A Pie

Make a pie(代替1)ppchart.com/#/

make a pie (代替2) analysis.datains.cn/finance-adm…

make a pie (代替3)www.isqqw.com/homepage

DataV:DataV

HighCharts: Highcharts 演示 | Highcharts

vue-seamless-scroll: chenxuan0000.github.io/vue-seamles…

数据可视化平台(各个地区的json文件) 各个地区的json文件 用来echarts注册地图