从0到1实现大屏可视化

10,257 阅读3分钟

简介

随着大数据的蓬勃发展,各行业对数据价值的重视程度增加。大屏可视化也已经在各个企业中应用。本节介绍如何从 0 到 1 实现一个简单大屏项目。

搭建项目

npx create-react-app 项目名
  • 进入项目根目录,添加可视化工具。
  • DataV,提供了很多边框和一些大屏需要的组件。
npm i @jiaminghi/data-view-react
  • echarts,图表绘制工具,你能想到的它基本都有。
npm i echarts

image.png

  • 一个简单的项目就搭建完成了。这个示例项目中我把多余的文件都删除了。

大屏适配

  • 大屏项目需要在不同分辨率下进行展示,所以在开发前就需要确认选用什么方式进行适配。
  • 这里主要介绍 3、4两种方式,常用方式:
  1. pxvh\vw% 比。
  • 根据设计图的 px 尺寸,把宽高分层100份。在开发时,所有的长度单位都按这份比例来编写。
  1. 媒体查询 @media
  • 根据设计图,在不同分辨率下写出对应的样式。需要写大量的样式,定制化要求不多就不要考虑。
@media only screen and (max-width: 1000px) { 
  .div-class { width: 720px; } 
}
@media only screen and (max-width: 1920px) { 
  .div-class { width: 1200px; } 
}
  1. pxrem
  • CSS中规定 1rem 的大小就是根元素<html>font-size的值。
  • 当使用了其他组件,其内部设置的都是px。需要在添加一个根据font-size的值计算当前比例下设置的长度转换为对应的px值。
  • 监听onresize方法,实时计算当前分辨率下font-size的值。开发时全程使用rem布局。
// 计算 fontSize
function setFontSize() {
  let designWidth = 1920 
  let designHeight = 1080 
  var fontSize =
    document.documentElement.clientWidth / document.documentElement.clientHeight 
    < designWidth / designHeight
      ? (document.documentElement.clientWidth / designWidth) * 100
      : (document.documentElement.clientHeight / designHeight) * 100
  document.querySelector('html').style.fontSize = fontSize + 'px'
}

// 防抖 在一定时间内 只执行最后一次
const debounce = (fn, delay) => {
  let timer
  return function () {
    if (timer) {
      clearTimeout(timer)
    }
    timer = setTimeout(() => {
      fn()
    }, delay)
  }
}
.App {
  height: 100vh;
  width: 100vw;
  font-size: 16px;
}

.box-x {
  width: 4rem;
  height: 2rem;
}
  • 使用。
  useEffect(() => {
    setFontSize()
    const cancalDebounce = debounce(setFontSize, 100)
    // 监听
    window.addEventListener('resize', cancalDebounce)

    return () => {
      // 移除
      window.removeEventListener('resize', cancalDebounce)
    }
  }, [])

1.gif

  1. transform属性的 scale 方法。
  • 计算缩放比,对整个元素进行缩放。
// 缩放比
function scale() {
  let designWidth = 1920
  let designHeight = 1080
  let scale =
    document.documentElement.clientWidth / document.documentElement.clientHeight 
    < designWidth / designHeight
      ? document.documentElement.clientWidth / designWidth
      : document.documentElement.clientHeight / designHeight
  return scale
}
.App {
  width: 1920px;
  height: 1080px;
  transform-origin: 0 0;
  position: absolute;
  left: 50%;
  top: 50%;
}

.box-x {
  width: 400px;
  height: 200px;
}
  • 使用
  const [state, setState] = useState({ scale: 1 })
  useEffect(() => {
    setState({
      scale: scale()
    })

    window.onresize = function () {
      setState({
        scale: scale()
      })
    }

    return () => {
      // 清除
      window.onresize = null
    }
  }, [])
<div
  className="App"
  style={{
    transform: `scale(${state.scale}) translate(-50%,-50%)`
  }}
>...</div>

2.gif

小结

