javascript - d3 : update of chart via exit/remove/merge does not process changed label text properly

标签 javascript d3.js

对于 d3.js (d3.v4.js),基于 https://bl.ocks.org/mbostock/3884955 (多系列折线图),如果必须处理新数据,我需要更新标签文本。

这个例子几乎可以工作了。出了点问题,因为旧标签文本 (Old York) 与新标签文本 (New York) 仍然在图表中可见。

这是我的代码:

    <script src="https://d3js.org/d3.v4.min.js"></script>
    <style>
        .axis--x path {
            display: none;
        }
            
        .line {
            fill: none;
            stroke: steelblue;
            stroke-width: 1.5px;
        }
            
    </style>
    <button>Click me</button>
    <svg width="960" height="500"></svg>
    <!--<script src="d3.v4.js"></script>-->
            
    <script>
        var svg = d3.select("svg"),
            margin = {
                top: 20,
                right: 80,
                bottom: 30,
                left: 50
            },
            width = svg.attr("width") - margin.left - margin.right,
            height = svg.attr("height") - margin.top - margin.bottom,
            g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");
            
        var parseTime = d3.timeParse("%Y%m%d");
            
        var x = d3.scaleTime().range([0, width]),
            y = d3.scaleLinear().range([height, 0]),
            z = d3.scaleOrdinal(d3.schemeCategory10);
            
        var line = d3.line()
            .curve(d3.curveBasis)
            .x(function (d) {
                return x(d.date);
            })
            .y(function (d) {
                return y(d.temperature);
            });
            
        var data = [{
            "date": "1136156400000",
            "Old York": 63.4,
            "San Francisco": 62.7,
            "Austin": 72.2
        }, {
            "date": "1167692400000",
            "Old York": 58.0,
            "San Francisco": 59.9,
            "Austin": 67.7
        }, {
            "date": "1199228400000",
            "Old York": 53.3,
            "San Francisco": 59.1,
            "Austin": 69.4
        }, {
            "date": "1230850800000",
            "Old York": 55.7,
            "San Francisco": 58.8,
            "Austin": 68.0
        }, {
            "date": "1262386800000",
            "Old York": 62.3,
            "San Francisco": 55.1,
            "Austin": 71.9
        }];
            
        var data2 = [{
            "date": "1136156400000",
            "New York": 263.4,
            "San Francisco": 262.7,
            "Austin": 372.2
        }, {
            "date": "1167692400000",
            "New York": 458.0,
            "San Francisco": 259.9,
            "Austin": -367.7
        }, {
            "date": "1199228400000",
            "New York": 153.3,
            "San Francisco": 259.1,
            "Austin": 369.4
        }, {
            "date": "1230850800000",
            "New York": 155.7,
            "San Francisco": 258.8,
            "Austin": 368.0
        }, {
            "date": "1262386800000",
            "New York": 162.3,
            "San Francisco": 255.1,
            "Austin": 371.9
        }];
    
    
        // d3.tsv("data.tsv", type, function (error, data) {
        //     if (error) throw error;
    
        data.columns = ["date", "Old York", "San Francisco", "Austin"];
    
        var cities = data.columns.slice(1).map(function (id) {
            return {
                id: id,
                values: data.map(function (d) {
                    return {
                        date: d.date,
                        temperature: d[id]
                    };
                })
            };
        });
    
        x.domain(d3.extent(data, function (d) {
            return d.date;
        }));
    
        y.domain([
            d3.min(cities, function (c) {
                return d3.min(c.values, function (d) {
                    return d.temperature;
                });
            }),
            d3.max(cities, function (c) {
                return d3.max(c.values, function (d) {
                    return d.temperature;
                });
            })
        ]);
        g.append("g")
            .attr("class", "axis axis--x")
            .attr("transform", "translate(0," + height + ")")
            .call(d3.axisBottom(x));
        g.append("g")
            .attr("class", "axis axis--y")
            .call(d3.axisLeft(y))
            .append("text")
            .attr("transform", "rotate(-90)")
            .attr("y", 6)
            .attr("dy", "0.71em")
            .attr("fill", "#000")
            .text("Temperature, ºF");
    
        update();
        d3.select("button").on("click", function () {
            // cities.splice(0, 1);
            data = data2;
            data.columns = ["date", "New York", "San Francisco", "Austin"];
            //            console.log(JSON.stringify(cities));
            update();
        });
    
        function update() {
    //        data.columns = ["date", "New York", "San Francisco", "Austin"];
            cities = data.columns.slice(1).map(function (id) {
                return {
                    id: id,
                    values: data.map(function (d) {
                        return {
                            date: d.date,
                            temperature: d[id]
                        };
                    })
                };
            });
    
    
            x.domain(d3.extent(data, function (d) {
                return d.date;
            }));
            y.domain([
                d3.min(cities, function (c) {
                    return d3.min(c.values, function (d) {
                        return d.temperature;
                    });
                }),
                d3.max(cities, function (c) {
                    return d3.max(c.values, function (d) {
                        return d.temperature;
                    });
                })
            ]);
            z.domain(cities.map(function (c) {
                return c.id;
            }));
    
            var city = g.selectAll(".city")
                .data(cities);
    
            city.append("text")
                .datum(function (d) {
                    return {
                        id: d.id,
                        value: d.values[d.values.length - 1]
                    };
                })
                .attr("transform", function (d) {
                    return "translate(" + x(d.value.date) + "," + y(d.value.temperature) + ")";
                })
                .attr("x", 3)
                .attr("dy", "0.35em")
                .style("font", "10px sans-serif")
                .text(function (d) {
                    return d.id;
                });
    
            // var text = g.selectAll(".text")
            //     .data(texts);
    
            city.exit().remove();
    
            var cityEnter = city.enter().append("g")
                .attr("class", "city");
    
            cityEnter.append("path")
                .attr("class", "line")
                .attr("d", function (d) {
                    return line(d.values);
                })
                .style("stroke", function (d) {
                    return z(d.id);
                });
    
    
            city = cityEnter.merge(city);
    
            cityEnter.append("text")
            //        city.append("text")
                .datum(function (d) {
                    return {
                        id: d.id,
                        value: d.values[d.values.length - 1]
                    };
                })
                .attr("transform", function (d) {
                    return "translate(" + x(d.value.date) + "," + y(d.value.temperature) + ")";
                })
                .attr("x", 3)
                .attr("dy", "0.35em")
                .style("font", "10px sans-serif")
                .text(function (d) {
                    return d.id;
                });
    
    
            city.select("path")
            //            .transition().duration(1000)
                .attr("d", function (d) {
                    return line(d.values);
                });
    
            city.select("text").datum(function (d) {
                return {
                    id: d.id,
                    value: d.values[d.values.length - 1]
                };
            })
            //            .transition().duration(1000)
                .attr("transform", function (d) {
                    return "translate(" + x(d.value.date) + "," + y(d.value.temperature) + ")";
                });
    
            svg.select(".axis--y")
            //            .transition().duration(1000)
                .call(d3.axisLeft(y));
        }
    
    </script>

