1

I have started playing with P5JS, but I wanted to create a tooltip on mouse over for each of the data points when the pointer is over it.

How can I do this? I have seen some examples using the map function, but unsure how this would work here.

Appreciate any help! I am not a JS dev just yet!

Rffff
  • 13
  • 3
  • For p5.js it is preferable to include the relevant code in your question as a snippet. For more information see this StackOverflow question: https://stackoverflow.com/questions/67410651/how-do-i-include-a-runnable-p5-js-sketch-in-a-stackoverflow-question – Paul Wheeler Jul 21 '21 at 20:46

1 Answers1

1

Generally speaking displaying tooltips that are specific to graphics displayed on a canvas involves "hit testing," which is to say: checking if the mouse is hovering over the specific graphics, and then some mechanism for displaying the tooltip.

Since your graphics are all circles, hit testing is quite simple. For each circle that you draw, check the distance to the mouse position. If the distance is less than the radius of the circle than the mouse is hovering over that circle:

let mouseDist = dist(posX, posY, mouseX, mouseY);
if (mouseDist < earthquakeMag * 5) {
  // display tooltip, or set a flag to display the
  // tooltip after the rest of the graphics have been
  // displayed
}

As for displaying the tooltip you have two options: 1) you can rely on the native behavior of browser elements by setting the title attribute of the canvas element, or 2) you can display your own tooltip. The advantage of the former is that it is very trivial, but the advantage of the latter is that you have more control over where/when/how the tooltip is rendered.

Option 1:

let c;

function setup() {
  c = createCanvas(500,500);
  // ...
}

function draw() {
  // ...
  for (var i = 0; i < this.data.getRowCount(); i++) {
    // ...

    let mouseDist = dist(posX, posY, mouseX, mouseY);
    if (mouseDist < earthquakeMag * 5) {
      c.elt.title = 'hit!';
    }
  }
}

Option 2:

  let tooltipText;

  for (var i = 0; i < this.data.getRowCount(); i++) {
    // ...
    
    let mouseDist = dist(posX, posY, mouseX, mouseY);
    if (mouseDist < earthquakeMag * 5) {
      // If we displayed the tooltip at this point then
      // some of the circles would overlap it.
      tooltipText = date_[i];
    }

    // ...
  }
  
  if (tooltipText) {
    // measure the width of the tooltip
    let w = textWidth(tooltipText);

    // save the current fill/stroke/textAlign state
    push();

    // draw a lightgray rectangle with a dimgray border
    fill('lightgray');
    stroke('dimgray');
    strokeWeight(1);
    // draw this rectangle slightly below and to the
    // right of the mouse
    rect(mouseX + 10, mouseY + 10, w + 20, 24, 4);
    textAlign(LEFT, TOP);
    noStroke();
    fill('black');
    text(tooltipText, mouseX + 20, mouseY + 16);

    // restore the previous fill/stroke/textAlign state
    pop();
  }
Paul Wheeler
  • 18,988
  • 3
  • 28
  • 41
  • I Was trying to edit the post and post in the format that you have mentioned but you have been quicker than me! Wonderful answer! Will have a go now and let you know if I get stuck anywhere but everything makes sense! Thank you very very much! – Rffff Jul 21 '21 at 21:17