2016-04-13 18 views
1

Araç ipuçlarıyla D3.js kullanarak çok satırlı bir grafik hazırladım. Her şey bu grafikte iyi çalışıyor ancak grafikteki tüm grafikler için araç ipuçlarına stil eklemek istiyorum ancak bunu yapamıyorum. Çok satırlı D3.js çizgi grafik biçiminde araç ipucunu şekillendirme

var margin = { 
 
    top: 20, 
 
    right: 30, 
 
    bottom: 30, 
 
    left: 40 
 
    }, 
 
    width = 960 - margin.left - margin.right, 
 
    height = 500 - margin.top - margin.bottom; 
 

 
var z = d3.scale.category20c(); 
 

 
var svg = d3.select("body").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 + ")"); 
 

 
var parseDate = d3.time.format("%Y-%m-%dT%H:%M:%S.%LZ"); 
 

 
var data = [{ 
 
    data: [ 
 
    ["2016-01-20T05:31:17.000Z", 95.9, {}], 
 
    ["2016-01-20T05:31:47.000Z", 95.9, {}], 
 
    ["2016-01-20T05:32:17.000Z", 95.4, {}], 
 
    ["2016-01-20T05:32:47.000Z", 96.1, {}], 
 
    ["2016-01-20T05:33:17.000Z", 95.7, {}], 
 
    ["2016-01-20T05:33:47.000Z", 95.9, {}], 
 
    ["2016-01-20T05:34:17.000Z", 95.5, {}], 
 
    ["2016-01-20T05:34:47.000Z", 95.9, {}], 
 
    ["2016-01-20T05:35:17.000Z", 95.8, {}], 
 
    ["2016-01-20T05:35:47.000Z", 95.9, {}], 
 
    ["2016-01-20T05:36:17.000Z", 95.7, {}], 
 
    ["2016-01-20T05:36:47.000Z", 95.7, {}], 
 
    ["2016-01-20T05:37:17.000Z", 95.9, {}], 
 
    ["2016-01-20T05:37:47.000Z", 95.5, {}], 
 
    ["2016-01-20T05:38:17.000Z", 95.4, {}], 
 
    ["2016-01-20T05:38:47.000Z", 95.8, {}], 
 
    ["2016-01-20T05:39:17.000Z", 96.0, {}], 
 
    ["2016-01-20T05:39:47.000Z", 96.1, {}], 
 
    ["2016-01-20T05:40:17.000Z", 95.8, {}], 
 
    ["2016-01-20T05:40:47.000Z", 96.0, {}], 
 
    ["2016-01-20T05:41:17.000Z", 95.9, {}], 
 
    ["2016-01-20T05:41:47.000Z", 94.9, {}], 
 
    ["2016-01-20T05:42:17.000Z", 95.8, {}], 
 
    ["2016-01-20T05:42:47.000Z", 95.9, {}], 
 
    ["2016-01-20T05:43:17.000Z", 95.8, {}], 
 
    ["2016-01-20T05:43:47.000Z", 96.0, {}], 
 
    ["2016-01-20T05:44:17.000Z", 95.7, {}], 
 
    ["2016-01-20T05:44:47.000Z", 96.0, {}], 
 
    ["2016-01-20T05:45:17.000Z", 95.9, {}], 
 
    ["2016-01-20T05:45:47.000Z", 96.0, {}], 
 
    ["2016-01-20T05:46:17.000Z", 95.8, {}], 
 
    ["2016-01-20T05:46:47.000Z", 96.0, {}], 
 
    ["2016-01-20T05:47:17.000Z", 95.7, {}], 
 
    ["2016-01-20T05:47:47.000Z", 96.2, {}], 
 
    ["2016-01-20T05:48:17.000Z", 95.8, {}], 
 
    ["2016-01-20T05:48:47.000Z", 95.9, {}], 
 
    ["2016-01-20T05:49:17.000Z", 95.7, {}], 
 
    ["2016-01-20T05:49:47.000Z", 95.9, {}], 
 
    ["2016-01-20T05:50:18.000Z", 95.7, {}], 
 
    ["2016-01-20T05:50:48.000Z", 95.8, {}], 
 
    ["2016-01-20T05:51:18.000Z", 95.7, {}], 
 
    ["2016-01-20T05:51:48.000Z", 95.9, {}], 
 
    ["2016-01-20T05:52:18.000Z", 95.5, {}], 
 
    ["2016-01-20T05:52:48.000Z", 95.9, {}], 
 
    ["2016-01-20T05:53:18.000Z", 95.8, {}], 
 
    ["2016-01-20T05:53:48.000Z", 95.9, {}], 
 
    ["2016-01-20T05:54:18.000Z", 95.7, {}], 
 
    ["2016-01-20T05:54:48.000Z", 95.9, {}], 
 
    ["2016-01-20T05:55:18.000Z", 95.8, {}], 
 
    ["2016-01-20T05:55:48.000Z", 95.8, {}], 
 
    ["2016-01-20T05:56:18.000Z", 95.6, {}], 
 
    ["2016-01-20T05:56:48.000Z", 95.7, {}], 
 
    ["2016-01-20T05:57:18.000Z", 95.7, {}], 
 
    ["2016-01-20T05:57:48.000Z", 95.8, {}], 
 
    ["2016-01-20T05:58:18.000Z", 95.7, {}], 
 
    ["2016-01-20T05:58:48.000Z", 95.7, {}], 
 
    ["2016-01-20T05:59:18.000Z", 95.6, {}], 
 
    ["2016-01-20T05:59:48.000Z", 95.8, {}], 
 
    ["2016-01-20T06:00:18.000Z", 95.7, {}], 
 
    ["2016-01-20T06:00:48.000Z", 95.7, {}], 
 
    ["2016-01-20T06:01:18.000Z", 95.6, {}], 
 
    ["2016-01-20T06:01:48.000Z", 95.7, {}], 
 
    ["2016-01-20T06:02:18.000Z", 95.8, {}], 
 
    ["2016-01-20T06:02:48.000Z", 95.8, {}], 
 
    ["2016-01-20T06:03:18.000Z", 95.8, {}], 
 
    ["2016-01-20T06:03:48.000Z", 95.8, {}], 
 
    ["2016-01-20T06:04:18.000Z", 95.8, {}], 
 
    ["2016-01-20T06:04:48.000Z", 95.8, {}], 
 
    ["2016-01-20T06:05:18.000Z", 95.7, {}], 
 
    ["2016-01-20T06:05:48.000Z", 95.7, {}] 
 
    ], 
 
    label: "a" 
 
}, { 
 
    data: [ 
 
    ["2016-01-20T05:31:17.000Z", 90.9, {}], 
 
    ["2016-01-20T05:31:47.000Z", 91.9, {}], 
 
    ["2016-01-20T05:32:17.000Z", 92.4, {}], 
 
    ["2016-01-20T05:32:47.000Z", 90.1, {}], 
 
    ["2016-01-20T05:33:17.000Z", 89.7, {}], 
 
    ["2016-01-20T05:33:47.000Z", 91.9, {}], 
 
    ["2016-01-20T05:34:17.000Z", 85.5, {}], 
 
    ["2016-01-20T05:34:47.000Z", 93.9, {}], 
 
    ["2016-01-20T05:35:17.000Z", 94.8, {}], 
 
    ["2016-01-20T05:35:47.000Z", 93.9, {}], 
 
    ["2016-01-20T05:36:17.000Z", 92.7, {}], 
 
    ["2016-01-20T05:36:47.000Z", 95.7, {}], 
 
    ["2016-01-20T05:37:17.000Z", 92.9, {}], 
 
    ["2016-01-20T05:37:47.000Z", 93.5, {}], 
 
    ["2016-01-20T05:38:17.000Z", 93.4, {}], 
 
    ["2016-01-20T05:38:47.000Z", 93.8, {}], 
 
    ["2016-01-20T05:39:17.000Z", 93.0, {}], 
 
    ["2016-01-20T05:39:47.000Z", 93.1, {}], 
 
    ["2016-01-20T05:40:17.000Z", 93.8, {}], 
 
    ["2016-01-20T05:40:47.000Z", 93.0, {}], 
 
    ["2016-01-20T05:41:17.000Z", 93.9, {}], 
 
    ["2016-01-20T05:41:47.000Z", 93.9, {}], 
 
    ["2016-01-20T05:42:17.000Z", 92.8, {}], 
 
    ["2016-01-20T05:42:47.000Z", 92.9, {}], 
 
    ["2016-01-20T05:43:17.000Z", 93.8, {}], 
 
    ["2016-01-20T05:43:47.000Z", 93.0, {}], 
 
    ["2016-01-20T05:44:17.000Z", 93.7, {}], 
 
    ["2016-01-20T05:44:47.000Z", 93.0, {}], 
 
    ["2016-01-20T05:45:17.000Z", 93.9, {}], 
 
    ["2016-01-20T05:45:47.000Z", 93.0, {}], 
 
    ["2016-01-20T05:46:17.000Z", 93.8, {}], 
 
    ["2016-01-20T05:46:47.000Z", 96.0, {}], 
 
    ["2016-01-20T05:47:17.000Z", 92.7, {}], 
 
    ["2016-01-20T05:47:47.000Z", 92.2, {}], 
 
    ["2016-01-20T05:48:17.000Z", 92.8, {}], 
 
    ["2016-01-20T05:48:47.000Z", 92.9, {}], 
 
    ["2016-01-20T05:49:17.000Z", 92.7, {}], 
 
    ["2016-01-20T05:49:47.000Z", 92.9, {}], 
 
    ["2016-01-20T05:50:18.000Z", 93.7, {}], 
 
    ["2016-01-20T05:50:48.000Z", 93.8, {}], 
 
    ["2016-01-20T05:51:18.000Z", 92.7, {}], 
 
    ["2016-01-20T05:51:48.000Z", 92.9, {}], 
 
    ["2016-01-20T05:52:18.000Z", 92.5, {}], 
 
    ["2016-01-20T05:52:48.000Z", 94.9, {}], 
 
    ["2016-01-20T05:53:18.000Z", 94.8, {}], 
 
    ["2016-01-20T05:53:48.000Z", 94.9, {}], 
 
    ["2016-01-20T05:54:18.000Z", 94.7, {}], 
 
    ["2016-01-20T05:54:48.000Z", 94.9, {}], 
 
    ["2016-01-20T05:55:18.000Z", 94.8, {}], 
 
    ["2016-01-20T05:55:48.000Z", 93.8, {}], 
 
    ["2016-01-20T05:56:18.000Z", 94.6, {}], 
 
    ["2016-01-20T05:56:48.000Z", 94.7, {}], 
 
    ["2016-01-20T05:57:18.000Z", 93.7, {}], 
 
    ["2016-01-20T05:57:48.000Z", 93.8, {}], 
 
    ["2016-01-20T05:58:18.000Z", 93.7, {}], 
 
    ["2016-01-20T05:58:48.000Z", 93.7, {}], 
 
    ["2016-01-20T05:59:18.000Z", 93.6, {}], 
 
    ["2016-01-20T05:59:48.000Z", 93.8, {}], 
 
    ["2016-01-20T06:00:18.000Z", 93.7, {}], 
 
    ["2016-01-20T06:00:48.000Z", 93.7, {}], 
 
    ["2016-01-20T06:01:18.000Z", 93.6, {}], 
 
    ["2016-01-20T06:01:48.000Z", 94.7, {}], 
 
    ["2016-01-20T06:02:18.000Z", 94.8, {}], 
 
    ["2016-01-20T06:02:48.000Z", 94.8, {}], 
 
    ["2016-01-20T06:03:18.000Z", 94.8, {}], 
 
    ["2016-01-20T06:03:48.000Z", 94.8, {}], 
 
    ["2016-01-20T06:04:18.000Z", 94.8, {}], 
 
    ["2016-01-20T06:04:48.000Z", 94.8, {}], 
 
    ["2016-01-20T06:05:18.000Z", 94.7, {}], 
 
    ["2016-01-20T06:05:48.000Z", 94.7, {}] 
 
    ], 
 
    label: "b" 
 
}] 
 

 

 
var x = d3.time.scale() 
 
    .range([0, width]); 
 

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

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

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

 
var line = d3.svg.line() 
 
    .interpolate("monotone") 
 
    .x(function(d) { 
 
    return x(parseDate.parse(d[0])); 
 
    }) 
 
    .y(function(d) { 
 
    return y(d[1]); 
 
    }); 
 

 
