javascript - 如何使用带有 d3.js 图形的 React Router 重定向到另一个屏幕
问题描述
import React, { Component } from "react";
import * as d3 from "d3";
import ApiHelper from "../../api/ApiHelper";
import { scaleLinear } from "d3-scale";
import { max } from "d3-array";
import { connect } from "react-redux";
import "../../css/styles.css";
import { NavLink } from "react-router-dom";
class JarvisDonutChart extends Component {
constructor(props) {
super(props);
this.state = {
uid: props.uid,
width: props.width,
height: props.height,
title: props.title,
colorscheme: props.colorscheme,
Dates: props.CalendarDates,
fromDate: props.CalendarDates.fromDate,
toDate: props.CalendarDates.toDate,
graphTitle: props.graphTitle,
chartData: []
};
}
componentDidMount() {
this.getChartData();
}
getChartData = () => {
ApiHelper.GetDonutChartData(
this.state.uid,
this.state.fromDate,
this.state.toDate
)
.then(response => {
console.log(
"<--- Request is successfull and below is the response -->"
);
console.log(response.data.responses);
const res = response.data.responses;
this.setState({ chartData: res }, this.drawChart);
// setloading(false);
})
.catch(error => {
this.setState({ chartData: [] });
switch (error.response.status) {
case 403:
console.log("Error code --> " + 403);
this.props.history.push("/unAuthorizedPage");
break;
default:
console.log("Error String --->" + error);
}
});
};
drawChart() {
const data = this.state.chartData;
// const data = ApiHelper.GetDonutChartData(
// "abeab3cb-778e-4a19-a957-43bc74248b04179"
// );
const colorscheme = this.state.colorscheme;
console.log("Inside Donut Chart Component");
console.log(data);
var width = this.state.width;
var height = this.state.height;
var margin = Math.min(this.state.width, this.state.height) * 0.01;
// The radius of the pieplot is half the width or half the height (smallest one). I subtract a bit of margin.
var radius = Math.min(this.state.width, this.state.height) / 2 - margin;
// append the svg object to the div called 'my_dataviz'
const svg = d3
// .select("#abeab3cb-778e-4a19-a957-43bc74248b04")
.select("[uid=" + this.state.uid + "]")
.attr("width", this.state.width)
.attr("height", this.state.height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
// Compute the position of each group on the pie:
var pie = d3.pie().value(function(d) {
//console.log(d.value.value);
//d.value.(responsefield)
return d.value.value;
});
var data_ready = pie(d3.entries(data));
console.log("<-- Checking data-ready --> ");
console.log(data_ready);
// Define the div for the tooltip
var div = d3
.select("#" + this.props.uid + "_tooltip")
// .append("div")
// .attr("id", "jarvis_tooltip")
// .attr("class", "tooltip")
.attr("rx", 3)
.attr("ry", 3);
// console.log(data_ready);
// console.log(colorscheme);
// Build the pie chart: Basically, each part of the pie is a path that we build using the arc function.
svg
.selectAll("whatever")
.data(data_ready)
.enter()
.append("a")
.attr(
"href",
(d, i) =>
`/drilldown-page/${this.state.title}/${this.state.graphTitle}/${data_ready[i].data.value.name}`
)
.append("path")
.attr(
"d",
d3
.arc()
.innerRadius(radius * 0.45) // This is the size of the donut hole
.outerRadius(radius)
.cornerRadius(radius * 0.03) // sets how rounded the corners are on each slice
.padAngle(radius * 0.0001) // effectively dictates the gap between slices
)
.attr("fill", (d, i) => this.state.colorscheme[i])
.attr("stroke", "black")
.style("stroke-width", "0.7px")
.style("opacity", 0.9)
.on("mouseover", function(d) {
d3.select(this)
.attr("stroke", "white")
.attr("stroke-width", 1.5);
d3.select(this).style("cursor", "pointer");
div.style("display", "inline");
// console.log("mouseover event triggered");
})
.on("mouseout", function(d, i) {
d3.select(this)
.attr("fill", colorscheme[i])
.attr("stroke", "black")
.attr("stroke-width", 0.5);
d3.select(this).style("cursor", "default");
div.style("display", "none");
// console.log("mouseout event triggered");
})
.on("mousemove", function(d) {
div
.text(d.value)
.style("left", d3.mouse(d3.select("body").node())[0] + 15 + "px")
.style("top", d3.mouse(d3.select("body").node())[1] + 20 + "px");
// console.log("mouseover event triggered");
});
}
render() {
return (
<div>
<svg
uid={this.props.uid}
width={this.state.width}
height={this.state.height}
/>
<div id={this.props.uid + "_tooltip"} className="jarvis_tooltip" />
</div>
);
}
}
function mapStateToProps(state) {
return {
CalendarDates: state.calendarDates,
fromDate: state.calendarDates.fromDate,
toDate: state.calendarDates.toDate
};
}
export default connect(mapStateToProps)(JarvisDonutChart);
我正在使用 d3.js 在我们的应用程序中构建交互式图表,用户的要求是,如果用户单击条形图或圆环图,那么它应该将他带到另一个屏幕,其中仅包含与该组数据相关的详细信息。
在 d3.js 我使用下面的代码
.attr("xlink:href", (d, i) =>
/drilldown-page/${this.state.title}/${this.state.graphTitle}/${data_ready[i].data.value.name}
)
我现在面临的问题是,因为它刷新了页面并且整个 redux 存储再次启动,所以存储中的所有数据(如日历日期)都消失了。
所以我怎么能用这个任何想法使用react-router???
解决方案
我自己想通了,我实施的解决方案如下。
D3.js 提供了事件处理方法,即 selection.on()。所以附加一个事件处理程序以单击图形元素并在回调函数中调用一个函数。
并且在新函数中使用 history.push 重定向到不同的 URL。
附上代码
.on("click", function(d) {
console.log("<--- Inside Event generator --->");
console.log(d);
clickHandler(d);
});
const clickHandler = d => {
console.log("<-- Inside Event Handler function --->");
console.log(d.name);
this.props.history.push(
`/drilldown-page/${this.state.title}/${this.state.graphTitle}/${d.name}`
);
};
希望我的回答对使用 React 和 d3.js 并坚持重定向的人有所帮助。
推荐阅读
- c++ - 比较两个 std::vectors/arrays 或一般来说两个 stl contianers
- c# - asp.nep mvc:将当前 httpcontext 的值设置为常量变量
- javascript - 如何从嵌套引用中展平我的数据?
- css - CSS背景图片网址未显示
- git - git:无法挑选范围
- javascript - 无法读取调用时未定义的属性 X
- oracle - 在 Oracle 中使用 CASE 表达式
- python - 是否有与 Python 的 pandas.merge_asof 等效的 R?
- visual-studio - 如何在 azure devops 中运行 Visual Studio 构建
- ios - 如何通过在 swift 中实现观察者从 Firebase 实时数据库中获取嵌套数据