首页 > js 用canvas 画圆清除问题?

js 用canvas 画圆清除问题?

我在用js写一个五子棋游戏,利用canvas画棋盘和棋子,为了实现悔棋功能,我用clearRect()清除了原来的棋子,再重新画被清除的部分棋盘,却总是出现了一个圆,请大神帮帮忙,谢谢!

<!DOCTYPE html>
<html lang="en">

<head>
    <meter charset="UTF-8"></meter>
    <meta name="viewport" content="user-scalable=no, initial-scale=1.0, maximum-scale=1.0, width=device-width">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <title>Chess by sheepbao</title>
    <script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
    <!--width="450px" height="450px" -->
</head>

<body onbeforeunload="oneLeave()">
    <canvas id="chess" width="450px" height="450px"></canvas>
    <button onclick="gameover()">结束游戏</button>
    <button id="undo">悔棋</button>
    <script type="text/javascript">
    var cell, half_cell;
    var chess = document.getElementById('chess');
    var context = chess.getContext('2d');
    var undo = document.getElementById('undo');

    function layout() {
        var avaih = window.innerHeight,
            avaiw = window.innerWidth;
        var min = Math.min(avaih, avaiw);
        /*    chess.style.width = (min - 5) + 'px';
            chess.style.height = (min - 5) + 'px';*/
        var w = min - 5;
        chess.width = w;
        chess.height = w;

        cell = Math.floor(w / 15);
        half_cell = cell / 2;

        console.log(w, cell, half_cell);
        // context.strokeStyle = "#BFBFBF";
        for (var i = 0; i < 15; i++) {
            context.moveTo(half_cell, half_cell + (cell * i));
            context.lineTo(w - half_cell, half_cell + (cell * i));

            context.moveTo(half_cell + cell * i, half_cell);
            context.lineTo(half_cell + cell * i, w - half_cell);
            context.stroke();
        }

    }
    layout();

    //chesspiece
    var oneStep = function(x, y, black) {
        console.log("oneStep", x, y, black);

        context.beginPath();
        context.arc(half_cell + cell * x, half_cell + cell * y, half_cell * 0.8, 0, 2 * Math.PI);
        context.closePath();
        var gradient = context.createRadialGradient(half_cell + cell * x + 2, half_cell + cell * y - 2, 13, half_cell + cell * x + 2, half_cell + cell * y - 2, 0);
        if (black) {
            //black
            gradient.addColorStop(0, "#0A0A0A");
            gradient.addColorStop(1, "#636766");
        } else {
            gradient.addColorStop(0, "#D1D1D1");
            gradient.addColorStop(1, "#F9F9F9");
        }

        context.fillStyle = gradient;
        context.fill();
        context.stroke();

    }

    function undoStep(x, y) {

        console.log(chess.width, chess.height);
        context.clearRect((x + 0.1) * cell, (y + 0.1) * cell, 0.8 * cell, 0.8 * cell);

        console.log("undoStep:", x, y,
            "rect:", (x + 0.1) * cell, (y + 0.1) * cell, 0.8 * cell, 0.8 * cell);

        // context.globalCompositeOperation = "source-over";
        context.moveTo(cell * (x + 0.1), (0.5 + y) * cell);
        context.lineTo(cell * (x + 0.9), (0.5 + y) * cell);

        context.moveTo((0.5 + x) * cell, cell * (y + 0.1));
        context.lineTo((0.5 + x) * cell, cell * (y + 0.9));
        context.stroke();


    }

    chess.onclick = function(e) {
        var x = e.offsetX;
        var y = e.offsetY;
        meX = Math.floor(x / cell);
        meY = Math.floor(y / cell);
        console.log("click:", meX, meY);
        oneStep(meX, meY, true);

    }

    undo.onclick = function(e) {

        undoStep(meX, meY);
    }
    </script>
</body>

</html>


看了你的代码,你的棋盘线跟棋子都是用path实现的, context.stroke(); 会把所有path stroke出来(就是描边的意思),而你悔棋的函数没有清除上一步棋对应的path,因此context.stroke();描画棋盘线的时候也把棋子描边出来了。ps:棋盘线因为是固定且不变的,所以其实可以通过另外的一个canvas作为背景去展示,这样可以优化重绘的性能。


点击悔棋按钮之后,之所以会重绘上一次绘制的圆圈,是因为路径没有闭合的原因,
修改意见:你的undoStep()函数,擦除矩形后,在调用context.beginPath();开始一段新的路径,如下图:

另外,你擦除的区域和重绘的区域太小啦,你改了之后就能看见,太小了


只看了描述,没有看代码。
你的这个想法实现起来比较麻烦,简单的方法是重画整个画布,这样你只关注数据就可以了。


创建一个二维数组,用作棋盘的数据。
在每一回合里,下棋或者悔棋都操作这个数组。
操作完数据,把画布全清,重新用数据画一个棋盘。

【热门文章】
【热门文章】