var ary = []; 
 
data.forEach(function(d) { 
 
    ary.push(d.data); 
 
}); 
 

 
x.domain(d3.extent(d3.merge(ary), function(d) { 
 
    return parseDate.parse(d[0]); 
 
})); 
 

 
y.domain([ 
 
    d3.min(data, function(c) { 
 
    return d3.min(c.data, function(v) { 
 
     return v[1]; 
 
    }); 
 
    }), 
 
    d3.max(data, function(c) { 
 
    return d3.max(c.data, function(v) { 
 
     return v[1]; 
 
    }); 
 
    }) 
 
]); 
 

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

 
svg.append("g") 
 
    .attr("class", "y axis") 
 
    .call(yAxis); 
 

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

 
series.append("path") 
 
    .attr("class", "line") 
 
    .attr("d", function(d) { 
 
    return line(d.data); 
 
    }) 
 
    .style("stroke", function(d, i) { 
 
    return z(i); 
 
    }); 
 

 
series.append("text") 
 
    .datum(function(d) { 
 
    return { 
 
     label: d.label, 
 
     data: d.data[d.data.length - 1] 
 
    }; 
 
    }) 
 
    .attr("transform", function(d) { 
 
    return "translate(" + x(parseDate.parse(d.data[0])) + "," + y(d.data[1]) + ")"; 
 
    }) 
 
    .attr("x", 3) 
 
    .attr("dy", ".35em"); 
 

 
