前言

最近正在学习数据可视化, 这里记录一下一些心得与成果, 采用的技术是 (svg + react + d3)。 这种实现可视化方式本人个人感觉超级不错,如果你是有一定的基础的同学,强烈推荐一下。

效果

整体效果如下:

这个是普通的速度仪表盘,有没有开发太多的动态交互,唯一的交互是点击图片最上面的加速减速就能够调整速度了。

开发思路

搭建开发环境

使用create-react-app创建一个新的项目,添加依赖d3

yarn add d3

初始化数据

这里速度范围是[0, 200], 对应角度范围个人设置是[150, 390], 很明显这是一个线性比例尺。速度间隔是2。代码如下

const scale = d3.scaleLinear().domain([0, 200]).range([150, 360 + 30])
const ticks = scale.ticks(100) // 200 / 2 => 100 

构建外部圈


function Chart(props) {const { width, height, margin } = propsreturn (<svg width={width} height={height}><g transform={`translate(${margin.left}, ${margin.top})`}>{props.children}</g></svg>)
}......
export default class Meter extends Component { ...     render () {// config => {width: xxx, height: xxx, margin: xxx}return (<div className={'container'}><Chart {...config}><g><circle cx={0} cy={0} r={204} fill={'rgba(158, 158, 158, .4)'}></circle><circle cx={0} cy={0} r={196} fill={'#FFF'}></circle><circle cx={0} cy={0} r={200} fill={'transparent'} stroke={'#000'}></circle></g></Chart></div>)}
}

上面其实是绘画了三个圆, 利用SVG后面的绘制的图画,会覆盖前面的图画的特性。先画最外面,然后最里面,最后中间的圆。 就把最外层的圈给描绘出来了,效果如下:

描绘刻度尺

接着上面的代码结构,我们开始刻画刻度尺

    ......
export default class Meter extends Component { ...     render () {// config => {width: xxx, height: xxx, margin: xxx}return (<div className={'container'}><Chart {...config}><g><circle cx={0} cy={0} r={204} fill={'rgba(158, 158, 158, .4)'}></circle><circle cx={0} cy={0} r={196} fill={'#FFF'}></circle><circle cx={0} cy={0} r={200} fill={'transparent'} stroke={'#000'}></circle></g><g fill={'transport'} stroke={'#000000'}>{ticks.map((tick) => {let IS_20_TIME = tick % 20 === 0let title = IS_20_TIME ? <text x={160} dominantBaseline={'middle'} textAnchor={'end'}>{tick}</text> : ''return (<g transform={`rotate(${scale(tick)})`} key={tick}><path d={`M165, 0L185,0`} strokeWidth={IS_20_TIME ? 3 : 1}></path>{title}</g>)})}</g></Chart></div>)}
}

这里刻画刻度尺,我的思路很简单,刻度尺是对速度大小的描述,而速度跟角度又是线性相关,反过来,速度对应角度。所以,我只是需要根据速度所对应的角度,而对水平刻度进行旋转即可。效果大家可以看到:

指向针

指向针其实就是一个圆 + 三角形的组合,代码如下:

 <circle cx={0} cy={0} r={10} fill={'#'}></circle><path d={`M-20, 5L-20, -5L130, 0Z`} transform={`rotate(150)`}><animateTransform ></animateTransform></path>

上面本人实现的比较粗糙,大家可以把这个封装成一个shape, 以后可以直接复用的,后面如果需要旋转,可以通过<g>元素来实现。

到这一步,一个简单的仪表盘就初具原型了

控制指针转动

指针的转动是根据速度来的,所以我们需要先定义一个speed的状态。

constructor(props) {super(props)this.state = {speed: 0}}

接下来,我们需要把speed映射到指针上面。怎么处理呢
还记得前面定义的scale,这个是一个线性比例尺,通过它我们能够获取不同速度对应的角度
我们把上面的指向针代码进行改造

const {speed} = this.state
......
<circle cx={0} cy={0} r={10} fill={'#'}></circle>
<path d={`M-20, 5L-20, -5L130, 0Z`} transform={`rotate(${scale(speed)})`}><animateTransform ></animateTransform>
</path>

这样我们设置不同的speed就能在页面控制指针指向不同的刻度尺。

速度标识区间

所谓的速度标识区间,其实就是几段圆弧,通过不同的颜色来告知进入不同的速度区间。
这里我对圆弧进行了封装,底层通过d3的arc方法来创建圆弧。

function LArc(props) {const { start, end, color } = propslet _arc = d3.arc()({innerRadius: 165,outerRadius: 185,startAngle: Math.PI * 2 * (scale(start) + 90) / 360,endAngle: Math.PI * 2 * (scale(end) + 90) / 360})return (<path d={_arc} fill={color}></path>)
}

这里其实还有一个问题,就是需要先加载速度标识区间,然后再去添加刻度尺,不然标识区间会覆盖刻度尺(切记)。
这样一个基本速度仪表盘就出来了

如果你能明白上面的实现思路,我觉得你可以自己实现一个时钟

如果你想了解更多:比如指示器如何实现的
请参考
https://github.com/cookhot/i-...
(本人会在里面不定期增加新图表哦)

手动实现一个速度仪表盘相关推荐

