D3.js 如何在数据更新期间同步散点图和折线图?
我有一个滑块,可以在生成数据的函数中调整参数。到目前为止,我能够在更改此滑块时正确调整折线图。然而,分散点似乎到处都是,我不知道为什么它会这样做 是否有办法将散点绑定到折线图,以便它们同步更新 我也不确定退出选择是否正常工作。理想情况下,如果数据大小增加,我希望图形追加,反之亦然 附件是一个最低限度的工作示例D3.js 如何在数据更新期间同步散点图和折线图?,d3.js,D3.js,我有一个滑块,可以在生成数据的函数中调整参数。到目前为止,我能够在更改此滑块时正确调整折线图。然而,分散点似乎到处都是,我不知道为什么它会这样做 是否有办法将散点绑定到折线图,以便它们同步更新 我也不确定退出选择是否正常工作。理想情况下,如果数据大小增加,我希望图形追加,反之亦然 附件是一个最低限度的工作示例 轴 每次滑块移动时都会更新x轴和y轴域,因此也应该更新轴。通过将轴图形代码放置到函数中并在数据更改时调用它,可以快速解决此问题 具有按键功能的数据绑定 你离这里很近。之所以scatter
scatter.enter()
和scatter.exit()
没有按照您的预期运行,是因为默认情况下,d3.js使用数组索引作为每个项的键(即ID)绑定数据。这就是它如何识别要添加的新项、不需要重新绘制的现有项以及要删除的旧项。它适用于许多情况。但在你的情况下,它没有,因为你的轴改变了。因此,每个点,即使它们在更改之前已经存在于数据中,也必须以新的x/y比例重新绘制。告诉它重新绘制它们的一种方法是在绑定时将键设置为null(.data(data,d=>null)
)。另一种方法是简单地选择所有点,使用.remove()
和.append()
删除并重新绘制它们,而不使用enter()
/exit()
绑定
完整示例:
//让sinWave=Math.sin(x)
让范围=功能(启动、停止、步进){
步骤=步骤| | 1;
设arr=[]
for(让i=开始;i<停止;i+=步进){
arr.push(i);
}
返回arr;
}
让generateSinWave=函数(x){
让y=[]
x、 forEach(函数(i){
y、 推(数学罪(一))
});
返回y;
}
const generateData=(n)=>{
x=范围(0,n,1)
y=生成短波(x)
让标签=['x','y']
让数据=[]
for(设i=0;ixScale(d.x))
.y(d=>yScale(d.y))
//.曲线(d3.曲线自然);
让svg=d3.select('.viz')
.append('svg')
.attr(“viewBox”`0${width+margin.left+margin.right}${height+margin.top+margin.bottom}`)
.attr(“保存Aspectratio”、“xMinYMin满足”)
//.attr('width',`${width+margin.left+margin.right}px`)
//.attr('height',`${height+margin.top+margin.bottom}px`)
//.classed(“svg内容”,真);
.append('g')
.attr('类','折线图容器')
.attr('transform','translate(${margin.left},${margin.top})`);
/*d3.选择(“折线图容器”)
.attr(“样式”,“轮廓:细黑;”)
.attr(“保证金权利”、“102px”)*/
const chartGroup=svg.append('g').attr('class','linechart'))
//画x轴
const xAxisDraw=svg
.append('g')
.attr('class','x轴')
//.style('font','14px无衬线')
.attr('transform','translate(0,${height/2})`);
常量yAxisDraw=svg
.append('g')
.attr('class','y轴');
函数drawAxis(){
常数xAxis=d3.axisBottom(xScale).ticksizeout(0);
xAxisDraw.call(xAxis);
常数yAxis=d3
.axisLeft(yScale)
.滴答声(10)
//.tickSizeInner(-width);
yAxisDraw.call(yAxis);
}
//x轴标签
append('text')
.attr('类','轴标签')
.attr('text-anchor','end')
.text(“X轴”)
.attr('x',宽度)
.attr('y',高度-页边距。底部+50)
//y轴标签
append('text')
.attr('类','轴标签')
.attr('text-anchor','end')
.attr('transform'、'rotate(-90'))
.attr('x',边距顶部+50-(高度/2))
.attr('y',左边距-160)
.text(“Y轴”)
//抽头
const header=svg
.append('g')
.attr('类','图表标题')
.attr('transform','translate(${width/2-75},${margin.top-75})`)
.append('文本')
header.append('tspan')。text('Sine wave'))
函数构建行(数据){
域([d3.min(数据,d=>d.x),d3.max(数据,d=>d.x)])
yScale.domain([d3.min(数据,d=>d.y),d3.max(数据,d=>d.y)])
牵引轴();
data=data.sort(函数(a,b){
返回a-b
})
让lines=chartGroup.selectAll(“.line series”).data([data]);
让scatter=chartGroup.selectAll(“.scatterpoints”).data(数据,d=>null);
行。输入()
.append(“路径”)
.attr('class','line series')
.attr(“d”,d=>抽绳(d))
.attr(“填充”,“无”)
.attr(“笔划”、“黑色”)
.attr(“笔划宽度”,1.5)
.合并(行)
输入()
.附加(“g”)
.attr('类','分散点')
.附加(“圆圈”)
.attr(“cx”,d=>xScale(d.x))
.attr(“cy”,d=>yScale(d.y))
.attr(“r”,5)
.attr(“填充”、“黑色”)
//.合并(分散)
lines.attr(“d”,d=>drawine(d))
散点属性(“cx”,函数(d,i){
设tmp=data[i]
返回xScale(tmp)
}).attr(“cy”,函数(d,i){
设tmp=data[i]
返回yScale(tmp)
});
scatter.exit().remove()
//console.log(data.length)
}
设xRangeSlaider=document.getElementById('slider-x-range');
xRangeSlaider.min=10;
xRangeSlaider.max=100;
让数据=生成数据(xRangeSloider.value)
建筑线(数据)
d3.选择(“#滑块-x范围”)
.on(“更改”,d=>{
//d3.选择所有(“.scatter points”).data(data.exit()。//删除()
数据=生成数据(xRangeSlaider.value)
建筑线(数据)
});代码>
svg{
显示:内联块
chartGroup
.selectAll(".line-series")
.data([data])
.enter()
.append("path")
.attr('class', 'line-series')
.attr("d", d => drawLine(d))
.attr("fill", 'none')
.attr("stroke", "black")
.attr("stroke-width", 1.5)
.merge(lines)
chartGroup
.selectAll(".scatter-points")
.data(data)
.enter()
.append("g")
.attr('class', 'scatter-points')
.append("circle")
.attr("cx", d => xScale(d.x))
.attr("cy", d => yScale(d.y))
.attr("r", 5)
.attr("fill", "black")
// .merge(scatter)
lines.attr("d", d => drawLine(d))
scatter.attr("cx", function(d,i){
let tmp = data[i]
return xScale(tmp)
}).attr("cy", function(d,i){
let tmp = data[i]
return yScale(tmp)
});
lines.exit().remove()
scatter.exit().remove()