【问题标题】:How to add a tooltip to D3.js subplot如何向 D3.js 子图添加工具提示
【发布时间】:2021-03-26 16:54:42
【问题描述】:

我目前正在尝试在 d3.js 中创建一个“平面图”,我意识到这在 D3 语言中并不是一个真正的东西。但是,我找到了this thread,它概述了如何完成任务。从这篇文章中,我将折线图从垂直转换为水平,并在需要的地方添加了一些额外的填充元素。

现在我想为每个绘图添加一个工具提示。从使用其他代码片段来看,这似乎非常具有挑战性。出于某种原因,我无法弄清楚如何将工具提示附加到每个单独的图上。关于我如何能够做到这一点的任何想法?

目前的样子:

// Data and manipluation:
const data = d3.range(25).map(i => ({
        bib: Math.floor(i / 5) + 1,
        ratio: -1 + Math.random() * 5,
        run: [1, 2, 3, 4, 5][i % 5],
        run: [1, 2, 3, 4, 5][i % 5],
        name: ['metric1', 'metric2', 'metric3', 'metric4', 'metric5'][Math.floor(i / 5)]
        }));

const grouped = d3.group(data,d=>d.bib);


// Dimensions:
const height = 800;
const width = 700;
const margin = {
       top: 10,
       left: 50,
       right: 50,
       bottom: 50
    }
const padding = 30;
const doublePadding = padding * 2;

const plotHeight = (height-doublePadding)/grouped.size - padding;
const plotWidth = width-padding*2;

// const plotWidth = (width-padding)/grouped.size - padding;
// const plotHeight = height-padding*2;

const svg = d3.select("#chart1")
  .append("svg")
  .attr("width", margin.left+width+margin.right)
  .attr("height", margin.top+height+margin.bottom+(padding*grouped.size));
  
const g = svg.append("g")
  .attr("transform","translate("+[margin.left,margin.top]+")");

//Scales:
 const xScale = d3.scaleLinear()
   .domain(d3.extent(data, d => d.run))
   .range([0, plotWidth]);
     
const yScale = d3.scaleLinear()
   .domain(d3.extent(data, d => d.ratio))
   .range([plotHeight,0]);
   
// Place plots:
const plots = g.selectAll(null)
  .data(grouped)
  .enter()
  .append("g")
  .attr("transform", function(d,i) {
     return "translate("+[padding,i*(doublePadding+plotHeight)+padding]+")";
   })
   
//Optional plot background:
plots.append("rect")
  .attr("width",plotWidth)
  .attr("height",plotHeight)
  .attr("fill","#ddd");
   

// Plot actual data
plots.selectAll(null)
     .data(d=>d[1])
     .enter()
     .append("circle")
     .attr("r", 4)
     .attr("cy", d=>yScale(d.ratio))
     .attr("cx", d=>xScale(d.run))

// Plot line if needed:
plots.append("path")
  .attr("d", function(d) {
    return d3.line()
               .x(d=>xScale(d.run))
               .y(d=>yScale(d.ratio))
               (d[1])
   })
   .attr("stroke", "#333")
   .attr("stroke-width", 1)
   .attr("fill","none")
   
// Plot names if needed:
plots.append("text")
  .attr("x", plotWidth/2)
  .attr("y", -10)
  .text(function(d) {
    return d[1][0].name;
  })
  .attr("text-anchor","middle");
   
// Plot axes     
 plots.append("g")
   .attr("transform","translate("+[0,plotHeight]+")")
   .call(d3.axisBottom(xScale).ticks(4));

 plots.append("g")
   .attr("transform","translate("+[-padding,0]+")")
   .call(d3.axisLeft(yScale))
<head>
  <!-- Load d3.js -->
  <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.6.1/d3.min.js"></script>
</head>

<body>
  <div class="graph-container">
    <div id="chart1"></div>
  </div>
</body>

【问题讨论】:

    标签: javascript d3.js


    【解决方案1】:

    fiddle 中查看解决方案:

    添加一个带有背景和文本的 g 元素:

    const tooltip = d3.select('svg')
      .append('g')
      .style('visibility', 'hidden');
      
    tooltip.append('rect')  
      .attr('width', 100)
      .attr('height', 50)
      .style('fill', '#fff')
      .style('stroke', '#000')
      
    tooltip.append('text')
      .attr('x', 20)
      .attr('y', 20)
    

    mouseentermousevovemouseleave 上更新它:

    plots.append("rect")
      .attr("width",plotWidth)
      .attr("height",plotHeight)
      .attr("fill","#ddd")
      .on("mouseenter", (e, d) => {
        tooltip.style('visibility', 'visible');
        tooltip.select('text').text(d[0]);  
      })
      .on("mouseleave", () => tooltip.style('visibility', 'hidden'))
      .on("mousemove", e => tooltip.attr('transform', `translate(${e.clientX},${e.clientY})`))
    

    【讨论】:

    • 感谢迈克尔的回答!我已经开始处理代码,我至少可以看到工具提示,所以这是一个很好的开始!但是,我仍然在努力解决一些问题。 1. 工具提示似乎设置为悬停在整个图表上,而不是特定的数据点。如何使工具提示仅出现在点上? 2. 我确信我可以解决这个问题,但是一旦 1 完成,我就必须更改工具提示以包含该特定点的数据。 3. 工具提示现在不合适。如何将其与光标或数据点在位置上对齐?
    • 其实我真的只关注第1个问题,剩下的等我弄清楚1之后再说。感谢Michael的帮助!
    猜你喜欢
    • 2014-05-14
    • 2012-12-21
    • 1970-01-01
    • 2013-12-02
    • 1970-01-01
    • 2016-02-01
    • 1970-01-01
    • 2018-11-24
    • 1970-01-01
    相关资源
    最近更新 更多