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

SVG井字棋游戏onClick事件随机失效问题求助

井字棋点击事件随机失效的问题修复

你的井字棋点击事件看似随机失效,其实是三个明确的代码问题导致的,逐个给你理清楚:

1. 回合判断的赋值错误

你在判断当前回合时写了if (whosTurn = "x"),这是赋值操作而非比较判断,每次执行到这里都会强制把whosTurn设为"x",直接打乱了回合切换的逻辑,导致点击后的行为完全不可预测。
要改成比较判断:if (whosTurn === "x")(严格相等推荐)或者if (whosTurn == "x")。

2. 冗余的无效代码

代码里存在eleXstyle == "black"这类语句,只是做了一次值比较,没有任何实际作用(既没赋值也没影响逻辑),完全可以删掉,避免干扰代码逻辑。

3. SVG元素层级导致的点击拦截

SVG元素是按定义顺序渲染的,后定义的元素会覆盖在先定义的元素上方。你的rect是最先定义的,后面的line和circle都在rect上层,哪怕这些元素是透明的,点击时也会被它们拦截(但这些元素没绑定点击事件),导致rect的onclick无法触发。
解决办法是给所有rect加上style="pointer-events: all;",让它们无视层级拦截,直接响应点击。


修复后的完整代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Tic Tac Toe</title>

    <script>
        let whosTurn = "o";

        function clickedSquare(x1,x2, o) {
            console.log('hi!')
            var eleX = document.getElementById(x1);
            var eleXR = document.getElementById(x2)
            var eleO = document.getElementById(o);
           
            var eleXstyle = eleX.getAttribute("stroke");
            var eleOstyle = eleO.getAttribute("stroke");

            if (eleXstyle === "transparent" && eleOstyle === "transparent") {
                // 修复:改成比较判断
                if (whosTurn === "x") {
                    eleX.setAttribute( "stroke", "black");
                    eleXR.setAttribute( "stroke", "black");
                    whosTurn = "o"
                } else {
                    eleO.setAttribute( "stroke", "black");
                    whosTurn = "x"
                }
            }
            console.log(whosTurn)
        }
        function checkForWinner() {
            // 后续可补充获胜判断逻辑
        }
    </script>
