简体   繁体   English

如何让胜利原生cursor容器x和y轴线只与图形上的点相交而不与触摸点相交

[英]How to make the victory native cursor container x and y axis line only intersect the point on the graph not on the touch point

How to make the victory native cursor container x and y axis line only intersect the point on the graph not on the touch point.Since by default the draggable cursor intersect the touch point but I want that the draggable cursor must intersect only at the point on the graph wherever I touch the graph it only show the nearest point on the graph corresponding to my touch point.如何使胜利本机 cursor 容器 x 和 y 轴线仅与图形上的点相交而不与触摸点相交。因为默认情况下可拖动的 cursor 与触摸点相交但我希望可拖动的 cursor 必须仅在点上相交无论我在哪里触摸图形,图形都只显示图形上与我的触摸点相对应的最近点。

Please some on tell how to do it.请告诉一些人如何去做。

Here is the solution:这是解决方案:

import React, { Component } from 'react'
import { Text, StyleSheet, View } from 'react-native'
import {VictoryArea,VictoryChart,createContainer,VictoryTooltip,VictoryScatter,VictoryLine } from 'victory-native';
import {range, first, last,maxBy } from 'lodash';
import Svg,{Line} from 'react-native-svg';

const VictoryZoomVoronoiContainer = createContainer( "cursor","voronoi");

const data = range(20,81).map((x) => ({x, y: x*x}));

const findClosestPointSorted = (data, value) => {  
  if (value === null) return null;
    const start = first(data).x;
    const range = (last(data).x - start);
  const index = Math.round((value - start)/range * (data.length - 1));
  return data[index];
};

export default class Chart extends Component {
    componentWillMount()
    {
        this.setState({ymax:maxBy(data,function(o) { return o.y; }).y})
    }

    state = {
        activePoint:null,
        data:data,
        ymax :0
    }
    handleCursorChange(value) {           

    this.setState({
        activePoint: findClosestPointSorted(data, value)
    });
  }

    render() {
        const { activePoint } = this.state;
        const point = activePoint ?
            <VictoryScatter name = "scatter" data={[activePoint]} style={{data: {size: 200,fill:'#ffffff',stroke:'#1bad53',strokeWidth:2} }}/>
          : null;

        return (
            <View>
                <VictoryChart
                    height={300}
                    width={350}
                    containerComponent={
                        <VictoryZoomVoronoiContainer
                        voronoiDimension="x"
                        cursorDimension="x"
                        voronoiBlacklist={["scatter"]}
                        labelComponent={<VictoryTooltip style={{fill:'red'}}  flyoutStyle={{
                        fill:  'rgba(52, 52, 52, 0.8)',}}/>}
                        onCursorChange={(value)=>{this.handleCursorChange(value)}}
                        labels={cursor => {

                            try {

                                return(activePoint.x?`${activePoint.x}, ${Math.round(activePoint.y)}\ndjh`:null)
                            } catch (error) {
                                console.log(error)
                            }
                        }}
                        />
                    }
                 >

            <VictoryArea
            name = "area"
            data={data}
            interpolation="cardinal"
            style={{
            data: { 
                fill: '#1bad53',
                stroke: '#05a543',
                strokeWidth: 2
            }
            }}
            />
             {point}

          {activePoint?<Line  x1= {50} x2="300" y1={250-(200/this.state.ymax)*activePoint.y} y2={250-(200/this.state.ymax)*activePoint.y} stroke="black" strokeWidth="1"/>:null}

        </VictoryChart>
            </View>
        )
    }
}

Echoing on @Rajat Verma's answer, Victory allows you to pass in a cursorComponent prop where you can use your own custom svg Line component (custom color, strokeWidth, etc.)回应@Rajat Verma 的回答,Victory 允许您传入一个cursorComponent道具,您可以在其中使用自己的自定义 svg Line 组件(自定义颜色、strokeWidth 等)

Additionally, it is useful to note that VictoryCursorContainer does not behave as it should in cases where you are also using the zoomDomain prop from VictoryZoomContainer (cursor will not match up with rendered line when zooming).此外,请注意 VictoryCursorContainer 在您还使用zoomDomain道具的情况下不会表现出应有的行为(缩放时光标与渲染线不匹配)。 A solution to this is taking out VictoryZoomContainer and manually filtering your original dataset to mimic the zoom.对此的解决方案是取出 VictoryZoomContainer 并手动过滤原始数据集以模拟缩放。 Hope it helps!希望能帮助到你!

There is a typo in the accepted answer, use: const VictoryCursorVoronoiContainer = createContainer('cursor', 'voronoi') .接受的答案中有一个错字,请使用: const VictoryCursorVoronoiContainer = createContainer('cursor', 'voronoi') And don't forget to use voronoiBlacklist prop to exclude items out of your voronoi diagram!并且不要忘记使用voronoiBlacklist道具从您的 voronoi 图表中排除项目!

In my instance, I only cared about showing the y value of my data, and please correct me if I'm wrong or oversimplified this - but this works exactly as needed for my case:在我的例子中,我只关心显示我的数据的 y 值,如果我错了或过于简单化,请纠正我——但这完全符合我的情况的需要:

<VictoryChart
   containerComponent={
      <VictoryCursorContainer
          cursorDimension="x"
          cursorLabel={({datum}) => `${data[Math.round(datum.x) - 1]["y"]}`}
         />}
>

The cursorLabel component basically finds the closest x value of the chart pointer, converts it to an integer and we use this integer to index our data object. Of course we need to subtract 1 due to 0 indexing in our object whereas the charts positioning is not 0 indexing. cursorLabel 组件基本上找到图表指针最接近的 x 值,将其转换为 integer,我们使用这个 integer 来索引我们的数据 object。当然,由于 object 中的 0 索引,我们需要减去 1,而图表定位不是0索引。 Note that data is an array of objects such as [{x: a date, y: some value},]请注意,数据是一个对象数组,例如 [{x: 一个日期, y: 一些值},]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM