React项目中使用HighCharts
大家都知道BizCharts是基于react封装的一套图表工具,而HighCharts是基于jQuery的。但是由于本人对BizCharts甚是不熟,所以在react项目开发中选择了HighCharts,在使用及对接数据的时候也是遇到了各种问题。
下面简单说下项目需求:首先是两个网络数据源,要求随时间的变化网络折线图不断更新,且当展示一定的数据点后开始折线图从右往左平移。
下面附上该组件所有代码。
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import assign from 'object-assign'
import { autorun } from 'mobx'
import { observer } from 'mobx-react'
import Highcharts from 'highcharts'
import _ from 'lodash'
import ClassNames from 'classnames'
import './index.less'
@observer
class NetworkStatus extends Component {
static propTypes = {
style: PropTypes.object,
onClose: PropTypes.func,
localPings: PropTypes.array,
fullPings: PropTypes.array,
}
static defaultProps = {
style: {},
onClose: _.noop,
localPings: [],
fullPings: [],
}
state = {
stopFullPing: false,
avgFullPingDelay: 0,
lastFullPingDelay: 0,
avgLocalPingDelay: 0,
lastLocalPingDelay: 0,
}
componentDidMount() {
const newChart = Highcharts.chart('chart_wrap', {
chart: {
type: 'spline',
animation: false,
marginRight: 10,
},
// 自定义数据列颜色,默认从第一个数据列起调用第一个颜色代码,依次往后。
colors: ['#f08500', '#9dc239'],
// 不显示右下角的版权信息
credits: {
enabled: false,
},
plotOptions: {
series: {
// 去掉鼠标悬浮到曲线上的默认线条加粗效果
states: {
hover: {
enabled: false,
},
},
// 禁用图例点击事件
events: {
legendItemClick(e) {
return false
},
},
},
},
// 是否使用国际标准时间
time: {
useUTC: false,
},
// 不显示头部标题
title: {
text: null,
},
xAxis: {
type: 'datetime',
// tickPixelInterval: 150,
tickInterval: 60000,
// labels: {
// step: 60,
// },
},
yAxis: {
title: {
text: null,
},
},
// 修改图例样式
legend: {
enabled: true,
itemStyle: { color: '#4a4a4a', fontSize: '12px', fontWeight: 'normal' },
itemHoverStyle: { cursor: 'normal' },
},
// 不显示导出按钮
exporting: {
enabled: false,
},
// 数据列具体数据设置
series: [{
// 表示使用哪个y轴
yAxis: 0,
name: 'Full Ping Delays',
lineWidth: 1,
// 不显示曲线上的实心圆点
marker: {
enabled: false,
},
data: [],
}, {
yAxis: 0,
name: 'Ping Delays',
lineWidth: 1,
// 不显示曲线上的实心圆点
marker: {
enabled: false,
},
data: [],
}],
})
this.chart = newChart
this.initChartData(this.props.fullPings, this.props.localPings)
// store中存储的网络数据每次更新时触发以下代码的执行,即动态往折线图中添加点。
this.cancelAutoRuns = [
autorun(() => {
if (!_.isEmpty(this.props.fullPings)) {
const fullPingsArrayLength = this.props.fullPings.length
let totalFullPingDelay = 0
_.forEach(this.props.fullPings, (pings) => {
totalFullPingDelay += pings.delay
})
this.setState({
avgFullPingDelay: Math.round(totalFullPingDelay / fullPingsArrayLength),
lastFullPingDelay: this.props.fullPings[fullPingsArrayLength - 1].delay,
})
const x = this.props.fullPings[fullPingsArrayLength - 1].time
const y = this.props.fullPings[fullPingsArrayLength - 1].delay
const seriesData = this.chart.series[0].data
const shift = seriesData.length > 200
if (x !== seriesData[seriesData.length - 1].x) {
this.chart.series[0].addPoint([x, y], false, shift, false)
}
this.chart.redraw()
}
}),
autorun(() => {
if (!_.isEmpty(this.props.localPings)) {
const localPingsArrayLength = this.props.localPings.length
let totalLocalPingDelay = 0
_.forEach(this.props.localPings, (pings) => {
totalLocalPingDelay += pings.delay
})
this.setState({
avgLocalPingDelay: Math.round(totalLocalPingDelay / localPingsArrayLength),
lastLocalPingDelay: this.props.localPings[localPingsArrayLength - 1].delay,
})
const x = this.props.localPings[localPingsArrayLength - 1].time
const y = this.props.localPings[localPingsArrayLength - 1].delay
const seriesData = this.chart.series[1].data
const shift = seriesData.length > 200
if (x !== seriesData[seriesData.length - 1].x) {
this.chart.series[1].addPoint([x, y], false, shift, false)
}
this.chart.redraw()
}
}),
]
}
componentWillUnmount() {
this.chart.destroy()
_.forEach(this.cancelAutoRuns, f => f())
}
chart = null
cancelAutoRuns = null
// 初始化localPings和fullPings折线图数据
initChartData = (fullPings, localPings) => {
if (_.isEmpty(fullPings) || _.isEmpty(localPings)) {
return
}
const fullPingsArrayLength = fullPings.length
const localPingsArrayLength = localPings.length
let totalFullPingDelay = 0
let totalLocalPingDelay = 0
// 初始化数据时,当store中存储的网络数据少于折线图中定义的展示的点的个数(200)时就直接循环store中所有的数据,当store中数据大于点个数时,取store中后200个数据进行展示
if (fullPingsArrayLength > 200 && localPingsArrayLength > 200) {
const newFullPings = fullPings.slice(-200)
const newLocalPings = localPings.slice(-200)
this.cyclicPingsData(newFullPings, newLocalPings)
} else {
this.cyclicPingsData(fullPings, localPings)
}
_.forEach(fullPings, (pings) => {
totalFullPingDelay += pings.delay
})
_.forEach(localPings, (pings) => {
totalLocalPingDelay += pings.delay
})
this.setState({
avgFullPingDelay: Math.round(totalFullPingDelay / fullPingsArrayLength),
lastFullPingDelay: fullPings[fullPingsArrayLength - 1].delay,
avgLocalPingDelay: Math.round(totalLocalPingDelay / localPingsArrayLength),
lastLocalPingDelay: localPings[localPingsArrayLength - 1].delay,
})
}
cyclicPingsData = (fullPings, localPings) => {
_.forEach(fullPings, (pings) => {
const x = pings.time
const y = pings.delay
this.chart.series[0].addPoint([x, y], false, false, true)
})
_.forEach(localPings, (pings) => {
const x = pings.time
const y = pings.delay
this.chart.series[1].addPoint([x, y], false, false, true)
})
this.chart.redraw()
}
handleClickCloseBtn = () => {
this.props.onClose()
}
handleClickChangeBtn = () => {
const { stopFullPing } = this.state
this.setState({ stopFullPing: !stopFullPing })
// 点击按钮的同时隐藏或显示 Full Ping Delays 折线
if (!this.state.stopFullPing) {
this.chart.series[0].hide()
} else {
this.chart.series[0].show()
}
}
render() {
const wrapStyles = assign({}, this.props.style)
const hideFullPingTextClasses = ClassNames({
hide: this.state.stopFullPing === true,
})
return (
<div className="network_status_component_wrap" style={wrapStyles}>
<div className="header">
<span
className="exit_icon"
onClick={this.handleClickCloseBtn}
role="button"
tabIndex="0"
/>
</div>
<div className="container_wrap">
<div className="text_information_wrap">
<p className="text_one_p">
<span>server: <span className="black_color">47.94.115.241:501</span></span>
<span
className="button_span"
onClick={this.handleClickChangeBtn}
role="button"
tabIndex="0"
>
{
this.state.stopFullPing ? 'start full ping' : 'stop full ping'
}
</span>
<span className="black_color">124.204.55.50 中国 北京 鹏博士/联通</span>
</p>
<p id="text_two_p" className={hideFullPingTextClasses}>
<span className="margin_right">avg full ping delay: <span>{this.state.avgFullPingDelay}</span> ms</span>
<span>last full ping delay: <span>{this.state.lastFullPingDelay}</span> ms</span>
</p>
<p className="text_three_p">
<span className="margin_right">avg ping delay: <span>{this.state.avgLocalPingDelay}</span> ms</span>
<span>last ping delay: <span>{this.state.lastLocalPingDelay}</span> ms</span>
</p>
</div>
<div id="chart_wrap" />
</div>
</div>
)
}
}
export default NetworkStatus
如下是效果图:

