Published unlisted
Edited
Aug 9, 2019
2 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
version5()
Insert cell
version6()
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
viewof a = "myName"
Insert cell
Insert cell
squarePadding = 1

Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
function version4() {
const svg = drawChessboard();
const dataArray = game1;
// paths
const sel1 = d3.select(svg)
.selectAll("path.piece-move")
.data(dataArray);
sel1.join("path")
.attr("class", "piece-move")
.attr("d", (d, i) => {
let str = {};
const dx = (i % 2) ? -2 : 2;
const dy = (i % 2) ? -2 : 2;
str = "M " + (squareToPosition(d.from).x + dx) + " " + (squareToPosition(d.from).y + dy);
str += " L " + (squareToPosition(d.to).x + dx) + " " + (squareToPosition(d.to).y + dy);
return str;
})
//.style("stroke", (d, i) => (i % 2) ? "steelblue" : "orange")
.style("stroke", "white")
.style("stroke-width", 7)
.style("stroke-linejoin", "round")
.style("fill", "none");
sel1.join("path")
.attr("class", "piece-move")
.attr("d", (d, i) => {
let str = {};
const dx = (i % 2) ? -2 : 2;
const dy = (i % 2) ? -2 : 2;
str = "M " + (squareToPosition(d.from).x + dx) + " " + (squareToPosition(d.from).y + dy);
str += " L " + (squareToPosition(d.to).x + dx) + " " + (squareToPosition(d.to).y + dy);
return str;
})
// .style("stroke", (d, i) => (i % 2) ? "steelblue" : "orange")
.style("stroke", (d, i) => colorOfPieces.get(d.piece + d.color))
.style("fill", (d, i) => colorOfPieces.get(d.piece + d.color))
.style("stroke-width", 5)
.style("stroke-linejoin", "round");
// .style("fill", "none");
// pieces from, to
const sel2 = d3.select(svg)
.selectAll("circle")
.data(dataArray);
sel2
.join("circle")
.attr("class", "piece-square from")
// .style("fill", (d, i) => (i % 2) ? "steelblue" : "orange")
.style("fill", (d, i) => colorOfPieces.get(d.piece + d.color))
.attr("cx", (d, i) => {
const dx = (i % 2) ? -2 : 2;
return squareToPosition(d.from).x + dx;
})
.attr("cy", (d, i) => {
const dy = (i % 2) ? -2 : 2;
return squareToPosition(d.from).y + dy;
})
.attr("r", 8);
sel2
.join("circle")
.attr("class", "piece-square to")
// .style("fill", (d, i) => d.captured ? ((i % 2) ? "orange" : "steelblue") : (i % 2) ? "steelblue" : "orange")
// .style("stroke", (d, i) => d.captured ? ((i % 2) ? "steelblue" : "orange") : "none")
.style("fill", (d, i) =>
d.captured ?
(d.color === "w" ? colorOfPieces.get(d.captured + "b") : colorOfPieces.get(d.captured + "b") )
: colorOfPieces.get(d.piece + d.color))
.style("stroke", (d, i) => d.captured ? colorOfPieces.get(d.piece + d.color) : "none")
.style("stroke-width", 6)
.attr("cx", (d, i) => {
const dx = (i % 2) ? -2 : 2;
return squareToPosition(d.to).x + dx;
})
.attr("cy", (d, i) => {
const dy = (i % 2) ? -2 : 2;
return squareToPosition(d.to).y + dy;
})
.attr("r", 8);
d3.select(svg).selectAll(".piece-move")
.filter((d,i) => !(d.from[0] === d.to[0] || d.from[1] === d.to[1]))
.style("filter","url(#glow)");
return svg;
}
Insert cell
function version5() {
const svg = drawChessboard({"white": "white", "black": "lightgrey"});
const dataArray = game1;
// paths
const sel1 = d3.select(svg)
.selectAll("path.piece-move")
.data(dataArray);
sel1.join("path")
.attr("class", "piece-move")
.attr("d", (d, i) => {
let str = {};
const dx = (i % 2) ? -2 : 2;
const dy = (i % 2) ? -2 : 2;
str = "M " + (squareToPosition(d.from).x + dx) + " " + (squareToPosition(d.from).y + dy);
str += " L " + (squareToPosition(d.to).x + dx) + " " + (squareToPosition(d.to).y + dy);
return str;
})
//.style("stroke", (d, i) => (i % 2) ? "steelblue" : "orange")
.style("stroke", "white")
.style("stroke-width", 7)
.style("stroke-linejoin", "round")
.style("fill", "none");
sel1.join("path")
.attr("class", "piece-move")
.attr("id", (d,i) => "move-" + i)
.attr("d", (d, i) => {
let str = {};
const dx = (i % 2) ? -2 : 2;
const dy = (i % 2) ? -2 : 2;
str = "M " + (squareToPosition(d.from).x + dx) + " " + (squareToPosition(d.from).y + dy);
str += " L " + (squareToPosition(d.to).x + dx) + " " + (squareToPosition(d.to).y + dy);
return str;
})
// .style("stroke", (d, i) => (i % 2) ? "steelblue" : "orange")
.style("stroke", (d, i) => colorOfPieces.get(d.piece + d.color))
.style("fill", (d, i) => colorOfPieces.get(d.piece + d.color))
.style("stroke-width", 5)
.style("stroke-linejoin", "round");
// .style("fill", "none");

sel1.join("text").append("textPath")
.attr("href", (d,i) => "#move-" + i)
.attr("text-anchor","middle")
.attr("startOffset","50%")
.text(d => d.san);
// pieces from, to
const sel2 = d3.select(svg)
.selectAll("circle")
.data(dataArray);
sel2
.join("circle")
.attr("class", "piece-square from")
// .style("fill", (d, i) => (i % 2) ? "steelblue" : "orange")
.style("fill", (d, i) => colorOfPieces.get(d.piece + d.color))
.attr("cx", (d, i) => {
const dx = (i % 2) ? -2 : 2;
return squareToPosition(d.from).x + dx;
})
.attr("cy", (d, i) => {
const dy = (i % 2) ? -2 : 2;
return squareToPosition(d.from).y + dy;
})
.attr("r", 8);
sel2
.join("circle")
.attr("class", "piece-square to")
// .style("fill", (d, i) => d.captured ? ((i % 2) ? "orange" : "steelblue") : (i % 2) ? "steelblue" : "orange")
// .style("stroke", (d, i) => d.captured ? ((i % 2) ? "steelblue" : "orange") : "none")
.style("fill", (d, i) =>
d.captured ?
(d.color === "w" ? colorOfPieces.get(d.captured + "b") : colorOfPieces.get(d.captured + "b") )
: colorOfPieces.get(d.piece + d.color))
.style("stroke", (d, i) => d.captured ? colorOfPieces.get(d.piece + d.color) : "none")
.style("stroke-width", 6)
.attr("cx", (d, i) => {
const dx = (i % 2) ? -2 : 2;
return squareToPosition(d.to).x + dx;
})
.attr("cy", (d, i) => {
const dy = (i % 2) ? -2 : 2;
return squareToPosition(d.to).y + dy;
})
.attr("r", 8);
d3.select(svg).selectAll(".piece-move")
.filter((d,i) => !(d.from[0] === d.to[0] || d.from[1] === d.to[1]))
.style("filter","url(#glow)");
return svg;
}
Insert cell
function version6() {
const svg = drawChessboard({"white": "white", "black": "lightgrey"});
const dataArray = game1;
// paths
const sel1 = d3.select(svg)
.selectAll("path.piece-move")
.data(dataArray);
sel1.join("path")
.attr("class", "piece-move")
.attr("d", (d, i) => {
let str = {};
const dx = (i % 2) ? -2 : 2;
const dy = (i % 2) ? -2 : 2;
str = "M " + (squareToPosition(d.from).x + dx) + " " + (squareToPosition(d.from).y + dy);
str += " L " + (squareToPosition(d.to).x + dx) + " " + (squareToPosition(d.to).y + dy);
return str;
})
//.style("stroke", (d, i) => (i % 2) ? "steelblue" : "orange")
.style("stroke", "white")
.style("stroke-width", 7)
.style("stroke-linejoin", "round")
.style("fill", "none");
sel1.join("path")
.attr("class", "piece-move")
.attr("id", (d,i) => "move-" + i)
.attr("d", (d, i) => {
let str = {};
const dx = (i % 2) ? -2 : 2;
const dy = (i % 2) ? -2 : 2;
str = "M " + (squareToPosition(d.from).x + dx) + " " + (squareToPosition(d.from).y + dy);
str += " L " + (squareToPosition(d.to).x + dx) + " " + (squareToPosition(d.to).y + dy);
return str;
})
// .style("stroke", (d, i) => (i % 2) ? "steelblue" : "orange")
.style("stroke", (d, i) => colorOfPieces.get(d.piece + d.color))
.style("fill", (d, i) => colorOfPieces.get(d.piece + d.color))
.style("stroke-width", 5)
.style("stroke-linejoin", "round");
// .style("fill", "none");

const pathText = sel1.join("text");
pathText.append("textPath")
.attr("href", (d,i) => "#move-" + i)
.attr("text-anchor","middle")
.attr("startOffset","50%")
.text(d => d.san);
pathText.attr("transform", rotate);
// pieces from, to
const sel2 = d3.select(svg)
.selectAll("circle")
.data(dataArray);
sel2
.join("circle")
.attr("class", "piece-square from")
// .style("fill", (d, i) => (i % 2) ? "steelblue" : "orange")
.style("fill", (d, i) => colorOfPieces.get(d.piece + d.color))
.attr("cx", (d, i) => {
const dx = (i % 2) ? -2 : 2;
return squareToPosition(d.from).x + dx;
})
.attr("cy", (d, i) => {
const dy = (i % 2) ? -2 : 2;
return squareToPosition(d.from).y + dy;
})
.attr("r", 8);
sel2
.join("circle")
.attr("class", "piece-square to")
// .style("fill", (d, i) => d.captured ? ((i % 2) ? "orange" : "steelblue") : (i % 2) ? "steelblue" : "orange")
// .style("stroke", (d, i) => d.captured ? ((i % 2) ? "steelblue" : "orange") : "none")
.style("fill", (d, i) =>
d.captured ?
(d.color === "w" ? colorOfPieces.get(d.captured + "b") : colorOfPieces.get(d.captured + "b") )
: colorOfPieces.get(d.piece + d.color))
.style("stroke", (d, i) => d.captured ? colorOfPieces.get(d.piece + d.color) : "none")
.style("stroke-width", 6)
.attr("cx", (d, i) => {
const dx = (i % 2) ? -2 : 2;
return squareToPosition(d.to).x + dx;
})
.attr("cy", (d, i) => {
const dy = (i % 2) ? -2 : 2;
return squareToPosition(d.to).y + dy;
})
.attr("r", 8);
d3.select(svg).selectAll(".piece-move")
.filter((d,i) => !(d.from[0] === d.to[0] || d.from[1] === d.to[1]))
.style("filter","url(#glow)");
return svg;
}
Insert cell
squareToPosition("d1")
Insert cell
rotate({from: "h1", to: "g4"})
Insert cell
squareToPosition("h1")
Insert cell
squareToPosition("g4")
Insert cell
function rotate(d) {
const xFrom = squareToPosition(d.from).x;
const xTo = squareToPosition(d.to).x;
if (xTo < xFrom) {
// const bbox = this.getBBox();
// const rx = bbox.x + bbox.width / 2;
// const ry = bbox.y + bbox.height / 2;
const rx = xTo + ((xFrom - xTo) / 2);
const yFrom = squareToPosition(d.from).y;
const yTo = squareToPosition(d.to).y;
const ry = (yTo > yFrom)
? yFrom + ((yTo - yFrom) / 2)
: yTo + ((yFrom - yTo) / 2);
console.log("rx: " + rx);
console.log("ry: " + ry);
return 'rotate(180 ' + rx + ' ' + ry + ')';
}
else {
return 'rotate(0)';
}
}
Insert cell
[...piecePositions.values()]
Insert cell
colorOfPieces = {
const myMap = new Map();
myMap.set("pw", "#9ecae1");
myMap.set("pb", "#3182bd");
myMap.set("rw", "#a1d99b");
myMap.set("rb", "#31a354");
myMap.set("nw", "#bdbdbd");
myMap.set("nb", "#636363");
myMap.set("bw", "#fdae6b");
myMap.set("bb", "#e6550d");
myMap.set("qw", "#bcbddc");
myMap.set("qb", "#756bb1");
myMap.set("kw", "#fc9272");
myMap.set("kb", "#de2d26");
return myMap;
}
Insert cell
colorOfPieces.get("qw")
Insert cell
testMap = {
return new Map().set({a: "a"}, "success");
}
Insert cell
testMap.get({a: "a"})
Insert cell
pos = squareToPosition("e4");
Insert cell
drawChessboard()
Insert cell
oldsquareColorWhite = "#030"
Insert cell
OldsquareColorBlack = "black"
Insert cell
myChess = require("chess.js")
Insert cell
{
const chess = new myChess();

// make some moves
chess.move('e4');
chess.move('e5');
chess.move('f4');

return chess.ascii();
}
Insert cell
Insert cell
anyPgn = {
let lichessAPI;
let ret;
if (window.location.search.length === 0) {
if (typeof object.message !== "undefined") {
lichessAPI = "https://lichess.org/game/export/" + object.message.substr(20, 8);
ret = d3.text(lichessAPI);
} else {
ret = object;
}
} else {
lichessAPI = "https://lichess.org/game/export/" + window.location.search.slice(-8);
ret = d3.text(lichessAPI);
}
return ret;
}
Insert cell
window.location.search.length

