在Javascript中在棋盘上画箭头

5
我正在尝试制作自己的棋局分析板,用于教授国际象棋。我目前已经有了棋盘、可以拖放的棋子,以及清空棋盘和设置不同棋局位置的方法。我还可以单击方格以突出显示它们。
我希望能够从一个方格画箭头到另一个方格,以显示攻击和影响线,但我不知道如何实现。我的棋盘由
标签组成。下面是一个简短的示例(为简洁起见,伪代码和实际代码)。
// 一些CSS样式来定义方格的宽度、高度和颜色 CSS样式类“暗方格” CSS样式类“亮方格”
// 我的棋盘由
标签组成
<div id="board">
    <div id="a1" class="lightsquare"></div>
    <div id="a2" class="darksquare"></div>
    <div id="a3" class="lightsquare"></div>
    //second rank
    <div id="b1" class="darksquare"></div>
    <div id="b2" class="lightsquare"></div>
    <div id="b3" class="darksquare"></div>

    //third rank
    <div id="c1" class="lightsquare"></div>
    <div id="c2" class="darksquare"></div>
    <div id="c3" class="lightsquare"></div>
</div>

我可以在棋盘上放置棋子、移动它们、拿走其他的棋子、清空棋盘、设置独特的位置以及突出显示单个方格,但我还希望能够让用户在棋盘上实时地点击、拖动和绘制箭头,同时仍然能够操纵棋盘上的棋子。
我查看了使用 <canvas> 标签,但根据我阅读和研究的情况,似乎这个标签并不是设计用于我所需要的功能。
有人有任何关于如何在JavaScript中实现这一点的想法吗?我还没有学会使用JQuery,并且希望避免使用JQuery,因为我不想下载额外的文件或者必须连接互联网才能使用这个程序。

请参考以下链接:https://dev59.com/2mIj5IYBdhLWcg3wpWlx - Pete
哦,行和列。如果HTML中有一个具有这些属性的元素,那么就不需要使用DIV了... - RoToRa
3个回答

4

经过一个月的摸索,我终于找到了解决方案。虽然我很努力地尝试使用< div >标签和图片来解决这个问题,但当箭头被旋转时,我始终无法使其正确定位。因此,我又回到了尝试使用< canvas >标签,并最终找到了可行的解决方案。

function drawArrow(fromx, fromy, tox, toy){
            //variables to be used when creating the arrow
            var c = document.getElementById("myCanvas");
            var ctx = c.getContext("2d");
            var headlen = 10;

            var angle = Math.atan2(toy-fromy,tox-fromx);

            //starting path of the arrow from the start square to the end square and drawing the stroke
            ctx.beginPath();
            ctx.moveTo(fromx, fromy);
            ctx.lineTo(tox, toy);
            ctx.strokeStyle = "#cc0000";
            ctx.lineWidth = 22;
            ctx.stroke();

            //starting a new path from the head of the arrow to one of the sides of the point
            ctx.beginPath();
            ctx.moveTo(tox, toy);
            ctx.lineTo(tox-headlen*Math.cos(angle-Math.PI/7),toy-headlen*Math.sin(angle-Math.PI/7));

            //path from the side point of the arrow, to the other side point
            ctx.lineTo(tox-headlen*Math.cos(angle+Math.PI/7),toy-headlen*Math.sin(angle+Math.PI/7));

            //path from the side point back to the tip of the arrow, and then again to the opposite side point
            ctx.lineTo(tox, toy);
            ctx.lineTo(tox-headlen*Math.cos(angle-Math.PI/7),toy-headlen*Math.sin(angle-Math.PI/7));

            //draws the paths created above
            ctx.strokeStyle = "#cc0000";
            ctx.lineWidth = 22;
            ctx.stroke();
            ctx.fillStyle = "#cc0000";
            ctx.fill();
        }

这段代码将根据鼠标按下和松开事件时正方形的坐标来获取起始和结束坐标。然后,它将使用这些坐标来确定如何绘制箭头并使其正确旋转。