React项目中使用HighCharts的更多相关文章
- 如何在非 React 项目中使用 Redux
本文作者:胡子大哈 原文链接:https://scriptoj.com/topic/178/如何在非-react-项目中使用-redux 转载请注明出处,保留原文链接和作者信息. 目录 1.前言 2. ...
- 如何优雅地在React项目中使用Redux
前言 或许你当前的项目还没有到应用Redux的程度,但提前了解一下也没有坏处,本文不会安利大家使用Redux 概念 首先我们会用到哪些框架和工具呢? React UI框架 Redux 状态管理工具,与 ...
- react项目中实现元素的拖动和缩放实例
在react项目中实现此功能可借助 react-rnd 库,文档地址:https://github.com/bokuweb/react-rnd#Screenshot .下面是实例运用: import ...
- React项目中实现右键自定义菜单
最近在react项目中需要实现一个,右键自定义菜单功能.找了找发现纯react项目里没有什么工具可以实现这样的功能,所以在网上搜了搜相关资料.下面我会附上完整的组件代码. (注:以下代码非本人原创,具 ...
- React项目中使用Mobx状态管理(二)
并上一节使用的是普通的数据状态管理,不过官方推荐使用装饰器模式,而在默认的react项目中是不支持装饰器的,需要手动启用. 官方参考 一.添加配置 官方提供了四种方法, 方法一.使用TypeScrip ...
- 在react项目中使用ECharts
这里我们要在自己搭建的react项目中使用ECharts,我们可以在ECharts官网上看到有一种方式是在 webpack 中使用 ECharts,我们需要的就是这种方法. 我们在使用ECharts之 ...
- 优雅的在React项目中使用Redux
概念 首先我们会用到哪些框架和工具呢? React UI框架 Redux 状态管理工具,与React没有任何关系,其他UI框架也可以使用Redux react-redux React插件,作用:方便在 ...
- 深入浅出TypeScript(5)- 在React项目中使用TypeScript
前言 在第二小节中,我们讨论了利用TypeScript创建Web项目的实现,在本下节,我们讨论一下如何结合React创建一个具备TypeScript类型的应用项目. 准备 Webpack配置在第二小节 ...
- redux在react项目中的应用
今天想跟大家分享一下redux在react项目中的简单使用 1 1.redux使用相关的安装 yarn add redux yarn add react-redux(连接react和redux) 2. ...
随机推荐
- 有多个正整数存放在数组中,编写一个函数要求偶数在左边由小到大顺序放置,奇数在右边,也是由小到大顺序放置,Java实现
思路: * 1.首先分左右 * 2.分好再排序(左边和右边都单独排序) 第一步:分左右 可得注意了: 大体思路最先是从两头出发分成4种情况讨论(左or右,奇数or偶数)循环处理,出口是双层的嵌套循环( ...
- RDLC报表刷新问题
使用RDLC做报表,当数据源发生改变时重新绑定数据发现报表没有变化,跟踪时发现数据绑定已经正确执行,前端也显示了加载过程,但内容未刷新. 在代码中使用了 ReportViewer1.LocalRepo ...
- F#周报2019年第2期
新闻 Rider上的拼写助手,对未使用引用的代码分析及更多F#相关特性的更新 .NET开源革命开始 ML.NET 0.9发布记录 测试驱动的集成开发环境 Giraffe在GitHub上超过了1000个 ...
- Codeforces 706C - Hard problem - [DP]
题目链接:https://codeforces.com/problemset/problem/706/C 题意: 给出 $n$ 个字符串,对于第 $i$ 个字符串,你可以选择花费 $c_i$ 来将它整 ...
- java8新特性--Stream的基本介绍和使用
什么是Stream? Stream是一个来自数据源的元素队列并可以进行聚合操作. 数据源:流的来源. 可以是集合,数组,I/O channel, 产生器generator 等 聚合操作:类似SQL语句 ...
- spss缺失值填充步骤
缺失值填充是数据预处理最基本的步骤,一般能想到的是固定值填充(均值等统计学方法).根据与本列有相关关系的列函数表示来填充.这次我用的是em算法进行填充,具体原理后续补充. 主要记录一下步骤: 工具栏: ...
- http 你造吗?
HTTP是一个属于应用层的面向对象的协议,由于其简捷.快速的方式,适用于分布式超媒体信息系统.它于1990年提出,经过几年的使用与发展,得到不断地完善和扩展.目前在WWW中使用的是HTTP/1.0的第 ...
- 公网k8s
dm :32750/swagger/ 统一在 cd /opt/iot 删除容器,自动创建容器 dm 更新dm和acl包 dm源文件chart包 cd /var/lib/helmrepo/ h ...
- netframework webapi exceptionless
1.webapi项目 添加nuget exceptionless webapi 2.在exceptionless server端添加项目,注意key 3.修改api项目的webconfig &l ...
- Linux文件系统的硬连接和软连接
title: Linux文件系统的硬连接和软连接 date: 2018-02-06T20:26:25+08:00 tags: ["文件系统"] categories: [" ...