</head>
<body>
    <svg width="500" height="500" style="background-color: black;" viewBox="0 0 500 500">
        <!-- 修复:给每个rect添加pointer-events: all -->
        <rect width="160" height="160" x="0" y="0" fill="red" style="pointer-events: all;" onclick="clickedSquare('x1l','x1r','circle1');"></rect>
        <rect width="160" height="160" x="170" y="0" fill="white" style="pointer-events: all;" onclick="clickedSquare('x2l','x2r','circle2'); checkForWinner();"></rect>
        <rect width="160" height="160" x="340" y="0" fill="white" style="pointer-events: all;" onclick="clickedSquare('x3l','x3r','circle3'); checkForWinner();"></rect>
        <rect width="160" height="160" x="0" y="170" fill="white" style="pointer-events: all;" onclick="clickedSquare('x4l','x4r','circle4'); checkForWinner();"></rect>
        <rect width="160" height="160" x="170" y="170" fill="white" style="pointer-events: all;" onclick="clickedSquare('x5l','x5r','circle5'); checkForWinner();"></rect>
        <rect width="160" height="160" x="340" y="170" fill="white" style="pointer-events: all;" onclick="clickedSquare('x6l','x6r','circle6'); checkForWinner();"></rect>
        <rect width="160" height="160" x="0" y="340" fill="white" style="pointer-events: all;" onclick="clickedSquare('x7l','x7r','circle7'); checkForWinner();"></rect>
        <rect width="160" height="160" x="170" y="340" fill="white" style="pointer-events: all;" onclick="clickedSquare('x8l','x8r','circle8'); checkForWinner();"></rect>
        <rect width="160" height="160" x="340" y="340" fill="white" style="pointer-events: all;" onclick="clickedSquare('x9l','x9r','circle9'); checkForWinner();"></rect>

        <line x1="20" y1="20" x2="130" y2="120" stroke="transparent" stroke-width="5px" class="exes x1" id="x1l"></line>
        <line x1="130" y1="20" x2="20" y2="120" stroke="transparent" stroke-width="5px" class="exes x1" id="x1r"></line>

        <line x1="190" y1="20" x2="300" y2="120" stroke="transparent" stroke-width="5px" class="exes x2" id="x2l"></line>
        <line x1="300" y1="20" x2="190" y2="120" stroke="transparent" stroke-width="5px" class="exes x2" id="x2r"></line>
        
        <line x1="360" y1="20" x2="470" y2="120" stroke="transparent" stroke-width="5px" class="exes x3" id="x3l"></line>
        <line x1="470" y1="20" x2="360" y2="120" stroke="transparent" stroke-width="5px" class="exes x3" id="x3r"></line>


        <line x1="20" y1="190" x2="130" y2="290" stroke="transparent" stroke-width="5px" class="exes x4" id="x4l"></line>
        <line x1="130" y1="190" x2="20" y2="290" stroke="transparent" stroke-width="5px" class="exes x4" id="x4r"></line>

        <line x1="190" y1="190" x2="300" y2="290" stroke="transparent" stroke-width="5px" class="exes x5" id="x5l"></line>
        <line x1="300" y1="190" x2="190" y2="290" stroke="transparent" stroke-width="5px" class="exes x5" id="x5r"></line>
        
        <line x1="360" y1="190" x2="470" y2="290" stroke="transparent" stroke-width="5px" class="exes x6" id="x6l"></line>
        <line x1="470" y1="190" x2="360" y2="290" stroke="transparent" stroke-width="5px" class="exes x6" id="x6r"></line>
        
        
        <line x1="20" y1="360" x2="130" y2="470" stroke="transparent" stroke-width="5px" class="exes x7" id="x7l"></line>
        <line x1="130" y1="360" x2="20" y2="470" stroke="transparent" stroke-width="5px" class="exes x7" id="x7r"></line>

        <line x1="190" y1="360" x2="300" y2="470" stroke="transparent" stroke-width="5px" class="exes x8" id="x8l"></line>
        <line x1="300" y1="360" x2="190" y2="470" stroke="transparent" stroke-width="5px" class="exes x8" id="x8r"></line>
        
        <line x1="360" y1="360" x2="470" y2="470" stroke="transparent" stroke-width="5px" class="exes x9" id="x9l"></line>
        <line x1="470" y1="360" x2="360" y2="470" stroke="transparent" stroke-width="5px" class="exes x9" id="x9r"></line>
       
        <circle cx="70" cy="70" r="60" stroke="transparent" stroke-width="5px" fill="transparent" class="circle" id="circle1"></circle>
        <circle cx="250" cy="70" r="60" stroke="transparent" stroke-width="5px" fill="transparent" class="circle" id="circle2"></circle>
        <circle cx="430" cy="70" r="60" stroke="transparent" stroke-width="5px" fill="transparent" class="circle" id="circle3"></circle>

        <circle cx="70" cy="250" r="60" stroke="transparent" stroke-width="5px" fill="transparent" class="circle" id="circle4"></circle>
        <circle cx="250" cy="250" r="60" stroke="transparent" stroke-width="5px" fill="transparent" class="circle" id="circle5"></circle>
        <circle cx="430" cy="250" r="60" stroke="transparent" stroke-width="5px" fill="transparent" class="circle" id="circle6"></circle>

        <circle cx="70" cy="430" r="60" stroke="transparent" stroke-width="5px" fill="transparent" class="circle" id="circle7"></circle>
        <circle cx="250" cy="430" r="60" stroke="transparent" stroke-width="5px" fill="transparent" class="circle" id="circle8"></circle>
        <circle cx="430" cy="430" r="60" stroke="transparent" stroke-width="5px" fill="transparent" class="circle" id="circle9"></circle>

    </svg>
</body>
</html>

内容的提问来源于stack exchange,提问作者Maddy Young

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 08:02:35