likes
comments
collection
share

React可视化大屏编辑器的实现方案

作者站长头像
站长
· 阅读数 35

前言

近两年一直在做数据分析可视化的项目,我主要是负责可视化大屏编辑器和可视化组件的开发,由于历史原因技术栈用的是jQuery。本人也很喜欢这个项目于是在空闲时间把主要功能用React+ts实现了下,在这里做一个记录

编辑器主要功能是从左侧选中组件,拖入到中间画布。可以对画布中的组件进行移动,缩放,旋转,通过右侧属性栏目设置组件样式和数据。redux中存放大屏基础配置JSON和画布中所有组件JSON。这些操作都是修改redux中组件的对应的配置项

编辑器最终大概是下面这样。顶部操作按钮区域(保存,预览等),左侧组件列表区域,中间大屏画布区域,右侧组件属性设置区域

React可视化大屏编辑器的实现方案

组件配置项

export interface Rect {
  left?: number
  top?: number
  width: number
  height: number
}

export interface Plugin {
  url: string
  name: string
}

export interface Data {
  type: 'static' | 'api'
  widgetData?: any
  apiUrl?: string
  loop?: number //s
  ruler?: any //数据规则
  displayForm: 'table' | 'codeEdit' //数据展示插件 表格,代码编辑器
}

export interface Widget {
  name: string
  plugin: Plugin
  rect: Rect
  rotate?: number
  img: string
  config: any
  dataConfig?: Data
}

大屏配置项

interface ScreenWidget {
  widgetId: string
  zIndex: number
  children?: ScreenWidget[]
}
export interface Screen {
  name: string
  width: number
  height: number
  coverImage: string
  scale: number
  screenZoom: 'scaling' | 'Hscaling' | 'Wscaling' | 'phone' | 'none'
  backgroundColor: string
  backgroundImage: string
  //大屏组件列表
  screenWidget: ScreenWidget[]
  //大屏组件层级
  widgetIndex: number
  //选中组件id集合
  activeWidgets: string[]
}

组件拖入

ahooks中的useDrop & useDrag,具体用法参考官网示例

组件移动

react-moveable

刻度尺

ruler

组件移动,参数设置修改redux中组件的对应的配置项

immutability-helper

设置参数时都是修改当前选中组件的配置,在设置时通过json路径设置

例如:修改柱状图第一个柱子的颜色,对应的路径是 config.bars.0.color

export const getObjByPath = (field: string, value: any) => {
  let obj = {}
  if (typeof field === 'undefined' || typeof value === 'undefined') {
    return undefined
  }
  if (typeof field === 'string' && field.indexOf('.') === -1) {
    obj[field] = { $set: value }
    return obj
  }
  const ids = field.split('.')
  let th = ''
  for (let i = 0; i < ids.length; i++) {
    th += "['" + ids[i] + "']"
    if (!eval(`obj${th}`)) {
      eval(`obj${th}={}`)
    }
  }
  eval(`obj${th}={$set: value}`)
  return obj
}
import update from 'immutability-helper'
const widget = getActiveWidget() //获取当前选中组件配置项
const path = 'config.bars.0.color'
const value = '#fff'
const obj = getObjByPath(path, value) 
const newWidgetObj = update(widget, obj)
setActiveWidget(newWidgetObj)  //更新当前选中组件配置项

实现方案的内容基本就是上面这些,下篇文章会写一些组件的动态加载,优化,错误处理和大屏保存后的组件定制化