##ChartWrapper:
这是我第一次发布问题。如果我错过了什么我向你道歉。提前谢谢。我的问题是,我从基于某些选择的api调用接收更新的数据,并将其传递给CharWrapper组件,该组件反过来调用D3Chart类中的updated()方法,用更新后的数据填充d3图表。但是,在第一次调用时,图表是正确填充的,但在第二次选择时,当我从api响应中获得更新的数据时,图表仍然保持原样,使用旧值。它没有得到更新
//此处的代码导出默认类ChartWrapper扩展了React.Component {
componentDidMount() {
this.tooltipRef = React.createRef();
this.mySvgRef = React.createRef();
this.legendRef = React.createRef();
this.setState({ chart: new D3Chart(this.refs.svgChart, this.refs.tooltip, this.refs.legends) });
}
shouldComponentUpdate() {
console.log("shouldComponentUpdate")
return false;
}
static getDerivedStateFromProps(nextProps, prevState) {
if (prevState) {
prevState.chart.update(nextProps.chartdata);
console.log("getDerivedStateFromProps : ", nextProps.chartdata)
return { chartdata: nextProps.chartdata }
}
return null;
}
render() {
return (<div>
<div className="svg" ref="svgChart"></div>
<div className="tag" ref="tooltip"></div>
<div className="legend" ref="legends">
</div>
</div>)
}
}enter code here
D3Chart组件代码:
下面是我的D3chart组件。我将其与react一起使用。为什么在对数据选择调用exit().remove()之后,较旧的数据仍然显示在窗口中。在过去的三天里,我一直在挣扎。任何建议都将受到高度赞赏。谢谢
注意: D3Chart类构造函数中的代码将只执行一次,并且只要我从api response中获得更新数据作为属性,就会调用update()函数。在此处输入代码
export default class D3Chart {
constructor(mySvgRef, tooltipRef, legendRef) {
const vis = this;
vis.tooltipRef = tooltipRef;
vis.ganttSvgRef = d3.select(mySvgRef)
.append("svg")
.attr("width", w + margin.left + margin.right)
.attr("height", h + margin.top + margin.bottom)
.attr("class", "svg")
.append('g')
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
vis.timeScale = d3.scaleTime()
.range([0, w - 100]);
vis.yScale = d3.scaleBand().rangeRound([0, h - margin.top - margin.bottom], 0);
vis.xAxisGroup = vis.ganttSvgRef.append("g")
.attr("className", "x top axis")
.attr('transform', 'translate(' + 20 + ', ' + 0 + ')')
vis.yAxisGroup = vis.ganttSvgRef.append("g")
.attr("className", "y axis")
.attr('transform', 'translate(' + margin.left + ', ' + 0 + ')')
vis.legendRef = d3.select(legendRef)
.style("width", w + margin.left + margin.right + 'px')
vis.ganttSvgRef.append("text")
.attr("transform",
"translate(" + 0 + " ," +
(h / 2) + ") rotate(-90)")
.style("text-anchor", "middle")
.text("Vessel in Terminal");
}
update = (chartData) => {
var barHeight = 50;
var gap = 95;
var topPadding = 0;
var sidePadding = 20;
const vis = this;
console.log("I am updated with : ", chartData)
var parseTime = d3.timeParse("%Y-%m-%d %H:%M:%S");
var slotNumber = [];
var vesselsNames = [];
var serviceName = [];
var serviceColorSelector = {}
for (var i = 0; i < chartData.length; i++) {
slotNumber.push(chartData[i].slot);
serviceName.push(chartData[i].serviceName_data);
vesselsNames.push(chartData[i].vesselName_data);
}
var uniqueService = [...new Set(serviceName)];
for (var i = 0; i < uniqueService.length; i++) {
serviceColorSelector[uniqueService[i]] = colArray[i];
}
slotNumber = this.checkUnique(slotNumber);
slotNumber.sort(function (a, b) {
return Number(a) - Number(b);
});
vis.timeScale.domain([d3.min(chartData, function (d) { return parseTime(d.arrivalTime_data); }),
d3.max(chartData, function (d) { return parseTime(d.departureTime_data); })])
vis.yScale.domain(slotNumber)
var xAxistop = d3.axisTop(vis.timeScale).ticks().tickSizeInner((-h + margin.top + margin.bottom))
vis.xAxisGroup
// .transition()
.call(xAxistop);
var yAxis = d3.axisLeft(vis.yScale)
vis.yAxisGroup
// .transition()
.call(yAxis);
console.log("vis.ganttSvgRef :", vis.ganttSvgRef)
if (slotNumber.length > 6) {
barHeight = this.calculateBarHeight(slotNumber.length, barHeight);
}
var rectangles = vis.ganttSvgRef
.selectAll("rect")
.data(chartData);
console.log("Reactangles : ", rectangles)
rectangles.exit().remove();
var innerRects = rectangles.enter().append("rect")
.attr("x", function (d) {
return vis.timeScale(parseTime(d.arrivalTime_data)) + sidePadding;
})
.attr("y", function (d, i) {
for (var j = 0; j < slotNumber.length; j++) {
if (d.slot == slotNumber[j]) {
return vis.yScale(d.slot);
}
}
})
.attr("width", function (d) {
return (vis.timeScale(parseTime(d.departureTime_data)) - vis.timeScale(parseTime(d.arrivalTime_data)));
})
.attr("height", barHeight)
.attr("stroke", "none")
.attr("fill", function (d) {
for (var i = 0; i < vesselsNames.length; i++) {
return serviceColorSelector[d.serviceName_data]
}
})
innerRects.on('mouseover', function (e) {
var tag = "";
tag = "Imo: " + d3.select(this).data()[0].imo_data + "<br/>" +
"Vessel: " + d3.select(this).data()[0].vesselName_data + "<br/>" +
"Service: " + d3.select(this).data()[0].serviceName_data;
var x = (this.x.animVal.value + this.width.animVal.value / 2) + "px";
var y = this.y.animVal.value + 25 + "px";
vis.tooltipRef.innerHTML = tag;
vis.tooltipRef.style.top = y;
vis.tooltipRef.style.left = x;
vis.tooltipRef.style.display = "block";
}).on('mouseout', function () {
vis.tooltipRef.style.display = "none";
});
var legend5 = vis.legendRef.selectAll(".legend5")
.data(serviceName)
legend5.exit().remove();
var p = legend5.enter().append("div")
.attr("class", "legends5").append("p")
.attr("class", "country-name")
p.append("span")
.attr("class", "key-dot")
.style("background", function (d, i) {
return serviceColorSelector[d]
})
p.insert("text")
.attr("class", "text-style")
.style("text-anchor", 'start')
.text(function (d, i) { return d })
}
checkUnique = (arr) => {
var hash = {}, result = [];
for (var i = 0, l = arr.length; i < l; ++i) {
if (!hash.hasOwnProperty(arr[i])) {
hash[arr[i]] = true;
result.push(arr[i]);
}
}
return result;
}
calculateBarHeight = (totalSlot, barheight) => {
let height = barheight;
let franction_x = totalSlot - 6;
let franction_y = 6;
let decrementRatio = franction_x / (franction_x + franction_y);
let decresedHeight = decrementRatio * barheight;
let rectHeight = Math.trunc(barheight - decresedHeight);
return rectHeight;
}
}
发布于 2021-04-15 14:38:29
打电话
d3.select(mySvgRef).selectAll('svg').remove();
在行之前
d3.select(mySvgRef).append('svg')...
发布于 2021-04-16 05:16:48
d3 V5:
我使用merge()方法来解决我的问题。希望对其他也有帮助
` var rectangles = vis.ganttSvgRef.selectAll("rect")
.data(chartData);
rectangles.exit().remove();
var innerRects = rectangles.enter().append("rect").merge(rectangles)
.attr("x", function (d) {
return vis.timeScale(parseTime(d.arrivalTime_data)) +
sidePadding;
})`
发布于 2021-04-22 16:34:33
如果您正在开发一个具有多个显示不同d3图表的小部件的仪表板,请使用以下代码:
d3.selectAll("#d3-donutChart > *").remove();
这将只清除特定的图表,而不是网页中的所有svg。
在为更新的数据重新绘制d3图之前添加此行。
https://stackoverflow.com/questions/67107991
复制