动态刻度可视化组件实现

前言

以前有个网友问我了一个颇有价值的问题, 有关实现数据可视化的问题, 可是这个可视化问题不是通常的柱状图, 折现图之类的,而是不规则刻度的数据可视化.因此笔者思考了一下决定本身实现一个动态刻度可视化组件的方案, 来解决这一类的需求.javascript

正文

最初的需求是这样的: css

咱们只须要输入文字, 数值比例, 就能生成如上图所示的刻度图.可是做为一名有追求的程序员, 须要对问题抽象化, 造成通用的解决方案,因此咱们开始重组需求:
由上图咱们能够拆解为一下几个需求点:

  • 支持数值自定义
  • 数值单位自定义
  • 支持刻度组件宽度自定义
  • 支持刻度线数量自定义
  • 支持刻度变化幅度自定义
  • 传入已有进度比例,即激活区范围
  • 支持刻度样式自定义
  • 支持数值样式自定义
  • 支持自定义说明文本以及说明文本自定义

以上就是笔者挖掘的通用需求,固然有其余需求也能够渐进的增长.前端

确认了以上需求以后,咱们开始选择技术选型, 笔者以前经常使用的技术栈是vuereact,因此接下来咱们初步确认该组件采用以下技术方案:vue

  • react + typescript + umi-library

若是你们擅长使用vue, 也能够, 笔者以前也写过如何搭建vue组件库相关的文章,感兴趣能够学习了解一下, 其本质思想是一致的.java

接下来咱们开始实现动态刻度可视化组件. 若是对umi不熟悉的,能够参考笔者以前写的文章从0到1教你搭建前端团队的组件系统(高级进阶必备).node

1. 定义基本属性类型

由以上需求分析咱们能够定义以下的属性类型:react

export interface TickerProps {
  width: number;
  maxHeight: number;
  percent: number;
  text: string;
  value: number;
  showValue: boolean;
  unit: string;
  lineNum: number;
  defaultColor: string;
  activeColor: string;
  textStyle: object;
  valueStyle: object;
}
复制代码

2. 组件总体结构

const Ticker: React.FC<TickerProps> = function(props:TickerProps) {
  const { 
    width = 100, 
    maxHeight = 10,
    percent = 50, 
    value,
    text = '瞬时能见度', 
    showValue = true, 
    unit = 'M', 
    lineNum = 12,
    defaultColor = '#06c',
    activeColor = 'red',
    valueStyle,
    textStyle
  } = props
  return (
    <div className="ticker"> { showValue && <div className="value" style={valueStyle}> { value || 0 } <span className="unit">{ unit }</span> </div> } <div className="tickerGraph"> <div className="tickerLine"> </div> <div className="tickerBar"></div> </div> { !!text && <div className="text">{ text }</div> } </div>
  );
};

export default Ticker;
复制代码

3. 视图搭建

有关刻度可视化咱们彻底采用dom实现, 因此这里笔者具体分析一下如何实现刻度视图: webpack

上图的思路就是用一个个dom来组装成随机刻度图形,因此咱们只要利用css实现这个形状, 也就成功了一半.至于激活状态,咱们会根据传入的数据量来决定激活范围,接下来会介绍如何渲染激活的刻度,也就是上图的红色区域.

4.特殊功能实现

由于该组件不少功能在搭建结构以后已经实现了, 这里咱们惟一关注的就是cssjs长度计算的问题, css实现方案有不少, 这里就不具体介绍了, 笔者这里重点介绍一下如何实现指定范围的随机高度:css3

// 生成指定范围的随机高度
const random = (min:number, max:number):number => {
  return min + Math.random() * (max - min)
}
复制代码

动态刻度条的随机高度咱们就是利用以上函数实现的, 刻度条内部实现以下:git

<div className="tickerLine" style={{borderBottomColor: defaultColor}}>
  {
    new Array(lineNum).fill(0).map((item:number, i: number) => {
      let isActive = (i + 1) <= Math.floor(lineNum * percent / 100)
      return <span 
               className="tick"
               style={{
                 height: random(3, maxHeight) + 'px', left: (gap + 2) * i + 'px',
                 backgroundColor: isActive ? activeColor : defaultColor
                }}>
             </span>
    })
  }
</div>
复制代码

gap为刻度之间的间距, 因为计算刻度的位置须要一点几何知识, 公式以下:

W = Lw * lineNum + gap * ( lineNum - 1)
复制代码

其中W表示刻度总宽度, Lw为刻度线宽度, lineNum为刻度线数量.

还有一个注意点就是激活态, 笔者使用以下函数来判断刻度是否具备激活状态:

let isActive = (i + 1) <= Math.floor(lineNum * percent / 100)
复制代码

这块也很是好理解, 也就是咱们传入的比率乘以线的总数量,便可求出哪些刻度线是须要激活的.

以上细节实现完成以后,咱们就能够来实现有点意思的刻度可视化方案啦, 以下展现的demo:

    1. 可见度测量
    1. 正态分布模型
    1. 标尺
    1. 光栅
    1. 自定义文本样式

github地址

一个基于react的轻量级刻度线可视化组件

更多开源体验地址

最后

若是想学习更多H5游戏, webpacknodegulpcss3javascriptnodeJScanvas数据可视化等前端知识和实战,欢迎在公号《趣谈前端》加入咱们的技术群一块儿学习讨论,共同探索前端的边界。

更多推荐

相关文章
相关标签/搜索