2016-10-14 2 views
0

Я создал линейную диаграмму, используя этот пример кода http://bl.ocks.org/d3noob/6eb506b129f585ce5c8a. Мне удалось его воссоздать.линейная диаграмма с подсказкой mouseover не работает в d3.js

что код

<!DOCTYPE html> 
 
<meta charset="utf-8"> 
 
<style> /* set the CSS */ 
 

 
body { font: 12px Arial;} 
 

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

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

 
</style> 
 
<body> 
 

 
<!-- load the d3.js library -->  
 
<script src="http://d3js.org/d3.v3.min.js"></script> 
 

 
<script> 
 

 
// Set the dimensions of the canvas/graph 
 
var margin = {top: 30, right: 20, bottom: 30, left: 50}, 
 
    width = 600 - margin.left - margin.right, 
 
    height = 270 - margin.top - margin.bottom; 
 

 
// Parse the date/time 
 
var parseDate = d3.time.format("%d-%b-%y").parse, 
 
    formatDate = d3.time.format("%d-%b"), 
 
    bisectDate = d3.bisector(function(d) { return d.date; }).left; 
 

 
// Set the ranges 
 
// var x = d3.time.scale().range([0, width]); 
 
var x = d3.scale.ordinal().rangePoints([0, width]); 
 
var y = d3.scale.linear().range([height, 0]); 
 

 
// Define the axes 
 
var xAxis = d3.svg.axis().scale(x) 
 
    .orient("bottom").ticks(5); 
 

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

 
// Define the line 
 
var valueline = d3.svg.line() 
 
    .interpolate('basis') 
 
    .x(function(d) { return x(d.date); }) 
 
    .y(function(d) { return y(d.close); }); 
 
    
 
// Adds the svg canvas 
 
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 lineSvg = svg.append("g"); 
 

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

 
// Get the data 
 
var data = [ 
 
    { 
 
    "date": "w1", 
 
    "close": 629.32 
 
    }, 
 
    { 
 
    "date": "w2", 
 
    "close": 124.31 
 
    }, 
 
    { 
 
    "date": "w3", 
 
    "close": 333.68 
 
    }, 
 
    { 
 
    "date": "w4", 
 
    "close": 236.23 
 
    } 
 
] 
 
    // data.forEach(function(d) { 
 
    //  // d.date = parseDate(d.date); 
 
    //  d.date = +d.date; 
 
    //  d.close = +d.close; 
 
    // }); 
 

 
    // Scale the range of the data 
 
    x.domain(data.map(function(d) { return d.date; })); 
 
    y.domain([0, d3.max(data, function(d) { return d.close; })]); 
 

 
    // Add the valueline path. 
 
    lineSvg.append("path") 
 
     .attr("class", "line") 
 
     .attr("d", valueline(data)); 
 

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

 
    // Add the Y Axis 
 
    svg.append("g") 
 
     .attr("class", "y axis") 
 
     .call(yAxis); 
 

 
    // append the x line 
 
    focus.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 
 
    focus.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 
 
    focus.append("circle") 
 
     .attr("class", "y") 
 
     .style("fill", "none") 
 
     .style("stroke", "blue") 
 
     .attr("r", 4); 
 

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

 
    // place the date at the intersection 
 
    focus.append("text") 
 
     .attr("class", "y3") 
 
     .style("stroke", "white") 
 
     .style("stroke-width", "3.5px") 
 
     .style("opacity", 0.8) 
 
     .attr("dx", 8) 
 
     .attr("dy", "1em"); 
 
    focus.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() { 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("circle.y") 
 
      .attr("transform", 
 
        "translate(" + x(d.date) + "," + 
 
           y(d.close) + ")"); 
 

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

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

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

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

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

 
     focus.select(".y") 
 
      .attr("transform", 
 
        "translate(" + width * -1 + "," + 
 
           y(d.close) + ")") 
 
         .attr("x2", width + width); 
 
    } 
 
</script> 
 
</body>

линия идет правильно, но им не в состоянии установить, как подсказку курсора, находящиеся выше примера .. я м перед ошибка, как инвертный Fuction не определена .. .

ответ

1

В диаграмме, к которой вы привязались, он использует шкалу времени для оси x (которая имеет инвертированную функцию). Вы используете порядковый масштаб (который не имеет инвертированной функции). Инверсная функция используется для вычисления значения по оси x для заданной позиции мыши.

Временная шкала всегда имеет соответствующее значение x для каждой позиции мыши (поскольку она непрерывна, поэтому независимо от того, где находится ваша мышь, у вас есть дата-время для этой позиции), в то время как порядковый масштаб не имеют соответствующее значение x для всех положений мыши, поскольку оно является дискретным, т. е. что такое x-значение, когда у вас есть мышь, например, w1 и w2?

Таким образом, ваше решение заключается в изменении масштаба времени (в этом случае вам нужно преобразовать w1, w2, w3 e.t.c. в объект даты).

Или, если вы хотите придерживаться порядкового номера, вам нужно удалить функцию инвертирования. Так как инверсная функция используется для вычисления значения x для данной позиции мыши, вы должны создать эту логику самостоятельно. Вдохновение можно найти в Inversion with ordinal scale. Поэтому заменить var x0 = x.invert(d3.mouse(this)[0]) на

var xPos = d3.mouse(this)[0]; 
    console.log("hovering at " + xPos); 
    var leftEdges = x.range(); 
    var width = x.rangeBand(); 
    var j; 
    for(j=0; xPos > (leftEdges[j] + width); j++) {} 
     //do nothing, just increment j until case fails 
    console.log("Clicked on " + x.domain()[j]); 
    var x0 = x.domain()[j]; 
+0

Большое вам спасибо. –

Смежные вопросы