如何用JavaScript实现点击盒子后模糊其余背景及未点击元素
实现点击Box后模糊其他背景元素的解决方案
要实现点击某个Box后,模糊蓝色/粉色背景及其他未被点击的Box,核心是通过**CSS滤镜(filter: blur())**给非目标元素添加模糊效果,同时配合JavaScript控制类的添加与移除,确保视觉焦点集中在被点击的Box上。
步骤1:添加模糊样式类
在CSS中新增模糊类,控制元素模糊效果的同时禁用其点击事件,避免干扰交互:
.blur { filter: blur(4px); pointer-events: none; /* 防止模糊元素拦截点击操作 */ transition: filter 0.5s ease; /* 保持动画过渡流畅 */ } .box { transition: transform 0.5s ease, filter 0.5s ease; /* 给Box添加滤镜过渡效果 */ }
步骤2:标记背景元素
修改foreignObjects数组,给蓝色、粉色背景的div添加统一类名background-element,方便后续批量选择操作:
const foreignObjects = [{ x: 0, y: 0, width: "100%", height: "100%", content: '<div xmlns="http://www.w3.org/1999/xhtml" class="background-element"></div>', style: { backgroundColor: "blue" } }, { x: 0, y: 0, width: 1200, height: 200, content: '<div class="background-element"></div>', style: { backgroundColor: "pink" } }, { x: 0, y: 300, width: 1200, height: 200, content: '<div class="background-element"></div>', style: { backgroundColor: "pink" } }, { x: 100, y: 0, width: 1000, height: 750, content: '<div class="container"></div>', style: {} } ];
步骤3:修改点击事件逻辑
在Box的点击事件中,添加模糊/取消模糊的控制逻辑,确保点击时只保留目标Box清晰:
div.addEventListener('click', () => { const backgroundElements = document.querySelectorAll('.background-element'); const allBoxes = document.querySelectorAll('.box'); // 先重置所有元素的模糊状态 backgroundElements.forEach(el => el.classList.remove('blur')); allBoxes.forEach(box => box.classList.remove('blur')); // 处理之前点击的Box重置 if (currentlyClickedBox && currentlyClickedBox !== div) { currentlyClickedBox.style.transform = 'none'; currentlyClickedBox.style.position = "relative"; } // 处理当前点击的Box:取消点击状态 if (currentlyClickedBox === div) { currentlyClickedBox.style.transform = 'none'; currentlyClickedBox.style.position = "relative"; currentlyClickedBox = null; } else { const translateXValue = -div.getBoundingClientRect().x; const translateXOffset = (translateXValue + additionalXValue) - (offsetValue + parseInt(div.getAttribute('data-offset-additional'))); currentlyClickedBox = div; div.style.transform = `translate(${translateXOffset}px, -350px) rotateY(180deg) scale(3)`; // 给背景元素和其他未点击的Box添加模糊 backgroundElements.forEach(el => el.classList.add('blur')); allBoxes.forEach(box => { if (box !== div) box.classList.add('blur'); }); } });
完整修改后代码
HTML
<svg id="mySvg" xmlns="http://www.w3.org/2000/svg" class="a p" viewBox="0 0 1200 800"></svg>
CSS
.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, filter 0.5s ease; } .blur { filter: blur(4px); pointer-events: none; transition: filter 0.5s ease; }
JavaScript
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; boxes.forEach(token => { const div = document.createElement('div'); div.className = token.class; applyStyles(div, token.style); div.setAttribute('data-offset-additional', offsetAdditional); div.addEventListener('click', () => { const backgroundElements = document.querySelectorAll('.background-element'); const allBoxes = document.querySelectorAll('.box'); // 重置所有模糊状态 backgroundElements.forEach(el => el.classList.remove('blur')); allBoxes.forEach(box => box.classList.remove('blur')); if (currentlyClickedBox && currentlyClickedBox !== div) { currentlyClickedBox.style.transform = 'none'; currentlyClickedBox.style.position = "relative"; } if (currentlyClickedBox === div) { currentlyClickedBox.style.transform = 'none'; currentlyClickedBox.style.position = "relative"; currentlyClickedBox = null; } else { const translateXValue = -div.getBoundingClientRect().x; const translateXOffset = (translateXValue + additionalXValue) - (offsetValue + parseInt(div.getAttribute('data-offset-additional'))); currentlyClickedBox = div; div.style.transform = `translate(${translateXOffset}px, -350px) rotateY(180deg) scale(3)`; // 添加模糊效果 backgroundElements.forEach(el => el.classList.add('blur')); allBoxes.forEach(box => { if (box !== div) box.classList.add('blur'); }); } }); container.appendChild(div); offsetAdditional = offsetAdditional + 20; }); } 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" class="background-element"></div>', style: { backgroundColor: "blue" } }, { x: 0, y: 0, width: 1200, height: 200, content: '<div class="background-element"></div>', style: { backgroundColor: "pink" } }, { x: 0, y: 300, width: 1200, height: 200, content: '<div class="background-element"></div>', style: { backgroundColor: "pink" } }, { 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" } } ]; renderForeignObjects();
内容的提问来源于stack exchange,提问作者Obsidia
相关产品推荐
相关产品推荐

