React based large screen monitoring

Technology stack

  • React
  • ReactRouter
  • Echarts

Project introduction

  • This project was written to familiarize yourself with front-end visualization while learning about Echarts
  • The page layout combines Flex with Grid
  • Use REM to match different screen sizes
  • Statistics, ring charts, bar charts, maps, etc. in the project come from Echarts, which can update data in real time
  • The data in this project is not real data, but written for presentation
  • I found dataV after writing the project. It seems to be directly used for visual update. I will try to use it next time

preview

  1. Preview the address
  2. Making the address

Screen adaptation

Screen adaptation

  • The design is 16:9, and the ideal large screen is 16:9
  • If the screen is wide, sway the play
  • If the screen is very high, play it up and down
  1. The formula
  • Wp is the page effective width, Hp is the page effective height
  • Page left and right center, center, around the white can be
  • The first case: the device is very wide, so the page height is the height of the screen, and the page width is calculated proportionally
  • The second case: the equipment is very high, on the play. The width of the page is the width of the screen, and the page height is calculated by 16:9
  1. Then set 1rem = Wp / 100 with JS in head.
  2. You can also set
  • Header: fixed width
Header: {width: px(2420); margin: 0 auto; }Copy the code
  • The width of main is about the width of the play
 main {
    width: px(2420);
    margin: 0 auto;
}
Copy the code

Rem calculation formula

1. Rem formula

  • The size of a div on the page/the width of the page = the size of a div on the page/the width of the page
  • 1rem = Wp / 100 launch: page width = 100*rem
  • In combination with the above two points, it can be concluded that: div size on the page = (div size in the design/width of the design) * 100 * REM
  • Suppose a div is 100px long and 1920px wide in your design,
  • The div is then 100/1920 X 100rem in length on the page
  • Finally, we can write a px() function to calculate rem for 100px

Rem is actually the font size in HTML

  • Review the rem
< script > const clientWidth = document. DocumentElement. ClientWidth/width/device const clientHeight = Document. The documentElement. ClientHeight window. / / equipment highly pageWidth = clientWidth/clientHeight > 16/9? clientHeight * (16 / 9) : clientWidth; // pageWidth const pageHeight = pageWidth/(16/9) // pageHeight const string = '<style> HTML {font-size:${pageWidth/100}px // 1rem </script> </head> <body> <div id="root"></div> <script> // root.style.width = pageWidth +'px' root.style.height= pageHeight+ 'px' root.style.marginTop = (clientHeight - Margin-top </script> <script type="module" SRC ="/ SRC /main.tsx"></script> </body>Copy the code

Code: Show a div

  • Not PX, rem
  • How do I convert PX to REM?
  • Div size on the page = (div size in the design/width of the design) * 100 * rem
  • In the SCSS file
@function px($n){
  @return $n/2420*100rem
}
Copy the code
  • use
 height: px(40);
Copy the code

Flex and Grid layouts

  1. To fill the page with main
  • Level: root> App> Home > Header + main
  • The Flex layout is set up for each layer
flex:1; Display: flex; // Use flex layout flex-direction:column; // The arrangementCopy the code
  1. Home includes header and main
  • html
 <div className="home">
      <header style={{backgroundImage:`url(${headerBg})`}}></header>
        <main>
            <section className="section1"></section>
            <section className="section2"></section>
            <section className="section3"></section>
            <section className="section4"></section>
            <section className="section5"></section>
        </main>
    </div>
Copy the code
  • The CSS uses the grid layout
@import ".. /shared/helper"; .home{ flex:1; display: flex; flex-direction:column; > header{ height:px(99); background-size:cover; } > main { flex: 1; display: grid; grid-template: "box1 box2 box4 box5" 755fr "box3 box3 box4 box5" 363fr / 366fr 361fr 811fr 747fr; > .section1 { grid-area: box1; background: pink; } > .section2 { grid-area: box2; background: lightgray; } > .section3 { grid-area: box3; background: lightblue; } > .section4 { grid-area: box4; background: lightcyan; } > .section5 { grid-area: box5; background: lightyellow; }}}Copy the code

