Shapes in JavaScript

How to make arbitrary D3.js-based SVG shapes in JavaScript. Examples of lines, circle, rectangle, and path.


New to Plotly?

Plotly is a free and open-source graphing library for JavaScript. We recommend you read our Getting Started guide for the latest installation or upgrade instructions, then move on to our Plotly Fundamentals tutorials or dive straight in to some Basic Charts tutorials.

var data = [
  {
    x: ['2015-02-01', '2015-02-02', '2015-02-03', '2015-02-04', '2015-02-05',
        '2015-02-06', '2015-02-07', '2015-02-08', '2015-02-09', '2015-02-10',
        '2015-02-11', '2015-02-12', '2015-02-13', '2015-02-14', '2015-02-15',
        '2015-02-16', '2015-02-17', '2015-02-18', '2015-02-19', '2015-02-20',
        '2015-02-21', '2015-02-22', '2015-02-23', '2015-02-24', '2015-02-25',
        '2015-02-26', '2015-02-27', '2015-02-28'],
    y: [-14, -17, -8, -4, -7, -10, -12, -14, -12, -7, -11, -7, -18, -14, -14,
        -16, -13, -7, -8, -14, -8, -3, -9, -9, -4, -13, -9, -6],
    mode: 'line',
    name: 'temperature'
  }
];

var layout = {

    // to highlight the timestamp we use shapes and create a rectangular

    shapes: [
        // 1st highlight during Feb 4 - Feb 6
        {
            type: 'rect',
            // x-reference is assigned to the x-values
            xref: 'x',
            // y-reference is assigned to the plot paper [0,1]
            yref: 'paper',
            x0: '2015-02-04',
            y0: 0,
            x1: '2015-02-06',
            y1: 1,
            fillcolor: '#d3d3d3',
            opacity: 0.2,
            line: {
                width: 0
            }
        },

        // 2nd highlight during Feb 20 - Feb 23
        
        {
            type: 'rect',
            xref: 'x',
            yref: 'paper',
            x0: '2015-02-20',
            y0: 0,
            x1: '2015-02-22',
            y1: 1,
            fillcolor: '#d3d3d3',
            opacity: 0.2,
            line: {
                width: 0
            }
        }
    ],
    height: 500,
    width: 500
}

Plotly.newPlot('myDiv', data, layout);
Click to copy
Feb 12015Feb 8Feb 15Feb 22−18−16−14−12−10−8−6−4
function normal_array( mean, stddev, size ){
    var arr = new Array(size), i;
    // from http://bl.ocks.org/nrabinowitz/2034281
    var generator = (function() {
        return d3.random.normal(mean, stddev);
    }());

    for( i=0; i< arr.length; i++ ){
        arr[i] = generator();
    }
    return arr;
}

var x0 = normal_array(2, 0.45, 300);
var y0 = normal_array(2, 0.45, 300);

var x1 = normal_array(6, 0.4, 200);
var y1 = normal_array(6, 0.4, 200)

var x2 = normal_array(4, 0.3, 200);
var y2 = normal_array(4, 0.3, 200);

console.log(x0);

var data = [
    {
        x: x0,
        y: y0,
        mode: 'markers'
    }, {
        x: x1,
        y: y1,
        mode: 'markers'
    }, {
        x: x2,
        y: y2,
        mode: 'markers'
    }, {
        x: x1,
        y: y0,
        mode: 'markers'
    }
];

var layout = {
    shapes: [
        {
            type: 'circle',
            xref: 'x',
            yref: 'y',
            x0: d3.min(x0),
            y0: d3.min(y0),
            x1: d3.max(x0),
            y1: d3.max(y0),
            opacity: 0.2,
            fillcolor: 'blue',
            line: {
                color: 'blue'
            }
        },
        {
            type: 'circle',
            xref: 'x',
            yref: 'y',
            x0: d3.min(x1),
            y0: d3.min(y1),
            x1: d3.max(x1),
            y1: d3.max(y1),
            opacity: 0.2,
            fillcolor: 'orange',
            line: {
                color: 'orange'
            }
        },
        {
            type: 'circle',
            xref: 'x',
            yref: 'y',
            x0: d3.min(x2),
            y0: d3.min(y2),
            x1: d3.max(x2),
            y1: d3.max(y2),
            opacity: 0.2,
            fillcolor: 'green',
            line: {
                color: 'green'
            }
        },
        {
            type: 'circle',
            xref: 'x',
            yref: 'y',
            x0: d3.min(x1),
            y0: d3.min(y0),
            x1: d3.max(x1),
            y1: d3.max(y0),
            opacity: 0.2,
            fillcolor: 'red',
            line: {
                color: 'red'
            }
        }
    ],
    height: 400,
    width: 480,
    showlegend: false
}

