Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/371.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何在Chart.js[React]中获取标签的onClick事件?_Javascript_Reactjs_Chart.js - Fatal编程技术网

Javascript 如何在Chart.js[React]中获取标签的onClick事件?

Javascript 如何在Chart.js[React]中获取标签的onClick事件?,javascript,reactjs,chart.js,Javascript,Reactjs,Chart.js,我有一个带标签的雷达图,我想在雷达图的标签上有一个点击事件,但是元素总是返回null。我注意到了其他堆栈溢出问题 还有这个。一个说用香草JS方法做,另一个对我不起作用,有人能告诉我我做错了什么吗 最终目标->我想获得单击的标签,并在该标签上添加一个点击切换,这样我就可以在雷达图中打开和关闭数据点 我的实现 class Chart extends Component { constructor(props) { super(props); this.state = {

我有一个带标签的雷达图,我想在雷达图的标签上有一个点击事件,但是元素总是返回null。我注意到了其他堆栈溢出问题 还有这个。一个说用香草JS方法做,另一个对我不起作用,有人能告诉我我做错了什么吗

最终目标->我想获得单击的标签,并在该标签上添加一个点击切换,这样我就可以在雷达图中打开和关闭数据点

我的实现

class Chart extends Component {
  constructor(props) {
    super(props);
    this.state = {
      chartData: props.chartData
    };
  }
  render() {
    return (
      <div className="chart">
        <Radar
          data={this.state.chartData}
          options={{
            title: {
              display: true,
              text: "Testing",
              fontSize: 25
            },
            legend: {
              display: true,
              position: "right"
            },
            onClick: function(evt, element) {
              // onClickNot working element null
              console.log(evt, element);
              if (element.length > 0) {
                console.log(element, element[0]._datasetInde);
                // you can also get dataset of your selected element
                console.log(data.datasets[element[0]._datasetIndex]);
              }
            }
          }}
        />
      </div>
    );
  }
}
类图扩展组件{
建造师(道具){
超级(道具);
此.state={
chartData:props.chartData
};
}
render(){
返回(
0) {
console.log(元素,元素[0]。_datasetide);
//您还可以获取所选元素的数据集
console.log(data.datasets[element[0]。\u datasetIndex]);
}
}
}}
/>
);
}
}

您可以运行修改数据集的函数:

您将在其中创建一个函数,其中包含您的数据集

chartClick(index) {
    console.log(index);
    //this.setState({}) Modify your datasets properties
  }
将函数作为道具传递

<Chart chartClick={this.chartClick} chartData={this.state.chartData} />
注意:此答案实现不实现删除线。删除线可以通过在标签字符串的每个字符之间放置unicode字符
\u0366
来实现。下面是一个如何使用Javascript实现这一点的示例。我之所以不在这里展示它,是因为当我在codesandbox上测试它时,它看起来并没有那么好

。在下面的示例中,我使用的是
chart.js
version
3.2.0
react-chartjs-2
version
3.0.3

我们可以使用每个标签的边界框和单击的位置来确定是否单击了标签

我在图表上使用了
ref
来访问标签数据

我已选择将标签对应的数据值设置为
0
。我这样做是因为如果要删除与标签对应的元素,标签将随之消失。如果您在下面的演示中看到它的实际应用,我的选择可能更有意义

const swapPreviousCurrent = (data) => {
  const temp = data.currentValue;
  data.currentValue = data.previousValue;
  data.previousValue = temp;
};

class Chart extends Component {
  constructor(props) {
    super(props);
    this.state = {
      chartData: props.chartData
    };
    this.radarRef = {};
    this.labelsStrikeThrough = props.chartData.datasets.map((dataset) => {
      return dataset.data.map((d, dataIndex) => {
        return {
          data: {
            previousValue: 0,
            currentValue: d
          },
          label: {
            previousValue: `${props.chartData.labels[dataIndex]} (x)`,
            currentValue: props.chartData.labels[dataIndex]
          }
        };
      });
    });
  }

