Как создать спидометр в реакции родного - PullRequest
0 голосов
/ 29 июня 2018

Я создаю диаграммы, используя d3 и svg в реагировать нативно, в котором я создал диаграмму прогресса. Я хотел бы использовать этот индикатор в качестве спидометра, когда стрелка показывает текущее значение. Может кто-нибудь сказать мне, как создать спидометр в реагировать родной.

    import React, { PureComponent } from 'react';
import {
  View,
} from 'react-native';
import PropTypes from 'prop-types';
import * as shape from 'd3-shape';
import Path from './animated-path';
import Svg, { G } from 'react-native-svg';

export default class Gauge extends PureComponent {
  state = {
    height: 0,
    width: 0,
  }

  _onLayout(event) {
    const {
      nativeEvent: {
        layout: {
          height,
          width,
        }
      }
    } = event;
    this.setState({height, width});
  }
  render() {
    const {
      style,
      progressColor,
      backgroundColor,
      strokeWidth,
      startAngle,
      endAngle,
      animate,
      animationDuration,
      children,
      cornerRadius,
    } = this.props

    let { progress } = this.props

    const {
      height, width
    } = this.state

    const outerDiameter = Math.min(width, height)

    if (!isFinite(progress) || isNaN(progress)) {
      progress = 0;
    }

    const data = [
      {
        key: 'rest',
        value: 1 - progress,
        color: backgroundColor,
      },
      {
        key: 'progress',
        value: progress,
        color: progressColor,
      }
    ]

    const pieSlices = shape
          .pie()
          .value(d => d.value)
          .sort((a) => a.key === 'rest' ? 1 : -1)
          .startAngle(startAngle)
          .endAngle(endAngle)
          (data)

    const arcs = pieSlices.map((slice, index) => (
      {
        ...data[index],
        ...slice,
        path: shape.arc()
        .outerRadius(outerDiameter / 2)
        .innerRadius((outerDiameter / 2) - strokeWidth)
        .startAngle(index === 0 ? startAngle : slice.startAngle)
        .endAngle(index === 0 ? endAngle : slice.endAngle)
        .cornerRadius(cornerRadius)
        (),
      }
    ))

    const extraProps = {
      width,
      height,
    }

    return (
      <View style={ style } onLayout={event => this._onLayout(event)}>
        {
          height > 0 && width > 0 &&
          <Svg style={{height, width}}>
            <G x={width / 2}
              y={height / 2}
              >
              {
                React.Children.map(children, child => {
                  if (child && child.props.belowChart) {
                    return React.cloneElement(child, extraProps)
                  }
                  return null
                })
              }
              {
                arcs.map((shape, index) => {
                  return (
                    <Path
                       key={index}
                       fill={shape.color}
                       d={shape.path}
                       animate={animate}
                       animationDuration={animationDuration}
                    />
                  )
                })
              }
              {
                React.Children.map(children, child => {
                  if (child && !child.props.belowChart) {
                    return React.cloneElement(child, extraProps)
                  }
                  return null
                })
              }
            </G>
          </Svg>
        }
      </View>
    )
  }
}

Gauge.propTypes = {
  progress: PropTypes.number.isRequired,
  style: PropTypes.any,
  progressColor: PropTypes.any,
  backgroundColor: PropTypes.any,
  strokeWidth: PropTypes.number,
  startAngle: PropTypes.number,
  endAngle: PropTypes.number,
  animate: PropTypes.bool,
  cornerRadius: PropTypes.number,
  animationDuration: PropTypes.number,
}

Gauge.defaultProps = {
  progressColor: 'black',
  backgroundColor: '#ECECEC',
  strokeWidth: 5,
  startAngle: 0,
  endAngle: Math.PI * 2,
  cornerRadius: 45,
}

App.js

<GaugeChartExample />

Полученный результат выглядит следующим образом:

Output

...