Plotly.newPlot('myDiv', data, layout);
Click to copy
var trace1 = {
  x: [2, 3.5, 6],
  y: [1, 1.5, 1],
  text: ['Vertical Line', 'Horizontal Dashed Line', 'Diagonal dotted Line'],
  mode: 'text'
};

var layout = {
  title: {
    text: 'Vertical and Horizontal Lines Positioned Relative to the Axes'
  },
  xaxis: {
    range: [0, 7]
  },
  yaxis: {
    range: [0, 2.5]
  },
  width: 500,
  height: 500,
  shapes: [

    //line vertical

    {
      type: 'line',
      x0: 1,
      y0: 0,
      x1: 1,
      y1: 2,
      line: {
        color: 'rgb(55, 128, 191)',
        width: 3
      }
    },

    //Line Horizontal

    {
      type: 'line',
      x0: 2,
      y0: 2,
      x1: 5,
      y1: 2,
      line: {
        color: 'rgb(50, 171, 96)',
        width: 4,
        dash: 'dashdot'
      }
    },

    //Line Diagonal

    {
      type: 'line',
      x0: 4,
      y0: 0,
      x1: 6,
      y1: 2,
      line: {
        color: 'rgb(128, 0, 128)',
        width: 4,
        dash: 'dot'
      }
    }
  ]
};

var data = [trace1];

Plotly.newPlot('myDiv', data, layout);
Click to copy
Vertical LineHorizontal Dashed LineDiagonal dotted Line024600.511.522.5
Vertical and Horizontal Lines Positioned Relative to the Axes
var trace1 = {
  x: [1.5, 3.5],
  y: [0.75, 2.5],
  text: ['Unfilled Circle', 'Filled Circle'],
  mode: 'text'
};

var layout = {
  title: {
    text: 'Circles'
  },
  xaxis: {
    range: [0, 4.5],
    zeroline: false
  },
  yaxis: {
    range: [0, 4.5]
  },
  width: 500,
  height: 500,
  shapes: [

    // Unfilled Circle

    {
      type: 'circle',
      xref: 'x',
      yref: 'y',
      x0: 1,
      y0: 1,
      x1: 3,
      y1: 3,
      line: {
        color: 'rgba(50, 171, 96, 1)'
      }
    },

    // Filled Circle

    {
      type: 'circle',
      xref: 'x',
      yref: 'y',
      fillcolor: 'rgba(50, 171, 96, 0.7)',
      x0: 3,
      y0: 3,
      x1: 4,
      y1: 4,
      line: {
        color: 'rgba(50, 171, 96, 1)'
      }
    }
  ]
};

var data = [trace1];

Plotly.newPlot('myDiv', data, layout);
Click to copy
Unfilled CircleFilled Circle0123401234
Circles
var trace1 = {
  x: [1.5, 3],
  y: [2.5, 2.5],
  text: ['Rectangle reference to the plot', 'Rectangle reference to the axes'],
  mode: 'text'
};

var layout = {
  title: {
    text: 'Rectangles Positioned Relative to the Plot and to the Axes'
  },
  xaxis: {
    range: [0, 4],
    showgrid: false
  },
  yaxis: {
    range: [0, 4]
  },
  width: 800,
  height: 600,
  shapes: [

    //Rectangle reference to the axes

    {
      type: 'rect',
      xref: 'x',
      yref: 'y',
      x0: 2.5,
      y0: 0,
      x1: 3.5,
      y1: 2,
      line: {
        color: 'rgb(55, 128, 191)',
        width: 3
      },
      fillcolor: 'rgba(55, 128, 191, 0.6)'
    },

    //Rectangle reference to the Plot

    {
      type: 'rect',
      xref: 'paper',
      yref: 'paper',
      x0: 0.25,
      y0: 0,
      x1: 0.5,
      y1: 0.5,
      line: {
        color: 'rgb(50, 171, 96)',
        width: 3
      },
      fillcolor: 'rgba(50, 171, 96, 0.6)'
    }
  ]
};

var data = [trace1];

Plotly.newPlot('myDiv', data, layout);
Click to copy
Rectangle reference to the plotRectangle reference to the axes00.511.522.533.5400.511.522.533.54
Rectangles Positioned Relative to the Plot and to the Axes
var trace1 = {
  x: [1.5, 4.5],
  y: [0.75, 0.75],
  text: ['Unfilled Rectangle', 'Filled Rectangle'],
  mode: 'text'
};