var mouseG = svg.append("g") 
 
    .attr("class", "mouse-over-effects"); 
 

 
mouseG.append("path") // this is the black vertical line to follow mouse 
 
    .attr("class", "mouse-line") 
 
    .style("stroke", "black") 
 
    .style("stroke-width", "1px") 
 
    .style("opacity", "0"); 
 

 
var lines = document.getElementsByClassName('line'); 
 

 
var mousePerLine = mouseG.selectAll('.mouse-per-line') 
 
    .data(data) 
 
    .enter() 
 
    .append("g") 
 
    .attr("class", "mouse-per-line"); 
 

 
mousePerLine.append("circle") 
 
    .attr("r", 7) 
 
    .style("stroke", function(d, i) { 
 
    return z(i); 
 
    }) 
 
    .style("fill", "none") 
 
    .style("stroke-width", "1px") 
 
    .style("opacity", "0"); 
 

 
mousePerLine.append("text") 
 
    .attr("transform", "translate(10,3)"); 
 

 
mouseG.append('svg:rect') // append a rect to catch mouse movements on canvas 
 
    .attr('width', width) // can't catch mouse events on a g element 
 
    .attr('height', height) 
 
    .attr('fill', 'none') 
 
    .attr('pointer-events', 'all') 
 
    .on('mouseout', function() { // on mouse out hide line, circles and text 
 
    d3.select(".mouse-line") 
 
     .style("opacity", "0"); 
 
    d3.selectAll(".mouse-per-line circle") 
 
     .style("opacity", "0"); 
 
    d3.selectAll(".mouse-per-line text") 
 
     .style("opacity", "0"); 
 
    }) 
 
    .on('mouseover', function() { // on mouse in show line, circles and text 
 
    d3.select(".mouse-line") 
 
     .style("opacity", "1"); 
 
    d3.selectAll(".mouse-per-line circle") 
 
     .style("opacity", "1"); 
 
    d3.selectAll(".mouse-per-line text") 
 
     .style("opacity", "1"); 
 
    }) 
 
    .on('mousemove', function() { // mouse moving over canvas 
 
    var mouse = d3.mouse(this); 
 
    d3.select(".mouse-line") 
 
     .attr("d", function() { 
 
     var d = "M" + mouse[0] + "," + height; 
 
     d += " " + mouse[0] + "," + 0; 
 
     return d; 
 
     }); 
 

 
    d3.selectAll(".mouse-per-line") 
 
     .attr("transform", function(d, i) { 
 
     console.log(width/mouse[0]) 
 
     var xDate = x.invert(mouse[0]), 
 
      bisect = d3.bisector(function(d) { 
 
      return d[0]; 
 
      }).right; 
 
     var idx = bisect(d.data, xDate); 
 

 
     var beginning = 0, 
 
      end = lines[i].getTotalLength(), 
 
      target = null; 
 

 
     while (true) { 
 
      target = Math.floor((beginning + end)/2); 
 
      var pos = lines[i].getPointAtLength(target); 
 
      if ((target === end || target === beginning) && pos.x !== mouse[0]) { 
 
      break; 
 
      } 
 
      if (pos.x > mouse[0]) end = target; 
 
      else if (pos.x < mouse[0]) beginning = target; 
 
      else break; //position found 
 
     } 
 

 
     d3.select(this).select('text') 
 
      .text(y.invert(pos.y).toFixed(2)); 
 

 
     return "translate(" + mouse[0] + "," + pos.y + ")"; 
 
     }); 
 
    });
