D3:使用更新重新缩放散点图元素,而不删除元素

D3: Rescaling scatter plot elements with Update, without removing elements

我有一些菜鸟问题。 我正在尝试根据按钮单击重新缩放散点图元素(圆圈和 X 轴)- 创建 'zoom in' activity。我为此降低了 X 轴域。

它在 Xaxis 上工作得很好,但在圆上更难。我必须将它们全部移除并重新绘制它们(代码中标记的地方)。当涉及很多元素时,这会使过程变慢,并且不允许应用于轴缩放的过渡。

是否可以只更改我不需要删除并重新绘制所有内容的圆圈的属性?

<!DOCTYPE html>
<html lang="en">
<head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
    <script src="https://d3js.org/d3.v4.min.js"></script>
</head>
<body>
<script>
    // Define Canvas size
    var width = 500;
    var height = 500;

    // Generate Toy Data
    var randomX = d3.randomUniform(0, 880);
    var randomY = d3.randomUniform(0, 800);
    data_x = [];
    data_y = [];
    for (i = 0; i < 10000; i++) {
        nume = Math.floor((Math.random() * 100));
        data_x.push(nume);
        data_y.push(nume);
    }

    // Scaling Coeffs
    var coeffX = 1;
    var coeffY = 1;
    var coeffR = 1;

    var coordX = (Math.max.apply(null, data_x)/coeffX);
    var coordy = (Math.max.apply(null, data_y)/coeffY);

    var x = d3.scaleLinear()
              .domain([0, coordX])
              .range([ 0, width]).nice();

    var y = d3.scaleLinear()
              .domain([0, coordy])
              .range([height, 0]).nice();

    var yAxis = d3.axisLeft(y).ticks(5);
    var xAxis = d3.axisBottom(x).ticks(5)


    //Create SVG element
    var canvas = d3.select("body")
            .append("svg")
            .attr("width", width+50)
            .attr("height", height+50)
            .append("g");

    // --------------- Draw Elements ---------------------
    var circles = canvas.selectAll("circlepoint")
            .data(data_x)
            .enter()
            .append("g");

        circles.append("circle")
            .attr("cx",function(d, i){
                var tempe = data_x[i];
                return x(tempe);
            })
            .attr("cy", function(d, i){
                var tempe = data_y[i];
                return y(tempe);
            })
            .attr("r", function(){
                return 3;
            })
            .style("stroke", "steelblue")
            .style("fill", "none")
            .attr("transform", "translate(40, -20)");

    var xsCont = canvas.append("g")
                .attr("transform", "translate(40, " + (height-20)  +")")
                .attr("class","xaxis")
                .call(xAxis);
    var ysCont = canvas.append("g")
                .attr("transform", "translate(40, -20)")
                .call(yAxis);

    function rescaleAxisX(tempCoeffX, tempCoeffR){

        coordX = (Math.max.apply(null, data_x)/tempCoeffX);
        x.domain([0, Math.max.apply(null, data_x)/tempCoeffX])

        // -------- This part works well-------
        canvas.select(".xaxis")
            .transition().duration(750)
            .call(xAxis);
        // -------- End -------------

        // -------- This one doesn't as expected-------
        circles.remove();
        circles = canvas.selectAll("circlepoint")
            .data(data_x)
            .enter()
            .append("g");

        circles.append("circle")
            .attr("cx",function(d, i){
                var tempe = data_x[i];
                return x(tempe);
            })
            .attr("cy", function(d, i){
                var tempe = data_y[i];
                return y(tempe);

            })
            .attr("r", function(d, i){
                return tempCoeffR;
            })
            .style("stroke", "steelblue")
            .style("fill", "none")
            .attr("transform", "translate(40, -20)");
    }
    // -------- End -------


    // Zoom in button
    var buttonZoomPlusX = d3.select("body")
            .append("input")
            .attr("type","button")
            .attr("class","button")
            .attr("value", "+")
            .on("click", function(){
                coeffX = coeffX + 1;
                coeffR = coeffR + 1;
                rescaleAxisX(coeffX, coeffR);
            })

</script>
</body>
</html>

这里实现了Fiddle https://jsfiddle.net/sma76ntq/

非常感谢

好吧,一如既往的菜鸟错误。缺少两件事: 1. 将一些 class 附加到圆圈中,以免 select 如果绘制更多圆圈 canvas 上的所有内容

circles.append("circle")
        .attr("cx",function(d, i){
            var tempe = data_x[i];
            return x(tempe);
        })
        .attr("cy", function(d, i){
            var tempe = data_y[i];
            return y(tempe);
            //return y(d.y);
        })
        .attr("r", function(){
            return 3;
        })
        .attr("class","eles")
        .style("stroke", "steelblue")
        .style("fill", "none")
        .attr("transform", "translate(40, -20)");
  1. 重绘 select classes 并更改属性。

        canvas.selectAll(".eles").data(data_x)
        .transition()
        .duration(750)
        .attr("cx",function(d, i){
            var tempe = data_x[i];
            return x(tempe);
        })
        .attr("cy", function(d, i){
            var tempe = data_y[i];
            return y(tempe);
        });
    

在这里 Fiddle 工作:https://jsfiddle.net/v7q14nbm/1/