【问题标题】:D3: Rescaling scatter plot elements with Update, without removing elementsD3:使用更新重新缩放散点图元素,而不删除元素
【发布时间】:2018-12-18 16:28:06
【问题描述】:

我有一些菜鸟问题。 我正在尝试根据按钮单击重新缩放散点图元素(圆圈和 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>

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

提前非常感谢

【问题讨论】:

  • 首先你的数据绑定是错误的,用xy字段创建一个对象数组。您使用 GW-Basic 方法,从长远来看很容易出错。检查如何正确执行散点图的示例
  • 感谢您的通知,但我不认为它的核心问题是为什么这种外壳不能按我想要的方式工作。不是吗?

标签: d3.js scaling scatter-plot


【解决方案1】:

嗯,这是菜鸟的错误,一如既往。缺少两件事: 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/

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-15
    相关资源
    最近更新 更多