Symbols

Symbol generator

The symbol generator returns path data for a number of predefined symbol types (circle, square, triangle, star etc.) that can be associated with categories as in a scatterplot. Symbols are centered at the origin. You can use a transform to move the symbol to a desired position.

The next example appends two circles (type d3.symbolCircle) in two different ways. The size of the symbol refers to its area.


const svg = d3.select("svg")
  .attr("width", "100%")
  .attr("height", "100%")
  .attr("viewBox", `0 0 100 30`)

svg.append("path")
  .style('fill', "red")
  .attr("transform", "translate(10,15)")
  .attr("d", d3.symbol(d3.symbolCircle, 78.5))

svg.append("path")
  .style('fill', "green")
  .attr("transform", "translate(20,15)")
  .attr("d", d3.symbol()
    .type(d3.symbolCircle)
    .size(78.5) // radius = approx. 5
  )

Result:

Fill or stroke

Some symbols are designed for filling, other symbols are designed for stroking and only symbolCircle is designed for both filling and striking.

d3.symbolsFill returns an array containing a set of symbol types designed for filling. d3.symbolsStroke returns an array containing a set of symbol types designed for stroking. Both are useful for a categorical shape encoding with an ordinal scale.


const shapeScale = d3.scaleOrdinal(["a", "b", "c"], d3.symbolsFill);

svg.append("path")
    .attr("transform", "translate(20, 20)")
    .attr("d", d3.symbol(shapeScale("c")));

Next example shows all symbols:

symbolsFill:

symbolsStroke:


// Code for the symbolsFill figure above:

const margin = {top: 10, right: 40, bottom: 30, left: 40},
      width = 640,
      height = 60;		

const svg = d3.select("svg")
  .attr("width", "100%")
  .attr("height", "100%")
  .attr("viewBox", `0 0 ${width} ${height}`);		  

const symbolNames = [ "symbolCircle", "symbolCross", "symbolDiamond", "symbolSquare", "symbolStar", "symbolTriangle", "symbolWye" ];
const scaleX = d3.scalePoint()
  .domain(symbolNames)
  .range([margin.left, width - margin.right]);
const shapeScale = d3.scaleOrdinal(symbolNames, d3.symbolsFill);  

// Add X axis:
svg.append("g")
  .attr("transform", `translate(0,${height - margin.bottom})`)
  .call(d3.axisBottom(scaleX).tickPadding(10))
  .call(g => g.select(".domain").remove());

// Add symbols:  
svg
  .selectAll()
  .data(symbolNames)
  .join('path')
    .attr("transform", (d, i) => `translate(${scaleX(d)}, ${height - margin.bottom - 15})`)
    .attr("d", d => d3.symbol(shapeScale(d))())		
    .attr("stroke", "none")
    .attr("fill", "currentColor");