docs: function( id, el, opts ){
  
              /** belongs to: CanvasRenderer
               * class Layer
               *
               * A rendering layer for the canvas renderer.
               *
               * Create by calling [[CanvasRenderer#addLayer]].
               **/
  
              var self = this
                  ,bodies = []
                  ,styles = Physics.util.extend({}, this.options.styles)
                  ,layer = {
                      /**
                       * Layer#id = String
                       *
                       * The layer's ID
                       **/
                      id: id
                      /**
                       * Layer#el = HTMLElement
                       *
                       * The layer's Canvas
                       **/
                      ,el: el || document.createElement('canvas')
                      /** related to: Physics.util.options
                        * Layer#options( options ) -> Object
                        * - options (Object): The options to set as an object
                        * + (Object): The options
                        *
                        * Set options on this layer.
                        *
                        * Access options directly from the options object.
                        *
                        * Example:
                        *
                        * ```javascript
                        * this.options.someOption;
                        * ```
                        **/
                      ,options: Physics.util.options({
                          width: this.el.width
                          ,height: this.el.height
                          ,manual: false
                          ,autoResize: true
                          ,follow: null
                          ,offset: null
                          ,scale: 1
                          ,zIndex: 1
                      })( opts )
                  }
                  ;
  
              if ( id in this._layers ){
                  throw 'Layer "' + id + '" already added.';
              }
  
              this.el.parentNode.insertBefore( layer.el, this.el );
              layer.el.style.position = 'absolute';
              layer.el.style.zIndex = layer.options.zIndex;
              layer.el.className += ' pjs-layer-' + layer.id;
              layer.ctx = layer.el.getContext('2d');
              layer.ctx.scale( 1, 1 );
              layer.el.width = layer.options.width;
              layer.el.height = layer.options.height;
  
              /**
               * Layer#bodies = Array
               *
               * The Bodies this layer is rendering.
               *
               * The "main" layer will render all world bodies if it's empty.
               **/
              layer.bodies = bodies;
  
              /**
               * Layer#reset( [arr] ) -> this
               * - arr (Array): Array to replace the current stack of Bodies.
               *
               * Reset the stack.
               **/
              layer.reset = function( arr ){
  
                  bodies = arr || [];
                  return layer;
              };
  
              /**
               * Layer#addToStack( arr ) -> this
               * Layer#addToStack( body ) -> this
               * - body (Body): Body to add
               * - arr (Array): Array of bodies to add
               *
               * Add body (bodies) to the rendering stack for this layer.
               *
               * Bodies must be added to the stack in order to be rendered by this layer UNLESS it is the "main" layer.
               **/
              layer.addToStack = function( thing ){
  
                  if ( Physics.util.isArray( thing ) ){
                      bodies.push.apply( bodies, thing );
                  } else {
                      bodies.push( thing );
                  }
                  return layer;
              };
  
              /**
               * Layer#removeFromStack( arr ) -> this
               * Layer#removeFromStack( body ) -> this
               * - body (Body): Body to remove
               * - arr (Array): Array of bodies to remove
               *
               * Remove body (bodies) from the rendering stack for this layer.
               **/
              layer.removeFromStack = function( thing ){
  
                  var i, l;
  
                  if ( Physics.util.isArray( thing ) ){
                      for ( i = 0, l = thing.length; i < l; ++i ){
                          layer.removeFromStack(thing[ i ]);
                      }
                  } else {
                      i = Physics.util.indexOf( bodies, thing );
                      if ( i > -1 ){
                          bodies.splice( i, 1 );
                      }
                  }
                  return layer;
              };
  
              /**
               * Layer#render( [clear] ) -> this
               * - clear (Boolean): Clear the canvas (default: `true`)
               *
               * Render the bodies in this layer's stack.
               *
               * If you want you can replace this function with your own to do custom rendering.
               *
               * Example:
               *
               * ```javascript
               * layer.render = myCustomRenderFn;
               * ```
               **/
              layer.render = function( clear ){
  
                  var body
                      ,scratch = Physics.scratchpad()
                      ,offset = scratch.vector().set(0, 0)
                      ,scale = layer.options.scale
                      ,view
                      ,i
                      ,l = bodies.length
                      ,t = self._interpolateTime
                      ,stack = (l || layer.id !== 'main') ? bodies : self._world._bodies
                      ;
  
                  if ( layer.options.manual ){
                      scratch.done();
                      return layer;
                  }
  
                  if ( layer.options.offset ){
                      if ( layer.options.offset === 'center' ){
                          offset.add( layer.el.width * 0.5, layer.el.height * 0.5 ).mult( 1/scale );
                      } else {
                          offset.vadd( layer.options.offset ).mult( 1/scale );
                      }
                  }
  
                  if ( layer.options.follow ){
                      offset.vsub( layer.options.follow.state.pos );
                      offset.sub( layer.options.follow.state.vel.get(0)*t, layer.options.follow.state.vel.get(1)*t );
                  }
  
                  if ( clear !== false ){
                      layer.ctx.clearRect(0, 0, layer.el.width, layer.el.height);
                  }
  
                  if ( scale !== 1 ){
                      layer.ctx.save();
                      layer.ctx.scale( scale, scale );
                  }
  
                  for ( i = 0, l = stack.length; i < l; ++i ){
  
                      body = stack[ i ];
                      if ( !body.hidden ){
                          view = body.view || ( body.view = self.createView(body.geometry, body.styles || styles[ body.geometry.name ]) );
                          self.drawBody( body, body.view, layer.ctx, offset );
                      }
                  }
  
                  if ( scale !== 1 ){
                      layer.ctx.restore();
                  }
  
                  scratch.done();
                  return layer;
              };
  
              // remember layer
              this._layers[ id ] = layer;
  
              return layer;
          }