Introduction: Demo is a project built by using @vue/ CLI 4.5.15. Refer to juejin.cn/post/700908… Juejin. Cn/post / 696610… Try and summarize.

Adaptation scheme selection

Vw and VH adaptation scheme (non-proportional adaptation)

The window adapter

The full browser window size is 100vw * 100vh. 1vw is 1% of the browser window width, and vH is the same. At this point we can calculate the proportion of DOM elements to the width and height of the browser window. For example, 500px to VW is 500 times 100/1920vw

  • Use VW and VH adaptation schemes to fit different display screens.

    // Use the SCSS math function
    @use 'sass:math';
    
    // The width of the default design draft
    $designWidth: 1920;
    // Default design height
    $designHeight: 1080;
    
    // px to vw
    @function vw($px) {
      // Similar to division operator ($px/$designWidth) * 100vw
      @return math.div($px.$designWidth) * 100vw;
    }
    
    // convert px to vh
    @function vh($px) {
      @return math.div($px.$designHeight) * 100vh;
    }
    Copy the code
  • Configure the path utils. SCSS in vue.config.js for global use.

    module.exports = {
      css: {
        // Configure utils. SCSS globally. For details, refer to vue-CLI official website
        loaderOptions: {
          sass: {
            prependData: '@import "@/assets/styles/utils.scss"; '}}}}Copy the code
  • Use width:vw(300) instead of width:300px where necessary

    .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;
    }
    Copy the code

Dynamic DOM element adaptation

In some cases, DOM elements need to be created dynamically, and there is no way to apply styles to dynamically created elements. Therefore, we need to dynamically assign CSS attributes to the element as we create it.

// Define the dimensions of the design draft
const designWidth = 1920
const designHeight = 1080

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

use

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

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

Proportional scaling adaptation scheme

Adaptation scheme based on Transform

<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// The width of the design draft can be adjusted according to the actual project
                const designHeight = 1080// The height of the design draft can be adjusted according to the actual project
                // (window width/window height) < (design width/design height)? (Window width/design draft height) : (Window height/design draft height)
                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>
Copy the code

Proportional scaling based on REM

  • Calculates the fontSize value of the root element HTML dynamically based on the screen size.

    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()
    };
    Copy the code
  • Set the DOM element style

    $design_width: 1366;// The width of the design draft can be adjusted according to the actual project
    $design_height: 768;// The height of the design draft can be adjusted according to the actual project
    
    @function px2rem($px) {
       $design_font_size: 12;
       @return ($px/$design_font_size) + rem;
    }
    
    div {
      width: px2rem(500);
      height: px2rem(500);
    }
    Copy the code

Echart chart adaptation and business assembly

Business selling

Background:

  • In a real project, each type of chartoptionConfiguration items and similar configuration items. We can separate these duplicates or similar configurations into a separate configuration file.
  • It has the same chart configuration, but the data has changed, so there is no need to keep reinventing the wheel.

Effects to be achieved after encapsulation:

  • We need to separate the business data from the chart configuration and only pass the business data when it is used.
  • Different icon styles can be achieved by passing different custom configuration items in ICONS of the same type.
  • The chart displays normally no matter what data is passed. (You need to make judgments about the data being passed, similarundefined,nullEtc.)

Break down the idea:

  • Place all chart components incomponents/ChartsFolder.
  • Each chart is stored in a separate foldercomponents/Chart/Under.
  • The default configuration items for each chart are storeddefaultOption.jsIn the.
├ ─ ─ the SRC │ ├ ─ ─ components │ │ ├ ─ ─ Charts │ │ │ ├ ─ ─ BarChart │ │ │ │ ├ ─ ─ defaultOption. Js │ │ │ │ ├ ─ ─ index. The vueCopy the code

