How to Make a D3 Chart in Astrology

An astrology wheel is a polar chart. D3 already has pie and arc. Here's the drawing half, with fake planet positions on purpose.

D3 Astrology Examples
← All posts
How to Make a D3 Chart in Astrology

How to make a D3 chart in astrology is, as a programming problem, a labeled ring. Twelve signs, equal width, planets sitting at ecliptic longitudes. I don't cast charts. I do know how to draw a circle that other people insist on calling a wheel.

The preview uses fake planet positions so we can talk about the SVG. Plug in numbers from an ephemeris when you have them. If you wanted a normal dashboard chart instead, start from D3 graph examples or the D3.js page.

The drawing problem, not the sky

Astrology software has two halves. One half computes where the planets were. The other half paints a wheel. D3 is the second half. Mixing them in one file is how you get a 400-line script nobody can debug.

A natal chart as drawn in the West often puts the Ascendant on the left. This example puts 0° Aries at the top because the math is obvious: longitude 0 lives at 12 o'clock. Rotate the whole group when you want the house cusps to match a printed chart.

A D3 astrology wheel

Twelve slices from d3.pie with value: 1 so they're equal. Planet marks are circles on a smaller radius. Abbreviations around the rim are the first three letters of each sign, not glyphs. Glyphs are a font problem, not a D3 problem.

Preview

The code

d3.pie already lives in the polar world. You don't need a custom layout. Longitude to x/y is high-school trigonometry. The - 90 is so 0° sits at the top of the SVG, not at 3 o'clock.

Code

const signs = ["Aries", "Taurus", "Gemini", "Cancer", "Leo", "Virgo",
  "Libra", "Scorpio", "Sagittarius", "Capricorn", "Aquarius", "Pisces"];

const pie = d3.pie().value(() => 1).sort(null);
const arc = d3.arc().innerRadius(132).outerRadius(168);

svg.append("g")
  .attr("transform", "translate(210,210)")
  .selectAll("path")
  .data(pie(signs.map((name) => ({ name }))))
  .join("path")
  .attr("d", arc);

function xy(longitude, r) {
  const a = ((longitude - 90) * Math.PI) / 180;
  return [210 + r * Math.cos(a), 210 + r * Math.sin(a)];
}

const [x, y] = xy(42, 96); // Sun at 42° ecliptic longitude
svg.append("circle").attr("cx", x).attr("cy", y).attr("r", 7);

Real planet positions

For actual longitudes you want an ephemeris (Swiss Ephemeris and ports of it are the usual path), plus a birth time and a lat/long. That's outside D3. Feed this wheel an array of { name, lon } and stop there.

Aspect lines are just line segments between those points. Houses are another pie, inner radius smaller, if you want them. I would not compute Placidus in the render function.

Polar charts that aren't zodiacs — skill wheels, wind roses — use the same pie + arc setup. The sankey and map posts cover the layouts that don't fit on a circle.

Questions I get

How do I make a D3 chart in astrology?

Treat the natal wheel as a polar chart. Twelve equal slices are a pie with value 1. Planet positions are ecliptic longitudes you plot on a circle with sine and cosine. D3 draws the wheel; an ephemeris library gives real longitudes.

Does this calculate my natal chart?

No. The planet marks in the example are hardcoded. A real chart needs birth time, place, and an ephemeris. This post is the drawing step.

Should astrology charts use D3 or a canvas library?

D3 is a good fit because the wheel is SVG arcs and text. Canvas is fine if you paint a lot of aspect lines. I would not start with Chart.js; it does not think in zodiac degrees.

Latest posts

All posts

Cytoscape JS Examples

Cytoscape JS examples are node-link graphs, not bar charts. Here are four I actually paste: force, hierarchy, circle, and tap to highlight.

Cytoscape Examples Networks
Read post

Bar Charts Explained

A bar is a number you can compare at a glance. Here's when to use one, the four layouts I actually ship, and the mistakes that make a bar chart lie.

Charts Examples JavaScript
Read post