Я сталкиваюсь с этой проблемой, когда пытаюсь получить гистограмму с элементами, разделенными и видимыми для конкретного бина. Но когда данные изменяются, все идет в enter() и ничего не происходит в обновлении, кажется. Таким образом, все существующие элементы также переходят и появляются сверху, а не просто меняют свои значения. Пожалуйста, взгляните на код, который я приложил ниже, который выводит изображение в виде прикрепленного изображения. Не могу понять, почему обновление не работает, только войти туда. Я не могу поделиться всем кодом, но это основная проблема.
let initialRender = true;
let selectedData1 = true;
const margin = {
top: 10,
right: 30,
bottom: 30,
left: 30
},
width = 550 - margin.left - margin.right,
height = 150 - margin.top - margin.bottom;
function printChart(asd, data, dataGradients) {
const svg = d3.select('#data-viz')
// const isZoomed = map.getZoom() > zoomThreshold;
// if (isZoomed !== changedZoom) {
// initialRender = true;
// changedZoom = isZoomed;
// }
// X axis and scale ------------->>>>>>>>>>>>>>>>>>>>
const xScale = d3.scaleLinear()
.domain(d3.extent(data.map(d => d.value)))
.range([0, width])
const xAxisCall = d3.axisBottom(xScale)
.tickFormat(d3.format(".2s"))
.ticks(5)
.tickSizeOuter(0);
let xAxis = null
if (initialRender) {
d3.select(".axis-x").remove()
xAxis = svg.append("g")
.attr("class", "axis-x")
.attr("transform", "translate(0," + 115 + ")")
initialRender = false
} else {
xAxis = d3.select(".axis-x")
}
xAxis.transition()
.duration(2000)
.ease(d3.easeSinInOut)
.call(xAxisCall)
// X axis and scale <<<<<<<<<<<<<<<<-----------------------------
const binMin = 5;
const binMax = 150;
const tDuration = 3000;
// Just to calculate max elements in each bin ---------->>>>>>>>>>>>>>>>>>
let histogram = d3.histogram()
.value(d => d.value)
.domain(xScale.domain())
.thresholds(xScale.ticks(10));
let bins = histogram(data).filter(d => d.length > 0);
console.log(bins);
const max = d3.max(bins.map(bin => bin.length))
const maxBinSize = max <= 10 ? 10 : max
// Just to calculate max elements in each bin <<<<<<<<<<<<----------------
// Decide parameters for histogram ------------>>>>>>>>>>>>>>>>>
const dotSizeScale = d3.scaleLinear()
.domain([binMin, binMax])
.range([10, 4])
const dotSize = dotSizeScale(maxBinSize);
const dotSpacingScale = d3.scaleLinear()
.domain([binMin, binMax])
.range([12, 6])
const dotSpacing = dotSpacingScale(maxBinSize);
const thresholdScale = d3.scaleLinear()
.domain([binMin, binMax])
.range([10, 100])
const threshold = thresholdScale(maxBinSize);
const yTransformMarginScale = d3.scaleLinear()
.domain([binMin, binMax])
.range([100, 100])
const yTransformMargin = yTransformMarginScale(maxBinSize);
if (dotSize !== 10) {
d3.selectAll('.gBin').remove()
d3.selectAll('rect').remove()
}
histogram = d3.histogram()
.value(d => d.value)
.domain(xScale.domain())
.thresholds(xScale.ticks(threshold));
bins = histogram(data).filter(d => d.length > 0);
// Decide parameters for histogram <<<<<<<<<<<<<<<<<<<<--------------------------
// Y axis scale -------------------->>>>>>>>>>>>>>>>>>>>
var yScale = d3.scaleLinear()
.range([height, 0]);
yScale.domain([0, d3.max(bins, (d) => d.length)]);
svg.append("g")
.attr("class", "axis-y")
.call(d3.axisLeft(yScale));
d3.select(".axis-y")
.remove()
// Y axis scale <<<<<<<<<<<<<<<<<<<<<<<-----------------
const binGroup = svg.selectAll(".gBin")
.data(bins,
(d) => {
console.log('id 1', d.x0)
return d.x0
}
)
binGroup
.exit()
.transition()
.duration(2000)
.style("opacity", 0)
.remove()
const binGroupEnter = binGroup
.enter()
.append("g")
.merge(binGroup)
.attr("class", "gBin")
.attr("x", 1)
.attr("transform", function(d) {
return "translate(" + xScale(d.x0) + "," + yTransformMargin + ")";
})
.attr("width", 10)
const elements = binGroupEnter.selectAll("rect")
.data(d => d.map((p, i) => ({
id: p.id,
idx: i,
value: p.value,
})),
function(d) {
console.log('id 2', d)
return d.id
}
)
elements.exit()
.transition()
.duration(tDuration)
.style("opacity", 0)
.remove()
elements
.enter()
.append("rect")
.merge(elements)
.attr("y", -(height + margin.top))
// .on("mouseover", tooltipOn)
// .on("mouseout", tooltipOff)
.transition()
.delay(function(d, i) {
return 50 * i;
})
.duration(tDuration)
.attr("id", d => d.value)
.attr("y", (d, i) => -(i * dotSpacing))
.attr("width", dotSize)
.attr("height", dotSize)
// .style("fill", (d) => getBinColor(d.value, dataGradients))
.style("fill", 'red')
}
const data1 = [{
id: 1,
value: 14
}, {
id: 13,
value: 12
}, {
id: 2,
value: 50
}, {
id: 32,
value: 142
}]
const data2 = [{
id: 1,
value: 135
}, {
id: 7,
value: 2
}, {
id: 2,
value: 50
}, {
id: 32,
value: 50
}]
printChart(null, data1, null)
function changeData() {
selectedData1 ?
printChart(null, data2, null) :
printChart(null, data1, null)
selectedData1 = !selectedData1
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.min.js"></script>
<svg width="550" height="250" id="data-viz">
<g transform="translate(30, 100)">
</g>
</svg>
<button onclick="changeData()"> Update data </button>