美文网首页React Native开发
React Native下基于victory-native实现可

React Native下基于victory-native实现可

作者: Ankh | 来源:发表于2019-04-01 01:05 被阅读0次

我司的一个心率图需求 :
  每5分钟采一个点,那么一天1440分钟,大概会有288个数据点, 所以在app上基本就是1sp 对应 1个数据点,看起来密密麻麻的,使用静态图表展示确实不够友好,这种情况下原本 react-native-svg-charts 这个库就无法满足需求了。

这个时候我有两个选择 :
- 使用第三方库
- 基于 `svg + d3` 手撸一个

项目中是自己手撸的,在iphone6下还是比较卡顿,那低端安卓机就不用讲了,能优化的都优化了,尽力了。

最近空下来。就试着尝试用 victory-native 这个库实现了一遍

先来介绍下这个库吧,从这个库的官网来看,是一个叫 FormidableLabs 的组织,开源了web端的基于svg实现的react图表库,该库能够交互式动态展现图表,可以说功能非常强大,然后他们在此基础上又推出了react-native的兼容版,强大之处就是缩放类功能完美移植。

最终效果图

简单来说,用victory-native构建一个图表
1、第一步就是用 VictoryChart包裹

return(
<VictoryChart>
    {...}
</VictoryChart>
)

2、要实现缩放,那么第二步则是


return (
<VictoryChart
    minDomain={{ x: 0 }}
    maxDomain={{ x: 1440 }}
    containerComponent={
         <VictoryZoomContainer
            zoomDimension="x"
            onZoomDomainChange={this.handleDomainChange}
            zoomDomain={{ x: xDomain, y: yDomain }}
            minimumZoom={minimumZoom}
            clipContainerComponent={
                        <VictoryClipContainer
                                    clipPadding={{ top: 10, right: 10, bottom: 10, left: 10 }}
                        />
            }
            onTouchStart={(evt) => {
                        this.locationX = evt.nativeEvent.locationX;
            }}
         />
    }
>
    {...children...}
</VictoryChart>
)

说明
1、VictoryChart的 minDomain 和 maxDomain 一定要指定因为它能够确定图表最大的Domain
  在数据点为空的情况下也能按正常情况缩放
2、容器指定为 VictoryZoomContainer
  zoomDimension 指定需要缩放的轴系
  onZoomDomainChange 缩放过程的响应回调
  zoomDomain 指定图表初始显示的x轴和y轴 范围
  minimumZoom 指定缩放的最小间距
  clipContainerComponent 由于标记数据点可能被默认ClipPath
    截断,所以根据自身情况添加一定 clipPadding使图表完全展现
  onTouchStart 触摸开始的回调,可以用于实现自定义 tip

3、有了事件响应容器之后,就需要添加 X轴 和 Y轴

<VictoryChart
    containerComponent={
        <VictoryZoomContainer />
    }
>
    <AxisWrapper tickValues={this._tickValues}>
        <VictoryAxis
            axisComponent={<LineSegment lineComponent={<NoopComponent />} />}
            tickFormat={this.xTickFormat}
            style={{
                grid: {
                    stroke: 'gray',
                    strokeDasharray: '5 5',
                },
            }}
        />
    </AxisWrapper>
    <VictoryAxis
        dependentAxis
        axisComponent={<LineSegment lineComponent={<NoopComponent />} />}
        style={{
            grid: {
                    stroke: 'gray',
                    strokeDasharray: '5 5',
                }, 
            }}
      />
    {...children...}
</VictoryChart>

说明
1、由于 VictoryAxis 的 tickValues 官方默认只接受 数组 类型
  则需要添加 WrapperComponent 接受一个函数来自定义 轴 的label 显示
2、若想不显示坐标系的坐标线,需要将axisComponent的LineSegment的lineComponent置为 ()=>null 的组件
3、通过style.grid来设置网图的样式,符合svg标准
4、dependentAxis ture表示Y轴,false表示X轴

4、添加曲线以及渐变色之后