Chart boards

  • The adaptation of the screen can be solved by using the above scheme.

  • Chart adaptation needs to use the echarts official resize event.

  • Font fit for chart: Depending on the project requirements, if you need to adapt the font for chart, you can use the following methods.

    /* Echarts chart font, spacing adaptive */
    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))}Copy the code

For example,

  • Legend components: SRC/components/BarChart/index. The vue

    <template>
      <! -- Empty business data -->
      <h1 v-if=! "" isEmpty">There is no data</h1>
      <div v-else class="barChart" ref=barChart></div>
    </template>
    <script>
    import * as echarts from 'echarts/core'
    // Monitor element size changes
    import ResizeListener from 'element-resize-detector'
    import { merge } from 'lodash'
    import baseOption from './defaultOption' // Default configuration
    export default {
      data: () = > ({
        intanceChart: null // Legend component
      }),
      mounted () {
        // When the DOM element to draw the icon exists
        if (this.$refs.barChart) {
          this.initializationChart() // Initialize the chart
          window.addEventListener('resize'.this.handleWindowResize) // Monitor window size
          this.addChartResizeListener() // Monitor echart size}},props: {
        // Business data
        seriesData: {
          type: Array.required: true.default: () = >[]},// Chart configuration items that require special customization
        extraOption: {
          type: Object.default: () = >({})}},// Listen for changes in service data
      watch: {
        // Listen for changes in business data. If there is no data, do not draw the icon and display normal DOM elements
        isEmpty: {
          handler (newVal) {
            if (newVal) {
              this.$nextTick(() = > {
                this.initializationChart() // Initialize icon data
                window.addEventListener('resize'.this.handleWindowResize) // Monitor window size
                this.addChartResizeListener() // Monitor echart size}}}}),// Update the legend when the business data changes
        seriesData: {
          deep: true,
          handler () {
            this.updateChartView()
          }
        },
        // Listen for custom configuration items for font adaptation
        extraOption: {
          deep: true,
          handler (newVal) {
            this.instanceChart.setOption(newVal) // Resize the legend component}}},computed: {
        // Check whether the service data is empty
        isEmpty () {
          return this.seriesData.length
        }
      },
      methods: {
        /* 01. Merge configuration item data, combine default configuration item and custom configuration item into one option */
        assembleDataToOption () {
          return merge(
            {},
            baseOption,
            {
              series: this.seriesData
            },
            this.extraOption
          )
        },
        // 02. Initialize the chart component
        initializationChart () {
          this.instanceChart = echarts.init(this.$refs.barChart) // Component instance
          const fullOption = this.assembleDataToOption() // The merged option
          this.instanceChart.setOption(fullOption, true)},// 03. Update echart view
        updateChartView () {
          if (!this.$refs.barChart) return
          const fullOption = this.assembleDataToOption() // The merged option
          this.instanceChart.setOption(fullOption, true)},// 04. Monitor the chart element size and update the echart view when it changes
        addChartResizeListener () {
          const instance = ResizeListener({
            strategy: 'scroll'.callOnAdd: true
          })
          instance.listenTo(this.$el, () = > {
            if (!this.instanceChart) return
            this.instanceChart.resize()
          })
        },
        // 05. Automatically adapt echart when window is zoomed
        handleWindowResize () {
          if (!this.$refs.barChart) return
          this.instanceChart.resize()
        }
      }
    }
    </script>
    <style scoped>
    .barChart {
      width: 100%;
      height: 100%;
    }
    </style>
    Copy the code
  • Use the illustration

    <template>
      <div class="chart">
        <bar-chart :seriesData="seriesData" :extraOption="extraOption"/>
      </div>
    </template>
    
    <script>
    import barChart from '@/components/BarChart'
    import { fitChartSize } from '@/utils/echartUtils'
    // Business data
    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 () {
        // When the window size changes, reassign to the custom configuration to implement font adaptation
        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>
    Copy the code

Still a little small caton, hope to see the big man can put forward some solutions

Example repository address: gitee.com/coderlzw/ec…