Cauder
Cauder

Reputation: 2607

How do I use mouseover for an element hidden behind an invisible element?

I have a button that is a rectangle and text and an invisible rectangle on top. The invisible rectangle helps make sure that a user can click anywhere on the button, including over the word PLAY.

The invisible rectangle is preventing my .on("mouseover") effect from working, which changes the color of the button.

This is my code -

// svg element
var ticker = d3.select("#ticker").select("svg")
    .attr("width", 300)
    .attr("height", 50);

// group for button elements
ticker = d3.select("#ticker").select("svg")
    .attr("class", "ticker")
    .attr("transform", "translate(0,0)")
    .append("g")

// button with color
ticker.append("rect")
    .attr("class", "pauseplay")
    .attr("x", "120")
    .attr("y", "0")
    .attr("height","30")
    .attr("width","100")
    .attr("rx","5")
    .style("fill","#FF5960")
    .on("mouseover", function() { d3.select(this).style("fill", "#ff7b7b"); })
    .on("mouseout", function() { d3.select(this).style("fill", "#FF5960"); })

  // button text
  ticker.append("text")
    .attr("class","btn-text")
    .attr("x","150")
    .attr("y","20")
    .text("PAUSE")
    .style("fill","white")

  // invisible button
  ticker.append("rect")
  .attr("class","play")
  .attr("x", "120")
  .attr("y", "0")
  .attr("height","30")
  .attr("width","100")
  .style("opacity","0")
  .on("click", function() {
    PAUSED = !PAUSED;
      t.stop();
      // Play it.
      if (!PAUSED) {
        ticker.selectAll(".btn-text").text("PAUSE")
        timer();    }
      // Pause it.
      else {
        ticker.selectAll(".btn-text").text("PLAY")
      }     })

I'd like for the user to be able to hover anywhere, but also have the color change on mouseover.

Upvotes: 1

Views: 192

Answers (2)

abvlle
abvlle

Reputation: 138

I think the easiest way would be to create a hover function trigerred by the invisible button (you have to add IDs) like for example :

ticker.append("rect")
.attr("class", "pauseplay")
.attr("id","myID")
.attr("x", "120")
.attr("y", "0")
.attr("height","30")
.attr("width","100")
.attr("rx","5")
.style("fill","#FF5960")
.on("mouseout", function() { d3.select(this).style("fill", "#FF5960"); })

 // invisible button
ticker.append("rect")
.attr("class","play")
.attr("x", "120")
.attr("y", "0")
.attr("height","30")
.attr("width","100")
.style("opacity","0")
.on("mouseover", function() { d3.select("#myID").style("fill", "#ff7b7b"); })
.on("click", function() {
PAUSED = !PAUSED;
  t.stop();
  // Play it.
  if (!PAUSED) {
    ticker.selectAll(".btn-text").text("PAUSE")
    timer();    }
  // Pause it.
  else {
    ticker.selectAll(".btn-text").text("PLAY")
  }     })

Upvotes: 1

Gerardo Furtado
Gerardo Furtado

Reputation: 102188

You're bending over backwards, you don't need that invisible rectangle. Just set the text's pointer-events to none and add the event listener to the visible rectangle.

Here is your code with that change:

// svg element
var ticker = d3.select("#ticker").select("svg")
  .attr("width", 300)
  .attr("height", 50);

// group for button elements
ticker = d3.select("#ticker").select("svg")
  .attr("class", "ticker")
  .attr("transform", "translate(0,0)")
  .append("g")

// button with color
ticker.append("rect")
  .attr("class", "pauseplay")
  .attr("x", "120")
  .attr("y", "0")
  .attr("height", "30")
  .attr("width", "100")
  .attr("rx", "5")
  .style("fill", "#FF5960")
  .on("mouseover", function() {
    d3.select(this).style("fill", "#ff7b7b");
  })
  .on("mouseout", function() {
    d3.select(this).style("fill", "#FF5960");
  })
  .on("click", function() {
    console.log("click")
  })

// button text
ticker.append("text")
  .attr("class", "btn-text")
  .attr("x", "150")
  .attr("y", "20")
  .text("PAUSE")
  .style("fill", "white")
  .attr("pointer-events", "none");
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<div id="ticker">
  <svg></svg>
</div>

Upvotes: 2

Related Questions