JoSch
JoSch

Reputation: 990

p5.js: Render canvas on top of html-elements without blocking mouse interactions

I'm trying to render an ellipsis with p5.js that follows the mouse and changes when the mouse interacts with elements on a page.

I have a simple setup where I'm hiding the regular cursor with CSS and draw a circle at mouse-X and -Y every time the canvas refreshes. Everything works as expected, but the canvas sits behind the page elements, so my "new cursor" will appear behind all the buttons, links, etc. I tried solving this by giving the button a z-index of -1 and setting the canvas' pointer-events to none, but mouseenter and mouseleave are not registered with the button sitting behind the canvas now (my assumption was that pointer-events: none; will make the mouse "ignore" the canvas and hence hover the button).

How can I solve this?

Here's a minimal setup of my problem:

let x = 100,
  y = 100,
  angle1 = 0.0,
  segLength = 50;

function setup() {
  createCanvas(710, 400);
}

function draw() {
  clear();
  x = mouseX;
  y = mouseY;
  let c; 
  //
  if (document.getElementById("defaultCanvas0").classList.contains("hover")) {
    c = color(255, 0, 0);
    ellipse(x, y, 30, 30).fill(c);
  } else {
  	c = color(0, 255, 0);
    ellipse(x, y, 20, 20).fill(c);
  }
  //
  
}

const button = document.getElementById("testButton"),
  test = document.getElementById("defaultCanvas0");

//
// Listen for hover
button.addEventListener("mouseenter", function(e) {
  document.getElementById("defaultCanvas0").classList.add("hover")
})
button.addEventListener("mouseleave", function(e) {
  document.getElementById("defaultCanvas0").classList.remove("hover")
})
body, * {
  cursor: none;
}

#testButton {
  position: absolute;
  top: 100px;
  left: 100px;
  z-index: 0;
}

canvas {
  pointer-events: none
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.0.0/p5.min.js"></script>
<div>
  <button id="testButton">
    button
  </button>
</div>

Upvotes: 2

Views: 2012

Answers (1)

Malte
Malte

Reputation: 566

Following your idea of

giving the button a z-index of -1 and setting the canvas' pointer-events to none,

you only have to also set the canvas' position to absolute to make it work, see snippet below. I guess if the position is not absolute, the canvas does not know where to "pass on" the pointer-events.

let x = 100,
  y = 100,
  angle1 = 0.0,
  segLength = 50;

function setup() {
  createCanvas(710, 400);
}

function draw() {
  clear();
  x = mouseX;
  y = mouseY;
  let c; 
  //
  if (document.getElementById("defaultCanvas0").classList.contains("hover")) {
    c = color(255, 0, 0);
    ellipse(x, y, 30, 30).fill(c);
  } else {
  	c = color(0, 255, 0);
    ellipse(x, y, 20, 20).fill(c);
  }
  //
  
}

const button = document.getElementById("testButton"),
  test = document.getElementById("defaultCanvas0");

//
// Listen for hover
button.addEventListener("mouseenter", function(e) {
  document.getElementById("defaultCanvas0").classList.add("hover")
})
button.addEventListener("mouseleave", function(e) {
  document.getElementById("defaultCanvas0").classList.remove("hover")
})
body, * {
  cursor: none;
}

#testButton {
  position: absolute;
  top: 100px;
  left: 100px;
  z-index: -1;
}

canvas {
  position: absolute;
  pointer-events: none
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.0.0/p5.min.js"></script>
<div>
  <button id="testButton">
    button
  </button>
</div>

Upvotes: 2

Related Questions