Background and border

  1. Frame:
  • Add ::before to section
  • Use box-shadow as a shadow
section{ &::before{ content: ''; position: absolute; left: 0; right: 0; bottom: 0; top: 0; border-radius: 4px; box-shadow: 17px 0 0 -16px #0e325f, -17px 0 0 -16px #0e325f, 0 17px 0 -16px #0e325f, 0 -17px 0 -16px #0e325f, 9px 0 0 -8px #0d4483, -9px 0 0 -8px #0d4483, 0 9px 0 -8px #0d4483, 0 -9px 0 -8px #0d4483,; }}Copy the code

The chart

  1. Use every
  • import * as echarts from “echarts”;
  const divRef = useRef(null)
  useEffect(()=>{
        var myChart = echarts.init(divRef.current);
        myChart.setOption(createEchartsOptions({
            xAxis: {
            options
        }));
    },[])
    return (
        <div className="title bordered">
            <h2>title</h2>
            <div ref={divRef} className="chart"></div>
        </div>
    )
Copy the code
  1. Section layout
  • Each section may contain more than one chart
  • Section1 contains chart1 and chart2
            <section className="section1">
                <Chart1></Chart1>
                <Chart2></Chart2>
            </section>
Copy the code
  • css
    • Flex layout
    • Chart1 and chart2 are arranged vertically
    • space-between
> .section1 {
      grid-area: box1;
      display: flex;
      flex-direction: column;
      justify-content: space-between;
    }
Copy the code
  1. Each chart
  • It is divided into title area and chart area
  • chart1
    • Use flex layout overall
    • Title uses the H2 tag
<div className=" traffic statistics bordered"> < H2 >< div ref={divRef} className="chart"></div> </div>Copy the code
  • css
. Height :px(315); Display :flex; // flex layout flex-direction:column; align-items:center; H2 {// flex-shrink:0; border:1px solid #0a5299; border-bottom-left-radius:4px; border-bottom-right-radius:4px; font-size:px(22); line-height:px(24); // Row height :px(10) px(28); text-shadow: 0 0 px(3) white; }. Chart {// chart area flex:1; //flex width:100%; // full width}}Copy the code

Optimization of Echarts options

  1. Using Echart to set options, found many options are repetitive, in line with the idea of encapsulation, eliminate duplication
  2. Create two files:
  • BaseEchartOptions: Some basic echartOptions
  • CreateEchartsOptions: Process the basic echartOptions and the options specific to each chart to do a consolidation
  1. code
  • baseEchartOptions
import {px} from "./px";

export const baseEchartOptions ={
    title: {show: false},
    legend: {show: false},
    grid:{
        x:px(40),
        y:px(40),
        x2:px(40),
        y2:px(40)
    },
    textStyle:{
        fontSize:px(12),
        color:'#79839e'
    },
}

Copy the code
  • createEchartsOptions
    • Options parameters include baseEchartOptions and options specific to each chart
import {baseEchartOptions} from './base-echart-options'; import {px} from './px'; Export const createEchartsOptions = (options) => {const result = {// Destruct options... baseEchartOptions, ... options, }; if (! (options? .xAxis? .axisLabel? .fontSize)) { result.xAxis = result.xAxis || {}; result.xAxis.axisLabel = result.xAxis.axisLabel || {}; result.xAxis.axisLabel.fontSize = px(12); } if (! (options? .yAxis? .axisLabel? .fontSize)) { result.yAxis = result.yAxis || {}; result.yAxis.axisLabel = result.yAxis.axisLabel || {}; result.yAxis.axisLabel.fontSize = px(12); } return result; };Copy the code
  1. use
  • import
import {createEchartsOptions} from ".. /shared/create-echarts-options";Copy the code
  • Use: pass in the required options to createEchartsOptions for integration
useEffect(()=>{ var myChart = echarts.init(divRef.current); myChart.setOption(createEchartsOptions({ xAxis: { ... }, yAxis: { ... }, series: [...] })); }, [])Copy the code