var layout = {
  title: {
    text: 'Rectangle Positioned Relative to the Axes'
  },
  xaxis: {
    range: [0, 7],
    showgrid: false
  },
  yaxis: {
    range: [0, 3.5]
  },
  width: 500,
  height: 500,
  shapes: [

    //Unfilled Rectangle

    {
      type: 'rect',
      x0: 1,
      y0: 1,
      x1: 2,
      y1: 3,
      line: {
        color: 'rgba(128, 0, 128, 1)'
      }
    },

    //Filled Rectangle

    {
      type: 'rect',
      x0: 3,
      y0: 1,
      x1: 6,
      y1: 2,
      line: {
        color: 'rgba(128, 0, 128, 1)',
        width: 2
      },
      fillcolor: 'rgba(128, 0, 128, 0.7)'
    }
  ]
};

var data = [trace1];

Plotly.newPlot('myDiv', data, layout);
Click to copy
Unfilled RectangleFilled Rectangle024600.511.522.533.5
Rectangle Positioned Relative to the Axes
var trace1 = {
  x: [2, 6],
  y: [1, 1],
  text: ['Line positioned relative to the plot', 'Line positioned relative to the axes'],
  mode: 'text'
};

var layout = {
  title: {
    text: 'Lines Positioned Relative to the Plot & to the Axes'
  },
  xaxis: {
    range: [0, 8]
  },
  yaxis: {
    range: [0, 2]
  },
  width: 500,
  height: 500,
  shapes: [

    //Line reference to the axes

    {
      type: 'line',
      xref: 'x',
      yref: 'y',
      x0: 4,
      y0: 0,
      x1: 8,
      y1: 1,
      line: {
        color: 'rgb(55, 128, 191)',
        width: 3
      }
    },

    //Line reference to the plot

    {
      type: 'line',
      xref: 'paper',
      yref: 'paper',
      x0: 0,
      y0: 0,
      x1: 0.5,
      y1: 0.5,
      line: {
        color: 'rgb(50, 171, 96)',
        width: 3
      }
    }
  ]
};

var data = [trace1];

Plotly.newPlot('myDiv', data, layout);
Click to copy
Line positioned relative to the plotLine positioned relative to the axes0246800.511.52
Lines Positioned Relative to the Plot & to the Axes
var trace1 = {
  x: [2, 1, 8, 8],
  y: [0.25, 9, 2, 6],
  text: ['filled triangle', 'filled Polygon', 'Quadratic Bezier Curves', 'Cubic Bezier Curves'],
  mode: 'text'
};

var layout = {
  title: {
    text: 'Basic Arbitrary SVG Paths'
  },
  xaxis: {
    range: [0, 9],
    zeroline: false
  },
  yaxis: {
    range: [0, 11],
    showgrid: false
  },
  width: 500,
  height: 500,
  shapes: [

    //Quadratic Bezier Curves

    {
      type: 'path',
      path: 'M 4,4 Q 6,0 8,4',
      line: {
        color: 'rgb(93, 164, 214)'
      }
    },

    //Cubic Bezier Curves

    {
      type: 'path',
      path: 'M 1,4 C 2,8 6,4 8,8',
      line: {
        color: 'rgb(207, 114, 255)'
      }
    },

    //Filled Triangle

    {
      type: 'path',
      path: 'M 1 1 L 1 3 L 4 1 Z',
      fillcolor: 'rgba(44, 160, 101, 0.5)',
      line: {
        color: 'rgb(44, 160, 101)'
      }
    },

    //Filled Polygon

    {
      type: 'path',
      path: ' M 3,7 L2,8 L2,9 L3,10, L4,10 L5,9 L5,8 L4,7 Z',
      fillcolor: 'rgba(255, 140, 184, 0.5)',
      line: {
        color: 'rgb(255, 140, 184)'
      }
    }
  ]
};

var data = [trace1];

Plotly.newPlot('myDiv', data, layout);
Click to copy
filled trianglefilled PolygonQuadratic Bezier CurvesCubic Bezier Curves024680246810
Basic Arbitrary SVG Paths
var trace1 = {
  x: [1, 1.75, 2.5],
  y: [1, 1, 1],
  type: 'scatter',
  mode: 'text',
  text: ['A', 'A+B', 'B'],
  textfont: {
    color: 'black',
    size: 18,
    family: 'Arial'
  }
};

var layout = {
  title: {
    text: 'Venn Diagram with Circle Shapes'
  },
  xaxis: {
    showticklabels: false,
    tickmode: 'linear',
    showgrid: false,
    zeroline: false
  },
  yaxis: {
    showticklabels: false,
    tickmode: 'linear',
    showgrid: false,
    zeroline: false
  },
  shapes: [{
    opacity: 0.3,
    xref: 'x',
    yref: 'y',
    fillcolor: 'blue',
    x0: 0,
    y0: 0,
    x1: 2,
    y1: 2,
    type: 'circle',
    line: {
      color: 'blue'
    }
  }, {
    opacity: 0.3,
    xref: 'x',
    yref: 'y',
    fillcolor: 'gray',
    x0: 1.5,
    y0: 0,
    x1: 3.5,
    y1: 2,
    type: 'circle',
    line: {
      color: 'gray'
    }
  }],
  margin: {
    l: 20,
    r: 20,
    b: 100
  },
  height: 500,
  width: 500
};

