Skip to content

What is Charming?

Charming (or Charming.js) is a free, open-source JavaScript library that creates animated and interactive SVG. Charming lets you create dynamic and expressive generative art and visualizations effortlessly. Here's a quick example that give you a sense of Charming:

js
const app = cm.render({
  width: 200,
  height: 50,
  loop: true,
  draw: () => [
    SVG.circle({
      cx: Math.abs(Math.sin(Date.now() / 1000) * 200),
      cy: 25,
      r: 20,
      stroke: "red",
      strokeWidth: 4,
    }),
  ],
});

document.body.append(app.node());

Based on SVG

Charming provides a tagged template literal for building SVG with interpolated attributes. For example, to create a white circle on a black background:

js
const app = cm.render({
  width: 100,
  height: 100,
  draw: () => [
    SVG.rect({x: 0, y: 0, width: 100, height: 100, fill: "black"}),
    SVG.circle({cx: 50, cy: 50, r: 40, fill: "white"}),
  ],
});

document.body.append(app.node());

Please refer to Charming Render for more information.

Fluid Transition

Charming makes it easier than ever to create fluid transitions. The exported transition decorators lets you apply transitions declaratively to child nodes, whether SVG or HTML. For example, you can create a circle that smoothly change colors and radius over time.

js
play = Inputs.button("Replay");
js
const app = cm.render({
  width: 100,
  height: 100,
  draw: () => [
    SVG.rect({x: 0, y: 0, width: 100, height: 100, fill: "black"}),
    SVG.circle({
      cx: 50,
      cy: 50,
      r: 40,
      fill: "#4B68C9",
      decorators: [
        {
          type: cm.transition,
          keyframes: [
            {attr: {fill: "#E5B442", r: 0}, duration: 1000},
            {attr: {fill: "#EE7A64", r: 40}, duration: 2000},
          ],
        },
      ],
    }),
  ],
});

document.body.append(app.node());

Incremental Updates

Work in progress.

js
const width = 600;
const height = 150;
let x = width / 2;
let y = height / 2;

const app = cm.render({
  width: 600,
  height: 150,
  loop: true,
  draw: () => {
    x += cm.random(-1, 1);
    y += cm.random(-1, 1);
    x = cm.constrain(x, 0, width);
    y = cm.constrain(y, 0, height);
    return [SVG.circle({cx: x, cy: y, fill: "black", r: 20})];
  },
});

document.body.append(app.node());

Reactivity for Interaction

js
const state = cm.state({clicked: false});

const app = cm.render({
  width: 100,
  height: 100,
  styleBackground: "black",
  draw: () => [
    SVG.circle({
      cx: 50,
      cy: 50,
      r: 40,
      fill: state.clicked ? "red" : "white",
      styleCursor: "pointer",
      onClick: () => (state.clicked = !state.clicked),
    }),
  ],
});

document.body.append(app.node());

A Collection of Tools

Charming provides a set of modular tools that you can use together or independently. For example,

Built on and learn with D3

Charming is built with D3 and integrates seamlessly with it. It simplifies D3's complexity, making it more accessible and easier to learn.