Chess Board with Pieces for Position Diagrams — Apache ECharts

A chess board visualization with pieces that can be positioned programmatically to display specific game positions, puzzles, or notable games. Pieces are defined using a dictionary mapping squares (e.g., 'e4': 'K') to standard chess notation where uppercase letters represent white pieces (K/Q/R/B/N/P) and lowercase represent black pieces (k/q/r/b/n/p). Unicode chess symbols provide clean, recognizable piece rendering.

Chess Board with Pieces for Position Diagrams rendered with Apache ECharts

Renders

JavaScript source (Apache ECharts)

// anyplot.ai
// chessboard-pieces: Chess Board with Pieces for Position Diagrams
// Library: echarts 6.1.0 | JavaScript 22.23.2
// Quality: 92/100 | Created: 2026-09-01
//# anyplot-orientation: square

const t = window.ANYPLOT_TOKENS;

// --- Data (in-memory, deterministic) ----------------------------------------
// Scholar's Mate, final position after 1.e4 e5 2.Bc4 Nc6 3.Qh5 Nf6?? 4.Qxf7#
const FILES = ["a", "b", "c", "d", "e", "f", "g", "h"];
const RANKS = ["1", "2", "3", "4", "5", "6", "7", "8"];

const PIECES = {
  a1: "R", b1: "N", c1: "B", e1: "K", g1: "N", h1: "R", c4: "B", f7: "Q",
  a2: "P", b2: "P", c2: "P", d2: "P", e4: "P", f2: "P", g2: "P", h2: "P",
  a8: "r", c8: "b", d8: "q", e8: "k", f8: "b", h8: "r", c6: "n", f6: "n",
  a7: "p", b7: "p", c7: "p", d7: "p", e5: "p", g7: "p", h7: "p",
};

const PIECE_GLYPH = {
  K: "♔", Q: "♕", R: "♖", B: "♗", N: "♘", P: "♙",
  k: "♚", q: "♛", r: "♜", b: "♝", n: "♞", p: "♟",
};

// Chess white/black is a stronger real-world color convention than the
// abstract Imprint categorical order (Imprint semantic exception — see
// default-style-guide.md), so piece color stays a fixed ivory/ink pair
// independent of theme, exactly like the Imprint categorical hues stay
// constant across light/dark.
const PIECE_WHITE_FILL = "#F5F1E6";
const PIECE_WHITE_STROKE = "#1A1A17";
const PIECE_BLACK_FILL = "#1A1A17";
const PIECE_BLACK_STROKE = "#F5F1E6";

// Board squares: light square at h1, standard orientation (white at bottom).
// Both square tones are alpha-blends over the page background rather than a
// solid theme token, so the light/dark luminance ordering stays correct in
// both themes (a solid t.elevatedBg is nearly black in dark mode, which would
// read *darker* than the ochre-blended dark square). Dark squares use the
// Imprint ochre hue — the palette's documented "wood" semantic anchor.
const LIGHT_SQUARE = "rgba(245, 241, 230, 0.45)";
const DARK_SQUARE = "rgba(189, 130, 51, 0.45)";

// Checkmate emphasis: 4.Qxf7# — the queen delivers mate from f7, checking the
// king on e8. A soft amber outline on those two squares calls out the
// decisive move without adding chart junk (pieces + squares stay untouched).
const HIGHLIGHT_SQUARES = new Set(["f7", "e8"]);

const squares = [];
FILES.forEach((file, col) => {
  RANKS.forEach((rank, row) => {
    const isLight = (col + row) % 2 === 1;
    squares.push([file, rank, isLight ? 1 : 0]);
  });
});

const pieces = Object.keys(PIECES).map((square) => {
  const file = square[0];
  const rank = square[1];
  const code = PIECES[square];
  const isWhite = code === code.toUpperCase();
  return [file, rank, PIECE_GLYPH[code], isWhite ? 1 : 0];
});

const highlights = [...HIGHLIGHT_SQUARES].map((square) => [square[0], square[1]]);

// --- Init ---------------------------------------------------------------
const chart = echarts.init(document.getElementById("container"));

// --- Option ---------------------------------------------------------------
const title = "Scholar's Mate · chessboard-pieces · javascript · echarts · anyplot.ai";