  1. Qt官方示例-速度仪表盘

    该刻度盘控件为一个速度仪表盘. 预览 运行演示 分析 采用Qml语言实现: 使用到了图片素材(刻度盘,指示器,指示器阴影,覆盖层): 它结合了Image元素,Rotation变换和SpringAnim ...

  2. 自定义View实战(一) 汽车速度仪表盘

    自定义View实战(一) 汽车速度仪表盘 转载请以链接形式标明出处: http://blog.csdn.net/lxk_1993/article/details/51373269 本文出自:[lxk_ ...

  3. R语言使用rnorm函数生成正太分布数据、使用plot函数生成画布、设定轴标签、设定轴范围、轴标题、使用locator函数将图像进入定位模式、在画布内手动绘制一个多边形

    R语言使用rnorm函数生成正太分布数据.使用plot函数生成画布.设定轴标签.设定轴范围.轴标题.使用locator函数将图像进入定位模式.在画布内手动绘制一个多边形 目录 R语言使用rnorm函数 ...

  4. 汽车大灯灯座模具设计_汽车换挡器模具设计_汽车速度仪表盘模具设计_汽车变速箱.solidworks 设计_汽车烟灰上盖模具设计_汽车内部饰条模具设计_汽车悬架悬挂系统模型_车灯装饰件模具设计……

    汽车中控面板模具设计 小车汽车保险杠模具设计 升降工程车 履带雪地摩托车结构3D图纸 step格式 汽车底盘悬架设计3D图纸 汽车后视灯模具设计 电动车模型 全向轮机器人车底盘3D图纸 Fusion ...

  5. 如何用JavaScript手动实现一个栈

    什么是栈(Stack) 栈是一种遵从后进先出(LIFO)原则的有序集合. 新添加的或待删除的元素都保存在栈的末尾,称为栈顶,另一端叫栈底. 在栈里,新元素都靠近栈顶,旧元素都接近栈底 现实中的例子 在 ...

  6. uglifyjs报错 webpack_基于vue2.X的webpack基本配置,教你手动撸一个webpack4的配置

    webpack说复杂也不复杂.不复杂,核心概念不外乎是entry, output, loader, plugins.webpack4还新增了optimization选项,用于代码分割和打包优化.现在w ...

  7. 从原理到实践手动拼凑一个Linux系统

    从原理到实践手动拼凑一个Linux系统 转载于:https://blog.51cto.com/suninger123/1371464

  8. 三、如何手动实现一个微前端框架雏形

    如何手动实现一个微前端框架雏形 一.了解微前端 1. 什么是微前端 为了解决一整块儿庞大的前端服务所带来的变更和拓展方面的限制,将整体前端服务拆分成一些更小.更简单的,能够独立开发.测试部署的小块儿. ...

  9. vsc写vue生成基本代码快捷键_基于vue2.X的webpack基本配置,教你手动撸一个webpack4的配置...

    webpack说复杂也不复杂.不复杂,核心概念不外乎是entry, output, loader, plugins.webpack4还新增了optimization选项,用于代码分割和打包优化.现在w ...

最新文章

  1. 【jquery】$.each的使用方法
  2. 如何将spring源码作为导入eclipse中,变成一个普通的项目(git、github)
  3. Proguard 部分类不混淆的技巧
  4. python去重保留唯一一个值_Python DataFrame使用drop_duplicates()函数去重(保留重复值,取重复值)...
  5. 蓝桥杯第六届国赛JAVA真题----表格计算
  6. Linux内核:了解Linux内核抢占
  7. 深度学习——Optimizer算法学习笔记
  8. 数据--第43课 - 图课后练习
  9. Delphi 的绘图功能[2] - 入门
  10. Linux下nohup、crontab的使用
  11. java 表格布局_Java怎样把表格放在绝对定位的面板上
  12. Node.js开发框架Express4.x
  13. 想你的风还是吹到了长沙
  14. android工程模式的指令,华为手机怎么进入工程模式 华为进工程模式指令
  15. 抽象类和接口的区别(之二)
  16. asterisk注册河南联通ims
  17. 【毕业设计】51-基于Multisim的篮球比赛24秒倒计时计时器的设计(仿真工程+相关芯片资料+答辩论文)
  18. 如何从 SQL Server 中的 SELECT 更新?
  19. 正弦函数的傅里叶级数展开计算
  20. 计算机基础知识集体备课,计算机集体备课(三)

热门文章

  1. php找不到dns地址,dns异常是什么意思
  2. 一个html文档的文件主题,HTML清单
  3. 存储过程提示data truncation_手机DATA重新分区教程(超详细)
  4. linux用不用装固态硬盘驱动,固态硬盘要不要安装驱动?总算弄明白了
  5. python函数分为_python 函数
  6. python绘图函数m_python绘图数据m
  7. 2022年全球及中国集电环行业发展格局与十四五供需现状分析报告
  8. CryptoAPI与openssl RSA非对称加密解密(PKCS1 PADDING)交互
  9. [c++]C++关键字之friend
  10. oracle 清空表数据的2种方式及速度比较