D3-工具提示上的html结构

时间:2018-11-07 15:32:11

标签: d3.js

我在这里有一个矮人-https://plnkr.co/edit/qDi8bm3xh3hdaV059AXX?p=preview

当鼠标悬停在条形图上时,它是带有工具提示的简单条形图。

在工具提示中,我要显示未用于构建栏的数据中的信息。

我可以在示例中执行此操作,但是可以创建html结构以将更多数据添加到工具提示中。

d3.selectAll('.bar').on("mouseover", ()=>{
  d3.select('.chart-tooltip').style("display", null)
})
.on("mouseout", ()=>{
  d3.select('.chart-tooltip').style("display", "none")
    .transition()
    .duration(500)
});

d3.selectAll('.bar').on("mousemove", (d)=>{
let html = d.day;

d3.select('.chart-tooltip')
.style("left", d3.event.pageX + 15 + "px")
.style("top", d3.event.pageY - 25 + "px")
  .html(html)
});

1 个答案:

答案 0 :(得分:1)

如果可以将新工具提示数据与要渲染的工具栏<->匹配,则可以使用d3选择器的索引来匹配数组中的数据,请参见示例:

const data_tooltip = [
  {
   text: 'BAR 1',
   html: '<strong>BAR 1</strong>'
 },
 {
   text: 'BAR 2',
   html: '<strong>BAR 2</strong>'
 }
];


d3.selectAll('.bar').on("mousemove", (d, index)=>{ // index iterator of your bar event

    d3.select('.chart-tooltip')
    .style("left", d3.event.pageX + 15 + "px")
    .style("top", d3.event.pageY - 25 + "px")
      .html(data_tooltip[index].html)
  });

const w = 400;
const h = 300;

const margin = {
  top: 20,
  bottom: 60,
  left: 40,
  right: 20
}

const width = w - margin.left - margin.right
const height = h - margin.top - margin.bottom

const data = [
  {
   phase: 'One',
   start: 118,
   finish: 102,
   day: 'Monday',
   time: 'Morning'
 },
 {
   phase: 'Two',
   start: 100,
   finish: 112,
   day: 'Tuesday',
   time: 'Afternoon'
 }
];


const data_tooltip = [
  {
   text: 'BAR 1',
   html: '<strong>BAR 1</strong>'
 },
 {
   text: 'BAR 2',
   html: '<strong>BAR 2</strong>'
 }
];

const x = d3.scaleBand()
  .range([0, width])
  .padding(.33)

const y = d3.scaleLinear()  
  .rangeRound([height, 0]);

const svg = d3.select("body").append("svg")
  .attr("id", "svg")
  .attr("width", w)
  .attr("height", h);

const chart = svg.append('g')
  .attr("transform", "translate(" + margin.left + "," + margin.top + ")")
  .attr("preserveAspectRatio", "xMinYMin meet");  

const tooltip = d3.select('body').append("div")
	.classed('tooltip chart-tooltip', true)
	.style('display', 'none');  

const y_axis = d3.axisLeft()
  .scale(y)
  .tickSize(-width)

const x_axis = d3.axisBottom()
  .scale(x)
  .tickSize(-height )
  .tickPadding(10)  

const update = (data) =>{

  x.domain(data.map(function(d) { 
    return d.phase
  }));

  y.domain(
    d3.extent(
      d3.extent(data, (d) => {
        return d.start+2;    
      })
      .concat(d3.extent(data, (d) => {
        return d.finish-6;    
      })        
    )
  ));
    
  chart.append("g")
    .classed('y-axis', true)
    .call(y_axis)
  
  chart.append("g")
    .call(x_axis)
    .classed('x-axis', true)
    .attr("transform", "translate(0," + height + ")")

  const bar = chart.selectAll(".bar")
    .data(data)

    bar.enter()
    .append("rect")
    .attr('class', 'bar')
    .attr('data-arrow', (d, i) => {
          return d.start > d.finish ? 'down' : 'up'
        })
    .attr("x", (d, i) => {
      return x(d.phase)
    })
    .attr("width", (d, i) => {
      return x.bandwidth()
    })
    .attr("y", (d, i) => {
      if(d.start < d.finish){
        return y(d.finish);
      }else{
        return y(d.start);
      }
    })
    .attr("height", (d, i) => {
      if(d.start < d.finish){
        return y(d.start) - y(d.finish);
      }else{
        return y(d.finish) - y(d.start);
      }
    });
    
    d3.selectAll('.bar').on("mouseover", ()=>{
          d3.select('.chart-tooltip').style("display", null)
        })
        .on("mouseout", ()=>{
          d3.select('.chart-tooltip').style("display", "none")
            .transition()
            .duration(500)
        });

      d3.selectAll('.bar').on("mousemove", (d, i)=>{
        
        d3.select('.chart-tooltip')
        .style("left", d3.event.pageX + 15 + "px")
        .style("top", d3.event.pageY - 25 + "px")
          .html(data_tooltip[i].html)
      });

      d3.selectAll('g.tick')
        .filter((d) => d==100)
        .attr('class', 'grid-100')

}
  
update(data)
body{
  background:#f5f6f7;
}

h1, h2 {
  font-family: Lato;
}

#svg{
  background-color: white;
}

.bar{
  shape-rendering: crispEdges;
  fill: mediumvioletred;
}

.bar-label{
  fill: white;
}

.bar-label{
  text-anchor: end;
}

.grid line{
  stroke: #bbb;
}

.grid .tick:nth-child(7) line{
  stroke-width: 3;
  stroke: #999;
}

.divide{
  fill: lightgrey;
}

.bar-1{
  fill: red;
  
}
	
.chart-tooltip{
  background: lightgrey;
  border-radius: 4px;
  display: inline-block;
  font-family: sans-serif;
  font-size: 12px;
  padding: 10px;
  position: absolute;
  width: auto;
}
<script src="https://d3js.org/d3.v5.min.js"></script>
<div id="app"></div>