Display a text over an hovered area

Hello,

Say I have several automata: https://imgur.com/a/bga8qgE and I want to have a text displayed when the user hovers any arc. How could I do this?

The automata was created using the usual functions arc, rect, line and ellipse.
I’ve tried looking into tickle (https://p5js.org/examples/interaction-tickle.html?fbclid=IwAR1hkyiRNGDVIgffvldHSbL9HMBKJHO-gOAWTdPKn9G36FZ-qAwdyJ0Ld3k) and mouse functions but to no avail.

Hi! How do you create this automata? Have you created a class to handle them? If you have, create a mouseover method in that class that returns a boolean if mouseX and mouseY are inside the bounding box and group the automata in an ArrayList. Iterate through the ArrayList in draw() and if it finds mouseOver to be true, draw the appropriate text.

1 Like

Hello,

The automata is created “by hand”:

function drawArc(e1,e2,a,k){
  var x = 155+(a-1)*230, y= 140+(4-e1)*50-(e2-e1)*25, h = 2+(e2-e1)*50;
  if (k==1){
    if (e2>=e1){
      arc(x,y,50+(e2-e1)*30,h, 3 * PI / 2,  PI / 2, OPEN);
      line(x,y-h/2, x+8,y-h/2-8);
      line(x,y-h/2, x+8,y-h/2+8);
    }
    else {
      arc(x-30,y, 50+(e1-e2)*30, h, 3 * PI / 2,  PI / 2, OPEN);
      line(x-38,y-h/2-9, x-30,y-h/2-1);
      line(x-38,y-h/2+7, x-30,y-h/2-1);
    }
  }
  else if (k==2){
    if (e2<e1){
      arc(x,y,50+(e1-e2)*30,h, PI / 2, 3* PI / 2, OPEN);
      line(x,y-h/2, x+8,y-h/2-8);
      line(x,y-h/2, x+8,y-h/2+8);
    }
    else {
      arc(x-30,y, 50+(e2-e1)*30, h,  PI / 2,  3*PI / 2, OPEN);
      line(x-38,y-h/2-9, x-30,y-h/2-1);
      line(x-38,y-h/2+7, x-30,y-h/2-1);
    }
  }


}

What’s a class?

Ok basically what you do

you want to have 3 arrays (lists) that hold your data for mouse hover :

  • First x[] holds x position of automata

  • 2nd holds y position: y []

  • 3rd text you want to display : text[]

Idea

Idea is that in the first line of each 3 lists the data of the 1st automata

2nd line - again distributed over 3 arrays- data for 2nd automata

Before setup () declare them as :

float[] x = new float [5];
float[] y = new float [5];
String [] text = new String [5];

Now in setup() put the data in the 3 parallel arrays:

// first automata
x[0] = 100;
y[0] = 200; // adjust
text[0] = “first automata“;

//2nd automata
x[1]=333;
y[1]=444; // adjust
text[1]= “2nd automata whatever…“;

Now for loop i over them and check

 if(dist(mouseX, mouseY, x[],y[]) < 50) {
     
    text( text[], x[],y[] );
 
 }

question : what belongs into the 5 empty brackets [] ?

dist here gives you the distance between mouse and current automata position checked in this for loop iteration

If this distance is small enough we show the text

OOP and classes

Since you asked.

Now this whole solution is far from perfect or beautiful

One point is that you store the automata position in an array and in your code (where you display them). So that’s double storing. Instead where you display them you could also use the array data x and y.

Next step would be to bundle the data for one automata in a package so all data for one automata is in one place. For this approach you would make a Automata class holding the data. This approach is called object oriented programming (oop). There is a tutorial on that.

Essentially the class Automata is the cookie maker and the objects are the cookies (your automata). Hence the name oop.
You can store the automata then in an array, so you need only one array and not 3.

Moreover you could place a display function and a mouse hover function inside the class so each automata has its functions.

Chrisir

2 Likes

I think I get the idea but how can I adapt it so that there are (potentially) multiple texts displayed for a single automata (one for each arc)?

I’ll look into oop, thanks!

Another thing I want to do is being able to freely move around/drag the arcs: do you know how it could be done?

Do you mean they are chosen randomly from a list of texts? You could have arrays text1, text2 etc. and have a random number that tells which one to use. You could also use a 2D array (a grid, see tutorials). Essentially each cell holds a text and then you have one index that is the automatas index and one that is the random number.

Drag and Drop

Anyway: when you click (use function mousePressed) on an Automata and you hold the mouse set a global variable hold = true; For loop over all automata and check which one was clicked; store that number i_clicked=i;

make a function mouseReleased where you say hold=false;

this function gets called automatically

In draw move the selected automata according to the mouse movement by changing the value in the arrays x and y at Position i_clicked.

Not randomly, there are as many texts as there are arcs for each automata.

Also, I want the text to be gone when I’m no longer hovering the area (it currently stays forever), how can I do that?

This is for the drag and drop part

make a function mouseReleased where you say hold=false;

this function gets called automatically


In draw only show the text when hold is true

Or set i_clicked= -1; in mouseReleased, indicating no automata is selected. Then check this value in draw() and don’t show the text when i_clicked==-1;

Attention, when you use -1 in the arrays program will crash. So always check if it’s -1 before using it

I’m not following, at the moment I have a function drawArc(automata) that I call in draw() for every automata and I added the test if(dist(mouseX, mouseY, x y) < 50) in this function drawArc.

Where should I define & call mouseReleased?

Sorry, my bad.

I was referring to the drag and drop functionality, you were talking about the text()

Do you use background at the beginning of draw() ? You should.

This line : should provide it that the text only appears when the mouse is near the automata

if(dist(mouseX, mouseY, x y) < 50)

Hm.

My approach was using arrays. I am not sure you have done the arrays bit yet.

Each arc/automata has its position (x,y) and its text.

They are stored in arrays :

  float[] x = new float [5];
  float[] y = new float [5];
  String [] text = new String [5];

and defined separately for each arc in setup():

// first automata
x[0] = 100;
y[0] = 200; // adjust
text[0] = “first automata“;

//2nd automata
x[1]=333;
y[1]=444; // adjust
text[1]= “2nd automata whatever…

etc.

Your line if(dist(mouseX, mouseY, x y) < 50) should in fact be in a for loop (at the end of function drawArc) with i as a variable and use these arrays:

  if(dist(mouseX, mouseY, x[i],y[i]) < 50) {
     
     text( text[i], x[i],y[i] );
 
  }

Can you use the arrays in this way? Then each automata has its own position for mouse hover and its own text.

Chrisir :wink:

P.S.

QUICK DEMO


// Before setup () declare arrays  
float[] x = new float [3];
float[] y = new float [3];
String [] text = new String [3];

void setup() {

  size(900, 600);

  // Now in setup() put the data in the 3 parallel arrays:

  // first automata
  x[0] = 100;
  y[0] = 200; // adjust
  text[0] = "first automata";

  //2nd automata
  x[1]=333;
  y[1]=444; // adjust
  text[1]= "2nd automata whatever…";

  //3rd automata
  x[2]=333;
  y[2]=144; // adjust
  text[2]= "Third automata....\nVery Nice";
  //
}//function 

void draw() {

  background(0); 

  // for loop i over arrays and display them
  for (int i=0; i<x.length; i++) {
    fill(255); 
    rect( x[i], y[i], 
      17, 17);
  }//for

  // Now for loop i over arrays and check the distance to the mouse 
  for (int i=0; i<x.length; i++) {
    if (dist(mouseX, mouseY, x[i], y[i]) < 50) {
      fill(255, 0, 0); 
      text( text[i], 
        x[i], y[i] -17 );
    }//if
  }//for
}//function

I tried your example but the page is blank.

Why should I use background? background(0) is too dark.

I do iterate through the automata, my code is:

var overBox = false;
var locked = false;

function setup() {
  createCanvas(900, 800);
}

function draw(){

 
   for (every automata){
 
       for (every arc){
         drawArc(arc);


         overBox = (dist(mouseX, mouseY, x, y) < 50);

         if(!locked) {
                  text("text", x, y)
         }
        else {
         overBox = false;
       }
       }
     }

   }

function mousePressed() {
  if(overBox) {
    locked = true;
    fill(255);
  } else {
    locked = false;
    fill(255)
  }


}

function mouseReleased() {
  locked = false;
}

Currently, it does display the text I want when I hover an arc but the text still stays when I’m no longer hovering the arc.

It’s java mode, not js. Run it in java mode.

Why should I use background? background(0) is too dark.

Now, you need background to clear the canvas, otherwise the text won’t disappear. As with stroke or fill you can insert any gray value you want: background(200);