适配方案除了本节介绍的还有有很多。目前没有完美的方案,或多或少都有一点问题。比如等比缩放,当比例不对时会出现留白。百分比计算,当比例不对时会出现拉伸。开发中都是根据客户需求进行一步步优化,以求达到完美。

布局

  • 在拿到设计图后,通过设计图的布局来对页面进行层级划分,一般情况都是两层,背景层、图表层。当需要使用地图时,背景层就变成地图层。
  • 在开发时,每个图表都应该是一个单独的组件。这样能减少代码的耦合和多人开发时的冲突。
  • 这里使用的是第4种适配方案,因为没有设计图就随意开发了。

4.gif

  • 使用等比缩放方案,所有布局按设计稿开发就行。
  • 需要注意CSS命名需要一定规则,防止不同组件中的样式冲突。
// App.js

import { useState, useEffect } from 'react'
import { scale } from './util'
import { Box1, Box2, Box3, Box4, Box5, Head } from './content'
import './App.css'

function App() {
  const [state, setState] = useState({ scale: 1 })
  useEffect(() => {
    setState({
      scale: scale()
    })

    window.onresize = function () {
      setState({
        scale: scale()
      })
    }

    return () => {
      // 清除
      window.onresize = null
    }
  }, [])

  return (
    <div
      className="App"
      style={{
        transform: `scale(${state.scale}) translate(-50%,-50%)`
      }}
    >
      <Head></Head>
      <Box1 />
      <Box2 />
      <Box3 />
      <Box4 />
      <Box5 />
    </div>
  )
}
export default App

image.png

  • 代码比较多,这里就展示下目录。
  • 图表层的内容,都是存放在content目录下的。

绘制图表

  • 可视化开发工具很多,选择适合自己项目的就行了。
  • 本节选用的是echarts图表库,先简单的介绍一下它。

使用echarts

  • echarts 官网
  • 可随意切换 Canvas、SVG 两种渲染方式。
  • 企业中常用的图表都支持。
  • 是高级图表库,通过配置信息绘制图表。
  • 能配合百度地图进行可视化开发。
// content/Box1/Box.jsx

import { useEffect } from 'react'
import { BorderBox1 } from '@jiaminghi/data-view-react'
import * as echarts from 'echarts'
import './box.css'

function Box() {
  useEffect(() => {
    const chartDom = document.getElementById('box1-main')
    const myChart = echarts.init(chartDom)
    const option = {
      tooltip: {
        trigger: 'item'
      },
      legend: {
        top: '5%',
        left: 'center',
        textStyle: {
          color: '#fff'
        }
      },
      series: [
        {
          name: '职位',
          type: 'pie',
          radius: ['40%', '70%'],
          avoidLabelOverlap: false,
          itemStyle: {
            borderRadius: 10,
            borderColor: '#fff',
            borderWidth: 2
          },
          label: {
            show: false,
            position: 'center',
            textStyle: {
              color: '#fff'
            }
          },
          emphasis: {
            label: {
              show: true,
              fontSize: '40',
              fontWeight: 'bold'
            }
          },
          labelLine: {
            show: false
          },
          data: [
            { value: 1048, name: '后端' },
            { value: 735, name: '前端' },
            { value: 580, name: 'IOS' },
            { value: 484, name: '安卓' },
            { value: 300, name: '大数据' }
          ]
        }
      ]
    }
    option && myChart.setOption(option)
  }, [])

  return (
    <div className="box-1">
      <BorderBox1>
        <div id="box1-main" style={{ width: '590px', height: '500px' }}></div>
      </BorderBox1>
    </div>
  )
}

export default Box
  • echarts的使用就这么简单,配置好option属性就会自动绘制图表。
  • 想深入了解的多去看看示例,echarts 示例

1.gif

  • 在每一个组件中完善图表,一个简单的大屏可视化项目就完成了。

总结

大屏可视化项目最重要的是尺寸适配,后续出问题多的都是适配没做好。当然做的时候也需要细心,关注设计搞的颜色、尺寸、图表样式等。一些小的差异在放大后也会影响美观。

我正在参与掘金技术社区创作者签约计划招募活动,点击链接报名投稿