схема адаптации диаграмм

ECharts
схема адаптации диаграмм

предисловие:demoэто использовать@vue/cli 4.5.15Построенный проект, это сообщение в блоге относится кnuggets.capable/post/700908… Наггетс.Талант/пост/696610…Пробовал и резюмировал.

Выбор схемы адаптации

схема адаптации vw и vh (непропорциональная адаптация)

оконная адаптация

Полный размер окна браузера100vw * 100vh,1vwэто ширина окна браузера1%,vhТо же самое справедливо. В этот момент мы можем вычислитьDOMОтношение элемента к ширине и высоте окна браузера. Например500pxПеревести вvwтогда это500*100/1920vw

Snipaste_2021-12-02_17-50-45

scree01

  • использоватьvwа такжеvhСхема адаптации для адаптации к разным экранам мониторов.

    //使用scss的math函数
    @use 'sass:math';
    
    // 默认设计稿的宽度
    $designWidth: 1920;
    // 默认设计稿的高度
    $designHeight: 1080;
    
    // px转vw的函数
    @function vw($px) {
      // 类似除法运算符($px/$designWidth) * 100vw
      @return math.div($px, $designWidth) * 100vw;
    }
    
    // px转vh的函数
    @function vh($px) {
      @return math.div($px, $designHeight) * 100vh;
    }
    
  • существуетvue.config.jsСредняя конфигурацияutils.scssПуть можно использовать глобально.

    module.exports = {
      css: {
        // 全局配置utils.scss,详细配置参考vue-cli官网
        loaderOptions: {
          sass: {
            prependData: '@import "@/assets/styles/utils.scss";'
          }
        }
      }
    }
    
  • Используйте его там, где вам это нужноwidth:vw(300)заменить предыдущийwidth:300px

    .box {
      width: vw(300);
      height: vh(500);
      font-size: vh(16);
      background-color: rgb(132, 199, 77);
      margin-left: vw(10);
      margin-top: vh(10);
      border: vh(2) solid red;
    }
    

Адаптация динамического элемента DOM

В некоторых случаях,domЭлементы должны создаваться динамически. В настоящее время нет возможности добавить стили к динамически создаваемым элементам в приведенном выше решении. Поэтому нам нужно динамически назначать соответствующие свойства css элементу при его создании.

// 定义设计稿的尺寸
const designWidth = 1920
const designHeight = 1080

const styleUtil = {
  px2vw: function (_px) {
    return _px * 100 / designWidth + 'vw'
  },
  px2vh: function (_px) {
    return _px * 100 / designHeight + 'vh'
  }
}

использовать

import styleUtil from '@/utils/styleUtil.js'

dom.style.width = styleUtil.px2vw(300)
dom.style.height = styleUtil.px2vh(300)
dom.style.background = '#ccc'

动画 (1)

Схема адаптации пропорционального масштабирования

动画.gif

Схема адаптации на основе преобразования

<template>
    <div class="home" ref="home">
        <div class="left_container">
            <div class="left_top">
                <line-chart-page/>
            </div>
            <div class="left_center">
                <line-chart-page/>
            </div>
            <div class="left_bottom">
                <line-chart-page/>
            </div>
        </div>
        <div class="center_container">
            <div class="center_top">
                <Map/>
            </div>
            <div class="center_bottom">
                <bar-chart-page/>
            </div>
        </div>
        <div class="right_container">
            <div class="right_top">
                <line-chart-page/>

            </div>
            <div class="right_center">
                <line-chart-page/>

            </div>
            <div class="right_bottom">
                <line-chart-page/>
            </div>
        </div>
    </div>
</template>
<script>
    export default {
        mounted () {
            function setScale () {
                const designWidth = 1920// 设计稿的宽度,根据实际项目调整
                const designHeight = 1080// 设计稿的高度,根据实际项目调整
                // (窗口宽度 / 窗口高度) < (设计稿宽度 / 设计稿高度) ? (窗口宽度 / 设计稿高度) : (窗口高度 / 设计稿高度)
                const scale = document.documentElement.clientWidth / document.documentElement.clientHeight < designWidth / designHeight
                        ? (document.documentElement.clientWidth / designWidth)
                        : (document.documentElement.clientHeight / designHeight)
                document.querySelector('.home').style.transform = `scale(${scale})`
            }

            setScale()

            window.onresize = function () {
                setScale()
            }
        },
    }
</script>

