更新工具提示d3js

时间:2019-11-24 09:58:23

标签: javascript d3.js

我目前正在处理d3js多重图表,该多重图表具有一个工具提示,可详细显示图表中的数据。对于该图表,我还有一个下拉列表,用于选择数据并允许更改图表上显示的内容。问题:当我更改内容时,图形上的曲线数可能会变化,并且如果我显示3条曲线的数据,然后更改为2条曲线的数据,则第三条曲线的标签仍会显示在工具提示上。 >

我尝试使用.remove()清除工具提示的内容,但是它完全删除了我的工具提示,不再显示。

这是我的代码:

var keys = data.columns.slice(1);

var parseTime = d3.timeParse("%Y%m%d"),
    formatDate = d3.timeFormat("%Y-%m-%d"),
    bisectDate = d3.bisector(d => d.date).left,
    formatValue = d3.format(",.0f");

data.forEach(function(d) {
    d.date = parseTime(d.date);
    return d;
})

var svgMultichart = d3.select("#multichart"),
    margin = {top: 15, right: 35, bottom: 15, left: 35},
    widthMultichart = +svgMultichart.attr("width") - margin.left - margin.right,
    heightMultichart = +svgMultichart.attr("height") - margin.top - margin.bottom;

var x = d3.scaleTime()
    .rangeRound([margin.left, widthMultichart - margin.right])
    .domain(d3.extent(data, d => d.date))

var y = d3.scaleLinear()
    .rangeRound([heightMultichart - margin.bottom, margin.top]);

var z = d3.scaleOrdinal(d3.schemeCategory10);

var line = d3.line()
    .curve(d3.curveCardinal)
    .x(d => x(d.date))
    .y(d => y(d.degrees));

svgMultichart.append("g")
    .attr("class","x-axis")
    .attr("transform", "translate(0," + (heightMultichart - margin.bottom) + ")")
    .call(d3.axisBottom(x).tickFormat(d3.timeFormat("%b")));

svgMultichart.append("g")
    .attr("class", "y-axis")
    .attr("transform", "translate(" + margin.left + ",0)");

var focus = svgMultichart.append("g")
    .attr("class", "focus")
    .style("display", "none");

focus.append("line").attr("class", "lineHover")
    .style("stroke", "#999")
    .attr("stroke-width", 1)
    .style("shape-rendering", "crispEdges")
    .style("opacity", 0.5)
    .attr("y1", -heightMultichart)
    .attr("y2",0);

focus.append("text").attr("class", "lineHoverDate")
    .attr("text-anchor", "middle")
    .attr("font-size", 12);

var overlay = svgMultichart.append("rect")
    .attr("class", "overlay")
    .attr("x", margin.left)
    .attr("width", widthMultichart - margin.right - margin.left)
    .attr("height", heightMultichart)

update(d3.select('#selectbox').property('value'), 0);

function update(input, speed) {

    var copy = keys.filter(f => f.includes(input))

    var param = copy.map(function(id) {
        return {
            id: id,
            values: data.map(d => {return {date: d.date, degrees: +d[id]}})
        };
    });

    y.domain([
        d3.min(param, d => d3.min(d.values, c => c.degrees)),
        d3.max(param, d => d3.max(d.values, c => c.degrees))
    ]).nice();

    svgMultichart.selectAll(".y-axis").transition()
        .duration(speed)
        .call(d3.axisLeft(y).tickSize(-widthMultichart + margin.right + margin.left))

    var parametre = svgMultichart.selectAll(".param")
        .data(param);

        console.log(focus) 

    parametre.exit().remove();

    parametre.enter().insert("g", ".focus").append("path")
        .attr("class", "line param")
        .style("stroke", d => z(d.id))
        .merge(parametre)
    .transition().duration(speed)
        .attr("d", d => line(d.values))

    tooltip(d3.select('#selectbox').property('value'),copy);
}

function tooltip(input,copy) {
    var labels = focus.selectAll(".lineHoverText").data(function(d){
        return keys.filter(f => f.includes(input))
    }); 

    labels.enter().append("text")
        .attr("class", "lineHoverText")
        .style("fill", d => z(d))
        .attr("text-anchor", "start")
        .attr("font-size",12)
        .attr("dy", (_, i) => 1 + i * 2 + "em")
        .merge(labels);

    var circles = focus.selectAll(".hoverCircle")
        .data(copy)

    circles.enter().append("circle")
        .attr("class", "hoverCircle")
        .style("fill", d => z(d))
        .attr("r", 2.5)
        .merge(circles);

    svgMultichart.selectAll(".overlay")
        .on("mouseover", function() { focus.style("display", null); })
        .on("mouseout", function() { focus.style("display", "none"); })
        .on("mousemove", mousemove);

    function mousemove() {

        var x0 = x.invert(d3.mouse(this)[0]),
            i = bisectDate(data, x0, 1),
            d0 = data[i - 1],
            d1 = data[i],
            d = x0 - d0.date > d1.date - x0 ? d1 : d0;

        focus.select(".lineHover")
            .attr("transform", "translate(" + x(d.date) + "," + heightMultichart + ")");

        focus.select(".lineHoverDate")
            .attr("transform", 
                "translate(" + x(d.date) + "," + (heightMultichart + margin.bottom) + ")")
            .text(formatDate(d.date));

        focus.selectAll(".hoverCircle")
            .attr("cy", e => y(d[e]))
            .attr("cx", x(d.date));

        focus.selectAll(".lineHoverText")
            .attr("transform", 
                "translate(" + (x(d.date)) + "," + heightMultichart / 2.5 + ")")
            .text(e => e + " - " + formatValue(d[e]));

        x(d.date) > (widthMultichart - widthMultichart / 4) 
            ? focus.selectAll("text.lineHoverText")
                .attr("text-anchor", "end")
                .attr("dx", -10)
            : focus.selectAll("text.lineHoverText")
                .attr("text-anchor", "start")
                .attr("dx", 10)
    }
}

var selectbox = d3.select("#selectbox")
    .on("change", function() {
        update(this.value, 750);
    })

0 个答案:

没有答案