最佳答案

您正在附加一个新的 <text>在更新中选择。由于您要更新组合选择中的文本,因此您甚至不需要更新文本值。您可以删除这部分:

   city.append("text")
                .datum(function (d) {
                    return {
                        id: d.id,
                        value: d.values[d.values.length - 1]
                    };
                })
                .attr("transform", function (d) {
                    return "translate(" + x(d.value.date) + "," + y(d.value.temperature) + ")";
                })
                .attr("x", 3)
                .attr("dy", "0.35em")
                .style("font", "10px sans-serif")
                .text(function (d) {
                    return d.id;
                });

您还需要更新文本:

 city.select("text").datum(function (d) {
        return {
            id: d.id,
            value: d.values[d.values.length - 1]
        };
    })
    .text(function (d) {
        return d.id;
    })

这是更新后的代码:

    <script src="https://d3js.org/d3.v4.min.js"></script>
    <style>
        .axis--x path {
            display: none;
        }
            
        .line {
            fill: none;
            stroke: steelblue;
            stroke-width: 1.5px;
        }
            
    </style>
    <button>Click me</button>
    <svg width="960" height="500"></svg>
    <!--<script src="d3.v4.js"></script>-->
            
    <script>
        var svg = d3.select("svg"),
            margin = {
                top: 20,
                right: 80,
                bottom: 30,
                left: 50
            },
            width = svg.attr("width") - margin.left - margin.right,
            height = svg.attr("height") - margin.top - margin.bottom,
            g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");
            
        var parseTime = d3.timeParse("%Y%m%d");
            
        var x = d3.scaleTime().range([0, width]),
            y = d3.scaleLinear().range([height, 0]),
            z = d3.scaleOrdinal(d3.schemeCategory10);
            
        var line = d3.line()
            .curve(d3.curveBasis)
            .x(function (d) {
                return x(d.date);
            })
            .y(function (d) {
                return y(d.temperature);
            });
            
        var data = [{
            "date": "1136156400000",
            "Old York": 63.4,
            "San Francisco": 62.7,
            "Austin": 72.2
        }, {
            "date": "1167692400000",
            "Old York": 58.0,
            "San Francisco": 59.9,
            "Austin": 67.7
        }, {
            "date": "1199228400000",
            "Old York": 53.3,
            "San Francisco": 59.1,
            "Austin": 69.4
        }, {
            "date": "1230850800000",
            "Old York": 55.7,
            "San Francisco": 58.8,
            "Austin": 68.0
        }, {
            "date": "1262386800000",
            "Old York": 62.3,
            "San Francisco": 55.1,
            "Austin": 71.9
        }];
            
        var data2 = [{
            "date": "1136156400000",
            "New York": 263.4,
            "San Francisco": 262.7,
            "Austin": 372.2
        }, {
            "date": "1167692400000",
            "New York": 458.0,
            "San Francisco": 259.9,
            "Austin": -367.7
        }, {
            "date": "1199228400000",
            "New York": 153.3,
            "San Francisco": 259.1,
            "Austin": 369.4
        }, {
            "date": "1230850800000",
            "New York": 155.7,
            "San Francisco": 258.8,
            "Austin": 368.0
        }, {
            "date": "1262386800000",
            "New York": 162.3,
            "San Francisco": 255.1,
            "Austin": 371.9
        }];
    
    
        // d3.tsv("data.tsv", type, function (error, data) {
        //     if (error) throw error;
    
        data.columns = ["date", "Old York", "San Francisco", "Austin"];
    
        var cities = data.columns.slice(1).map(function (id) {
            return {
                id: id,
                values: data.map(function (d) {
                    return {
                        date: d.date,
                        temperature: d[id]
                    };
                })
            };
        });
    
        x.domain(d3.extent(data, function (d) {
            return d.date;
        }));
    
        y.domain([
            d3.min(cities, function (c) {
                return d3.min(c.values, function (d) {
                    return d.temperature;
                });
            }),
            d3.max(cities, function (c) {
                return d3.max(c.values, function (d) {
                    return d.temperature;
                });
            })
        ]);
        g.append("g")
            .attr("class", "axis axis--x")
            .attr("transform", "translate(0," + height + ")")
            .call(d3.axisBottom(x));
        g.append("g")
            .attr("class", "axis axis--y")
            .call(d3.axisLeft(y))
            .append("text")
            .attr("transform", "rotate(-90)")
            .attr("y", 6)
            .attr("dy", "0.71em")
            .attr("fill", "#000")
            .text("Temperature, ºF");
    
        update();
        d3.select("button").on("click", function () {
            // cities.splice(0, 1);
            data = data2;
            data.columns = ["date", "New York", "San Francisco", "Austin"];
            //            console.log(JSON.stringify(cities));
            update();
        });
    
        function update() {
    //        data.columns = ["date", "New York", "San Francisco", "Austin"];
            cities = data.columns.slice(1).map(function (id) {
                return {
                    id: id,
                    values: data.map(function (d) {
                        return {
                            date: d.date,
                            temperature: d[id]
                        };
                    })
                };
            });
    
    
            x.domain(d3.extent(data, function (d) {
                return d.date;
            }));
            y.domain([
                d3.min(cities, function (c) {
                    return d3.min(c.values, function (d) {
                        return d.temperature;
                    });
                }),
                d3.max(cities, function (c) {
                    return d3.max(c.values, function (d) {
                        return d.temperature;
                    });
                })
            ]);
            z.domain(cities.map(function (c) {
                return c.id;
            }));
    
            var city = g.selectAll(".city")
                .data(cities);        
    
            // var text = g.selectAll(".text")
            //     .data(texts);
    
            city.exit().remove();
    
            var cityEnter = city.enter().append("g")
                .attr("class", "city");
    
            cityEnter.append("path")
                .attr("class", "line")
                .attr("d", function (d) {
                    return line(d.values);
                })
                .style("stroke", function (d) {
                    return z(d.id);
                });
    
    
            city = cityEnter.merge(city);
    
            cityEnter.append("text")
            //        city.append("text")
                .datum(function (d) {
                    return {
                        id: d.id,
                        value: d.values[d.values.length - 1]
                    };
                })
                .attr("transform", function (d) {
                    return "translate(" + x(d.value.date) + "," + y(d.value.temperature) + ")";
                })
                .attr("x", 3)
                .attr("dy", "0.35em")
                .style("font", "10px sans-serif")
                .text(function (d) {
                    return d.id;
                });
    
    
            city.select("path")
            //            .transition().duration(1000)
                .attr("d", function (d) {
                    return line(d.values);
                });
    
            city.select("text").datum(function (d) {
                return {
                    id: d.id,
                    value: d.values[d.values.length - 1]
                };
            })
            .text(function (d) {
                return d.id;
            })
            //            .transition().duration(1000)
                .attr("transform", function (d) {
                    return "translate(" + x(d.value.date) + "," + y(d.value.temperature) + ")";
                });
    
            svg.select(".axis--y")
            //            .transition().duration(1000)
                .call(d3.axisLeft(y));
        }
    
    </script>

关于javascript - d3 : update of chart via exit/remove/merge does not process changed label text properly,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42797393/

相关文章:

javascript - 何时在 AngularJS 中使用 Worker 和 Factory 函数

javascript - js中的字符串到日期转换器问题

javascript - 如何持续发送ajax请求直到收到响应?

javascript - 移动栏的位置标签,最大化/最小化屏幕,文本不稳定(在 C3.js - D3.js 中)

javascript - 如何处理 Sequelize 嵌套/复合查询?

javascript - 随着用户输入更改输入框文本的颜色

d3.js - 使用比例绘制网格或矩形

javascript - 获取可拖动箭头 D3 的 Angular 值

javascript - 迭代中的异步函数 - javascript

javascript - 如何使用 Rails 数据库中的数据创建 d3 图形