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);
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);
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);
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);
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);
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);
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);
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);
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);
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);

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);