javascripthtmlcssblur

How can I properly use blur to multiple elements with an exception of one using javascript


Is there a way to blur the all the background elements except the clicked box. Reason why the background element needed to be blurred is that I want the clicked box to be the focal point.

I tried some Javascript like

if (div.firstChild && div.firstChild.classList.contains('container')) {
      renderBoxes(div.firstChild);
}

And so on. but it doesn't work properly as I intended.

My expected is to blur the blue, pink backgrounds and the other boxes that are not clicked.

function applyStyles(element, styles) {
  for (const [key, value] of Object.entries(styles)) {
    element.style[key] = value;
  }
}

let currentlyClickedBox = null;

function renderBoxes(container) {
  let numberOfBoxes = boxes.length;
  let additionalXValue = 500 - (9 - numberOfBoxes) * 10;
  let offsetValue = 40;
  let offsetAdditional = 0;

  // Loop through tokens array
  boxes.forEach(token => {
    // Create a new div for each token
    const div = document.createElement('div');
    div.className = token.class;
    applyStyles(div, token.style);

    // Add additional offset to each token
    div.setAttribute('data-offset-additional', offsetAdditional);

    // Add click event listener to each token
    div.addEventListener('click', () => {
      // Check if another token was previously clicked
      if (currentlyClickedBox && currentlyClickedBox !== div) {
        // Reset previously clicked token
        currentlyClickedBox.style.transform = 'none';
        currentlyClickedBox.style.position = "relative";
      }

      // Check if this token is currently clicked
      if (currentlyClickedBox === div) {
        // Reset clicked token
        currentlyClickedBox.style.transform = 'none';
        currentlyClickedBox.style.position = "relative";
        currentlyClickedBox = null;
      } else {
        const translateXValue = -div.getBoundingClientRect().x; // Get the px distance of right corner to token;

        // (Adjust token to center) - (Offset of each token) 
        const translateXOffset = (translateXValue + additionalXValue) - (offsetValue + parseInt(div.getAttribute('data-offset-additional')));

        // Transform clicked token
        currentlyClickedBox = div;

        div.style.transform = `translate(${translateXOffset}px, -350px) rotateY(180deg) scale(3)`;
      }
    });

    // Append token div to container
    container.appendChild(div);
    offsetAdditional = offsetAdditional + 20; // Increment additional offset each token
  });
}

function renderForeignObjects() {
  const svg = document.getElementById('mySvg');

  foreignObjects.forEach(obj => {
    const foreignObject = document.createElementNS('http://www.w3.org/2000/svg', 'foreignObject');
    foreignObject.setAttribute('x', obj.x);
    foreignObject.setAttribute('y', obj.y);
    foreignObject.setAttribute('width', obj.width);
    foreignObject.setAttribute('height', obj.height);

    const div = document.createElement('div');
    div.innerHTML = obj.content;
    applyStyles(div.firstChild, obj.style);

    if (div.firstChild && div.firstChild.classList.contains('container')) {
      renderBoxes(div.firstChild);
    }

    foreignObject.appendChild(div);
    svg.appendChild(foreignObject);
  });
}

const foreignObjects = [{
    x: 0,
    y: 0,
    width: "100%",
    height: "100%",
    content: '<div xmlns="http://www.w3.org/1999/xhtml"></div>',
    style: {
      backgroundColor: "blue"
    }
  },
  {
    x: 0,
    y: 0,
    width: 1200,
    height: 200,
    content: '<div></div>',
    style: {
      backgroundColor: "pink"
    }
  },
  {
    x: 0,
    y: 300,
    width: 1200,
    height: 200,
    content: '<div></div>',
    style: {
      backgroundColor: "pink"
    }
  },
  {
    // Whole page
    x: 100,
    y: 0,
    width: 1000,
    height: 750,
    content: '<div class="container"></div>',
    style: {}
  }
];

const boxes = [{
    y: -50,
    class: "box",
    style: {
      width: "110px",
      height: "110px",
      margin: "0 5px",
      backgroundColor: "#ccc"
    }
  },
  {
    class: "box",
    style: {
      width: "110px",
      height: "110px",
      margin: "0 5px",
      backgroundColor: "#ddd"
    }
  },
  {
    class: "box",
    style: {
      width: "110px",
      height: "110px",
      margin: "0 5px",
      backgroundColor: "#ccc"
    }
  }
];

// Call the function to render foreign objects
renderForeignObjects();
.a {
  height: 100vh;
  width: 100%;
}

div {
  width: 100%;
  height: 100%;
  background-size: contain;
  background-position: center;
  background-repeat: no-repeat;
}

.container {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  position: relative;
}

.box {
  transition: transform 0.5s ease;
}
<svg id="mySvg" xmlns="http://www.w3.org/2000/svg" class="a p" viewBox="0 0 1200 800"></svg>


Solution

  • you can do it with this algorithm:

    1. Assign a class to box's container showing that one box is active e.g. active

    2. Assign another class to the currently active box e.g. focused

    3. now use this additional css to your code:

    .container.active box:not(.focused) {
        filter: blur(5px);
    }
    

    css above means :"when container is active, blur every box that is not the focused one"


    Hope it helped. ^_^