Insert cell
object
Insert cell
game1 = {
const chess = new myChess();
//chess.load_pgn(myPgn);
chess.load_pgn(anyPgn);
/*
// make some moves
chess.move('e4');
chess.move('c5');
chess.move('Nf3');
chess.move('Nc6');
chess.move('d4');
chess.move('cxd4');
*/
return chess.history({ verbose: true });
}
Insert cell
Insert cell
pieceMoves = {
const myMap = new Map();
// initialize
const pieces = ["wRa1", "wNb1", "wBc1", "wQd1", "wKe1", "wBf1", "wNg1", "wRh1",
"wPa2", "wPb2", "wPc2", "wPd2", "wPe2", "wPf2", "wPg2", "wPh2",
"bRa8", "bNb8", "bBc8", "bQd8", "bKe8", "bBf8", "bNg8", "bRh8",
"bPa7", "bPb7", "bPc7", "bPd7", "bPe7", "bPf7", "bPg7", "bPh7"
];
let obj, ar;
for (let p of pieces) {
ar = [];
obj = {"square": p.slice(-2), moves: 0.5, isCaptured: false,
hasCaptured: false, hasCapturedPiece: "", hasEval: 0, hasTimeSpent: 0};
ar.push(obj);
myMap.set(p, ar);
}
// populate with game moves
let value = {};
let newValue = {};
for (let move of game1) {
for (let [key, ar] of myMap) {
value = ar[ar.length - 1];
newValue = {};
if (value.isCaptured) continue; // piece does not exist any more
if (move.color !== key.charAt(0)) { // wrong color
if (move.to === value.square) {
value.isCaptured = true;
} else {
value.moves = value.moves + .5;
}
ar[ar.length - 1] = value;
myMap.set(key, ar);
} else { //same color
if (move.from === value.square) {
Object.assign(newValue, obj);
newValue.square = move.to;
if (move.captured) {
newValue.hasCaptured = true;
newValue.hasCapturedPiece = move.captured.toUpperCase();
}
ar.push(newValue);
} else {
value.moves = value.moves + .5;
ar[ar.length - 1] = value;
}
myMap.set(key, ar);
}
} // end for .. myMap
} // end for .. game1
return myMap;
}
Insert cell
Insert cell
a = [...piecePositions.values()]
Insert cell
Insert cell
squareToPosition("e4")
Insert cell
function drawChessboard( squareColors = {white: "#030", black: "black"}) {
const squareColorWhite = squareColors.white;
const squareColorBlack = squareColors.black;
const squareTotal = squareWidth + squarePadding;
const w = squareTotal * 8 + squarePadding;
// const svg = DOM.svg(600, 600);
const svg = DOM.svg(w, w);
// specify defs
const defs = d3.select(svg)
.append("defs");
const filter = defs.append("filter")
// .attr("filterUnits", "userSpaceOnUse")
.attr("id","glow");

filter.append("feGaussianBlur")
.attr("class", "blur")
.attr("stdDeviation","4.5")
.attr("result","coloredBlur");

const feMerge = filter.append("feMerge");
feMerge.append("feMergeNode")
.attr("in","coloredBlur");
feMerge.append("feMergeNode")
.attr("in","SourceGraphic");
/*
<defs>
<filter id="f1" x="0" y="0">
<feGaussianBlur in="SourceGraphic" stdDeviation="15" />
</filter>
</defs>
.attr("id", "f1")
//.attr("x", "0")
//.attr("y", "0")
.append("feGaussianBlur")
.attr("in", "SourceGraphic")
.attr("stdDeviation", "15");
*/
d3.select(svg).append("rect")
.style("fill",squareColorBlack)
.attr("width", w)
.attr("height", w);
const numSquares = d3.range(64);
// draw squares
d3.select(svg)
.append("g")
.attr("transform", "translate(" + squarePadding + ", " + squarePadding + ")")
.selectAll("rect.square")
.data(numSquares)
.join("rect")
.attr("class", "square")
.style("fill", d => (d % 16 < 8) ? ((d % 2) ? squareColorBlack : squareColorWhite)
: (!(d % 2) ? squareColorBlack : squareColorWhite))
.style("stroke", "none")
.attr("x", d => (d % 8) * squareTotal)
.attr("y", d => Math.floor(d / 8) * squareTotal)
.attr("width", squareWidth)
.attr("height", squareWidth);
return svg;
}
Insert cell
function drawChessboard2() {
const squareTotal = squareWidth + squarePadding;
const w = squareTotal * 8 + squarePadding;
const svg = DOM.svg(600, 600);
d3.select(svg).append("rect")
.style("fill",squareColorBlack)
.attr("width", w)
.attr("height", w);
// Compute various radii 128, 120, 112, 104 etc.
const numSquares = d3.range(64);
// draw squares
d3.select(svg)
.append("g")
.attr("class", "chess-translate")
.attr("transform", "translate(" + squarePadding + ", " + squarePadding + ")")
.selectAll("rect.square")
.data(numSquares)
.join("rect")
.attr("class", "square")
.style("fill", d => (d % 16 < 8) ? ((d % 2) ? squareColorBlack : squareColorWhite)
: (!(d % 2) ? squareColorBlack : squareColorWhite))
.style("stroke", "none")
.attr("x", d => (d % 8) * squareTotal)
.attr("y", d => Math.floor(d / 8) * squareTotal)
.attr("width", squareWidth)
.attr("height", squareWidth)
;
return svg;
}
Insert cell
viewof color = html`<input type="color" value="#0000ff">`
Insert cell
Insert cell
viewof value = html`<input type=range>`
Insert cell
value
Insert cell
Insert cell
Insert cell
Insert cell
import {textarea} from "@jashkenas/inputs"
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more