D3.js 如何在数据更新期间同步散点图和折线图?

D3.js 如何在数据更新期间同步散点图和折线图?,d3.js,D3.js,我有一个滑块,可以在生成数据的函数中调整参数。到目前为止,我能够在更改此滑块时正确调整折线图。然而,分散点似乎到处都是,我不知道为什么它会这样做 是否有办法将散点绑定到折线图,以便它们同步更新 我也不确定退出选择是否正常工作。理想情况下,如果数据大小增加,我希望图形追加,反之亦然 附件是一个最低限度的工作示例 轴 每次滑块移动时都会更新x轴和y轴域,因此也应该更新轴。通过将轴图形代码放置到函数中并在数据更改时调用它,可以快速解决此问题 具有按键功能的数据绑定 你离这里很近。之所以scatter

我有一个滑块,可以在生成数据的函数中调整参数。到目前为止,我能够在更改此滑块时正确调整折线图。然而,分散点似乎到处都是,我不知道为什么它会这样做

是否有办法将散点绑定到折线图,以便它们同步更新

我也不确定退出选择是否正常工作。理想情况下,如果数据大小增加,我希望图形追加,反之亦然

附件是一个最低限度的工作示例

  • 每次滑块移动时都会更新x轴和y轴域,因此也应该更新轴。通过将轴图形代码放置到函数中并在数据更改时调用它,可以快速解决此问题

  • 具有按键功能的数据绑定
  • 你离这里很近。之所以
    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()