Пропорциональное масштабирование на основе rem

  • Динамически вычислять корневой элемент на основе размера экранаhtmlизfontSizeстоимость.

    setFontSize()
    function setFontSize(){
        let designWidth = 1366; 
        let designHeight = 768; 
        var fontSize = 
            document.documentElement.clientWidth/document.documentElement.clientHeight < designWidth/designHeight ? 
            (document.documentElement.clientWidth / designWidth) * 12:
            (document.documentElement.clientHeight / designHeight) * 12;
        document.querySelector('html').style.fontSize = fontSize + 'px';
    }
    window.onresize = function () {
        setFontSize()
    };
    
  • настраиватьDOMстиль элемента

    $design_width: 1366;//设计稿的宽度,根据实际项目调整
    $design_height: 768;//设计稿的高度,根据实际项目调整
    
    @function px2rem($px) {
       $design_font_size: 12;
       @return ($px/$design_font_size) + rem;
    }
    
    div {
      width: px2rem(500);
      height: px2rem(500);
    }
    

Адаптация диаграммы Echart и бизнес-упаковка

Деловая упаковка

задний план:

  • В реальном проекте,optionКонфигурации и аналогичные элементы конфигурации, мы можем извлечь эти повторяющиеся или похожие конфигурации и поместить их в отдельный файл конфигурации.
  • Также имеет ту же конфигурацию диаграммы, только данные изменились, поэтому нет необходимости повторять работу все время.

Эффект, которого необходимо добиться после инкапсуляции:

  • Нам нужно разделить бизнес-данные и конфигурацию диаграммы, и только при их использовании нужно передавать бизнес-данные.
  • Различные стили значков могут быть получены путем передачи различных элементов пользовательской конфигурации в один и тот же тип значка.
  • Графики отображаются нормально независимо от того, какие данные передаются. (Необходимо судить о переданных данных, аналогичноundefined,nullтак далее)

разделить идеи:

  • Поместите все компоненты диаграммы вcomponents/Chartsпапка.
  • Каждая диаграмма создается в отдельной папке и хранится вcomponents/Chart/Вниз.
  • Элементы конфигурации по умолчанию для каждой диаграммы хранятся вdefaultOption.jsсередина.
├── src
│ ├── components
│ │ ├── Charts
│ │ │ ├── BarChart
│ │ │ │ ├── defaultOption.js
│ │ │ │ ├── index.vue

Адаптация диаграммы

  • Адаптация экрана может быть решена с помощью вышеуказанного решения.

  • Необходимо использовать адаптацию диаграммыechartsОфициальныйresizeмероприятие.

  • Адаптация шрифта диаграммы: Это зависит от требований проекта.Если вам нужно адаптировать шрифт диаграммы, вы можете использовать следующие методы.

    /* Echarts图表字体、间距自适应 */
    export const fitChartSize = (size, defalteWidth = 1920) => {
      const clientWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth
      if (!clientWidth) return size
      const scale = (clientWidth / defalteWidth)
      return Number((size * scale).toFixed(3))
    }
    