  render() {
    return (
      <div className="chart">
        <Radar
          ref={(radarRef) => (this.radarRef = radarRef)}
          data={this.state.chartData}
          options={{
            title: {
              display: true,
              text: "Testing",
              fontSize: 25
            },
            legend: {
              display: true,
              position: "right"
            }
          }}
          getElementAtEvent={(element, event) => {
            const clickX = event.nativeEvent.offsetX;
            const clickY = event.nativeEvent.offsetY;
            const scale = this.radarRef.scales.r;
            const pointLabelItems = scale._pointLabelItems;
            pointLabelItems.forEach((pointLabelItem, index) => {
              if (
                clickX >= pointLabelItem.left &&
                clickX <= pointLabelItem.right &&
                clickY >= pointLabelItem.top &&
                clickY <= pointLabelItem.bottom
              ) {
                // We've clicked inside the bounding box, swap labels and label data for each dataset
                this.radarRef.data.datasets.forEach((dataset, datasetIndex) => {
                  swapPreviousCurrent(
                    this.labelsStrikeThrough[datasetIndex][index].data
                  );
                  swapPreviousCurrent(
                    this.labelsStrikeThrough[datasetIndex][index].label
                  );

                  this.radarRef.data.datasets[datasetIndex].data[
                    index
                  ] = this.labelsStrikeThrough[datasetIndex][
                    index
                  ].data.previousValue;

                  this.radarRef.data.labels[index] = this.labelsStrikeThrough[
                    datasetIndex
                  ][index].label.previousValue;
                });
                // labels and data have been changed, update the graph
                this.radarRef.update();
              }
            });
          }}
        />
      </div>
    );
  }
}
const swapPreviousCurrent=(数据)=>{
const temp=data.currentValue;
data.currentValue=data.previousValue;
data.previousValue=温度;
};
类图扩展组件{
建造师(道具){
超级(道具);
此.state={
chartData:props.chartData
};
this.radarRef={};
this.labelstrickethrough=props.chartData.datasets.map((数据集)=>{
返回dataset.data.map((d,dataIndex)=>{
返回{
数据:{
上一个值:0,
当前值:d
},
标签:{
上一个值:`${props.chartData.labels[dataIndex]}(x)`,
currentValue:props.chartData.labels[dataIndex]
}
};
});
});
}
render(){
返回(
(this.radarRef=radarRef)}
data={this.state.chartData}
选择权={{
标题:{
显示:对,
文本:“测试”,
尺寸:25
},
图例:{
显示:对,
位置:“右”
}
}}
getElementAtEvent={(元素,事件)=>{
const clickX=event.nativeEvent.offsetX;
const clickY=event.nativeEvent.offsetY;
常量刻度=此.radarRef.scales.r;
const pointLabelItems=刻度。_pointLabelItems;
forEach((pointLabelItem,索引)=>{
如果(
单击X>=pointLabelItem.left&&
单击X=pointLabelItem.top&&

clickY如果单击点,这是有效的,但在单击标签时不起作用。这也没有提到删除线。这可以通过使用来完成。另外,我认为对于OP的用例,它应该是
\u index
,而不是
\u datasetIndex
@BasvanderLinden您是否尝试使用
onementsclick={elems=>{}
?我尝试了
getElementAtEvent
onElementsClick
,如果单击标签,两者都会返回一个空数组。适用于点,而不是标签。@BasvanderLinden我以前使用getElementsAtEvent也能在点上获得它,我希望标签有东西,而不是点有可能吗?@danielm2402是的,我确实需要它来做标签而不是数据点。这对我来说也是非常棒的东西,可以学习和探索,防止重新渲染的调整也非常好。我看到的一件事是边界rec非常小,需要我们点击一个非常特定的区域,非常靠近标签开始的边缘要在一次单击中注册,否则需要多次单击(2)要使其工作,请让我看看是否可以增加用于的边界rec的框labels@INFOSYS解释小边界框的最简单方法是使
if
语句更宽松。例如,您可以使用
clickX>=pointLabelItem.left
而不是
clickX>=pointLabelItem.left-30
后者会有效地在左边给你一些点击填充。你可以对其他方向做类似的事情。你可以从顶部和左侧方向减去一个值,然后在右侧和底部方向加上一个值。
const swapPreviousCurrent = (data) => {
  const temp = data.currentValue;
  data.currentValue = data.previousValue;
  data.previousValue = temp;
};

class Chart extends Component {
  constructor(props) {
    super(props);
    this.state = {
      chartData: props.chartData
    };
    this.radarRef = {};
    this.labelsStrikeThrough = props.chartData.datasets.map((dataset) => {
      return dataset.data.map((d, dataIndex) => {
        return {
          data: {
            previousValue: 0,
            currentValue: d
          },
          label: {
            previousValue: `${props.chartData.labels[dataIndex]} (x)`,
            currentValue: props.chartData.labels[dataIndex]
          }
        };
      });
    });
  }

  render() {
    return (
      <div className="chart">
        <Radar
          ref={(radarRef) => (this.radarRef = radarRef)}
          data={this.state.chartData}
          options={{
            title: {
              display: true,
              text: "Testing",
              fontSize: 25
            },
            legend: {
              display: true,
              position: "right"
            }
          }}
          getElementAtEvent={(element, event) => {
            const clickX = event.nativeEvent.offsetX;
            const clickY = event.nativeEvent.offsetY;
            const scale = this.radarRef.scales.r;
            const pointLabelItems = scale._pointLabelItems;
            pointLabelItems.forEach((pointLabelItem, index) => {
              if (
                clickX >= pointLabelItem.left &&
                clickX <= pointLabelItem.right &&
                clickY >= pointLabelItem.top &&
                clickY <= pointLabelItem.bottom
              ) {
                // We've clicked inside the bounding box, swap labels and label data for each dataset
                this.radarRef.data.datasets.forEach((dataset, datasetIndex) => {
                  swapPreviousCurrent(
                    this.labelsStrikeThrough[datasetIndex][index].data
                  );
                  swapPreviousCurrent(
                    this.labelsStrikeThrough[datasetIndex][index].label
                  );

                  this.radarRef.data.datasets[datasetIndex].data[
                    index
                  ] = this.labelsStrikeThrough[datasetIndex][
                    index
                  ].data.previousValue;

                  this.radarRef.data.labels[index] = this.labelsStrikeThrough[
                    datasetIndex
                  ][index].label.previousValue;
                });
                // labels and data have been changed, update the graph
                this.radarRef.update();
              }
            });
          }}
        />
      </div>
    );
  }
}