<VictoryChart
    containerComponent={
        <VictoryZoomContainer />
    }
>
    <VictoryAxis />
    <VictoryAxis dependentAxis />
    <LinearGradient />
    <VictoryArea
        data={this._data}
        interpolation="monotoneX"
        style={{
            data: {
                stroke: lineColor,
                strokeWidth: lineStroke,
                fill: LinearGradient.fill,
            },
        }}
    />
    <VictoryScatter
        data={this._data}
        style={{ data: { stroke: lineColor, fill: lineColor } }}
    />
    {...children...}
</VictoryChart>

说明
1、添加一个LinearGradient 产生渐变效果,符合svg标准
2、interpolation monotoneX 曲线方式连接点,没有偏差
3、Area用来产生曲线以及下边沿的背景色,Scatter用于生成对应点

5、添加一个自定义的指示控件

<VictoryChart
    containerComponent={
        <VictoryZoomContainer />
    }
>
    <VictoryAxis />
    <VictoryAxis dependentAxis />
    <LinearGradient />
    <VictoryArea />
    <VictoryScatter />
    <CustomIndicator />
</VictoryChart>

说明
自定义实现一个 指示控件,具体实现方式可以滑到 本文最后 github的demo地址

最终的总体结构是这样的

<VictoryChart
    minDomain={{ x: 0 }}
    maxDomain={{ x: 1440 }}
    containerComponent={
        <VictoryZoomContainer
            zoomDimension="x"
            onZoomDomainChange={this.handleDomainChange}
            zoomDomain={{ x: xDomain, y: yDomain }}
            minimumZoom={minimumZoom}
                clipContainerComponent={
                    <VictoryClipContainer
                        clipPadding={{ top: 10, right: 10, bottom: 10, left: 10 }}
                    />
                }
                onTouchStart={(evt) => {
                    this.locationX = evt.nativeEvent.locationX;
                }}
        />
    }
>
    <AxisWrapper tickValues={this._tickValues}>
        <VictoryAxis
            axisComponent={<LineSegment lineComponent={<NoopComponent />} />}
            ickFormat={this.xTickFormat}
            style={{
                grid: {
                    stroke: 'gray',
                    strokeDasharray: '5 5',
                },
            }}
        />
    </AxisWrapper>
    <VictoryAxis
        dependentAxis
        axisComponent={<LineSegment lineComponent={<NoopComponent />} />}
        style={{
                grid: {
                stroke: 'gray',
                strokeDasharray: '5 5',
                },
        }}
    />
    <LinearGradient />
    <VictoryArea
        data={this._data}
        interpolation="monotoneX"
        style={{
            data: {
                stroke: lineColor,
                strokeWidth: lineStroke,
                fill: LinearGradient.fill,
            },
        }}
    />
    <VictoryScatter
        data={this._data}
        style={{ data: { stroke: lineColor, fill: lineColor } }}
    />
    <Lollipop getParent={() => this} />
</VictoryChart>

尝试了一番,在iphone6下还是卡顿,所以我之前手撸的纯js控件是真的尽力了。感觉是这个js回调机制还是耗能,对低端设备有高要求的同学还是手撸一个定制化原生控件,封装给RN层傻瓜式调用吧

对于victoryNative这个库的槽点就是文档偏少,官方给的案例都带点 案例仅供参考的感觉,上起手来偏生硬吧。不过确实是RN端图表类的一个解决方案。

victory-native 官方入口
victory-native github入口
https://github.com/little-buddy/RNZoomChartDemo 如果点击404,可粘贴该地址

以前看别人的博文,行云流水一气呵成,从来没考虑过会花多少时间,而当自己真心去总结的时候发现,篇幅再短可能都不止1个小时。

愿明天是 新的一天,大步走向前。─=≡Σ(((つ•̀ω•́)つ

相关文章

网友评论

    本文标题:React Native下基于victory-native实现可

    本文链接:https://www.haomeiwen.com/subject/pfeubqtx.html