chart.setOption({
  animation: false,
  backgroundColor: "transparent",
  title: {
    text: title,
    left: "center",
    top: 40,
    textStyle: { color: t.ink, fontSize: 21, fontWeight: 500 },
  },
  grid: {
    left: "center",
    top: 170,
    width: 900,
    height: 900,
    show: true,
    borderColor: t.inkSoft,
    borderWidth: 2,
    backgroundColor: "transparent",
  },
  xAxis: {
    type: "category",
    data: FILES,
    position: "bottom",
    axisLine: { show: false },
    axisTick: { show: false },
    splitLine: { show: false },
    axisLabel: { color: t.inkSoft, fontSize: 22, margin: 20 },
  },
  yAxis: {
    type: "category",
    data: RANKS,
    axisLine: { show: false },
    axisTick: { show: false },
    splitLine: { show: false },
    axisLabel: { color: t.inkSoft, fontSize: 22, margin: 20 },
  },
  series: [
    {
      type: "custom",
      coordinateSystem: "cartesian2d",
      data: squares,
      renderItem: (params, api) => {
        const isLight = api.value(2) === 1;
        const center = api.coord([api.value(0), api.value(1)]);
        const size = api.size([1, 1]);
        return {
          type: "rect",
          shape: {
            x: center[0] - size[0] / 2,
            y: center[1] - size[1] / 2,
            width: size[0],
            height: size[1],
          },
          style: {
            fill: isLight ? LIGHT_SQUARE : DARK_SQUARE,
            stroke: t.grid,
            lineWidth: 1,
          },
          silent: true,
        };
      },
      z: 1,
    },
    {
      type: "custom",
      coordinateSystem: "cartesian2d",
      data: highlights,
      renderItem: (params, api) => {
        const center = api.coord([api.value(0), api.value(1)]);
        const size = api.size([1, 1]);
        const inset = Math.min(size[0], size[1]) * 0.06;
        return {
          type: "rect",
          shape: {
            x: center[0] - size[0] / 2 + inset,
            y: center[1] - size[1] / 2 + inset,
            width: size[0] - inset * 2,
            height: size[1] - inset * 2,
            r: inset,
          },
          style: {
            fill: "transparent",
            stroke: t.amber,
            lineWidth: 3,
          },
          silent: true,
        };
      },
      z: 2,
    },
    {
      type: "custom",
      coordinateSystem: "cartesian2d",
      data: pieces,
      renderItem: (params, api) => {
        const isWhite = api.value(3) === 1;
        const center = api.coord([api.value(0), api.value(1)]);
        const size = api.size([1, 1]);
        const fontSize = Math.min(size[0], size[1]) * 0.62;
        return {
          type: "text",
          style: {
            text: api.value(2),
            x: center[0],
            y: center[1],
            textAlign: "center",
            textVerticalAlign: "middle",
            fontSize,
            fontFamily: '"Noto Sans Symbols 2", "DejaVu Sans", "Segoe UI Symbol", sans-serif',
            fill: isWhite ? PIECE_WHITE_FILL : PIECE_BLACK_FILL,
            stroke: isWhite ? PIECE_WHITE_STROKE : PIECE_BLACK_STROKE,
            lineWidth: isWhite ? 2.5 : 1.2,
          },
          silent: true,
        };
      },
      z: 3,
    },
  ],
});

chart.on("finished", () => {
  window.__anyplotReady = true;
});

Retrieve this implementation

Runnable source as JSON, for any HTTP client: https://api.anyplot.ai/specs/chessboard-pieces/echarts/code. Any spec id and library id listed in llms-full.txt fit the same URL shape; every URL below is complete and callable.

{
  "spec_id": "chessboard-pieces",
  "language": "javascript",
  "library": "echarts",
  "page": "https://anyplot.ai/chessboard-pieces/javascript/echarts",
  "hub": "https://anyplot.ai/chessboard-pieces",
  "code_json": "https://api.anyplot.ai/specs/chessboard-pieces/echarts/code",
  "spec_json": "https://api.anyplot.ai/specs/chessboard-pieces",
  "render_light_png": "https://storage.googleapis.com/anyplot-images/plots/chessboard-pieces/javascript/echarts/plot-light.png",
  "render_dark_png": "https://storage.googleapis.com/anyplot-images/plots/chessboard-pieces/javascript/echarts/plot-dark.png",
  "interactive_light_html": "https://storage.googleapis.com/anyplot-images/plots/chessboard-pieces/javascript/echarts/plot-light.html",
  "interactive_dark_html": "https://storage.googleapis.com/anyplot-images/plots/chessboard-pieces/javascript/echarts/plot-dark.html",
  "quality_score": 92.0,
  "license": "MIT",
  "guide": "https://anyplot.ai/llms.txt"
}

Part of Chess Board with Pieces for Position Diagrams on anyplot.ai.

Other implementations