Подтвердить что ты не робот

Как обновить SVG-путь с помощью d3.js

Я хотел бы применить общий шаблон обновления от официальной документации, чтобы обновить SVG-путь в событии мыши (но может быть кнопкой или что-то еще).

Но путь добавляется и не обновляется. Я думаю, почему я не правильно использую свойства enter и exit, но после некоторого различного пробного периода я не могу позволить ему работать.

Вот jsfiddle.

Мой код js находится здесь:

var shapeCoords = [
                  [10, 10], [100, 10], [100, 100], [10, 100]                  
                  ];

$(function() {
    var container = $('#container');

    // D3
    console.log("D3: ", d3);

    var svg = d3.select('#container')
                .append('svg:svg')
                .attr('height', 600)
                .attr('width', 800);

    var line = d3.svg.line()
                    .x(function(d) { return d[0]; })
                    .y(function(d) { return d[1]; })
                    .interpolate('linear');

    function render() {

            svg.data(shapeCoords)
                .append('svg:path')
                .attr('d', line(shapeCoords) + 'Z')
                .style('stroke-width', 1)
                .style('stroke', 'steelblue');
    }
    render();

    var mouseIsDown = false;  
    container.on('mousedown mouseup mousemove', function(e) {
        if (e.type == 'mousedown') {
            mouseIsDown = true; 
            shapeCoords[3] = [e.offsetX, e.offsetY];
        } else if (e.type == 'mouseup' ){
            mouseIsDown = false;
            shapeCoords[3] = [e.offsetX, e.offsetY];
        } else if (e.type == 'mousemove') {
            if (mouseIsDown) {
                shapeCoords[3] = [e.offsetX, e.offsetY];
                render();
            }
        }
    });


});

И html:

<!DOCTYPE html>
<html>
<head>
    <title>D3 mousemove</title>
    <script type="text/javascript" 
            src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js">
    </script>
    <script type="text/javascript" 
            src="http://mbostock.github.com/d3/d3.js">
    </script>
    <script type="text/javascript" src="script.js"></script>
    <style>
        #container { 
            width: 800px; 
            height: 600px; 
            border: 1px solid silver; }
        path, line {
            stroke: steelblue;
            stroke-width: 1;
            fill: none;
        }
    </style>
</head> 
<body>   
    <div id="container"></div>
</body>
</html>
4b9b3361

Ответ 1

Ваш код не выбирает существующий элемент, поэтому вместо обновления атрибута "d" существующего пути с помощью выбора update он добавляет новый путь каждый раз. Эта версия render() вызвала ожидаемое поведение. Подробнее о выборе здесь.

function render() {
    path = svg.selectAll('path').data([shapeCoords])
    path.attr('d', function(d){return line(d) + 'Z'})
        .style('stroke-width', 1)
        .style('stroke', 'steelblue');
    path.enter().append('svg:path').attr('d', function(d){return line(d) + 'Z'})
        .style('stroke-width', 1)
        .style('stroke', 'steelblue');
    path.exit().remove()

Как только вы запустите соединение данных на path с помощью .data(), операции, выполняемые в path, применимы только к выбору обновления. Это означает, что только те существующие элементы, которые по-прежнему имеют соответствующие элементы данных в новом соединении. Когда вы вызываете enter().append(), он добавляет новый элемент для каждого элемента данных без ранее существовавшего элемента, а затем применяет следующие операции только к этим элементам.

В приведенном выше примере первое path.attr() работает только на существующих элементах; те, которые применяются после path.enter(), применяются только к новым элементам. Он не показан в приведенном выше фрагменте, но enter() добавляет выбор ввода к выбору обновления: любые операции над path после вызова enter() будут применяться как к существующим, так и к новым элементам.

Ответ 2

Пожалуйста, попробуйте следующий код, я думаю, это то, что вы хотите. Проблема вызвана тем, что вы должны различать ввод, обновление и завершение, когда хотите обновлять элементы, иначе он будет добавлять данные снова и снова.

$(function() {
var container = $('#container');

// D3
console.log("D3: ", d3);

var svg = d3.select('#container')
            .append('svg:svg')
            .attr('height', 600)
            .attr('width', 800);

var line = d3.svg.line()
                .x(function(d) { return d[0]; })
                .y(function(d) { return d[1]; })
                .interpolate('linear');

svg.data(shapeCoords)
    .append('svg:path')
    .attr('d', line(shapeCoords) + 'Z')
    .style('stroke-width', 1)
    .style('stroke', 'steelblue');

function render() {

    var svg = d3.select('#container').select("svg").selectAll('path').data(shapeCoords);
    svg.enter().append('svg:path')
            .attr('d', line(shapeCoords) + 'Z')
            .style('stroke-width', 1)
            .style('stroke', 'steelblue');
    svg.attr('d', line(shapeCoords) + 'Z')
            .style('stroke-width', 1)
            .style('stroke', 'steelblue');    
    svg.exit().remove();    

}
render();