2016-07-09 91 views
0

我是新來的d3.js從堆棧溢出中得到以下代碼。我根據自己的需要定製了它。但是,當添加工具提示時,它不會根據鼠標移動而移動,並且只有日期顯示在y軸的頂部。我需要按順序顯示工具提示日期:date -newline- OP:一些價值-newline- IP:一些價值-newline-藥房:一些價值-newline-總計:OP + IP +藥房,鼠標懸停在行。d3.js - 多系列折線圖工具提示問題

TSV文件和代碼如下。提前致謝。

HTML文件

</!DOCTYPE html> 
<html> 
<head> 

<style> 

body { 
    font: 10px sans-serif; 
} 

.axis path, 
.axis line { 
    fill: none; 
    stroke: #000; 
    shape-rendering: crispEdges; 
} 


.line { 
    fill: none; 
    stroke: steelblue; 
    stroke-width: 1.5px; 
} 

</style> 
<script type="text/javascript" src="assets/js/plugins/visualization/d3/d3.min.js"></script> 
</head> 
<body> 
<div id="revenueStati"></div> 
<script> 
linchart(); 
function linchart(){ 
var margin = {top: 20, right: 80, bottom: 30, left: 50}, 
    width = 960 - margin.left - margin.right, 
    height = 500 - margin.top - margin.bottom; 

var parseDate = d3.time.format("%Y%m%d").parse; 
var formatDate = d3.time.format("%d-%b") 
var bisectDate = d3.bisector(function(d) { return d.date; }).left 
var x = d3.time.scale() 
    .range([0, width]); 

var y = d3.scale.linear() 
    .range([height-10, 0]); 

var color = d3.scale.category10(); 

var xAxis = d3.svg.axis() 
    .scale(x) 
    .orient("bottom").ticks(7); 

var yAxis = d3.svg.axis() 
    .scale(y) 
    .orient("left"); 

var line = d3.svg.line() 
    .interpolate("basis") 
    .x(function(d) { return x(d.date); }) 
    .y(function(d) { return y(d.temperature); }); 

var svg = d3.select("#revenueStati").append("svg") 
    .attr("width", width + margin.left + margin.right) 
    .attr("height", height + margin.top + margin.bottom) 
    .append("g") 
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 





d3.tsv("data.tsv", function(error, data) { 
    if (error) throw error; 

    color.domain(d3.keys(data[0]).filter(function(key) { return key !== "date"; })); 

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

    var cities = color.domain().map(function(name) { 
    return { 
     name: name, 
     values: data.map(function(d) { 
     return {date: d.date, temperature: +d[name]}; 
     }) 
    }; 
    }); 

    x.domain(d3.extent(data, function(d) { return d.date; })); 

    y.domain([ 
    d3.min(cities, function(c) { return d3.min(c.values, function(v) { return v.temperature; }); }), 
    d3.max(cities, function(c) { return d3.max(c.values, function(v) { return v.temperature; }); }) 
    ]); 

    svg.append("g") 
     .attr("class", "x axis") 
     .attr("transform", "translate(0," + height + ")") 
     .call(xAxis); 

    svg.append("g") 
     .attr("class", "y axis") 
     .call(yAxis) 
    .append("text") 
     .attr("transform", "rotate(-90)") 
     .attr("y", 6) 
     .attr("dy", ".71em") 
     .style("text-anchor", "end"); 

    var city = svg.selectAll(".city") 
     .data(cities) 
    .enter().append("g") 
     .attr("class", "city"); 

    city.append("path") 
     .attr("class", "line") 
     .attr("d", function(d) { return line(d.values); }) 
     .style("stroke", function(d) { return color(d.name); }); 

    city.append("text") 
     .datum(function(d) { return {name: d.name, 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", ".35em") 
     .text(function(d) { return d.name; }); 

     //// - tooltip 


city = svg.append("g") 
    .style("display", "none"); 
     // append the x line 
    city.append("line") 
     .attr("class", "x") 
     .style("stroke", "blue") 
     .style("stroke-dasharray", "3,3") 
     .style("opacity", 0.5) 
     .attr("y1", 0) 
     .attr("y2", height); 

    // append the y line 
    city.append("line") 
     .attr("class", "y") 
     .style("stroke", "blue") 
     .style("stroke-dasharray", "3,3") 
     .style("opacity", 0.5) 
     .attr("x1", width) 
     .attr("x2", width); 

    // append the circle at the intersection 
    city.append("circle") 
     .attr("class", "y") 
     .style("fill", "none") 
     .style("stroke", "blue") 
     .attr("r", 4); 

    // place the value at the intersection 
    city.append("text") 
     .attr("class", "y1") 
     .style("stroke", "white") 
     .style("stroke-width", "3.5px") 
     .style("opacity", 0.8) 
     .attr("dx", 8) 
     .attr("dy", "-.3em"); 
    city.append("text") 
     .attr("class", "y2") 
     .attr("dx", 8) 
     .attr("dy", "-.3em"); 

    // place the date at the intersection 
    city.append("text") 
     .attr("class", "y3") 
     .style("stroke", "white") 
     .style("stroke-width", "3.5px") 
     .style("opacity", 0.8) 
     .attr("dx", 8) 
     .attr("dy", "1em"); 
    city.append("text") 
     .attr("class", "y4") 
     .attr("dx", 8) 
     .attr("dy", "1em"); 

    // append the rectangle to capture mouse 
    svg.append("rect") 
     .attr("width", width) 
     .attr("height", height) 
     .style("fill", "none") 
     .style("pointer-events", "all") 
     .on("mouseover", function() { city.style("display", null); }) 
     .on("mouseout", function() { city.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; 

    city.select("circle.y") 
     .attr("transform", 
       "translate(" + x(d.date) + "," + 
          y(d.close) + ")"); 

    city.select("text.y1") 
     .attr("transform", 
       "translate(" + x(d.date) + "," + 
          y(d.close) + ")") 
     .text(d.close); 

    city.select("text.y2") 
     .attr("transform", 
       "translate(" + x(d.date) + "," + 
          y(d.close) + ")") 
     .text(d.close); 

    city.select("text.y3") 
     .attr("transform", 
       "translate(" + x(d.date) + "," + 
          y(d.close) + ")") 
     .text(formatDate(d.date)); 

    city.select("text.y4") 
     .attr("transform", 
       "translate(" + x(d.date) + "," + 
          y(d.close) + ")") 
     .text(formatDate(d.date)); 

    city.select(".x") 
     .attr("transform", 
       "translate(" + x(d.date) + "," + 
          y(d.close) + ")") 
        .attr("y2", height - y(d.close)); 

    city.select(".y") 
     .attr("transform", 
       "translate(" + width * -1 + "," + 
          y(d.close) + ")") 
        .attr("x2", width + width); 
    } 

}); 
} 

</script> 
</body> 

</html> 

data.tsv文件

date OP IP Pharmacy 
20160406 46905.00 10360.00 52558.00 
20160407 45415.00 10910.00 46665.00 
20160408 69770.00 10935.00 46377.00 
20160409 58455.00 29900.00 37352.00 
20160410 10345.00 7200.00 22971.00 
20160411 48680.00 14535.00 46482.00 
20160412 42452.00 16270.00 34859.00 

demo graph

+1

你在哪裏定義'd.close'。你正在把NaN當作你的位置。你的後期示例鏈接? – Klaujesi

+0

@Klaujesi我已經發布了所有代碼和tsv文件,目前無法使其在線。請幫助。 – JavDev

回答

1

你的代碼是從一個數據系列的實例採取與您有多個系列:

重要的從這裏開始:

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; 

city.select("circle.y") 
    .attr("transform", 
      "translate(" + x(d.date) + "," + // based on date 
         y(d.close) + ")"); // you need find y value 
              // d.close is not defined 

你有3個系列。你可以採取的最大值在某個日期和畫有圓圈:

var ymax = d3.max([+d["OP"],+d["IP"],+d["Pharmacy"]]) 
var xm = x(d.date); 
var ym = y(ymax); 

city.select("circle.y") 
    .attr("transform", 
      "translate(" + xm + "," + 
         ym + ")"); 

或者,畫三個圈,每個系列:

city.select("circle.y") 
    .attr("transform", 
      "translate(" + xm + "," + 
         y(+d["OP"]) + ")"); 

city.select("circle.y") 
    .attr("transform", 
      "translate(" + xm + "," + 
         y(+d["IP"]) + ")"); 

city.select("circle.y") 
    .attr("transform", 
      "translate(" + xm + "," + 
         y(+d["Pharmacy"]) + ")"); 

現在你知道如何calulate(X,Y )你可以用標籤做水平的&垂直虛線。

Here's s psudoworking code。我已經讓你完成它作爲作業:)