var data = [trace1];

Plotly.newPlot('myDiv', data, layout);
Click to copy
AA+BB
Venn Diagram with Circle Shapes
function linspace(a,b,n) {
  return d3.range(n).map(function(i){return a+i*(b-a)/(n-1);});
}

var xValues = linspace(1, 3, 200);

var yValues = [];

for ( var i = 0 ; i < xValues.length ; i++ ) {
  var result = xValues[i] * Math.sin(Math.pow(xValues[i], 2)) + 1;
  yValues.push(result);
};

var trace1 = {
  x: xValues,
  y: yValues,
  type: 'scatter'
};

var data = [trace1];

var layout = {
  title: {
    text: 'Rectangles Positioned Relative to the Plot and to the Axes'
  },
  shapes: [{
    type: 'line',
    x0: 1,
    y0: 2.30756,
    x1: 1.75,
    y1: 2.30756,
    opacity: 0.7,
    line: {
      color: 'red',
      width: 2.5
    }
  }, {
    type: 'line',
    x0: 2.5,
    y0: 3.80796,
    x1: 3.05,
    y1: 3.80796,
    opacity: 0.7,
    line: {
      color: 'red',
      width: 2.5
    }
  }, {
    type: 'line',
    x0: 1.90,
    y0: -1.1827,
    x1: 2.50,
    y1: -1.1827,
    opacity: 0.7,
    line: {
      color: 'red',
      width: 2.5
    }
  }],
  height: 500,
  width: 500
};

Plotly.newPlot('myDiv', data, layout);
Click to copy
11.522.53−101234
Rectangles Positioned Relative to the Plot and to the Axes

This example adds a label to a rectangle and a line on the graph, sets a font size and color on the rectangle, and positions its label 'top center' using textposition. On the line, we specify a yanchor of "top" to anchor the top of the label to its textposition. You can also draw new shapes on the graph and each new shape automatically gets a text label.

var data = [
  {
    x: [
      '2015-02-01', '2015-02-02', '2015-02-03', '2015-02-04', '2015-02-05',
      '2015-02-06', '2015-02-07', '2015-02-08', '2015-02-09', '2015-02-10',
      '2015-02-11', '2015-02-12', '2015-02-13', '2015-02-14', '2015-02-15',
      '2015-02-16', '2015-02-17', '2015-02-18', '2015-02-19', '2015-02-20',
      '2015-02-21', '2015-02-22', '2015-02-23', '2015-02-24', '2015-02-25',
      '2015-02-26', '2015-02-27', '2015-02-28',
    ],
    y: [
      14, 17, 8, 4, 7, 10, 12, 14, 12, 11, 10, 9, 18, 14, 14, 16, 13, 8, 8,
      7, 7, 3, 9, 9, 4, 13, 9, 6,
    ],
    mode: 'line',
  },
];

var layout = {
  title: {text: 'Product price changes and revenue growth'},
  xaxis: { title: {text: 'Date' }},
  yaxis: { title: {text: 'Revenue Growth' }},
  dragmode: 'drawline',

  shapes: [
    {
      type: 'rect',
      xref: 'x',
      yref: 'paper',
      x0: '2015-02-02',
      y0: 0,
      x1: '2015-02-08',
      y1: 1,
      fillcolor: '#d3d3d3',
      opacity: 0.2,
      editable: true,
      line: {
        width: 0,
      },
      label: {
        text: 'Price drop',
        font: { size: 10, color: 'green' },
        textposition: 'top center',
      },
    },
    {
      type: 'line',
      x0: '2015-02-01',
      y0: 8,
      x1: '2015-02-28',
      y1: 8,
      fillcolor: '#d3d3d3',
      opacity: 0.2,
      editable: true,
      label: {
        text: 'January average',
        yanchor: 'top',
      },
    },
  ],
  newshape: { label: { text: 'New shape text' } },
  height: 500,
  width: 500,
};

var config = { 'modeBarButtonsToAdd': [
  'drawline',
  'drawopenpath',
  'drawclosedpath',
  'drawcircle',
  'drawrect',
  'eraseshape'
  ]
};

Plotly.newPlot('myDiv', data, layout, config);
Click to copy
Feb 12015Feb 8Feb 15Feb 224681012141618
Price dropJanuary averageProduct price changes and revenue growthDateRevenue Growth