D3:使用Update重新调整散点图元素的比例,而无需删除元素

时间:2018-12-18 16:28:07

标签: d3.js scaling scatter-plot

我有一个菜鸟问题。 我试图基于按钮单击来重新缩放散点图元素(沿着X轴的圆)-创建“放大”活动。我为此降低了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>

在这里实现小提琴 https://jsfiddle.net/sma76ntq/

非常感谢

1 个答案:

答案 0 :(得分:0)

一如既往,这是菜鸟的错误。缺少两件事: 1.在圆形上添加一些类,以便在绘制更多圆形时不要在画布上选择所有内容

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. 在重绘时,只需选择类并更改属性即可。

        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);
        });
    

在这里工作的小提琴:https://jsfiddle.net/v7q14nbm/1/