如何正确过滤点击事件坐标,仅在蛋糕.icing糖霜层添加蜡烛
解决蜡烛仅能放置在蛋糕糖霜层的问题
问题根源
原代码绑定了整个.cake元素的点击事件,且用正圆距离判断(icingRadius取宽度的一半),但糖霜是椭圆(宽240px、高90px),导致判断范围不符合实际形状;同时原Y轴范围包含了糖霜下方区域,误判滴落部分的点击。
方案一:直接监听糖霜元素的点击(最简单)
把点击事件从.cake移到.icing上,只有点击糖霜区域才触发添加蜡烛,彻底避免误触滴落或其他区域。
修改后的JS代码:
const cake = document.querySelector(".cake"); const icing = document.querySelector(".icing"); let candles = []; function addCandle(left, top) { const candle = document.createElement("div"); candle.className = "candle"; // 基于icing的偏移调整蜡烛位置,适配点击坐标 candle.style.left = (icing.offsetLeft + left) + "px"; candle.style.top = (icing.offsetTop + top) + "px"; const flame = document.createElement("div"); flame.className = "flame"; candle.appendChild(flame); cake.appendChild(candle); candles.push(candle); } // 绑定到icing元素的点击事件 icing.addEventListener("click", function (event) { const rect = icing.getBoundingClientRect(); // 计算点击点相对于icing内部的坐标 const left = event.clientX - rect.left; const top = event.clientY - rect.top; addCandle(left, top); });
方案二:椭圆碰撞检测(保留cake点击事件)
如果需要保留整个蛋糕的点击事件,用椭圆方程判断点击点是否在糖霜的椭圆区域内(糖霜是宽240、高90的椭圆,圆心在icing的中心)。
修改addCandle函数中的判断逻辑:
function addCandle(left, top) { const icing = document.querySelector(".icing"); const cakeRect = cake.getBoundingClientRect(); // 计算点击点相对于cake的坐标 const clickX = event.clientX - cakeRect.left; const clickY = event.clientY - cakeRect.top; // 椭圆参数:中心坐标(相对于cake)、半长轴、半短轴 const ellipseCenterX = icing.offsetLeft + icing.offsetWidth / 2; const ellipseCenterY = icing.offsetTop + icing.offsetHeight / 2; const semiMajor = icing.offsetWidth / 2; // 长半轴(宽的一半) const semiMinor = icing.offsetHeight / 2; // 短半轴(高的一半) // 椭圆方程判断:(x-h)²/a² + (y-k)²/b² ≤ 1 const ellipseTest = Math.pow((clickX - ellipseCenterX), 2) / Math.pow(semiMajor, 2) + Math.pow((clickY - ellipseCenterY), 2) / Math.pow(semiMinor, 2); if (ellipseTest <= 1) { const candle = document.createElement("div"); candle.className = "candle"; candle.style.left = left + "px"; candle.style.top = top + "px"; const flame = document.createElement("div"); flame.className = "flame"; candle.appendChild(flame); cake.appendChild(candle); candles.push(candle); } else { console.log("Clicked outside of icing, no candle added."); } }
方案说明
- 方案一最直观,利用DOM事件的目标元素判断,无需复杂坐标计算,完全适配你的需求。
- 方案二更灵活,适合需要在整个蛋糕区域做其他交互,但要精准判断糖霜椭圆区域的场景。
内容的提问来源于stack exchange,提问作者Ayus Chatterjee
相关产品推荐
相关产品推荐

