在没有定义点的线图上使用d3-tip

时间:2016-12-21 08:12:33

标签: d3.js

所以我已经离开并使用它作为教程实现了与this类似的东西。但是,当它达到关于工具提示的点时,我想做一些稍微不同的事情,我真的想使用d3-tip。所以我花了很多时间学习如何使用d3-tip但似乎我看到的每个人都在定义元素,然后将mouseover和mouseout事件附加到它们以便显示工具提示。我不相信我能做到这一点,因为我使用之前根据鼠标在图表上的位置绘制圆圈的方法。所以我想知道如何让d3-tip与这个实现一起工作,或者它是否可能?

以下是我的代码:

var margin = {
  top: 20,
  left: 50,
  right: 50,
  bottom: 50
},
width = $element.innerWidth() - margin.left - margin.right,
height = 0.2 * width;

var parseTime = d3.timeParse('%m/%d/%Y');
data.forEach(function(d) {
  d.date = parseTime(d.date);
  d.price = +d.price;
});
data.sort(function(a, b) {
  return d3.ascending(a.date, b.date);
});
var formatDate = d3.timeFormat('%b %-d / %Y');
var bisectDate = d3.bisector(function(d) { return d.date; }).left;

var x = d3.scaleTime()
  .domain(d3.extent(data, function(d, i) {
    return d.date;
  }))
  .range([0, width]);
var y = d3.scaleLinear()
  .domain(d3.extent(data, function(d, i) {
    return d.price;
  }))
  .range([height, 0]);

var xAxis = d3.axisBottom(x)
  .tickSizeOuter(0);
var yAxis = d3.axisLeft(y)
  .ticks(5)
  .tickSizeOuter(0);

var area = d3.area()
  .x(function(d) { return x(d.date); })
  .y0(height)
  .y1(function(d) { return y(d.price); });

var line = d3.line()
  .x(function(d) { return x(d.date); })
  .y(function(d) { return y(d.price); });

var tip = d3.tip()
  .attr('class', 'd3-tip')
  .offset([-10, 0])
  .html(function(d) {
    return 'Closing: ' + d.price +
      '<br />' +
      'Date: ' + formatDate(d.date);
});

var svg = d3.select('#priceChart')
  .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 + ')');
svg.call(tip);

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

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

var areaSvg = svg.append('g');
areaSvg.append('path')
  .attr('class', 'area')
  .attr('d', area(data))
  .style('opacity', 0.3);

var lineSvg = svg.append('g');
lineSvg.append('path')
  .attr('class', 'line')
  .attr('d', line(data));

var focus = svg.append('g')
  .style('display', 'none');
focus.append('line')
    .attr('class', 'x dash')
    .attr('y1', 0)
    .attr('y2', height);
focus.append('line')
    .attr('class', 'y dash')
    .attr('x1', width)
    .attr('x2', width);
focus.append('circle')
  .attr('class', 'y circle')
  .attr('r', 5);

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.price) + ')');
  focus.select('.x')
    .attr('transform', 'translate(' + x(d.date) + ',' + y(d.price) + ')')
    .attr('y2', height - y(d.price));
  focus.select('.y')
    .attr('transform', 'translate(' + width * -1 + ',' + y(d.price) + ')')
    .attr('x2', width + width);
}

另外,我已经有了这个jsFiddle here,它显示了我目前所有的工作。我已经把所有东西都安排到位,这一切都很好,减去实际显示的工具提示。

1 个答案:

答案 0 :(得分:3)

我改变了你的小提琴,以便显示工具提示并相应地更新文本:

.on('mouseover', function(d) {
    focus.style('display', null);
    if(d!=undefined){
       tip.show(d);// give the tip the data it needs to show
    }
  })
  .on('mouseout', function() {
    focus.style('display', 'none');
    tip.hide();
  })

我还改变了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.price) + ')');
  focus.select('.x')
    .attr('transform', 'translate(' + x(d.date) + ',' + y(d.price) + ')')
    .attr('y2', height - y(d.price));
  focus.select('.y')
    .attr('transform', 'translate(' + width * -1 + ',' + y(d.price) + ')')
    .attr('x2', width + width);
  // we need to update the offset so that the tip shows correctly
  tip.offset([y(d.price) - 20, x(d.date) - (width/2)] ) //  [top, left]
  tip.show(d);

}

还更新了css:

.d3-tip:after {
    box-sizing: border-box;
    display: inline;
    font-size: 15px;
    width: 1%;
    line-height: 4;
    color: rgba(0, 0, 0, 0.8);
    content: "\25BC";
    position: absolute;
    text-align: center;
    pointer-events: none;
    left: 45%;
}

https://jsfiddle.net/mkaran/5t3ycyxs/1/

虽然可能有更好的方法。希望这有帮助!祝你好运!