zoukankan      html  css  js  c++  java
  • 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

    如下是效果图:

  • 相关阅读:
    SPSS Clementine 数据挖掘入门 (2)
    Oracle与SQL Server数据库管理对比
    在SharePoint中修改AD用户密码的WebPart
    【html】html 特殊字符大全
    【javascript】csshover 解决 ie6 下 hover 兼容问题
    【css】纯 css 制作带三角的边框
    【javascript】无缝滚动——上下
    【css】利用小数解析差异解决浏览器兼容性问题
    【javascript】checkbox——类似邮箱全选功能(完整版)
    【javascript】无缝滚动——左右
  • 原文地址:https://www.cnblogs.com/chenbeibei520/p/9849397.html
Copyright © 2011-2022 走看看