D3: Масштабирование элементов точечной диаграммы с обновлением без удаления элементов - PullRequest
0 голосов
/ 18 декабря 2018

У меня есть вопрос новичка.Я пытаюсь изменить масштаб элементов графика рассеяния (кружки вдоль оси 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/

Заранее большое спасибо

1 Ответ

0 голосов
/ 18 декабря 2018

Ну, это была ошибка новичка, как всегда.Две вещи отсутствовали: 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)");

при перерисовке просто выберите классы и измените атрибуты.

    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/

...