text.inner-circle { 
 
    font-weight: 400; 
 
    font-size: 12px; 
 
    text-transform: uppercase; 
 
} 
 

 
text.inner-text { 
 
    font-weight: 400; 
 
    font-size: 36px; 
 
    font-family: 'Metric Regular', 'Metric'; 
 
    text-align: center; 
 
    font-style: normal; 
 
    text-transform: uppercase; 
 
} 
 

 
path { 
 
    stroke: steelblue; 
 
    stroke-width: 2; 
 
    fill: none; 
 
} 
 

 
.axis path, 
 
.axis line { 
 
    fill: none; 
 
    stroke: grey; 
 
    stroke-width: 2; 
 
    shape-rendering: crispEdges; 
 
} 
 

 
.grid .tick { 
 
    stroke: lightgrey; 
 
    stroke-opacity: 0.7; 
 
    shape-rendering: crispEdges; 
 
} 
 

 
.grid path { 
 
    stroke-width: 0; 
 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

I x ve y değerleri, her iki her grafik hattının üst kısmında küçük bir beyaz kutu eklemek istiyor. Lütfen bana yardım edin.

JSFIDDLE

cevap

1

Böyle yapabilirsiniz:

İlk id x metin ve y-metin grubuna ekler ile bir metin yapmak (x hem görüntülemek istediğiniz kadar aşağıda gösterildiği gibi ve y değerleri).

mousePerLine.append("rect") 
    .attr("x", 0) 
    .attr("y", -10) 
    .attr("width", 70)//width of rectangle 
    .attr("height", 35)//height of rectangle 
    .style("stroke", function(d, i) { 
    return z(i); 
    }) 
    .attr("class", "tooltip-container")//add class for styling rectangle 
    .style("fill", "red")//give color red to it. 
    .style("opacity", "0") 
    .style("stroke-width", "1px"); 

çalışma kodu:

//for y text on tooltip 
d3.select(this).select('#y-text') 
    .text("y: " + y.invert(pos.y).toFixed(2)); 
//make date in the format %H:%M:%S for x tooltip 
d3.select(this).select('#x-text') 
    .text("x: " + d3.time.format("%X")(xDate)); 

Sonraki şekillendirme için araç ipucu etrafında bir dikdörtgen olun:

mousePerLine.append("text").attr("id", "x-text") 
    .attr("transform", "translate(10,3)"); 
mousePerLine.append("text").attr("id", "y-text") 
    .attr("transform", "translate(10,23)"); 

Sonraki böyle fare hareket yukarıda oluşturulan metinde değerlerini gösterebilir here

+0

Çözüm için teşekkür ederim ama bana bir şey daha yardımcı olabilir misiniz? Fare hareket ettiğinde satırı kaldırmak istiyorum ve aynı zamanda grafik kesiştiğinde veya birbirine yaklaştığında, benzer şekilde araç ipucunu konumlandırmak istiyorum, bu durumda, araç ipucu dikdörtgenleri birbiriyle kesişmemeli ve otomatik olarak hizalanmalarını değiştirmemelidir. mümkün mü? – nikunj2512

+0

@ nikunj2512, araç ipucunun kesiştiğini algılamak için bir algo almak zor, bu zor bir çağrıdır .. :( – Cyril