You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何正确过滤点击事件坐标,仅在蛋糕.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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 06:05:54