簡體   English   中英

D3.js:折線圖中水平和垂直焦點線(十字線)的位置錯誤

[英]D3.js: Wrong position of horizontal and vertical focus lines (crosshairs) in line chart

我為數據修改了該示例: 具有X和Y十字准線以及閾值線的D3js圖

它工作得很好,但是線條未在正確的位置顯示。 查看截圖。 在此處輸入圖片說明

我認為該域存在問題,但我無法弄清楚。 這是我的腳本:

更新:問題是由我放置文本的方式引起的。 任何想法如何以其他方式放置文本?

var svg = d3.select("svg"),
        margin = {top: 20, right: 50, 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.utcParse("%Y-%m-%dT%H:%M:%S.%LZ");
var bisectDate = d3.bisector(function(d) { return d.timestamp; }).left;
var formatValue = d3.format(",.2f");


d3.json("data.json", function(error, json) {
    if (error) throw error;
    var data = json[0].tideData;
    data.forEach(function(d) {
        d.timestamp = parseTime(d.timestamp);
    });

    var xDomain = d3.extent(data, function(d) { return d.timestamp; });
    var yDomain = d3.extent(data, function(d) { return d.tide; });

    var xScale =  d3.scaleTime().rangeRound([0, width]).domain(xDomain);
    var yScale = d3.scaleLinear().rangeRound([height, 0]).domain(yDomain);

    var line = d3.line()
            .defined(function(d) { return d.tide!=null; })
            .x(function(d) { return xScale(d.timestamp); })
            .y(function(d) { return yScale(d.tide); });

    g.append("g")
            .attr("class", "axis axis--x")
            .attr("transform", "translate(0," + height + ")")
            .call(d3.axisBottom(xScale));

    g.append("g")
            .attr("class", "axis axis--y")
            .call(d3.axisLeft(yScale))
            .append("text")
            .attr("fill", "#000")
            .attr("transform", "rotate(-90)")
            .attr("y", 6)
            .attr("dy", "0.71em")
            .style("text-anchor", "end")
            .text("Sea Level");

    g.append("path")
            .datum(data)
            .attr("class", "line")
            .attr("d", line);

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

    focus.append("circle")
            .attr("r", 4.5);

    focus.append("text")
            .attr("x", 9)
            .attr("dy", ".35em");

    focus.append('line')
            .attr('id', 'focusLineX')
            .attr('class', 'focusLine');

    focus.append('line')
            .attr('id', 'focusLineY')
            .attr('class', 'focusLine');

    g.append("rect")
            .attr("class", "overlay")
            .attr("width", width)
            .attr("height", height)
            .on("mouseover", function() { focus.style("display", null); })
            .on("mouseout", function() { focus.style("display", "none"); })
            .on("mousemove", mousemove);

    function mousemove() {
        var mouse = d3.mouse(this);
        var mouseDate = xScale.invert(mouse[0]);
        var i = bisectDate(data, mouseDate); // returns the index to the current data item

        var d0 = data[i - 1];
        var d1 = data[i];
        // work out which date value is closest to the mouse
        var d = mouseDate - d0[0] > d1[0] - mouseDate ? d1 : d0;

        var x = xScale(d.timestamp);
        var y = yScale(d.tide);

        focus.attr("transform", "translate(" + x + "," + y + ")");
        focus.select("text").text(formatValue(d.tide));
        focus.select('#focusLineX')
                .attr('x1', x).attr('y1', yScale(yDomain[0]))
                .attr('x2', x).attr('y2', yScale(yDomain[1]));
        focus.select('#focusLineY')
                .attr('x1', xScale(xDomain[0])).attr('y1', y)
                .attr('x2', xScale(xDomain[1])).attr('y2', y);

    }
});

問題是整個焦點變量的轉換。 我將圓和文本分別定位,現在可以使用:

        // focus tracking

        var focus = g.append('g').style('display', 'none')

        focus.append('circle')
                .attr('id', 'focusCircle')
                .attr('r', 4.5)
                .attr('class', 'circle focusCircle')

        focus.append("text")
                .attr("x", 9)
                .attr("dy", ".35em")

        focus.append('line')
                .attr('id', 'focusLineX')
                .attr('class', 'focusLine')

        focus.append('line')
                .attr('id', 'focusLineY')
                .attr('class', 'focusLine')

        g.append("rect")
                .attr("class", "overlay")
                .attr("width", width)
                .attr("height", height)
                .on("mouseover", function() { focus.style("display", null) })
                .on("mouseout", function() { focus.style("display", "none") })
                .on("mousemove", mousemove)

        function mousemove() {
            var mouse = d3.mouse(this)
            var mouseDate = xScale.invert(mouse[0])
            var i = bisectDate(data, mouseDate) // returns the index to the current data item

            var d0 = data[i - 1]
            var d1 = data[i]
            // work out which date value is closest to the mouse
            var d = mouseDate - d0[0] > d1[0] - mouseDate ? d1 : d0

            var x = xScale(d.date)
            var y = yScale(d.tide)

            focus.select("text")
                    .attr("transform", "translate(" + x + "," + y + ")")
                    .text(formatValue(d.tide))

            focus.select('#focusCircle')
                    .attr('cx', x)
                    .attr('cy', y)

            focus.select('#focusLineX')
                    .attr('x1', xScale(d.date)).attr('y1', yScale(yDomain[0]))
                    .attr('x2', xScale(d.date)).attr('y2', yScale(yDomain[1]))
            focus.select('#focusLineY')
                    .attr('x1', xScale(xDomain[0])).attr('y1', yScale(d.tide))
                    .attr('x2', xScale(xDomain[1])).attr('y2', yScale(d.tide))

        }

在創建焦點線的代碼中,您正在使用當前數據點(鼠標位置)開始行。

    focus.select('#focusLineX')
            .attr('x1', x).attr('y1', yScale(yDomain[0]))
            .attr('x2', x).attr('y2', yScale(yDomain[1]));
    focus.select('#focusLineY')
            .attr('x1', xScale(xDomain[0])).attr('y1', y)
            .attr('x2', xScale(xDomain[1])).attr('y2', y);

您的水平線應從y軸開始,並跨越點高處的寬度。 同樣,垂直線應從圖形的頂部開始,一直到底部(x軸)。

試試這個變化

   focus.select('#focusLineX')
            .attr('x1', x).attr('y1', 0)
            .attr('x2', x).attr('y2', heightOfChart);
    focus.select('#focusLineY')
            .attr('x1', 0).attr('y1', y)
            .attr('x2', widthOfChart).attr('y2', y);

希望能幫助到你

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM