skip to Main Content

How can i implement a progressive darkening effect where each interaction adds 10% more black or color to the square?

I tried to work with filter: brightness, the value of darkness is 0%, but the value of lightness is less 1000% and not every color at 1000% gives a white background.

const shadingMode = (elem) => {
  let currentBrightness = elem.style.filter.slice(11, -2);
  if (currentBrightness > 0) {
    console.log("currentBrightness " + currentBrightness);
    elem.style.filter = `brightness(${currentBrightness - 10}%)`;
    console.log("elem.style.filter 2: " + elem.style.filter);
  } else {
    currentBrightness = 0;
  }
};
const lightenMode = (elem) => {
  let currentBrightness = elem.style.filter.slice(11, -2);
  if (currentBrightness < 1000) {
    console.log("currentBrightness " + currentBrightness);
    elem.style.filter = `brightness(${parseInt(currentBrightness) + 100}%)`;
    console.log("elem.style.filter 2: " + elem.style.filter);
  } else {
    currentBrightness = 800;
  }
};

3

Answers


  1. When the left mouse button is clicked, the square will become darker.
    When you click with the right button, the square will become brighter

    I hope my example is useful to you.

    Example 1

    const square = document.getElementById('square');
    
    const darkenSquare = () => {
        let currentBrightness = square.dataset.brightness || 100;
        currentBrightness = parseInt(currentBrightness) - 10;
    
        if (currentBrightness >= 0) {
            square.style.filter = `brightness(${currentBrightness}%)`;
            square.dataset.brightness = currentBrightness;
        }
    };
    
    const lightenSquare = () => {
        let currentBrightness = square.dataset.brightness || 100;
        currentBrightness = parseInt(currentBrightness) + 10;
    
        if (currentBrightness <= 100) {
            square.style.filter = `brightness(${currentBrightness}%)`;
            square.dataset.brightness = currentBrightness;
        }
    };
    
    square.addEventListener('click', darkenSquare);
    square.addEventListener('contextmenu', (event) => {
        event.preventDefault();
        lightenSquare();
    });
    .square {
        width: 200px;
        height: 200px;
        background-color: blue;
    }
    <div class="square" id="square"></div>

    Example 2

    In this example I have used HSL color value. This allows by changing the light value to change the color to black or white.

    Left mouse button will fade to black. Right will light up to white

    const square = document.getElementById('square');
    
    const darkenSquare = () => {
        let currentBrightness = square.dataset.brightness;
        currentBrightness = parseInt(currentBrightness) - 10;
    
        if (currentBrightness >= 0) {
            square.style.backgroundColor = `hsl(240, 100%,${currentBrightness}%)`
            square.dataset.brightness = currentBrightness;
        }
    };
    
    const lightenSquare = () => {
        let currentBrightness = square.dataset.brightness;
        currentBrightness = parseInt(currentBrightness) + 10;
    
        if (currentBrightness <= 100) {
            square.style.backgroundColor = `hsl(240, 100%,${currentBrightness}%)`
            square.dataset.brightness = currentBrightness;
        }
    };
    
    square.addEventListener('click', darkenSquare);
    square.addEventListener('contextmenu', (event) => {
        event.preventDefault();
        lightenSquare();
    });
    .square {
        width: 200px;
        height: 200px;
        background-color: hsl(240, 100%, 50%);
    }
    <div class="square" id="square" style="background-color: hsl(240, 100%, 50%);" data-brightness="50"></div>
    Login or Signup to reply.
  2. Your shadingMode function seems to implement a darkening effect using the brightness CSS filter. It takes an element elem as input and reduces its brightness by 10% on each interaction.

    However, there are a couple of issues in the code that need to be addressed:

    The currentBrightness variable will be a string with a percentage symbol, e.g., "90%". When you use .slice(11, -2), it removes the % symbol and takes the numeric part as a string. You should convert it to a number using parseInt() or parseFloat() before performing arithmetic operations.

    Since you are using the brightness() filter, which modifies the brightness relative to the original brightness, you should set an initial brightness value for the element to work correctly.

    Here’s the corrected version of your shadingMode function:

    const shadingMode = (elem) => {
      let currentBrightness = parseFloat(elem.style.filter.slice(11, -1)); // Convert to a number
      if (isNaN(currentBrightness)) {
        // If currentBrightness is NaN, set an initial brightness value
        currentBrightness = 100;
      }
    
      if (currentBrightness > 0) {
        console.log("currentBrightness " + currentBrightness);
        elem.style.filter = `brightness(${currentBrightness - 10}%)`;
        console.log("elem.style.filter 2: " + elem.style.filter);
      } else {
        currentBrightness = 0;
      }
    };
    

    In this corrected version, I used parseFloat() to convert currentBrightness to a number. Additionally, if the brightness is not set (NaN), the function sets an initial brightness of 100% (fully bright). Then, it reduces the brightness by 10% on each interaction by updating the elem.style.filter property.

    Make sure to add an event listener to call this function when interacting with the element, such as on a click event. Also, ensure that the element you pass to shadingMode has a filter property, which can be modified to control its brightness.

    Login or Signup to reply.
  3. I personally would solve the problem like so: I’d place the element of which I want to change the darkness inside of a wrapper, alongside a "filter" element. The filter element is just a square the same size, with background color black. In js we read the opacity of the filter element, and increase it. I find that this is the "cleanest" version, as it requires barely any js code.

    Link to my Codepen

    HTML:

    <div id="wrapper">
      <div id="filter"></div>
      <div id="element"></div>
    </div>
    

    CSS:

    #wrapper{
      position: relative;
      width: 50px;
      height: 50px;
    }
    
    #element{
      position: absolute;
      width: 100%;
      height: 100%;
      background-color: green;
    }
    
    #filter{
      position: absolute;
      background-color: black;
      width: 100%;
      height: 100%;
      opacity: 0;
      transition: all 0.5s ease;
      z-index: 2;
      pointer-events: none;
    }
    

    JS:

    let wrapper = document.querySelector("#wrapper")
    let filter = document.querySelector("#filter");
    
    wrapper.addEventListener("click", function(){
      let currentOpacity = Number(filter.style.opacity);
      if(currentOpacity < 1) filter.style.opacity = currentOpacity + 0.1;
    })
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search