【问题标题】:How to update an svg path with d3.js如何使用 d3.js 更新 svg 路径
【发布时间】:2014-05-02 13:05:19
【问题描述】:

我想应用官方文档中的"general update pattern" 来更新鼠标事件上的 svg 路径(但可以是按钮或其他)。

但路径只是添加而不更新。我认为这就是为什么我没有正确使用 enterexit 属性但经过各种试验后,我无法让它工作。

这是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>

【问题讨论】:

    标签: javascript svg d3.js


    【解决方案1】:

    您的代码没有选择现有元素,因此不是通过update 选择更新现有路径的“d”属性,而是每次都附加一个新路径。这个版本的render() 产生了预期的行为。更多关于选择here.

    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()
    

    一旦您通过.data()path 上运行数据连接,在path 上执行的操作将仅适用于更新选择。意思是,只有那些在新连接下仍然具有相应数据元素的现有元素。当您调用enter().append() 时,它将为每个没有预先存在的元素的数据元素附加一个新元素,然后仅对这些元素应用以下操作。

    在上面,上面的第一个path.attr()只对现有元素进行操作;在path.enter() 之后应用的那些仅适用于新元素。它在上面的 sn-p 中没有出现,但enter() 将输入选择添加到更新选择中:在调用enter() 之后对path 的任何操作都将适用于现有元素和新元素。

    【讨论】:

    • 为什么要重复attr('d')
    • 我的意思是,为什么要先更改路径上“d”的attr,然后通过enter().append() 添加更多“d”?
    • 第一个attr("d") 只对现有元素起作用,随后的attr("d") 为新元素添加d 属性。 (上面添加了完整的解释。)干杯!
    【解决方案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();
    

    【讨论】:

    • 对不起,为什么要绑定3次数据??
    • @nkint 我只是想展示结果,并不关心。当然不需要重复3次,我重新编辑它,谢谢。
    猜你喜欢
    • 2012-08-17
    • 1970-01-01
    • 1970-01-01
    • 2022-01-20
    • 2021-02-08
    • 1970-01-01
    • 2017-01-09
    • 1970-01-01
    相关资源
    最近更新 更多