我使用了这段代码,它很棒。但问题是如何将画布覆盖在棋盘div上,并使得棋子可以在画布下方被访问到? - Vahid Alimohamadi
我使用CSS定位将画布直接放在棋盘的顶部。现在显然你想要能够点击棋盘上的棋子并移动它们,同时仍然能够绘制箭头。为此,我使用了pointerEvents属性。如果我想移动棋子,我只需单击并拖动棋子。如果我想绘制箭头,我按住Shift键,然后绘制箭头。 - SteampunkWizard
我用SVG实现了它,使用Raphael时太容易了。 - Vahid Alimohamadi

1
如果你想知道如何处理这个(有趣的)问题,我会这样做。
  1. 使用两个png图像创建箭头:在一个容器
    中,使用两个带有背景图像(箭身和箭尖)的
  2. 一旦您有了正确显示箭头的代码,请确保知道如何使用javascript将其附加到DOM。
  3. 现在尝试使用javascript使箭头变长或变短(通过更改包含箭身的
    的大小)。
  4. 一旦您能够做到这一点,就可以开始数学部分。使用javascript计算制作箭头时首先单击的
    和第二个单击的
    的坐标。当您拥有这些坐标时,使用勾股定理计算所需箭头的长度和旋转量(这是棘手的部分,但我以前已经做过了,因此如果您了解一些基本数学知识,则一定可以完成)。您实质上正在棋盘上创建三角形。
  5. 有了坐标、长度和旋转角度,您现在可以将箭头放置在游戏板上,调整长度和旋转角度,以使其以所需的方式显示。请记住,您还可以将箭头旋转350度以达到-10度。

如果你喜欢数学,那么这绝不是一件容易的事情,但考虑到国际象棋,我猜你会喜欢。

顺便说一下,这个问题当然可以用纯JS解决,但使用jQuery会更加容易且减少工作量。您也可以通过下载该库来离线使用jQuery。


我从未使用过画布,只用了纯HTML和JS,这是一个有趣的项目。在这里查看一些旋转信息:http://www.w3schools.com/cssref/playit.asp?filename=playcss_transform_rotate。你的主要挑战是从两个坐标计算长度和旋转,但如果你擅长数学,这只需要一晚上的时间(我想)。编程部分很容易,真的。谷歌“appendChild”,“update style javascript”,基本上这就是你所需要的。 - Derk Arts
我实际上能够根据您的建议自己找到大部分信息。我找到了Math.atan2运算符,并且现在已经成功地单击、拖动和释放了鼠标点击,并根据方向和长度将箭头指向四个方向之一并改变长度。现在让我发疯的是,我无论如何都不能让箭头改变位置到我想要的位置。我得到了我的起始坐标“startXY”和我的结束坐标“endXY”,从较大的x和y中减去较小的x和y。 - SteampunkWizard
一旦我得到了这个差异,我将其除以2并从较大的x和y中减去,希望得到一个XY坐标,该坐标位于我的起始和结束坐标之间,并使用它来决定我的左侧:x;顶部:y;坐标。然而,当我这样做时,箭头出现在完全不同的位置。我交换了x和y,以为可能是我弄错了坐标,但那也没有起作用...所以现在箭头的长度和旋转发生了变化,但它并没有定位到我想要的位置... - SteampunkWizard
很棒,你已经做得很好了,你也成功解决了定位问题吗?我认为你把它搞得比应该的更复杂了。如果你只是将“箭头div”定位在初始“鼠标点击位置”-(箭头div高度/2),并使用相同的左坐标,我认为那应该可以工作。如果你把你已经完成的部分放在JSFiddle上,我很乐意帮你完成最后一步。 - Derk Arts
另外,我建议开始使用jQuery,并了解如何将函数附加到具有类的元素(这非常容易)。您只需说 $(“.lightsquare”).mousedown(function(){getStart(this);}); 而不是每次都指定它。看到这一切,我担心您需要更多地投资于学习JS / jQuery和编程,这是一个很好的学习机会 :)。 - Derk Arts
显示剩余6条评论

0
我使用了以下代码来激活和禁用pointerEvents。
//检查是否按下了Shift键
    function disableImage(ev){
        if(ev.shiftKey == 1){
            var canvas = document.getElementById("arrowCanvas");
            canvas.style.pointerEvents = "all";
        }
    }

    function enableImage(){
        var canvas = document.getElementById("arrowCanvas");
        canvas.style.pointerEvents = "none";
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接