国际象棋在D3中移动

时间:2016-03-19 13:52:26

标签: javascript animation d3.js svg chess

在这个问题中讨论了用D3绘制国际象棋棋盘:

How to draw a chess board in D3?

enter image description here

此外,@ jbkunst还有一个令人难以置信的D3棋盘插件:

d3-chessboard plugin

enter image description here

但是,我想动画国际象棋动作,如下:

enter image description here

(但更顺畅;可配置的持续时间等。)

你有什么建议怎么做,D3风格?

我很高兴现在只有一个动作的动画。我稍后会建立更通用的解决方案。

3 个答案:

答案 0 :(得分:2)

这是一个使用链式转换的快速实现,使各个部分全面展开。我试图解释两种不同类型的动作," line"碎片在直线上移动(即主教,城堡)和"步骤"他们逐步移动的地方(即骑士)。我在前一个问题的基础上完成了你的工作。

// piece is the text element to move
// position is an object like { x: 4, y: 6 } of the board position to move to
// type is "step" or "line"
function movePiece(piece, position, type) {

  var p = d3.select(piece),
      d = p.datum();

  (function repeat() {

    if (type === "step"){
      if (position.y === d.y) {
        if (position.x === d.x) {
          return;
        } else if (position.x > d.x) {
          d.x += 1;
        } else {
          d.x -= 1;
        }
      } else {
        if (position.y > d.y) {
          d.y += 1;
        } else {
          d.y -= 1;
        }
      }
    } else {
      if (position.x === d.x &&
          position.y === d.y) {
          return;
      }
      else {
        if (position.x != d.x){
          if (position.x > d.x) {
            d.x += 1;
          } else {
            d.x -= 1;
          }
        }
        if (position.y != d.y){
          if (position.y > d.y) {
            d.y += 1;
          } else {
            d.y -= 1;
          }
        }
      }
    }

    p = p.transition()
      .transition()
      .attr("x", d.x * fieldSize)
      .attr("y", d.y * fieldSize)
      .each("end", repeat);
  })();
}

注意,我没有尝试编码是否属于合法行为。

完整示例:



<!DOCTYPE html>
<html>

<head>
  <script data-require="d3@3.5.3" data-semver="3.5.3" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"></script>
  <link rel="stylesheet" href="style.css" />
  <script src="script.js"></script>
</head>