Пример

  • компонент легенды:src/components/BarChart/index.vue

    <template>
      <!-- 空的业务数据 -->
      <h1 v-if="!isEmpty">没有数据</h1>
      <div v-else class="barChart" ref=barChart></div>
    </template>
    <script>
    import * as echarts from 'echarts/core'
    // 监控元素大小变化
    import ResizeListener from 'element-resize-detector'
    import { merge } from 'lodash'
    import baseOption from './defaultOption' // 默认配置
    export default {
      data: () => ({
        intanceChart: null // 图例组件
      }),
      mounted () {
        // 当绘制图标的DOM元素存在时
        if (this.$refs.barChart) {
          this.initializationChart() // 初始化图表
          window.addEventListener('resize', this.handleWindowResize) // 监听窗口尺寸
          this.addChartResizeListener() // 对echart尺寸监听
        }
      },
      props: {
        // 业务数据
        seriesData: {
          type: Array,
          required: true,
          default: () => []
        },
        // 需要特殊定制的图表配置项
        extraOption: {
          type: Object,
          default: () => ({})
        }
      },
      // 监听业务数据的变化
      watch: {
        // 监听业务数据的变化,如果没有数据就不绘制图标,展示普通DOM元素即可
        isEmpty: {
          handler (newVal) {
            if (newVal) {
              this.$nextTick(() => {
                this.initializationChart() // 初始化图标数据
                window.addEventListener('resize', this.handleWindowResize) // 监听窗口尺寸
                this.addChartResizeListener() // 对echart尺寸监听
              })
            }
          }
        },
        // 当业务数据发生变化的时候,更新图例
        seriesData: {
          deep: true,
          handler () {
            this.updateChartView()
          }
        },
        // 监听自定义配置项,适配字体
        extraOption: {
          deep: true,
          handler (newVal) {
            this.instanceChart.setOption(newVal) // 重新设置图例组件的大小
          }
        }
      },
      computed: {
        // 判断业务数据是否为空数据
        isEmpty () {
          return this.seriesData.length
        }
      },
      methods: {
        /* 01. 合并配置项数据,将默认配置项和自定以配置项和并为一个option */
        assembleDataToOption () {
          return merge(
            {},
            baseOption,
            {
              series: this.seriesData
            },
            this.extraOption
          )
        },
        // 02. 初始化图表组件
        initializationChart () {
          this.instanceChart = echarts.init(this.$refs.barChart) //  组件实例
          const fullOption = this.assembleDataToOption() // 合并后的option
          this.instanceChart.setOption(fullOption, true)
        },
        // 03. 更新echart视图
        updateChartView () {
          if (!this.$refs.barChart) return
          const fullOption = this.assembleDataToOption() // 合并后的option
          this.instanceChart.setOption(fullOption, true)
        },
        // 04.对chart元素尺寸进行监听,当发生变化时同步更新echart视图
        addChartResizeListener () {
          const instance = ResizeListener({
            strategy: 'scroll',
            callOnAdd: true
          })
          instance.listenTo(this.$el, () => {
            if (!this.instanceChart) return
            this.instanceChart.resize()
          })
        },
        // 05. 当窗口缩放的时候,自动适配echart
        handleWindowResize () {
          if (!this.$refs.barChart) return
          this.instanceChart.resize()
        }
      }
    }
    </script>
    <style scoped>
    .barChart {
      width: 100%;
      height: 100%;
    }
    </style>
    
  • Использовать легенду

    <template>
      <div class="chart">
        <bar-chart :seriesData="seriesData" :extraOption="extraOption"/>
      </div>
    </template>
    
    <script>
    import barChart from '@/components/BarChart'
    import { fitChartSize } from '@/utils/echartUtils'
    // 业务数据
    const seriesData = [
      { data: [320, 332, 301, 334, 390, 330, 320] },
      { data: [120, 132, 101, 134, 90, 230, 210] },
      { data: [220, 182, 191, 234, 290, 330, 310] },
      { data: [150, 232, 201, 154, 190, 330, 410] },
      { data: [862, 1018, 964, 1026, 1679, 1600, 1570] },
      { data: [620, 732, 701, 734, 1090, 1130, 1120] },
      { data: [120, 132, 101, 134, 290, 230, 220] },
      { data: [60, 72, 71, 74, 190, 130, 110] },
      { data: [62, 82, 91, 84, 109, 110, 120] }
    ]
    export default {
      name: 'BarChart',
      components: { barChart },
      data () {
        return { extraOption: {}, seriesData }
      },
      created () {
        this.extraOption = this.extraEchartOption()
      },
      mounted () {
        // 在监听到窗口大小发生变化时,重新对自定义配置赋值,实现字体的适应
        window.addEventListener('resize', () => {
          this.extraOption = this.extraEchartOption()
        })
      },
      methods: {
        extraEchartOption () {
          return {
            tooltip: {
              textStyle: {
                fontSize: fitChartSize(12)
              }
            },
            legend: {
              itemWidth: fitChartSize(20),
              itemHeight: fitChartSize(15),
              textStyle: {
                fontSize: fitChartSize(12),
                width: fitChartSize(12)
              }
            },
            grid: {
              left: fitChartSize(3),
              right: fitChartSize(3),
              bottom: fitChartSize(3)
            },
            xAxis: [
              {
                axisLabel: {
                  fontSize: fitChartSize(12)
                }
              }
            ],
            yAxis: [
              {
    
                axisLabel: {
                  fontSize: fitChartSize(12)
                }
              }
            ]
          }
        }
      }
    }
    </script>
    
    <style scoped lang="scss">
    .chart {
      width: 100%;
      height: 100%;
    }
    </style>
    

动画 (1)

Он все еще немного застрял, я надеюсь, что кто-то, кто его увидит, может дать мне совет.

Образец адреса склада:git ee.com/coder Ли Чонг Вей/EC…