Y02WK
Y02WK

Reputation: 13

RGBA opacity reseting (Etch-A-Sketch)

Am trying to do an Etch-A-Sketch project and currently hit some roadblocks. Currently am able to create a grid based off user input on prompt and clear the grid through a button.

The problem I'm facing now is in the function colorChange(), where I'm trying to get opacity of the background color to increase every time a mouse hover event is captured over the div. Everything works fine but opacity maxes out at 0.9 in the current code.

If instead using if (rgbaValue <= 0.9) or (rgbaValue < 1), the opacity value resets to 0.1 on the next hover after 0.9. How would I go about getting the opacity to 1 without resetting?

Code below:

html

<!DOCTYPE html>
<html>
    <link rel="stylesheet" href="style.css">

    <title>Etch A Sketch</title>
    <body>
        <div>
            <button type="button" onclick="clearGrid()">Click to clear grid</button>
        </div>
        <div id="container"></div>
        <script src="java.js"></script>
    </body>
</html>

javascript

let gridSize = 0;
let gridWidth = 0;

gridSize = window.prompt("Please input the amount of squares per side of grid that you want created");
gridWidth = 100/gridSize;
createGrid();
colorChange();

function createSquare() {      
    const mainBody = document.querySelector("#container");
    const gridMake = document.createElement("div");
    gridMake.classList.add("squaregrid");
    gridMake.style.width = gridWidth + "%";
    gridMake.style.paddingBottom = gridWidth + "%";
    mainBody.appendChild(gridMake);
}

function createGrid() {        
    gridCount = 0;
    while (gridCount < (gridSize*gridSize)) {
        createSquare();
        gridCount++
    }
}

function colorChange() {        
    const selectSquare = document.querySelectorAll(".squaregrid");
    selectSquare.forEach(square => square.addEventListener("mouseover", event => {
        square.classList.add('hover-change');
        const style = getComputedStyle(square);
        let styleDeep = style.backgroundColor;
        rgbaValue = parseFloat(styleDeep.replace(/^.*,(.+)\)/,'$1'));
        if (rgbaValue < 0.9) {
            square.style.backgroundColor = `rgba(0,0,0, ${rgbaValue + 0.1})`;
        }
        }))
}

function clearGrid() {
    const squareReset = document.querySelectorAll(".squaregrid");
    squareReset.forEach(square => square.style.backgroundColor = "");
    squareReset.forEach(square => square.classList.remove("hover-change"));
}

css

.squaregrid {
    box-sizing: border-box;
    display: inline-block;
    border: 0.05px solid black;
    margin:0;
}

html, body {
    line-height: 0; 
    height: 94vh;
    width: 94vh;
    margin-left: auto;
    margin-right: auto;
}

#container {
    display: block;
    overflow: hidden;
    margin-left: auto;
    margin-right: auto;
    border: 0.05px solid black;
}

.hover-change {
    background-color: rgba(0, 0, 0, 1);
}

button {
    display: block;
    margin-bottom: 5px;
}

Upvotes: 0

Views: 293

Answers (1)

Victor
Victor

Reputation: 181

The main problem with your code has to do with the way the browser handles full opacity.

The rgba() notation accepts a number in the range 0.0 to 1.0, inclusive, or a percentage, where the number 1 corresponds to 100%, for the value of the alpha channel. Any value outside the interval, though valid, is clamped to the nearest limit in the range.

A value greater than 1 or 100% will be clamped and omitted from the computed value

background-color: rgba(0, 0, 0, 0.5);  # computed (0, 0, 0, 0.5)
background-color: rgba(0, 0, 0, 1);    # computed (0, 0, 0)
background-color: rgba(0, 0, 0, 1.3);  # computed (0, 0, 0)

Your regex is capturing any character between the last comma in the rgba() notation and the closing parenthesis of the computed value. When the event listener is triggered after you have assigned the square an alpha value equal or greater than 1 your regex captures 0 and sets the alpha value accordingly.

In the Code snippet below you can see one way of solving the problem using an other regular expression.

Alternatively you could make use of the opacity property as @Luca Neri already suggested.

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title></title>
  <meta name="author" content="">
  <meta name="description" content="">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <style>
    body, html {
        margin: 0;
    }
    .squaregrid {
        display: grid;
    }
    .square {
        background-color: rgba(20, 20, 20, 0.1);
    }
    button {
        position: fixed;
        bottom: 0;
    }
  </style>
</head>
<body>
  <div class="squaregrid"></div>
  <button onclick="clearScreen()">CLEAR</button>
  <script>
   //request number of rows
   let rows = window.prompt("ENTER NUMBER OF ROWS")
   //create a grid
    document.getElementsByClassName("squaregrid")[0].style.gridTemplateColumns =   "repeat("+ 1000/rows+", 1fr)"
    //create Squares
    for (let i = 0; i < 1000; i++)   {
        let newSquare = document.createElement("div")
        newSquare.className = "square"
        newSquare.style.height = 100/rows + "vh"
        document.querySelector(".squaregrid").appendChild(newSquare)
    }  
    //get HTML Collection of all squares
    let allSquares = document.getElementsByClassName("square");
    //loop HTML Collection and add a mouseover event listener to each square
    for (square of allSquares) {
      square.addEventListener("mouseover", event => {
        //get computed background-color value of the square being hovered over
        let squareBackground = getComputedStyle(event.target).backgroundColor;
        //the regular expression
        let regex = /\d\.\d/
        //check if does not already have full opacity
        if (squareBackground.match(regex) != null) {
            //get the alpha channel of the square being hovered over
            let squareOpacity  = Number(squareBackground.match(regex))
            //increase alpha value
            event.target.style.backgroundColor = squareBackground.replace(regex, squareOpacity + 0.1)
        }
    })}
    //reset every square on the grid
    function clearScreen() {
      for (square of allSquares) {
        square.style.backgroundColor = "rgba(20, 20, 20, 0.1)"
      }
    }
    </script>
  </body>
</html>

Thanks for the feedback, @disinfor.

Upvotes: 1

Related Questions