<body>
  <script>
    var pieces = {
      NONE: {
        name: "None",
        code: " "
      },
      WHITE_KING: {
        name: "White King",
        code: "\u2654"
      },
      WHITE_QUEEN: {
        name: "White Queen",
        code: "\u2655"
      },
      WHITE_ROOK: {
        name: "White Rook",
        code: "\u2656"
      },
      WHITE_BISHOP: {
        name: "White Bishop",
        code: "\u2657"
      },
      WHITE_KNIGHT: {
        name: "White Knight",
        code: "\u2658"
      },
      WHITE_POWN: {
        name: "White Pown",
        code: "\u2659"
      },
      BLACK_KING: {
        name: "Black King",
        code: "\u265A"
      },
      BLACK_QUEEN: {
        name: "Black Queen",
        code: "\u265B"
      },
      BLACK_ROOK: {
        name: "Black Rook",
        code: "\u265C"
      },
      BLACK_BISHOP: {
        name: "Black Bishop",
        code: "\u265D"
      },
      BLACK_KNIGHT: {
        name: "Black Knight",
        code: "\u265E"
      },
      BLACK_POWN: {
        name: "Black Pown",
        code: "\u265F"
      },
    };

    var board = [],
      boardDimension = 8,
      fieldSize = 40;

    for (var i = 0; i < boardDimension * boardDimension; i++) {
      board.push({
        x: i % boardDimension,
        y: Math.floor(i / boardDimension),
        piece: pieces.NONE
      });
    };

    board[0].piece = pieces.BLACK_ROOK
    board[1].piece = pieces.BLACK_KNIGHT
    board[2].piece = pieces.BLACK_BISHOP
    board[3].piece = pieces.BLACK_QUEEN
    board[4].piece = pieces.BLACK_KING
    board[5].piece = pieces.BLACK_BISHOP
    board[6].piece = pieces.BLACK_KNIGHT
    board[7].piece = pieces.BLACK_ROOK

    board[8].piece = pieces.BLACK_POWN
    board[9].piece = pieces.BLACK_POWN
    board[10].piece = pieces.BLACK_POWN
    board[11].piece = pieces.BLACK_POWN
    board[12].piece = pieces.BLACK_POWN
    board[13].piece = pieces.BLACK_POWN
    board[14].piece = pieces.BLACK_POWN
    board[15].piece = pieces.BLACK_POWN

    board[6 * 8 + 0].piece = pieces.WHITE_POWN
    board[6 * 8 + 1].piece = pieces.WHITE_POWN
    board[6 * 8 + 2].piece = pieces.WHITE_POWN
    board[6 * 8 + 3].piece = pieces.WHITE_POWN
    board[6 * 8 + 4].piece = pieces.WHITE_POWN
    board[6 * 8 + 5].piece = pieces.WHITE_POWN
    board[6 * 8 + 6].piece = pieces.WHITE_POWN
    board[6 * 8 + 7].piece = pieces.WHITE_POWN

    board[7 * 8 + 0].piece = pieces.WHITE_ROOK
    board[7 * 8 + 1].piece = pieces.WHITE_KNIGHT
    board[7 * 8 + 2].piece = pieces.WHITE_BISHOP
    board[7 * 8 + 3].piece = pieces.WHITE_QUEEN
    board[7 * 8 + 4].piece = pieces.WHITE_KING
    board[7 * 8 + 5].piece = pieces.WHITE_BISHOP
    board[7 * 8 + 6].piece = pieces.WHITE_KNIGHT
    board[7 * 8 + 7].piece = pieces.WHITE_ROOK

    var svg = d3.select('body')
      .append('svg')
      .attr('width', 500)
      .attr('height', 500);

    svg.selectAll("rect")
      .data(board)
      .enter()
      .append("rect")
      .style("class", "fields")
      .style("class", "rects")
      .attr("x", function(d) {
        return d.x * fieldSize;
      })
      .attr("y", function(d) {
        return d.y * fieldSize;
      })
      .attr("width", fieldSize + "px")
      .attr("height", fieldSize + "px")
      .style("fill", function(d) {
        if (((d.x % 2 == 0) && (d.y % 2 == 0)) ||
          ((d.x % 2 == 1) && (d.y % 2 == 1)))
          return "beige";
        else
          return "tan";
      });

    var pieces = svg.selectAll("text")
      .data(board)
      .enter().append("text")
      .attr("x", function(d) {
        d.piece.x = d.x;
        return d.x * fieldSize;
      })
      .attr("y", function(d) {
        d.piece.y = d.y;
        return d.y * fieldSize;
      })
      .style("font-size", "40")
      .attr("text-anchor", "middle")
      .attr("dy", "35px")
      .attr("dx", "20px")
      .text(function(d) {
        return d.piece.code;
      })

    pieces
      .append("title")
      .text(function(d) {
        return d.piece.name;
      });

    movePiece(pieces[0][6], {
      x: 5,
      y: 2
    }, "step");
    
    movePiece(pieces[0][58], {
      x: 5,
      y: 4
    }, "line");
    
    function movePiece(piece, position, type) {
      
      var p = d3.select(piece),
          d = p.datum();
          
      (function repeat() {

        if (type === "step"){
          if (position.y === d.y) {
            if (position.x === d.x) {
              return;
            } else if (position.x > d.x) {
              d.x += 1;
            } else {
              d.x -= 1;
            }
          } else {
            if (position.y > d.y) {
              d.y += 1;
            } else {
              d.y -= 1;
            }
          }
        } else {
          if (position.x === d.x &&
              position.y === d.y) {
              return;
          }
          else {
            if (position.x != d.x){
              if (position.x > d.x) {
                d.x += 1;
              } else {
                d.x -= 1;
              }
            }
            if (position.y != d.y){
              if (position.y > d.y) {
                d.y += 1;
              } else {
                d.y -= 1;
              }
            }
          }
        }

        p = p.transition()
          .transition()
          .attr("x", d.x * fieldSize)
          .attr("y", d.y * fieldSize)
          .each("end", repeat);
      })();
    }
  </script>
</body>

</html>
&#13;
&#13;
&#13;

答案 1 :(得分:1)

如果您知道起始位置和停止位置,则可以为移动碎片的任何过程设置过渡()。这将使它以动画的方式介于各州之间。不过,这将是线性的,因此对于沿着网格沿直线移动的人来说看起来不错,如果不这样做则不太好(例如骑士)。对于一个骑士,我会首先沿着一个轴过渡,然后沿着另一个轴过渡。

答案 2 :(得分:1)

嗯,经过一些研究,我发现:http://blog.visual.ly/creating-animations-and-transitions-with-d3-js/几乎给出了与核子相同的答案:当你想在d3中改变一个元素的属性(如位置)时,你会做类似d3的事情。 select(selector).attr(attribute,value)你必须使用d3.select(selector).transition()。attr(attribute,value)

但是,插件绘制棋盘的方式,例如,你有g个元素代表正方形,包含一个矩形和一个文本。 rect是正方形的颜色,而文本是这个部分。如果更改g元素范围之外的文本转换,它将消失。无论哪种方式,感觉移动件都是错误的模型。

假设您正在绘制您的棋盘然后独立地绘制您的棋子,您可以使用上面链接中的示例将棋子移动到您想要的位置。小心骑士,你应该用两个过渡来移动它,可能你应该考虑一下捕捉动画。

这就是我得到的全部。

相关问题