我正在尝试完成类似于此处的内容:https : //www.opportunityatlas.org/。如果继续浏览此链接,然后单击“显示分布”以查看图形并选择“在屏幕上”,然后在地图上移动光标,您将看到矩形的大小发生更改,并且更新模式也有效,例如矩形已经在那里,它会水平移动到新值。
我尝试做同样的事情,但无法实现更新部分。您能指出我错过的地方吗?我已经附加了我的代码的一部分,其中有两个具有相同ID的数据集data1和data2,但是正如您所看到的,当您单击update更改数据集时,所有矩形均处于输入阶段,并且它们都不改变其位置现有的(在更新阶段没有)。如果有人可以指导我完成这一过程,将会很有帮助。如果还有其他方法可以实现我在链接中提供的同一图形,那么如果有其他方法也将很有帮助。提前致谢 !
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>
<button onclick="changeData()"> Update data </button>
<svg width="550" height="250" id="data-viz">
<g transform="translate(30, 100)">
</g>
</svg>
您的问题似乎是这些行:
if (dotSize !== 10) {
d3.selectAll('.gBin').remove();
d3.selectAll('rect').remove();
}
在计算任何选择之前,将删除所有元素,以便所有内容(bing
和element rect
)都变为enter
。
另一个有趣的事情是您的垃圾箱数据密钥。由于您正在使用,因此x0
您g
还将根据直方图函数计算仓位的方式进入/退出。
<html>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.min.js"></script>
<button onclick="changeData()">Update data</button>
<svg width="550" height="250" id="data-viz">
<g transform="translate(30, 100)"></g>
</svg>
<script>
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) {
console.clear();
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;
}
);
let eex = elements
.exit()
.transition()
.duration(tDuration)
.style('opacity', 0)
.remove();
console.log("rects exiting", eex.nodes().map(e => "rect" + e.getAttribute('id')))
let een = elements
.enter()
.append('rect')
.attr('id', (d) => d.value);
console.log("rects entering", een.nodes().map(e => "rect" + e.getAttribute('id')))
let eem = een
.merge(elements);
console.log("rects merge", eem.nodes().map(e => "rect" + e.getAttribute('id')))
eem
.attr('y', -(height + margin.top))
// .on("mouseover", tooltipOn)
// .on("mouseout", tooltipOff)
.transition()
.delay(function (d, i) {
return 50 * i;
})
.duration(tDuration)
.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>
</html>
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句