D3中的国际象棋走法
Chess moves in D3
本题讨论用D3画棋盘:
另外,@jbkunst 有一个令人难以置信的 D3 棋盘插件:
但是,我想为国际象棋走法制作动画,如下所示:
(但更流畅;具有可配置的持续时间等)
D3 风格,你有什么建议吗?
我会很高兴现在只有一个动作的动画。稍后我将构建更通用的解决方案。
如果您知道开始位置和停止位置,则可以为移动棋子的任何进程设置一个 transition()。这将使它以动画方式在各州之间切换。不过,这将是线性的,因此对于沿着网格直线移动的任何人来说它看起来都不错,如果不这样做则不太好(例如骑士)。对于骑士,我会先沿一个轴过渡,然后再沿另一个轴过渡。
好吧,经过一些研究,我发现了这个:http://blog.visual.ly/creating-animations-and-transitions-with-d3-js/ 几乎给出了与 nucleon 相同的答案:当你想改变 d3 中元素的属性(比如位置)并且你做了类似的事情d3.select(selector).attr(attribute,value) 并且你必须使用 d3.select(selector).transition().attr(attribute,value)
但是,插件绘制棋盘的方式,例如,您有 g 个元素代表正方形,包含一个矩形和一个文本。 rect 是正方形的颜色,而 text 是一块。如果您更改 g 元素范围之外的文本转换,它就会消失。无论哪种方式,移动棋子的模型都是错误的。
假设您正在绘制棋盘,然后独立绘制棋子,您可以使用上面 link 中的示例将棋子移动到您想要的位置。小心骑士,虽然你应该用两个转换来移动它,也许你应该考虑一下捕捉动画。
我只有这些了。
下面是一个快速实现,它使用链式转换使各个部分跨板。我试图解释两种不同类型的运动,"line" 棋子直线移动(即主教、城堡)和 "step" 逐步移动(即骑士)。我基于你在上一个问题中的工作。
// 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>
本题讨论用D3画棋盘:
另外,@jbkunst 有一个令人难以置信的 D3 棋盘插件:
但是,我想为国际象棋走法制作动画,如下所示:
(但更流畅;具有可配置的持续时间等)
D3 风格,你有什么建议吗?
我会很高兴现在只有一个动作的动画。稍后我将构建更通用的解决方案。
如果您知道开始位置和停止位置,则可以为移动棋子的任何进程设置一个 transition()。这将使它以动画方式在各州之间切换。不过,这将是线性的,因此对于沿着网格直线移动的任何人来说它看起来都不错,如果不这样做则不太好(例如骑士)。对于骑士,我会先沿一个轴过渡,然后再沿另一个轴过渡。
好吧,经过一些研究,我发现了这个:http://blog.visual.ly/creating-animations-and-transitions-with-d3-js/ 几乎给出了与 nucleon 相同的答案:当你想改变 d3 中元素的属性(比如位置)并且你做了类似的事情d3.select(selector).attr(attribute,value) 并且你必须使用 d3.select(selector).transition().attr(attribute,value)
但是,插件绘制棋盘的方式,例如,您有 g 个元素代表正方形,包含一个矩形和一个文本。 rect 是正方形的颜色,而 text 是一块。如果您更改 g 元素范围之外的文本转换,它就会消失。无论哪种方式,移动棋子的模型都是错误的。
假设您正在绘制棋盘,然后独立绘制棋子,您可以使用上面 link 中的示例将棋子移动到您想要的位置。小心骑士,虽然你应该用两个转换来移动它,也许你应该考虑一下捕捉动画。
我只有这些了。
下面是一个快速实现,它使用链式转换使各个部分跨板。我试图解释两种不同类型的运动,"line" 棋子直线移动(即主教、城堡)和 "step" 逐步移动(即骑士)。我基于你在上一个问题中的工作。
// 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>