[{"description":"Creates a popup component","tags":[{"title":"class","description":null,"type":null,"name":"Popup"},{"title":"param","description":null,"type":{"type":"NameExpression","name":"Object"},"name":"options"},{"title":"param","description":null,"type":{"type":"NameExpression","name":"Boolean"},"name":"options.closeButton"},{"title":"param","description":null,"type":{"type":"NameExpression","name":"Boolean"},"name":"options.closeOnClick"},{"title":"example","description":"var tooltip = new mapboxgl.Popup()\n .setLatLng(map.unproject(e.point))\n .setHTML(\"
Hello World!
\")\n .addTo(map);"},{"title":"name","name":"Popup"},{"title":"kind","kind":"class"}],"context":{"loc":{"start":{"line":22,"column":0},"end":{"line":28,"column":1}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/popup.js","code":"'use strict';\n\nmodule.exports = Popup;\n\nvar util = require('../util/util');\nvar Evented = require('../util/evented');\nvar DOM = require('../util/dom');\nvar LatLng = require('../geo/lat_lng');\n\n/**\n * Creates a popup component\n * @class Popup\n * @param {Object} options\n * @param {Boolean} options.closeButton\n * @param {Boolean} options.closeOnClick\n * @example\n * var tooltip = new mapboxgl.Popup()\n * .setLatLng(map.unproject(e.point))\n * .setHTML(\"Hello World!
\")\n * .addTo(map);\n */\nfunction Popup(options) {\n util.setOptions(this, options);\n util.bindAll([\n '_updatePosition',\n '_onClickClose'],\n this);\n}\n\nPopup.prototype = util.inherit(Evented, /** @lends Popup.prototype */{\n options: {\n closeButton: true,\n closeOnClick: true\n },\n\n /**\n * Attaches the popup to a map\n * @param {Map} map\n * @returns {Popup} `this`\n */\n addTo: function(map) {\n this._map = map;\n this._map.on('move', this._updatePosition);\n if (this.options.closeOnClick) {\n this._map.on('click', this._onClickClose);\n }\n this._update();\n return this;\n },\n\n /**\n * Removes the popup from the map\n * @example\n * var popup = new mapboxgl.Popup().addTo(map);\n * popup.remove();\n * @returns {Popup} `this`\n */\n remove: function() {\n if (this._container) {\n this._container.parentNode.removeChild(this._container);\n }\n\n if (this._map) {\n this._map.off('move', this._updatePosition);\n this._map.off('click', this._onClickClose);\n delete this._map;\n }\n\n return this;\n },\n\n /**\n * Get the current coordinates of popup element relative to map\n * @returns {LatLng}\n */\n getLatLng: function() {\n return this._latLng;\n },\n\n /**\n * Set the coordinates of a popup element to a map\n * @param {LatLng} latlng\n * @returns {Popup} `this`\n */\n setLatLng: function(latlng) {\n this._latLng = LatLng.convert(latlng);\n this._update();\n return this;\n },\n\n /**\n * Popuplate a popup element with text only content\n * @param {string} text\n * @returns {Popup} `this`\n */\n setText: function(text) {\n this._content = document.createTextNode(text);\n this._updateContent();\n return this;\n },\n\n /**\n * Popuplate a popup element with HTML content\n * @param {string} html\n * @returns {Popup} `this`\n */\n setHTML: function(html) {\n this._content = document.createDocumentFragment();\n\n var temp = document.createElement('body'), child;\n temp.innerHTML = html;\n while (true) {\n child = temp.firstChild;\n if (!child) break;\n this._content.appendChild(child);\n }\n\n this._updateContent();\n return this;\n },\n\n _update: function() {\n if (!this._map) { return; }\n\n if (!this._container) {\n this._container = DOM.create('div', 'mapboxgl-popup', this._map.getContainer());\n\n this._tip = DOM.create('div', 'mapboxgl-popup-tip', this._container);\n this._wrapper = DOM.create('div', 'mapboxgl-popup-content', this._container);\n\n if (this.options.closeButton) {\n this._closeButton = DOM.create('button', 'mapboxgl-popup-close-button', this._wrapper);\n this._closeButton.innerHTML = '×';\n this._closeButton.addEventListener('click', this._onClickClose);\n }\n }\n\n this._updateContent();\n this._updatePosition();\n },\n\n _updateContent: function() {\n if (!this._content || !this._container) { return; }\n\n var node = this._wrapper;\n\n while (node.hasChildNodes()) {\n node.removeChild(node.firstChild);\n }\n\n node.appendChild(this._closeButton);\n node.appendChild(this._content);\n },\n\n _updatePosition: function() {\n if (!this._latLng || !this._container) { return; }\n\n var pos = this._map.project(this._latLng).round(),\n anchor = this.options.anchor;\n\n if (!anchor) {\n var width = this._container.offsetWidth,\n height = this._container.offsetHeight;\n\n if (pos.y < height) {\n anchor = ['top'];\n } else if (pos.y > this._map.transform.height - height) {\n anchor = ['bottom'];\n } else {\n anchor = [];\n }\n\n if (pos.x < width / 2) {\n anchor.push('left');\n } else if (pos.x > this._map.transform.width - width / 2) {\n anchor.push('right');\n }\n\n if (anchor.length === 0) {\n anchor = 'bottom';\n } else {\n anchor = anchor.join('-');\n }\n\n this.options.anchor = anchor;\n }\n\n var anchorTranslate = {\n 'top': 'translate(-50%,0)',\n 'top-left': 'translate(0,0)',\n 'top-right': 'translate(-100%,0)',\n 'bottom': 'translate(-50%,-100%)',\n 'bottom-left': 'translate(0,-100%)',\n 'bottom-right': 'translate(-100%,-100%)',\n 'left': 'translate(0,-50%)',\n 'right': 'translate(-100%,-50%)'\n };\n\n var classList = this._container.classList;\n for (var key in anchorTranslate) {\n classList.remove('mapboxgl-popup-anchor-' + key);\n }\n classList.add('mapboxgl-popup-anchor-' + anchor);\n\n DOM.setTransform(this._container, anchorTranslate[anchor] + ' translate(' + pos.x + 'px,' + pos.y + 'px)');\n },\n\n _onClickClose: function() {\n this.remove();\n }\n});","path":"js/ui/popup.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/popup.js#L22-L28"},"params":[{"title":"param","description":null,"type":{"type":"NameExpression","name":"Object"},"name":"options"},{"title":"param","description":null,"type":{"type":"NameExpression","name":"Boolean"},"name":"options.closeButton"},{"title":"param","description":null,"type":{"type":"NameExpression","name":"Boolean"},"name":"options.closeOnClick"}],"examples":["var tooltip = new mapboxgl.Popup()\n .setLatLng(map.unproject(e.point))\n .setHTML(\"<h1>Hello World!</h1>\")\n .addTo(map);"],"name":"Popup","kind":"class","members":{"instance":[{"description":"Popuplate a popup element with text only content","tags":[{"title":"param","description":null,"type":{"type":"NameExpression","name":"string"},"name":"text"},{"title":"returns","description":"`this`","type":{"type":"NameExpression","name":"Popup"}},{"title":"name","name":"setText"},{"title":"memberof","description":"Popup"},{"title":"instance"}],"context":{"loc":{"start":{"line":96,"column":4},"end":{"line":100,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/popup.js","code":"{\n options: {\n closeButton: true,\n closeOnClick: true\n },\n\n /**\n * Attaches the popup to a map\n * @param {Map} map\n * @returns {Popup} `this`\n */\n addTo: function(map) {\n this._map = map;\n this._map.on('move', this._updatePosition);\n if (this.options.closeOnClick) {\n this._map.on('click', this._onClickClose);\n }\n this._update();\n return this;\n },\n\n /**\n * Removes the popup from the map\n * @example\n * var popup = new mapboxgl.Popup().addTo(map);\n * popup.remove();\n * @returns {Popup} `this`\n */\n remove: function() {\n if (this._container) {\n this._container.parentNode.removeChild(this._container);\n }\n\n if (this._map) {\n this._map.off('move', this._updatePosition);\n this._map.off('click', this._onClickClose);\n delete this._map;\n }\n\n return this;\n },\n\n /**\n * Get the current coordinates of popup element relative to map\n * @returns {LatLng}\n */\n getLatLng: function() {\n return this._latLng;\n },\n\n /**\n * Set the coordinates of a popup element to a map\n * @param {LatLng} latlng\n * @returns {Popup} `this`\n */\n setLatLng: function(latlng) {\n this._latLng = LatLng.convert(latlng);\n this._update();\n return this;\n },\n\n /**\n * Popuplate a popup element with text only content\n * @param {string} text\n * @returns {Popup} `this`\n */\n setText: function(text) {\n this._content = document.createTextNode(text);\n this._updateContent();\n return this;\n },\n\n /**\n * Popuplate a popup element with HTML content\n * @param {string} html\n * @returns {Popup} `this`\n */\n setHTML: function(html) {\n this._content = document.createDocumentFragment();\n\n var temp = document.createElement('body'), child;\n temp.innerHTML = html;\n while (true) {\n child = temp.firstChild;\n if (!child) break;\n this._content.appendChild(child);\n }\n\n this._updateContent();\n return this;\n },\n\n _update: function() {\n if (!this._map) { return; }\n\n if (!this._container) {\n this._container = DOM.create('div', 'mapboxgl-popup', this._map.getContainer());\n\n this._tip = DOM.create('div', 'mapboxgl-popup-tip', this._container);\n this._wrapper = DOM.create('div', 'mapboxgl-popup-content', this._container);\n\n if (this.options.closeButton) {\n this._closeButton = DOM.create('button', 'mapboxgl-popup-close-button', this._wrapper);\n this._closeButton.innerHTML = '×';\n this._closeButton.addEventListener('click', this._onClickClose);\n }\n }\n\n this._updateContent();\n this._updatePosition();\n },\n\n _updateContent: function() {\n if (!this._content || !this._container) { return; }\n\n var node = this._wrapper;\n\n while (node.hasChildNodes()) {\n node.removeChild(node.firstChild);\n }\n\n node.appendChild(this._closeButton);\n node.appendChild(this._content);\n },\n\n _updatePosition: function() {\n if (!this._latLng || !this._container) { return; }\n\n var pos = this._map.project(this._latLng).round(),\n anchor = this.options.anchor;\n\n if (!anchor) {\n var width = this._container.offsetWidth,\n height = this._container.offsetHeight;\n\n if (pos.y < height) {\n anchor = ['top'];\n } else if (pos.y > this._map.transform.height - height) {\n anchor = ['bottom'];\n } else {\n anchor = [];\n }\n\n if (pos.x < width / 2) {\n anchor.push('left');\n } else if (pos.x > this._map.transform.width - width / 2) {\n anchor.push('right');\n }\n\n if (anchor.length === 0) {\n anchor = 'bottom';\n } else {\n anchor = anchor.join('-');\n }\n\n this.options.anchor = anchor;\n }\n\n var anchorTranslate = {\n 'top': 'translate(-50%,0)',\n 'top-left': 'translate(0,0)',\n 'top-right': 'translate(-100%,0)',\n 'bottom': 'translate(-50%,-100%)',\n 'bottom-left': 'translate(0,-100%)',\n 'bottom-right': 'translate(-100%,-100%)',\n 'left': 'translate(0,-50%)',\n 'right': 'translate(-100%,-50%)'\n };\n\n var classList = this._container.classList;\n for (var key in anchorTranslate) {\n classList.remove('mapboxgl-popup-anchor-' + key);\n }\n classList.add('mapboxgl-popup-anchor-' + anchor);\n\n DOM.setTransform(this._container, anchorTranslate[anchor] + ' translate(' + pos.x + 'px,' + pos.y + 'px)');\n },\n\n _onClickClose: function() {\n this.remove();\n }\n}","path":"js/ui/popup.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/popup.js#L96-L100"},"params":[{"title":"param","description":null,"type":{"type":"NameExpression","name":"string"},"name":"text"}],"returns":[{"title":"returns","description":"`this`","type":{"type":"NameExpression","name":"Popup"}}],"name":"setText","memberof":"Popup","scope":"instance","members":{"instance":[],"static":[]},"path":["Popup","setText"]},{"description":"Popuplate a popup element with HTML content","tags":[{"title":"param","description":null,"type":{"type":"NameExpression","name":"string"},"name":"html"},{"title":"returns","description":"`this`","type":{"type":"NameExpression","name":"Popup"}},{"title":"name","name":"setHTML"},{"title":"memberof","description":"Popup"},{"title":"instance"}],"context":{"loc":{"start":{"line":107,"column":4},"end":{"line":120,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/popup.js","code":"{\n options: {\n closeButton: true,\n closeOnClick: true\n },\n\n /**\n * Attaches the popup to a map\n * @param {Map} map\n * @returns {Popup} `this`\n */\n addTo: function(map) {\n this._map = map;\n this._map.on('move', this._updatePosition);\n if (this.options.closeOnClick) {\n this._map.on('click', this._onClickClose);\n }\n this._update();\n return this;\n },\n\n /**\n * Removes the popup from the map\n * @example\n * var popup = new mapboxgl.Popup().addTo(map);\n * popup.remove();\n * @returns {Popup} `this`\n */\n remove: function() {\n if (this._container) {\n this._container.parentNode.removeChild(this._container);\n }\n\n if (this._map) {\n this._map.off('move', this._updatePosition);\n this._map.off('click', this._onClickClose);\n delete this._map;\n }\n\n return this;\n },\n\n /**\n * Get the current coordinates of popup element relative to map\n * @returns {LatLng}\n */\n getLatLng: function() {\n return this._latLng;\n },\n\n /**\n * Set the coordinates of a popup element to a map\n * @param {LatLng} latlng\n * @returns {Popup} `this`\n */\n setLatLng: function(latlng) {\n this._latLng = LatLng.convert(latlng);\n this._update();\n return this;\n },\n\n /**\n * Popuplate a popup element with text only content\n * @param {string} text\n * @returns {Popup} `this`\n */\n setText: function(text) {\n this._content = document.createTextNode(text);\n this._updateContent();\n return this;\n },\n\n /**\n * Popuplate a popup element with HTML content\n * @param {string} html\n * @returns {Popup} `this`\n */\n setHTML: function(html) {\n this._content = document.createDocumentFragment();\n\n var temp = document.createElement('body'), child;\n temp.innerHTML = html;\n while (true) {\n child = temp.firstChild;\n if (!child) break;\n this._content.appendChild(child);\n }\n\n this._updateContent();\n return this;\n },\n\n _update: function() {\n if (!this._map) { return; }\n\n if (!this._container) {\n this._container = DOM.create('div', 'mapboxgl-popup', this._map.getContainer());\n\n this._tip = DOM.create('div', 'mapboxgl-popup-tip', this._container);\n this._wrapper = DOM.create('div', 'mapboxgl-popup-content', this._container);\n\n if (this.options.closeButton) {\n this._closeButton = DOM.create('button', 'mapboxgl-popup-close-button', this._wrapper);\n this._closeButton.innerHTML = '×';\n this._closeButton.addEventListener('click', this._onClickClose);\n }\n }\n\n this._updateContent();\n this._updatePosition();\n },\n\n _updateContent: function() {\n if (!this._content || !this._container) { return; }\n\n var node = this._wrapper;\n\n while (node.hasChildNodes()) {\n node.removeChild(node.firstChild);\n }\n\n node.appendChild(this._closeButton);\n node.appendChild(this._content);\n },\n\n _updatePosition: function() {\n if (!this._latLng || !this._container) { return; }\n\n var pos = this._map.project(this._latLng).round(),\n anchor = this.options.anchor;\n\n if (!anchor) {\n var width = this._container.offsetWidth,\n height = this._container.offsetHeight;\n\n if (pos.y < height) {\n anchor = ['top'];\n } else if (pos.y > this._map.transform.height - height) {\n anchor = ['bottom'];\n } else {\n anchor = [];\n }\n\n if (pos.x < width / 2) {\n anchor.push('left');\n } else if (pos.x > this._map.transform.width - width / 2) {\n anchor.push('right');\n }\n\n if (anchor.length === 0) {\n anchor = 'bottom';\n } else {\n anchor = anchor.join('-');\n }\n\n this.options.anchor = anchor;\n }\n\n var anchorTranslate = {\n 'top': 'translate(-50%,0)',\n 'top-left': 'translate(0,0)',\n 'top-right': 'translate(-100%,0)',\n 'bottom': 'translate(-50%,-100%)',\n 'bottom-left': 'translate(0,-100%)',\n 'bottom-right': 'translate(-100%,-100%)',\n 'left': 'translate(0,-50%)',\n 'right': 'translate(-100%,-50%)'\n };\n\n var classList = this._container.classList;\n for (var key in anchorTranslate) {\n classList.remove('mapboxgl-popup-anchor-' + key);\n }\n classList.add('mapboxgl-popup-anchor-' + anchor);\n\n DOM.setTransform(this._container, anchorTranslate[anchor] + ' translate(' + pos.x + 'px,' + pos.y + 'px)');\n },\n\n _onClickClose: function() {\n this.remove();\n }\n}","path":"js/ui/popup.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/popup.js#L107-L120"},"params":[{"title":"param","description":null,"type":{"type":"NameExpression","name":"string"},"name":"html"}],"returns":[{"title":"returns","description":"`this`","type":{"type":"NameExpression","name":"Popup"}}],"name":"setHTML","memberof":"Popup","scope":"instance","members":{"instance":[],"static":[]},"path":["Popup","setHTML"]},{"description":"Set the coordinates of a popup element to a map","tags":[{"title":"param","description":null,"type":{"type":"NameExpression","name":"LatLng"},"name":"latlng"},{"title":"returns","description":"`this`","type":{"type":"NameExpression","name":"Popup"}},{"title":"name","name":"setLatLng"},{"title":"memberof","description":"Popup"},{"title":"instance"}],"context":{"loc":{"start":{"line":85,"column":4},"end":{"line":89,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/popup.js","code":"{\n options: {\n closeButton: true,\n closeOnClick: true\n },\n\n /**\n * Attaches the popup to a map\n * @param {Map} map\n * @returns {Popup} `this`\n */\n addTo: function(map) {\n this._map = map;\n this._map.on('move', this._updatePosition);\n if (this.options.closeOnClick) {\n this._map.on('click', this._onClickClose);\n }\n this._update();\n return this;\n },\n\n /**\n * Removes the popup from the map\n * @example\n * var popup = new mapboxgl.Popup().addTo(map);\n * popup.remove();\n * @returns {Popup} `this`\n */\n remove: function() {\n if (this._container) {\n this._container.parentNode.removeChild(this._container);\n }\n\n if (this._map) {\n this._map.off('move', this._updatePosition);\n this._map.off('click', this._onClickClose);\n delete this._map;\n }\n\n return this;\n },\n\n /**\n * Get the current coordinates of popup element relative to map\n * @returns {LatLng}\n */\n getLatLng: function() {\n return this._latLng;\n },\n\n /**\n * Set the coordinates of a popup element to a map\n * @param {LatLng} latlng\n * @returns {Popup} `this`\n */\n setLatLng: function(latlng) {\n this._latLng = LatLng.convert(latlng);\n this._update();\n return this;\n },\n\n /**\n * Popuplate a popup element with text only content\n * @param {string} text\n * @returns {Popup} `this`\n */\n setText: function(text) {\n this._content = document.createTextNode(text);\n this._updateContent();\n return this;\n },\n\n /**\n * Popuplate a popup element with HTML content\n * @param {string} html\n * @returns {Popup} `this`\n */\n setHTML: function(html) {\n this._content = document.createDocumentFragment();\n\n var temp = document.createElement('body'), child;\n temp.innerHTML = html;\n while (true) {\n child = temp.firstChild;\n if (!child) break;\n this._content.appendChild(child);\n }\n\n this._updateContent();\n return this;\n },\n\n _update: function() {\n if (!this._map) { return; }\n\n if (!this._container) {\n this._container = DOM.create('div', 'mapboxgl-popup', this._map.getContainer());\n\n this._tip = DOM.create('div', 'mapboxgl-popup-tip', this._container);\n this._wrapper = DOM.create('div', 'mapboxgl-popup-content', this._container);\n\n if (this.options.closeButton) {\n this._closeButton = DOM.create('button', 'mapboxgl-popup-close-button', this._wrapper);\n this._closeButton.innerHTML = '×';\n this._closeButton.addEventListener('click', this._onClickClose);\n }\n }\n\n this._updateContent();\n this._updatePosition();\n },\n\n _updateContent: function() {\n if (!this._content || !this._container) { return; }\n\n var node = this._wrapper;\n\n while (node.hasChildNodes()) {\n node.removeChild(node.firstChild);\n }\n\n node.appendChild(this._closeButton);\n node.appendChild(this._content);\n },\n\n _updatePosition: function() {\n if (!this._latLng || !this._container) { return; }\n\n var pos = this._map.project(this._latLng).round(),\n anchor = this.options.anchor;\n\n if (!anchor) {\n var width = this._container.offsetWidth,\n height = this._container.offsetHeight;\n\n if (pos.y < height) {\n anchor = ['top'];\n } else if (pos.y > this._map.transform.height - height) {\n anchor = ['bottom'];\n } else {\n anchor = [];\n }\n\n if (pos.x < width / 2) {\n anchor.push('left');\n } else if (pos.x > this._map.transform.width - width / 2) {\n anchor.push('right');\n }\n\n if (anchor.length === 0) {\n anchor = 'bottom';\n } else {\n anchor = anchor.join('-');\n }\n\n this.options.anchor = anchor;\n }\n\n var anchorTranslate = {\n 'top': 'translate(-50%,0)',\n 'top-left': 'translate(0,0)',\n 'top-right': 'translate(-100%,0)',\n 'bottom': 'translate(-50%,-100%)',\n 'bottom-left': 'translate(0,-100%)',\n 'bottom-right': 'translate(-100%,-100%)',\n 'left': 'translate(0,-50%)',\n 'right': 'translate(-100%,-50%)'\n };\n\n var classList = this._container.classList;\n for (var key in anchorTranslate) {\n classList.remove('mapboxgl-popup-anchor-' + key);\n }\n classList.add('mapboxgl-popup-anchor-' + anchor);\n\n DOM.setTransform(this._container, anchorTranslate[anchor] + ' translate(' + pos.x + 'px,' + pos.y + 'px)');\n },\n\n _onClickClose: function() {\n this.remove();\n }\n}","path":"js/ui/popup.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/popup.js#L85-L89"},"params":[{"title":"param","description":null,"type":{"type":"NameExpression","name":"LatLng"},"name":"latlng"}],"returns":[{"title":"returns","description":"`this`","type":{"type":"NameExpression","name":"Popup"}}],"name":"setLatLng","memberof":"Popup","scope":"instance","members":{"instance":[],"static":[]},"path":["Popup","setLatLng"]},{"description":"Removes the popup from the map","tags":[{"title":"example","description":"var popup = new mapboxgl.Popup().addTo(map);\npopup.remove();"},{"title":"returns","description":"`this`","type":{"type":"NameExpression","name":"Popup"}},{"title":"name","name":"remove"},{"title":"memberof","description":"Popup"},{"title":"instance"}],"context":{"loc":{"start":{"line":58,"column":4},"end":{"line":70,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/popup.js","code":"{\n options: {\n closeButton: true,\n closeOnClick: true\n },\n\n /**\n * Attaches the popup to a map\n * @param {Map} map\n * @returns {Popup} `this`\n */\n addTo: function(map) {\n this._map = map;\n this._map.on('move', this._updatePosition);\n if (this.options.closeOnClick) {\n this._map.on('click', this._onClickClose);\n }\n this._update();\n return this;\n },\n\n /**\n * Removes the popup from the map\n * @example\n * var popup = new mapboxgl.Popup().addTo(map);\n * popup.remove();\n * @returns {Popup} `this`\n */\n remove: function() {\n if (this._container) {\n this._container.parentNode.removeChild(this._container);\n }\n\n if (this._map) {\n this._map.off('move', this._updatePosition);\n this._map.off('click', this._onClickClose);\n delete this._map;\n }\n\n return this;\n },\n\n /**\n * Get the current coordinates of popup element relative to map\n * @returns {LatLng}\n */\n getLatLng: function() {\n return this._latLng;\n },\n\n /**\n * Set the coordinates of a popup element to a map\n * @param {LatLng} latlng\n * @returns {Popup} `this`\n */\n setLatLng: function(latlng) {\n this._latLng = LatLng.convert(latlng);\n this._update();\n return this;\n },\n\n /**\n * Popuplate a popup element with text only content\n * @param {string} text\n * @returns {Popup} `this`\n */\n setText: function(text) {\n this._content = document.createTextNode(text);\n this._updateContent();\n return this;\n },\n\n /**\n * Popuplate a popup element with HTML content\n * @param {string} html\n * @returns {Popup} `this`\n */\n setHTML: function(html) {\n this._content = document.createDocumentFragment();\n\n var temp = document.createElement('body'), child;\n temp.innerHTML = html;\n while (true) {\n child = temp.firstChild;\n if (!child) break;\n this._content.appendChild(child);\n }\n\n this._updateContent();\n return this;\n },\n\n _update: function() {\n if (!this._map) { return; }\n\n if (!this._container) {\n this._container = DOM.create('div', 'mapboxgl-popup', this._map.getContainer());\n\n this._tip = DOM.create('div', 'mapboxgl-popup-tip', this._container);\n this._wrapper = DOM.create('div', 'mapboxgl-popup-content', this._container);\n\n if (this.options.closeButton) {\n this._closeButton = DOM.create('button', 'mapboxgl-popup-close-button', this._wrapper);\n this._closeButton.innerHTML = '×';\n this._closeButton.addEventListener('click', this._onClickClose);\n }\n }\n\n this._updateContent();\n this._updatePosition();\n },\n\n _updateContent: function() {\n if (!this._content || !this._container) { return; }\n\n var node = this._wrapper;\n\n while (node.hasChildNodes()) {\n node.removeChild(node.firstChild);\n }\n\n node.appendChild(this._closeButton);\n node.appendChild(this._content);\n },\n\n _updatePosition: function() {\n if (!this._latLng || !this._container) { return; }\n\n var pos = this._map.project(this._latLng).round(),\n anchor = this.options.anchor;\n\n if (!anchor) {\n var width = this._container.offsetWidth,\n height = this._container.offsetHeight;\n\n if (pos.y < height) {\n anchor = ['top'];\n } else if (pos.y > this._map.transform.height - height) {\n anchor = ['bottom'];\n } else {\n anchor = [];\n }\n\n if (pos.x < width / 2) {\n anchor.push('left');\n } else if (pos.x > this._map.transform.width - width / 2) {\n anchor.push('right');\n }\n\n if (anchor.length === 0) {\n anchor = 'bottom';\n } else {\n anchor = anchor.join('-');\n }\n\n this.options.anchor = anchor;\n }\n\n var anchorTranslate = {\n 'top': 'translate(-50%,0)',\n 'top-left': 'translate(0,0)',\n 'top-right': 'translate(-100%,0)',\n 'bottom': 'translate(-50%,-100%)',\n 'bottom-left': 'translate(0,-100%)',\n 'bottom-right': 'translate(-100%,-100%)',\n 'left': 'translate(0,-50%)',\n 'right': 'translate(-100%,-50%)'\n };\n\n var classList = this._container.classList;\n for (var key in anchorTranslate) {\n classList.remove('mapboxgl-popup-anchor-' + key);\n }\n classList.add('mapboxgl-popup-anchor-' + anchor);\n\n DOM.setTransform(this._container, anchorTranslate[anchor] + ' translate(' + pos.x + 'px,' + pos.y + 'px)');\n },\n\n _onClickClose: function() {\n this.remove();\n }\n}","path":"js/ui/popup.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/popup.js#L58-L70"},"examples":["var popup = new mapboxgl.Popup().addTo(map);\npopup.remove();"],"returns":[{"title":"returns","description":"`this`","type":{"type":"NameExpression","name":"Popup"}}],"name":"remove","memberof":"Popup","scope":"instance","members":{"instance":[],"static":[]},"path":["Popup","remove"]},{"description":"Get the current coordinates of popup element relative to map","tags":[{"title":"returns","description":null,"type":{"type":"NameExpression","name":"LatLng"}},{"title":"name","name":"getLatLng"},{"title":"memberof","description":"Popup"},{"title":"instance"}],"context":{"loc":{"start":{"line":76,"column":4},"end":{"line":78,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/popup.js","code":"{\n options: {\n closeButton: true,\n closeOnClick: true\n },\n\n /**\n * Attaches the popup to a map\n * @param {Map} map\n * @returns {Popup} `this`\n */\n addTo: function(map) {\n this._map = map;\n this._map.on('move', this._updatePosition);\n if (this.options.closeOnClick) {\n this._map.on('click', this._onClickClose);\n }\n this._update();\n return this;\n },\n\n /**\n * Removes the popup from the map\n * @example\n * var popup = new mapboxgl.Popup().addTo(map);\n * popup.remove();\n * @returns {Popup} `this`\n */\n remove: function() {\n if (this._container) {\n this._container.parentNode.removeChild(this._container);\n }\n\n if (this._map) {\n this._map.off('move', this._updatePosition);\n this._map.off('click', this._onClickClose);\n delete this._map;\n }\n\n return this;\n },\n\n /**\n * Get the current coordinates of popup element relative to map\n * @returns {LatLng}\n */\n getLatLng: function() {\n return this._latLng;\n },\n\n /**\n * Set the coordinates of a popup element to a map\n * @param {LatLng} latlng\n * @returns {Popup} `this`\n */\n setLatLng: function(latlng) {\n this._latLng = LatLng.convert(latlng);\n this._update();\n return this;\n },\n\n /**\n * Popuplate a popup element with text only content\n * @param {string} text\n * @returns {Popup} `this`\n */\n setText: function(text) {\n this._content = document.createTextNode(text);\n this._updateContent();\n return this;\n },\n\n /**\n * Popuplate a popup element with HTML content\n * @param {string} html\n * @returns {Popup} `this`\n */\n setHTML: function(html) {\n this._content = document.createDocumentFragment();\n\n var temp = document.createElement('body'), child;\n temp.innerHTML = html;\n while (true) {\n child = temp.firstChild;\n if (!child) break;\n this._content.appendChild(child);\n }\n\n this._updateContent();\n return this;\n },\n\n _update: function() {\n if (!this._map) { return; }\n\n if (!this._container) {\n this._container = DOM.create('div', 'mapboxgl-popup', this._map.getContainer());\n\n this._tip = DOM.create('div', 'mapboxgl-popup-tip', this._container);\n this._wrapper = DOM.create('div', 'mapboxgl-popup-content', this._container);\n\n if (this.options.closeButton) {\n this._closeButton = DOM.create('button', 'mapboxgl-popup-close-button', this._wrapper);\n this._closeButton.innerHTML = '×';\n this._closeButton.addEventListener('click', this._onClickClose);\n }\n }\n\n this._updateContent();\n this._updatePosition();\n },\n\n _updateContent: function() {\n if (!this._content || !this._container) { return; }\n\n var node = this._wrapper;\n\n while (node.hasChildNodes()) {\n node.removeChild(node.firstChild);\n }\n\n node.appendChild(this._closeButton);\n node.appendChild(this._content);\n },\n\n _updatePosition: function() {\n if (!this._latLng || !this._container) { return; }\n\n var pos = this._map.project(this._latLng).round(),\n anchor = this.options.anchor;\n\n if (!anchor) {\n var width = this._container.offsetWidth,\n height = this._container.offsetHeight;\n\n if (pos.y < height) {\n anchor = ['top'];\n } else if (pos.y > this._map.transform.height - height) {\n anchor = ['bottom'];\n } else {\n anchor = [];\n }\n\n if (pos.x < width / 2) {\n anchor.push('left');\n } else if (pos.x > this._map.transform.width - width / 2) {\n anchor.push('right');\n }\n\n if (anchor.length === 0) {\n anchor = 'bottom';\n } else {\n anchor = anchor.join('-');\n }\n\n this.options.anchor = anchor;\n }\n\n var anchorTranslate = {\n 'top': 'translate(-50%,0)',\n 'top-left': 'translate(0,0)',\n 'top-right': 'translate(-100%,0)',\n 'bottom': 'translate(-50%,-100%)',\n 'bottom-left': 'translate(0,-100%)',\n 'bottom-right': 'translate(-100%,-100%)',\n 'left': 'translate(0,-50%)',\n 'right': 'translate(-100%,-50%)'\n };\n\n var classList = this._container.classList;\n for (var key in anchorTranslate) {\n classList.remove('mapboxgl-popup-anchor-' + key);\n }\n classList.add('mapboxgl-popup-anchor-' + anchor);\n\n DOM.setTransform(this._container, anchorTranslate[anchor] + ' translate(' + pos.x + 'px,' + pos.y + 'px)');\n },\n\n _onClickClose: function() {\n this.remove();\n }\n}","path":"js/ui/popup.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/popup.js#L76-L78"},"returns":[{"title":"returns","description":null,"type":{"type":"NameExpression","name":"LatLng"}}],"name":"getLatLng","memberof":"Popup","scope":"instance","members":{"instance":[],"static":[]},"path":["Popup","getLatLng"]},{"description":"Attaches the popup to a map","tags":[{"title":"param","description":null,"type":{"type":"NameExpression","name":"Map"},"name":"map"},{"title":"returns","description":"`this`","type":{"type":"NameExpression","name":"Popup"}},{"title":"name","name":"addTo"},{"title":"memberof","description":"Popup"},{"title":"instance"}],"context":{"loc":{"start":{"line":41,"column":4},"end":{"line":49,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/popup.js","code":"{\n options: {\n closeButton: true,\n closeOnClick: true\n },\n\n /**\n * Attaches the popup to a map\n * @param {Map} map\n * @returns {Popup} `this`\n */\n addTo: function(map) {\n this._map = map;\n this._map.on('move', this._updatePosition);\n if (this.options.closeOnClick) {\n this._map.on('click', this._onClickClose);\n }\n this._update();\n return this;\n },\n\n /**\n * Removes the popup from the map\n * @example\n * var popup = new mapboxgl.Popup().addTo(map);\n * popup.remove();\n * @returns {Popup} `this`\n */\n remove: function() {\n if (this._container) {\n this._container.parentNode.removeChild(this._container);\n }\n\n if (this._map) {\n this._map.off('move', this._updatePosition);\n this._map.off('click', this._onClickClose);\n delete this._map;\n }\n\n return this;\n },\n\n /**\n * Get the current coordinates of popup element relative to map\n * @returns {LatLng}\n */\n getLatLng: function() {\n return this._latLng;\n },\n\n /**\n * Set the coordinates of a popup element to a map\n * @param {LatLng} latlng\n * @returns {Popup} `this`\n */\n setLatLng: function(latlng) {\n this._latLng = LatLng.convert(latlng);\n this._update();\n return this;\n },\n\n /**\n * Popuplate a popup element with text only content\n * @param {string} text\n * @returns {Popup} `this`\n */\n setText: function(text) {\n this._content = document.createTextNode(text);\n this._updateContent();\n return this;\n },\n\n /**\n * Popuplate a popup element with HTML content\n * @param {string} html\n * @returns {Popup} `this`\n */\n setHTML: function(html) {\n this._content = document.createDocumentFragment();\n\n var temp = document.createElement('body'), child;\n temp.innerHTML = html;\n while (true) {\n child = temp.firstChild;\n if (!child) break;\n this._content.appendChild(child);\n }\n\n this._updateContent();\n return this;\n },\n\n _update: function() {\n if (!this._map) { return; }\n\n if (!this._container) {\n this._container = DOM.create('div', 'mapboxgl-popup', this._map.getContainer());\n\n this._tip = DOM.create('div', 'mapboxgl-popup-tip', this._container);\n this._wrapper = DOM.create('div', 'mapboxgl-popup-content', this._container);\n\n if (this.options.closeButton) {\n this._closeButton = DOM.create('button', 'mapboxgl-popup-close-button', this._wrapper);\n this._closeButton.innerHTML = '×';\n this._closeButton.addEventListener('click', this._onClickClose);\n }\n }\n\n this._updateContent();\n this._updatePosition();\n },\n\n _updateContent: function() {\n if (!this._content || !this._container) { return; }\n\n var node = this._wrapper;\n\n while (node.hasChildNodes()) {\n node.removeChild(node.firstChild);\n }\n\n node.appendChild(this._closeButton);\n node.appendChild(this._content);\n },\n\n _updatePosition: function() {\n if (!this._latLng || !this._container) { return; }\n\n var pos = this._map.project(this._latLng).round(),\n anchor = this.options.anchor;\n\n if (!anchor) {\n var width = this._container.offsetWidth,\n height = this._container.offsetHeight;\n\n if (pos.y < height) {\n anchor = ['top'];\n } else if (pos.y > this._map.transform.height - height) {\n anchor = ['bottom'];\n } else {\n anchor = [];\n }\n\n if (pos.x < width / 2) {\n anchor.push('left');\n } else if (pos.x > this._map.transform.width - width / 2) {\n anchor.push('right');\n }\n\n if (anchor.length === 0) {\n anchor = 'bottom';\n } else {\n anchor = anchor.join('-');\n }\n\n this.options.anchor = anchor;\n }\n\n var anchorTranslate = {\n 'top': 'translate(-50%,0)',\n 'top-left': 'translate(0,0)',\n 'top-right': 'translate(-100%,0)',\n 'bottom': 'translate(-50%,-100%)',\n 'bottom-left': 'translate(0,-100%)',\n 'bottom-right': 'translate(-100%,-100%)',\n 'left': 'translate(0,-50%)',\n 'right': 'translate(-100%,-50%)'\n };\n\n var classList = this._container.classList;\n for (var key in anchorTranslate) {\n classList.remove('mapboxgl-popup-anchor-' + key);\n }\n classList.add('mapboxgl-popup-anchor-' + anchor);\n\n DOM.setTransform(this._container, anchorTranslate[anchor] + ' translate(' + pos.x + 'px,' + pos.y + 'px)');\n },\n\n _onClickClose: function() {\n this.remove();\n }\n}","path":"js/ui/popup.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/popup.js#L41-L49"},"params":[{"title":"param","description":null,"type":{"type":"NameExpression","name":"Map"},"name":"map"}],"returns":[{"title":"returns","description":"`this`","type":{"type":"NameExpression","name":"Popup"}}],"name":"addTo","memberof":"Popup","scope":"instance","members":{"instance":[],"static":[]},"path":["Popup","addTo"]}],"static":[]},"path":["Popup"]},{"description":"Creates a map instance.","tags":[{"title":"class","description":null,"type":null,"name":"Map"},{"title":"param","description":null,"type":{"type":"NameExpression","name":"Object"},"name":"options"},{"title":"param","description":"HTML element to initialize the map in (or element id as string)","type":{"type":"NameExpression","name":"String"},"name":"options.container"},{"title":"name","name":"Map"},{"title":"kind","kind":"class"}],"context":{"loc":{"start":{"line":43,"column":0},"end":{"line":91,"column":2}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/map.js","code":"'use strict';\n\nvar Canvas = require('../util/canvas');\nvar util = require('../util/util');\nvar browser = require('../util/browser');\nvar Evented = require('../util/evented');\nvar DOM = require('../util/dom');\n\nvar Style = require('../style/style');\nvar AnimationLoop = require('../style/animation_loop');\nvar GLPainter = require('../render/painter');\n\nvar Transform = require('../geo/transform');\nvar Hash = require('./hash');\nvar Handlers = require('./handlers');\nvar Easings = require('./easings');\nvar LatLng = require('../geo/lat_lng');\nvar LatLngBounds = require('../geo/lat_lng_bounds');\nvar Point = require('point-geometry');\nvar Attribution = require('./control/attribution');\n\n/**\n * Creates a map instance.\n * @class Map\n * @param {Object} options\n * @param {String} options.container HTML element to initialize the map in (or element id as string)\n * @param {Number} [options.minZoom=0] Minimum zoom of the map\n * @param {Number} [options.maxZoom=20] Maximum zoom of the map\n * @param {Object} options.style Map style and data source definition (either a JSON object or a JSON URL), described in the [style reference](https://mapbox.com/mapbox-gl-style-spec/)\n * @param {Boolean} [options.hash=false] If `true`, the map will track and update the page URL according to map position\n * @param {Boolean} [options.interactive=true] If `false`, no mouse, touch, or keyboard listeners are attached to the map, so it will not respond to input\n * @param {Array} options.classes Style class names with which to initialize the map\n * @param {Boolean} [options.failIfMajorPerformanceCaveat=false] If `true`, map creation will fail if the implementation determines that the performance of the created WebGL context would be dramatically lower than expected.\n * @example\n * var map = new mapboxgl.Map({\n * container: 'map',\n * center: [37.772537, -122.420679],\n * zoom: 13,\n * style: style_object,\n * hash: true\n * });\n */\nvar Map = module.exports = function(options) {\n\n options = this.options = util.inherit(this.options, options);\n\n this.animationLoop = new AnimationLoop();\n this.transform = new Transform(options.minZoom, options.maxZoom);\n\n if (options.maxBounds) {\n var b = LatLngBounds.convert(options.maxBounds);\n this.transform.latRange = [b.getSouth(), b.getNorth()];\n this.transform.lngRange = [b.getWest(), b.getEast()];\n }\n\n util.bindAll([\n '_forwardStyleEvent',\n '_forwardSourceEvent',\n '_forwardLayerEvent',\n '_forwardTileEvent',\n '_onStyleLoad',\n '_onStyleChange',\n '_onSourceAdd',\n '_onSourceRemove',\n '_onSourceUpdate',\n 'update',\n 'render'\n ], this);\n\n this._setupContainer();\n this._setupControlPos();\n this._setupPainter();\n\n this.handlers = options.interactive && new Handlers(this);\n\n this._hash = options.hash && (new Hash()).addTo(this);\n // don't set position from options if set through hash\n if (!this._hash || !this._hash._onHashChange()) {\n this.setView(options.center, options.zoom, options.bearing, options.pitch);\n }\n\n this.sources = {};\n this.stacks = {};\n this._classes = {};\n\n this.resize();\n\n if (options.classes) this.setClasses(options.classes);\n if (options.style) this.setStyle(options.style);\n if (options.attributionControl) this.addControl(new Attribution());\n};\n\nutil.extend(Map.prototype, Evented);\nutil.extend(Map.prototype, Easings);\nutil.extend(Map.prototype, /** @lends Map.prototype */{\n\n options: {\n center: [0, 0],\n zoom: 0,\n bearing: 0,\n pitch: 0,\n\n minZoom: 0,\n maxZoom: 20,\n\n interactive: true,\n hash: false,\n\n attributionControl: true,\n\n failIfMajorPerformanceCaveat: false\n },\n\n addControl: function(control) {\n control.addTo(this);\n return this;\n },\n\n /**\n * Sets a map position\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @param {number} zoom Map zoom level\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setView: function(center, zoom, bearing, pitch) {\n this.stop();\n\n var tr = this.transform,\n zoomChanged = tr.zoom !== +zoom,\n bearingChanged = tr.bearing !== +bearing,\n pitchChanged = tr.pitch !== +pitch;\n\n tr.center = LatLng.convert(center);\n tr.zoom = +zoom;\n tr.bearing = +bearing;\n tr.pitch = +pitch;\n\n return this\n .fire('movestart')\n ._move(zoomChanged, bearingChanged, pitchChanged)\n .fire('moveend');\n },\n\n /**\n * Sets a map location\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setCenter: function(center) {\n this.setView(center, this.getZoom(), this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map zoom\n *\n * @param {number} zoom Map zoom level\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setZoom: function(zoom) {\n this.setView(this.getCenter(), zoom, this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map rotation\n *\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setBearing: function(bearing) {\n this.setView(this.getCenter(), this.getZoom(), bearing, this.getPitch());\n },\n\n /**\n * Sets a map angle\n *\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setPitch: function(pitch) {\n this.setView(this.getCenter(), this.getZoom(), this.getBearing(), pitch);\n },\n\n /**\n * Get the current view geographical point\n * @returns {LatLng}\n */\n getCenter: function() { return this.transform.center; },\n\n /**\n * Get the current zoom\n * @returns {number}\n */\n getZoom: function() { return this.transform.zoom; },\n\n /**\n * Get the current bearing in degrees\n * @returns {number}\n */\n getBearing: function() { return this.transform.bearing; },\n\n /**\n * Get the current angle in degrees\n * @returns {number}\n */\n getPitch: function() { return this.transform.pitch; },\n\n /**\n * @typedef {Object} [styleOptions]\n * @param {Boolean} [styleOptions.transition=true]\n */\n\n /**\n * Adds a style class to a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n addClass: function(klass, options) {\n if (this._classes[klass]) return;\n this._classes[klass] = true;\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Removes a style class from a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n removeClass: function(klass, options) {\n if (!this._classes[klass]) return;\n delete this._classes[klass];\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Helper method to add more than one class\n *\n * @param {Array} klasses An array of class names\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n setClasses: function(klasses, options) {\n this._classes = {};\n for (var i = 0; i < klasses.length; i++) {\n this._classes[klasses[i]] = true;\n }\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Check whether a style class is active\n *\n * @param {string} klass Name of style class\n * @returns {boolean}\n */\n hasClass: function(klass) {\n return !!this._classes[klass];\n },\n\n /**\n * Return an array of the current active style classes\n *\n * @returns {boolean}\n */\n getClasses: function() {\n return Object.keys(this._classes);\n },\n\n /**\n * Detect the map's new width and height and resize it.\n *\n * @returns {Map} `this`\n */\n resize: function() {\n var width = 0, height = 0;\n\n if (this._container) {\n width = this._container.offsetWidth || 400;\n height = this._container.offsetHeight || 300;\n }\n\n this._canvas.resize(width, height);\n\n this.transform.width = width;\n this.transform.height = height;\n this.transform._constrain();\n\n this.painter.resize(width, height);\n\n return this\n .fire('movestart')\n ._move()\n .fire('resize')\n .fire('moveend');\n },\n\n /**\n * Get the map's geographical bounds\n *\n * @returns {LatLngBounds}\n */\n getBounds: function() {\n return new LatLngBounds(\n this.transform.pointLocation(new Point(0, 0)),\n this.transform.pointLocation(this.transform.size));\n },\n\n /**\n * Get pixel coordinates (relative to map container) given a geographical location\n *\n * @param {LatLng} latlng\n * @returns {Object} `x` and `y` coordinates\n */\n project: function(latlng) {\n return this.transform.locationPoint(LatLng.convert(latlng));\n },\n\n /**\n * Get geographical coordinates given pixel coordinates\n *\n * @param {Array} point [x, y] pixel coordinates\n * @returns {LatLng}\n */\n unproject: function(point) {\n return this.transform.pointLocation(Point.convert(point));\n },\n\n /**\n * Get all features at a point ([x, y])\n *\n * @param {Array} point [x, y] pixel coordinates\n * @param {Object} params\n * @param {number} [params.radius=0] Optional. Radius in pixels to search in\n * @param {string} params.layer Optional. Only return features from a given layer\n * @param {string} params.type Optional. Either `raster` or `vector`\n * @param {featuresAtCallback} callback function that returns the response\n *\n * @callback featuresAtCallback\n * @param {Object|null} err Error _If any_\n * @param {Array} features Displays a JSON array of features given the passed parameters of `featuresAt`\n *\n * @returns {Map} `this`\n */\n featuresAt: function(point, params, callback) {\n var coord = this.transform.pointCoordinate(Point.convert(point));\n this.style.featuresAt(coord, params, callback);\n return this;\n },\n\n /**\n * Replaces the map's style object\n *\n * @param {Object} style A style object formatted as JSON\n * @returns {Map} `this`\n */\n setStyle: function(style) {\n if (this.style) {\n this.style\n .off('load', this._onStyleLoad)\n .off('error', this._forwardStyleEvent)\n .off('change', this._onStyleChange)\n .off('source.add', this._onSourceAdd)\n .off('source.remove', this._onSourceRemove)\n .off('source.load', this._onSourceUpdate)\n .off('source.error', this._forwardSourceEvent)\n .off('source.change', this._onSourceUpdate)\n .off('layer.add', this._forwardLayerEvent)\n .off('layer.remove', this._forwardLayerEvent)\n .off('tile.add', this._forwardTileEvent)\n .off('tile.remove', this._forwardTileEvent)\n .off('tile.load', this.update)\n .off('tile.error', this._forwardTileEvent)\n ._remove();\n\n this.off('rotate', this.style._redoPlacement);\n this.off('pitch', this.style._redoPlacement);\n }\n\n if (!style) {\n this.style = null;\n return this;\n } else if (style instanceof Style) {\n this.style = style;\n } else {\n this.style = new Style(style, this.animationLoop);\n }\n\n this.style\n .on('load', this._onStyleLoad)\n .on('error', this._forwardStyleEvent)\n .on('change', this._onStyleChange)\n .on('source.add', this._onSourceAdd)\n .on('source.remove', this._onSourceRemove)\n .on('source.load', this._onSourceUpdate)\n .on('source.error', this._forwardSourceEvent)\n .on('source.change', this._onSourceUpdate)\n .on('layer.add', this._forwardLayerEvent)\n .on('layer.remove', this._forwardLayerEvent)\n .on('tile.add', this._forwardTileEvent)\n .on('tile.remove', this._forwardTileEvent)\n .on('tile.load', this.update)\n .on('tile.error', this._forwardTileEvent);\n\n this.on('rotate', this.style._redoPlacement);\n this.on('pitch', this.style._redoPlacement);\n\n return this;\n },\n\n /**\n * Add a source to the map style.\n *\n * @param {string} id ID of the source. Must not be used by any existing source.\n * @param {Object} source source specification, following the\n * [Mapbox GL Style Reference](https://www.mapbox.com/mapbox-gl-style-spec/#sources)\n * @fires source.add\n * @returns {Map} `this`\n */\n addSource: function(id, source) {\n this.style.addSource(id, source);\n return this;\n },\n\n /**\n * Remove an existing source from the map style.\n *\n * @param {string} id ID of the source to remove\n * @fires source.remove\n * @returns {Map} `this`\n */\n removeSource: function(id) {\n this.style.removeSource(id);\n return this;\n },\n\n /**\n * Return the style source object with the given `id`.\n *\n * @param {string} id source ID\n * @returns {Object}\n */\n getSource: function(id) {\n return this.style.getSource(id);\n },\n\n /**\n * Add a layer to the map style. The layer will be inserted before the layer with\n * ID `before`, or appended if `before` is omitted.\n * @param {Layer} layer\n * @param {string=} before ID of an existing layer to insert before\n * @fires layer.add\n * @returns {Map} `this`\n */\n addLayer: function(layer, before) {\n this.style.addLayer(layer, before);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Remove the layer with the given `id` from the map. Any layers which refer to the\n * specified layer via a `ref` property are also removed.\n *\n * @param {string} id\n * @fires layer.remove\n * @returns {Map} this\n */\n removeLayer: function(id) {\n this.style.removeLayer(id);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Set the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {Array} filter filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n * @returns {Map} `this`\n */\n setFilter: function(layer, filter) {\n this.style.setFilter(layer, filter);\n return this;\n },\n\n /**\n * Get the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @returns {Array} filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n */\n getFilter: function(layer) {\n return this.style.getFilter(layer);\n },\n\n /**\n * Set the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {*} value value for the paint propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @param {string=} klass optional class specifier for the property\n * @returns {Map} `this`\n */\n setPaintProperty: function(layer, name, value, klass) {\n this.style.setPaintProperty(layer, name, value, klass);\n this.style._cascade(this._classes);\n this.update(true);\n return this;\n },\n\n /**\n * Get the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the paint propery\n */\n getPaintProperty: function(layer, name, klass) {\n return this.style.getPaintProperty(layer, name, klass);\n },\n\n /**\n * Set the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {*} value value for the layout propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @returns {Map} `this`\n */\n setLayoutProperty: function(layer, name, value) {\n this.style.setLayoutProperty(layer, name, value);\n return this;\n },\n\n /**\n * Get the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the layout propery\n */\n getLayoutProperty: function(layer, name) {\n return this.style.getLayoutProperty(layer, name);\n },\n\n /**\n * Get the Map's container as an HTML element\n * @returns {HTMLElement} container\n */\n getContainer: function() {\n return this._container;\n },\n\n /**\n * Get the Map's canvas as an HTML canvas\n * @returns {HTMLElement} canvas\n */\n getCanvas: function() {\n return this._canvas.getElement();\n },\n\n _move: function(zoom, rotate, pitch) {\n\n this.update(zoom).fire('move');\n\n if (zoom) this.fire('zoom');\n if (rotate) this.fire('rotate');\n if (pitch) this.fire('pitch');\n\n return this;\n },\n\n // map setup code\n _setupContainer: function() {\n var id = this.options.container;\n var container = this._container = typeof id === 'string' ? document.getElementById(id) : id;\n if (container) container.classList.add('mapboxgl-map');\n this._canvas = new Canvas(this, container);\n },\n\n _setupControlPos: function() {\n var corners = this._controlCorners = {};\n var prefix = 'mapboxgl-ctrl-';\n var container = this.getContainer();\n\n function createCorner(pos) {\n var className = prefix + pos;\n corners[pos] = DOM.create('div', className, container);\n }\n\n if (container && typeof document === 'object') {\n createCorner('top-left');\n createCorner('top-right');\n createCorner('bottom-left');\n createCorner('bottom-right');\n }\n },\n\n _setupPainter: function() {\n var gl = this._canvas.getWebGLContext(this.options.failIfMajorPerformanceCaveat);\n\n if (!gl) {\n console.error('Failed to initialize WebGL');\n return;\n }\n\n this.painter = new GLPainter(gl, this.transform);\n },\n\n _contextLost: function(event) {\n event.preventDefault();\n if (this._frameId) {\n browser.cancelFrame(this._frameId);\n }\n },\n\n _contextRestored: function() {\n this._setupPainter();\n this.resize();\n this.update();\n },\n\n /**\n * Is this map fully loaded? If the style isn't loaded\n * or it has a change to the sources or style that isn't\n * propagated to its style, return false.\n *\n * @returns {boolean} whether the map is loaded\n */\n loaded: function() {\n if (this._styleDirty || this._sourcesDirty)\n return false;\n if (this.style && !this.style.loaded())\n return false;\n return true;\n },\n\n /**\n * Update this map's style and re-render the map.\n *\n * @param {Object} updateStyle new style\n * @returns {Map} this\n */\n update: function(updateStyle) {\n if (!this.style) return this;\n\n this._styleDirty = this._styleDirty || updateStyle;\n this._sourcesDirty = true;\n\n this._rerender();\n\n return this;\n },\n\n /**\n * Call when a (re-)render of the map is required, e.g. when the\n * user panned or zoomed,f or new data is available.\n * @returns {Map} this\n */\n render: function() {\n if (this.style && this._styleDirty) {\n this._styleDirty = false;\n this.style._recalculate(this.transform.zoom);\n }\n\n if (this.style && this._sourcesDirty && !this._sourcesDirtyTimeout) {\n this._sourcesDirty = false;\n this._sourcesDirtyTimeout = setTimeout(function() {\n this._sourcesDirtyTimeout = null;\n }.bind(this), 50);\n this.style._updateSources(this.transform);\n }\n\n this.painter.render(this.style, {\n debug: this.debug,\n vertices: this.vertices,\n rotating: this.rotating,\n zooming: this.zooming\n });\n\n this.fire('render');\n\n if (this.loaded() && !this._loaded) {\n this._loaded = true;\n this.fire('load');\n }\n\n this._frameId = null;\n\n if (!this.animationLoop.stopped()) {\n this._styleDirty = true;\n }\n\n if (this._sourcesDirty || this._repaint || !this.animationLoop.stopped()) {\n this._rerender();\n }\n\n return this;\n },\n\n /**\n * Destroys the map's underlying resources, including web workers.\n * @returns {Map} this\n */\n remove: function() {\n if (this._hash) this._hash.remove();\n browser.cancelFrame(this._frameId);\n clearTimeout(this._sourcesDirtyTimeout);\n this.setStyle(null);\n return this;\n },\n\n _rerender: function() {\n if (this.style && !this._frameId) {\n this._frameId = browser.frame(this.render);\n }\n },\n\n _forwardStyleEvent: function(e) {\n this.fire('style.' + e.type, util.extend({style: e.target}, e));\n },\n\n _forwardSourceEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardLayerEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardTileEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _onStyleLoad: function(e) {\n this.style._cascade(this._classes, {transition: false});\n this._forwardStyleEvent(e);\n },\n\n _onStyleChange: function(e) {\n this.update(true);\n this._forwardStyleEvent(e);\n },\n\n _onSourceAdd: function(e) {\n var source = e.source;\n if (source.onAdd)\n source.onAdd(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceRemove: function(e) {\n var source = e.source;\n if (source.onRemove)\n source.onRemove(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceUpdate: function(e) {\n this.update();\n this._forwardSourceEvent(e);\n }\n});\n\nutil.extendAll(Map.prototype, {\n\n // debug code\n _debug: false,\n get debug() { return this._debug; },\n set debug(value) { this._debug = value; this.update(); },\n\n // show collision boxes\n _collisionDebug: false,\n get collisionDebug() { return this._collisionDebug; },\n set collisionDebug(value) {\n this._collisionDebug = value;\n for (var i in this.style.sources) {\n this.style.sources[i].reload();\n }\n this.update();\n },\n\n // continuous repaint\n _repaint: false,\n get repaint() { return this._repaint; },\n set repaint(value) { this._repaint = value; this.update(); },\n\n // show vertices\n _vertices: false,\n get vertices() { return this._vertices; },\n set vertices(value) { this._vertices = value; this.update(); }\n});","path":"js/ui/map.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/map.js#L43-L91"},"params":[{"title":"param","description":null,"type":{"type":"NameExpression","name":"Object"},"name":"options"},{"title":"param","description":"HTML element to initialize the map in (or element id as string)","type":{"type":"NameExpression","name":"String"},"name":"options.container"}],"name":"Map","kind":"class","members":{"instance":[{"description":"Zooms to a certain zoom level with easing.","tags":[{"title":"param","description":null,"type":{"type":"NameExpression","name":"Number"},"name":"zoom"},{"title":"param","description":null,"type":null,"name":"animOptions"},{"title":"fires","description":"movestart"},{"title":"fires","description":"moveend"},{"title":"returns","description":null,"type":{"type":"NameExpression","name":"this"}},{"title":"name","name":"zoomTo"},{"title":"memberof","description":"Map"},{"title":"instance"}],"context":{"loc":{"start":{"line":112,"column":4},"end":{"line":160,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/easings.js","code":"{\n isEasing: function() {\n return !!this._abortFn;\n },\n\n /**\n * Stop current animation\n *\n * @returns {this}\n */\n stop: function() {\n if (this._abortFn) {\n this._abortFn.call(this);\n delete this._abortFn;\n\n this._finishFn.call(this);\n delete this._finishFn;\n }\n return this;\n },\n\n _ease: function(frame, finish, options) {\n this._finishFn = finish;\n this._abortFn = browser.timed(function (t) {\n frame.call(this, options.easing(t));\n if (t === 1) {\n delete this._abortFn;\n this._finishFn.call(this);\n delete this._finishFn;\n }\n }, options.animate === false ? 0 : options.duration, this);\n },\n\n /**\n * Pan by a certain number of pixels\n *\n * @param {Array} offset [x, y]\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n panBy: function(offset, options) {\n this.panTo(this.transform.center, util.extend({offset: Point.convert(offset).mult(-1)}, options));\n return this;\n },\n\n /**\n * Pan to a certain location with easing\n *\n * @param {Object} latlng a `LatLng` object\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n panTo: function(latlng, options) {\n this.stop();\n\n latlng = LatLng.convert(latlng);\n\n options = util.extend({\n duration: 500,\n easing: util.ease,\n offset: [0, 0]\n }, options);\n\n var tr = this.transform,\n offset = Point.convert(options.offset).rotate(-tr.angle),\n from = tr.point,\n to = tr.project(latlng).sub(offset);\n\n if (!options.noMoveStart) {\n this.fire('movestart');\n }\n\n this._ease(function(k) {\n tr.center = tr.unproject(from.add(to.sub(from).mult(k)));\n this._move();\n }, function() {\n this.fire('moveend');\n }, options);\n\n return this;\n },\n\n /**\n * Zooms to a certain zoom level with easing.\n *\n * @param {Number} zoom\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n zoomTo: function(zoom, options) {\n this.stop();\n\n options = util.extend({\n duration: 500\n }, options);\n\n options.easing = this._updateEasing(options.duration, zoom, options.easing);\n\n var tr = this.transform,\n around = tr.center,\n startZoom = tr.zoom;\n\n if (options.around) {\n around = LatLng.convert(options.around);\n } else if (options.offset) {\n around = tr.pointLocation(tr.centerPoint.add(Point.convert(options.offset)));\n }\n\n if (options.animate === false) options.duration = 0;\n\n if (!this.zooming) {\n this.zooming = true;\n this.fire('movestart');\n }\n\n this._ease(function(k) {\n tr.setZoomAround(interpolate(startZoom, zoom, k), around);\n this.animationLoop.set(300); // text fading\n this._move(true);\n }, function() {\n this.ease = null;\n if (options.duration >= 200) {\n this.zooming = false;\n this.fire('moveend');\n }\n }, options);\n\n if (options.duration < 200) {\n clearTimeout(this._onZoomEnd);\n this._onZoomEnd = setTimeout(function() {\n this.zooming = false;\n this._rerender();\n this.fire('moveend');\n }.bind(this), 200);\n }\n\n return this;\n },\n\n /**\n * Zoom in by 1 level\n *\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n zoomIn: function(options) {\n this.zoomTo(this.getZoom() + 1, options);\n },\n\n /**\n * Zoom out by 1 level\n *\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n zoomOut: function(options) {\n this.zoomTo(this.getZoom() - 1, options);\n },\n\n /**\n * Rotate bearing by a certain number of degrees with easing\n *\n * @param {Number} bearing\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n rotateTo: function(bearing, options) {\n this.stop();\n\n options = util.extend({\n duration: 500,\n easing: util.ease\n }, options);\n\n var tr = this.transform,\n start = this.getBearing(),\n around = tr.center;\n\n if (options.around) {\n around = LatLng.convert(options.around);\n } else if (options.offset) {\n around = tr.pointLocation(tr.centerPoint.add(Point.convert(options.offset)));\n }\n\n bearing = this._normalizeBearing(bearing, start);\n\n this.rotating = true;\n this.fire('movestart');\n\n this._ease(function(k) {\n tr.setBearingAround(interpolate(start, bearing, k), around);\n this._move(false, true);\n }, function() {\n this.rotating = false;\n this.fire('moveend');\n }, options);\n\n return this;\n },\n\n /**\n * Sets map bearing to 0 (north) with easing\n *\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n resetNorth: function(options) {\n return this.rotateTo(0, util.extend({duration: 1000}, options));\n },\n\n /**\n * Zoom to contain certain geographical bounds\n *\n * @param {Array} bounds [[minLat, minLng], [maxLat, maxLng]]\n * @param {Object} options\n * @param {Number} [options.speed=1.2] How fast animation occurs\n * @param {Number} [options.curve=1.42] How much zooming out occurs during animation\n * @param {Function} options.easing\n * @param {Number} options.padding how much padding there is around the given bounds on each side in pixels\n * @param {Number} options.maxZoom\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n fitBounds: function(bounds, options) {\n\n options = util.extend({\n padding: 0,\n offset: [0, 0],\n maxZoom: Infinity\n }, options);\n\n bounds = LatLngBounds.convert(bounds);\n\n var offset = Point.convert(options.offset),\n tr = this.transform,\n nw = tr.project(bounds.getNorthWest()),\n se = tr.project(bounds.getSouthEast()),\n size = se.sub(nw),\n center = tr.unproject(nw.add(se).div(2)),\n\n scaleX = (tr.width - options.padding * 2 - Math.abs(offset.x) * 2) / size.x,\n scaleY = (tr.height - options.padding * 2 - Math.abs(offset.y) * 2) / size.y,\n\n zoom = Math.min(tr.scaleZoom(tr.scale * Math.min(scaleX, scaleY)), options.maxZoom);\n\n return options.linear ?\n this.easeTo(center, zoom, 0, options) :\n this.flyTo(center, zoom, 0, options);\n },\n\n /**\n * Easing animation to a specified location/zoom/bearing\n *\n * @param {Object} latlng a `LatLng` object\n * @param {Number} zoom\n * @param {Number} bearing\n * @param {Number} pitch\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n easeTo: function(latlng, zoom, bearing, pitch, options) {\n this.stop();\n\n options = util.extend({\n offset: [0, 0],\n duration: 500,\n easing: util.ease\n }, options);\n\n var tr = this.transform,\n offset = Point.convert(options.offset).rotate(-tr.angle),\n startZoom = this.getZoom(),\n startBearing = this.getBearing(),\n startPitch = this.getPitch();\n\n latlng = LatLng.convert(latlng);\n zoom = zoom === undefined ? startZoom : zoom;\n bearing = bearing === undefined ? startBearing : this._normalizeBearing(bearing, startBearing);\n pitch = pitch === undefined ? startPitch : pitch;\n\n var scale = tr.zoomScale(zoom - startZoom),\n from = tr.point,\n to = latlng ? tr.project(latlng).sub(offset.div(scale)) : tr.point,\n around;\n\n if (zoom !== startZoom) {\n around = tr.pointLocation(tr.centerPoint.add(to.sub(from).div(1 - 1 / scale)));\n this.zooming = true;\n }\n if (startBearing !== bearing) this.rotating = true;\n\n this.fire('movestart');\n\n this._ease(function (k) {\n if (zoom !== startZoom) {\n tr.setZoomAround(interpolate(startZoom, zoom, k), around);\n } else {\n tr.center = tr.unproject(from.add(to.sub(from).mult(k)));\n }\n\n if (bearing !== startBearing) {\n tr.bearing = interpolate(startBearing, bearing, k);\n }\n\n if (pitch !== startPitch) {\n tr.pitch = interpolate(startPitch, pitch, k);\n }\n\n this.animationLoop.set(300); // text fading\n this._move(zoom !== startZoom, bearing !== startBearing);\n }, function() {\n this.zooming = false;\n this.rotating = false;\n this.fire('moveend');\n }, options);\n\n return this;\n },\n\n /**\n * Flying animation to a specified location/zoom/bearing with automatic curve\n *\n * @param {Object} latlng a `LatLng` object\n * @param {Number} zoom\n * @param {Number} bearing\n * @param {Object} options\n * @param {Number} [options.speed=1.2] How fast animation occurs\n * @param {Number} [options.curve=1.42] How much zooming out occurs during animation\n * @param {Function} options.easing\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n flyTo: function(latlng, zoom, bearing, options) {\n this.stop();\n\n options = util.extend({\n offset: [0, 0],\n speed: 1.2,\n curve: 1.42,\n easing: util.ease\n }, options);\n\n latlng = LatLng.convert(latlng);\n\n var offset = Point.convert(options.offset),\n tr = this.transform,\n startZoom = this.getZoom(),\n startBearing = this.getBearing();\n\n zoom = zoom === undefined ? startZoom : zoom;\n bearing = bearing === undefined ? startBearing : this._normalizeBearing(bearing, startBearing);\n\n var scale = tr.zoomScale(zoom - startZoom),\n from = tr.point,\n to = tr.project(latlng).sub(offset.div(scale));\n\n if (options.animate === false) {\n return this.setView(latlng, zoom, bearing, this.getPitch());\n }\n\n var startWorldSize = tr.worldSize,\n rho = options.curve,\n V = options.speed,\n\n w0 = Math.max(tr.width, tr.height),\n w1 = w0 / scale,\n u1 = to.sub(from).mag(),\n rho2 = rho * rho;\n\n function r(i) {\n var b = (w1 * w1 - w0 * w0 + (i ? -1 : 1) * rho2 * rho2 * u1 * u1) / (2 * (i ? w1 : w0) * rho2 * u1);\n return Math.log(Math.sqrt(b * b + 1) - b);\n }\n\n function sinh(n) { return (Math.exp(n) - Math.exp(-n)) / 2; }\n function cosh(n) { return (Math.exp(n) + Math.exp(-n)) / 2; }\n function tanh(n) { return sinh(n) / cosh(n); }\n\n var r0 = r(0),\n w = function (s) { return (cosh(r0) / cosh(r0 + rho * s)); },\n u = function (s) { return w0 * ((cosh(r0) * tanh(r0 + rho * s) - sinh(r0)) / rho2) / u1; },\n S = (r(1) - r0) / rho;\n\n if (Math.abs(u1) < 0.000001) {\n if (Math.abs(w0 - w1) < 0.000001) return this;\n\n var k = w1 < w0 ? -1 : 1;\n S = Math.abs(Math.log(w1 / w0)) / rho;\n\n u = function() { return 0; };\n w = function(s) { return Math.exp(k * rho * s); };\n }\n\n options.duration = 1000 * S / V;\n\n this.zooming = true;\n if (startBearing !== bearing) this.rotating = true;\n\n this.fire('movestart');\n\n this._ease(function (k) {\n var s = k * S,\n us = u(s);\n\n tr.zoom = startZoom + tr.scaleZoom(1 / w(s));\n tr.center = tr.unproject(from.add(to.sub(from).mult(us)), startWorldSize);\n\n if (bearing !== startBearing) {\n tr.bearing = interpolate(startBearing, bearing, k);\n }\n\n this.animationLoop.set(300); // text fading\n\n this._move(true, bearing !== startBearing);\n }, function() {\n this.zooming = false;\n this.rotating = false;\n this.fire('moveend');\n }, options);\n\n return this;\n },\n\n // convert bearing so that it's numerically close to the current one so that it interpolates properly\n _normalizeBearing: function(bearing, currentBearing) {\n bearing = util.wrap(bearing, -180, 180);\n var diff = Math.abs(bearing - currentBearing);\n if (Math.abs(bearing - 360 - currentBearing) < diff) bearing -= 360;\n if (Math.abs(bearing + 360 - currentBearing) < diff) bearing += 360;\n return bearing;\n },\n\n _updateEasing: function(duration, zoom, bezier) {\n var easing;\n\n if (this.ease) {\n var ease = this.ease,\n t = (Date.now() - ease.start) / ease.duration,\n speed = ease.easing(t + 0.01) - ease.easing(t),\n\n // Quick hack to make new bezier that is continuous with last\n x = 0.27 / Math.sqrt(speed * speed + 0.0001) * 0.01,\n y = Math.sqrt(0.27 * 0.27 - x * x);\n\n easing = util.bezier(x, y, 0.25, 1);\n } else {\n easing = bezier ? util.bezier.apply(util, bezier) : util.ease;\n }\n\n // store information on current easing\n this.ease = {\n start: (new Date()).getTime(),\n to: Math.pow(2, zoom),\n duration: duration,\n easing: easing\n };\n\n return easing;\n }\n}","path":"js/ui/easings.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/easings.js#L112-L160"},"params":[{"title":"param","description":null,"type":{"type":"NameExpression","name":"Number"},"name":"zoom"},{"title":"param","description":null,"type":null,"name":"animOptions"}],"returns":[{"title":"returns","description":null,"type":{"type":"NameExpression","name":"this"}}],"name":"zoomTo","memberof":"Map","scope":"instance","members":{"instance":[],"static":[]},"path":["Map","zoomTo"]},{"description":"Zoom out by 1 level","tags":[{"title":"param","description":null,"type":null,"name":"animOptions"},{"title":"fires","description":"movestart"},{"title":"fires","description":"moveend"},{"title":"returns","description":null,"type":{"type":"NameExpression","name":"this"}},{"title":"name","name":"zoomOut"},{"title":"memberof","description":"Map"},{"title":"instance"}],"context":{"loc":{"start":{"line":182,"column":4},"end":{"line":184,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/easings.js","code":"{\n isEasing: function() {\n return !!this._abortFn;\n },\n\n /**\n * Stop current animation\n *\n * @returns {this}\n */\n stop: function() {\n if (this._abortFn) {\n this._abortFn.call(this);\n delete this._abortFn;\n\n this._finishFn.call(this);\n delete this._finishFn;\n }\n return this;\n },\n\n _ease: function(frame, finish, options) {\n this._finishFn = finish;\n this._abortFn = browser.timed(function (t) {\n frame.call(this, options.easing(t));\n if (t === 1) {\n delete this._abortFn;\n this._finishFn.call(this);\n delete this._finishFn;\n }\n }, options.animate === false ? 0 : options.duration, this);\n },\n\n /**\n * Pan by a certain number of pixels\n *\n * @param {Array} offset [x, y]\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n panBy: function(offset, options) {\n this.panTo(this.transform.center, util.extend({offset: Point.convert(offset).mult(-1)}, options));\n return this;\n },\n\n /**\n * Pan to a certain location with easing\n *\n * @param {Object} latlng a `LatLng` object\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n panTo: function(latlng, options) {\n this.stop();\n\n latlng = LatLng.convert(latlng);\n\n options = util.extend({\n duration: 500,\n easing: util.ease,\n offset: [0, 0]\n }, options);\n\n var tr = this.transform,\n offset = Point.convert(options.offset).rotate(-tr.angle),\n from = tr.point,\n to = tr.project(latlng).sub(offset);\n\n if (!options.noMoveStart) {\n this.fire('movestart');\n }\n\n this._ease(function(k) {\n tr.center = tr.unproject(from.add(to.sub(from).mult(k)));\n this._move();\n }, function() {\n this.fire('moveend');\n }, options);\n\n return this;\n },\n\n /**\n * Zooms to a certain zoom level with easing.\n *\n * @param {Number} zoom\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n zoomTo: function(zoom, options) {\n this.stop();\n\n options = util.extend({\n duration: 500\n }, options);\n\n options.easing = this._updateEasing(options.duration, zoom, options.easing);\n\n var tr = this.transform,\n around = tr.center,\n startZoom = tr.zoom;\n\n if (options.around) {\n around = LatLng.convert(options.around);\n } else if (options.offset) {\n around = tr.pointLocation(tr.centerPoint.add(Point.convert(options.offset)));\n }\n\n if (options.animate === false) options.duration = 0;\n\n if (!this.zooming) {\n this.zooming = true;\n this.fire('movestart');\n }\n\n this._ease(function(k) {\n tr.setZoomAround(interpolate(startZoom, zoom, k), around);\n this.animationLoop.set(300); // text fading\n this._move(true);\n }, function() {\n this.ease = null;\n if (options.duration >= 200) {\n this.zooming = false;\n this.fire('moveend');\n }\n }, options);\n\n if (options.duration < 200) {\n clearTimeout(this._onZoomEnd);\n this._onZoomEnd = setTimeout(function() {\n this.zooming = false;\n this._rerender();\n this.fire('moveend');\n }.bind(this), 200);\n }\n\n return this;\n },\n\n /**\n * Zoom in by 1 level\n *\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n zoomIn: function(options) {\n this.zoomTo(this.getZoom() + 1, options);\n },\n\n /**\n * Zoom out by 1 level\n *\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n zoomOut: function(options) {\n this.zoomTo(this.getZoom() - 1, options);\n },\n\n /**\n * Rotate bearing by a certain number of degrees with easing\n *\n * @param {Number} bearing\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n rotateTo: function(bearing, options) {\n this.stop();\n\n options = util.extend({\n duration: 500,\n easing: util.ease\n }, options);\n\n var tr = this.transform,\n start = this.getBearing(),\n around = tr.center;\n\n if (options.around) {\n around = LatLng.convert(options.around);\n } else if (options.offset) {\n around = tr.pointLocation(tr.centerPoint.add(Point.convert(options.offset)));\n }\n\n bearing = this._normalizeBearing(bearing, start);\n\n this.rotating = true;\n this.fire('movestart');\n\n this._ease(function(k) {\n tr.setBearingAround(interpolate(start, bearing, k), around);\n this._move(false, true);\n }, function() {\n this.rotating = false;\n this.fire('moveend');\n }, options);\n\n return this;\n },\n\n /**\n * Sets map bearing to 0 (north) with easing\n *\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n resetNorth: function(options) {\n return this.rotateTo(0, util.extend({duration: 1000}, options));\n },\n\n /**\n * Zoom to contain certain geographical bounds\n *\n * @param {Array} bounds [[minLat, minLng], [maxLat, maxLng]]\n * @param {Object} options\n * @param {Number} [options.speed=1.2] How fast animation occurs\n * @param {Number} [options.curve=1.42] How much zooming out occurs during animation\n * @param {Function} options.easing\n * @param {Number} options.padding how much padding there is around the given bounds on each side in pixels\n * @param {Number} options.maxZoom\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n fitBounds: function(bounds, options) {\n\n options = util.extend({\n padding: 0,\n offset: [0, 0],\n maxZoom: Infinity\n }, options);\n\n bounds = LatLngBounds.convert(bounds);\n\n var offset = Point.convert(options.offset),\n tr = this.transform,\n nw = tr.project(bounds.getNorthWest()),\n se = tr.project(bounds.getSouthEast()),\n size = se.sub(nw),\n center = tr.unproject(nw.add(se).div(2)),\n\n scaleX = (tr.width - options.padding * 2 - Math.abs(offset.x) * 2) / size.x,\n scaleY = (tr.height - options.padding * 2 - Math.abs(offset.y) * 2) / size.y,\n\n zoom = Math.min(tr.scaleZoom(tr.scale * Math.min(scaleX, scaleY)), options.maxZoom);\n\n return options.linear ?\n this.easeTo(center, zoom, 0, options) :\n this.flyTo(center, zoom, 0, options);\n },\n\n /**\n * Easing animation to a specified location/zoom/bearing\n *\n * @param {Object} latlng a `LatLng` object\n * @param {Number} zoom\n * @param {Number} bearing\n * @param {Number} pitch\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n easeTo: function(latlng, zoom, bearing, pitch, options) {\n this.stop();\n\n options = util.extend({\n offset: [0, 0],\n duration: 500,\n easing: util.ease\n }, options);\n\n var tr = this.transform,\n offset = Point.convert(options.offset).rotate(-tr.angle),\n startZoom = this.getZoom(),\n startBearing = this.getBearing(),\n startPitch = this.getPitch();\n\n latlng = LatLng.convert(latlng);\n zoom = zoom === undefined ? startZoom : zoom;\n bearing = bearing === undefined ? startBearing : this._normalizeBearing(bearing, startBearing);\n pitch = pitch === undefined ? startPitch : pitch;\n\n var scale = tr.zoomScale(zoom - startZoom),\n from = tr.point,\n to = latlng ? tr.project(latlng).sub(offset.div(scale)) : tr.point,\n around;\n\n if (zoom !== startZoom) {\n around = tr.pointLocation(tr.centerPoint.add(to.sub(from).div(1 - 1 / scale)));\n this.zooming = true;\n }\n if (startBearing !== bearing) this.rotating = true;\n\n this.fire('movestart');\n\n this._ease(function (k) {\n if (zoom !== startZoom) {\n tr.setZoomAround(interpolate(startZoom, zoom, k), around);\n } else {\n tr.center = tr.unproject(from.add(to.sub(from).mult(k)));\n }\n\n if (bearing !== startBearing) {\n tr.bearing = interpolate(startBearing, bearing, k);\n }\n\n if (pitch !== startPitch) {\n tr.pitch = interpolate(startPitch, pitch, k);\n }\n\n this.animationLoop.set(300); // text fading\n this._move(zoom !== startZoom, bearing !== startBearing);\n }, function() {\n this.zooming = false;\n this.rotating = false;\n this.fire('moveend');\n }, options);\n\n return this;\n },\n\n /**\n * Flying animation to a specified location/zoom/bearing with automatic curve\n *\n * @param {Object} latlng a `LatLng` object\n * @param {Number} zoom\n * @param {Number} bearing\n * @param {Object} options\n * @param {Number} [options.speed=1.2] How fast animation occurs\n * @param {Number} [options.curve=1.42] How much zooming out occurs during animation\n * @param {Function} options.easing\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n flyTo: function(latlng, zoom, bearing, options) {\n this.stop();\n\n options = util.extend({\n offset: [0, 0],\n speed: 1.2,\n curve: 1.42,\n easing: util.ease\n }, options);\n\n latlng = LatLng.convert(latlng);\n\n var offset = Point.convert(options.offset),\n tr = this.transform,\n startZoom = this.getZoom(),\n startBearing = this.getBearing();\n\n zoom = zoom === undefined ? startZoom : zoom;\n bearing = bearing === undefined ? startBearing : this._normalizeBearing(bearing, startBearing);\n\n var scale = tr.zoomScale(zoom - startZoom),\n from = tr.point,\n to = tr.project(latlng).sub(offset.div(scale));\n\n if (options.animate === false) {\n return this.setView(latlng, zoom, bearing, this.getPitch());\n }\n\n var startWorldSize = tr.worldSize,\n rho = options.curve,\n V = options.speed,\n\n w0 = Math.max(tr.width, tr.height),\n w1 = w0 / scale,\n u1 = to.sub(from).mag(),\n rho2 = rho * rho;\n\n function r(i) {\n var b = (w1 * w1 - w0 * w0 + (i ? -1 : 1) * rho2 * rho2 * u1 * u1) / (2 * (i ? w1 : w0) * rho2 * u1);\n return Math.log(Math.sqrt(b * b + 1) - b);\n }\n\n function sinh(n) { return (Math.exp(n) - Math.exp(-n)) / 2; }\n function cosh(n) { return (Math.exp(n) + Math.exp(-n)) / 2; }\n function tanh(n) { return sinh(n) / cosh(n); }\n\n var r0 = r(0),\n w = function (s) { return (cosh(r0) / cosh(r0 + rho * s)); },\n u = function (s) { return w0 * ((cosh(r0) * tanh(r0 + rho * s) - sinh(r0)) / rho2) / u1; },\n S = (r(1) - r0) / rho;\n\n if (Math.abs(u1) < 0.000001) {\n if (Math.abs(w0 - w1) < 0.000001) return this;\n\n var k = w1 < w0 ? -1 : 1;\n S = Math.abs(Math.log(w1 / w0)) / rho;\n\n u = function() { return 0; };\n w = function(s) { return Math.exp(k * rho * s); };\n }\n\n options.duration = 1000 * S / V;\n\n this.zooming = true;\n if (startBearing !== bearing) this.rotating = true;\n\n this.fire('movestart');\n\n this._ease(function (k) {\n var s = k * S,\n us = u(s);\n\n tr.zoom = startZoom + tr.scaleZoom(1 / w(s));\n tr.center = tr.unproject(from.add(to.sub(from).mult(us)), startWorldSize);\n\n if (bearing !== startBearing) {\n tr.bearing = interpolate(startBearing, bearing, k);\n }\n\n this.animationLoop.set(300); // text fading\n\n this._move(true, bearing !== startBearing);\n }, function() {\n this.zooming = false;\n this.rotating = false;\n this.fire('moveend');\n }, options);\n\n return this;\n },\n\n // convert bearing so that it's numerically close to the current one so that it interpolates properly\n _normalizeBearing: function(bearing, currentBearing) {\n bearing = util.wrap(bearing, -180, 180);\n var diff = Math.abs(bearing - currentBearing);\n if (Math.abs(bearing - 360 - currentBearing) < diff) bearing -= 360;\n if (Math.abs(bearing + 360 - currentBearing) < diff) bearing += 360;\n return bearing;\n },\n\n _updateEasing: function(duration, zoom, bezier) {\n var easing;\n\n if (this.ease) {\n var ease = this.ease,\n t = (Date.now() - ease.start) / ease.duration,\n speed = ease.easing(t + 0.01) - ease.easing(t),\n\n // Quick hack to make new bezier that is continuous with last\n x = 0.27 / Math.sqrt(speed * speed + 0.0001) * 0.01,\n y = Math.sqrt(0.27 * 0.27 - x * x);\n\n easing = util.bezier(x, y, 0.25, 1);\n } else {\n easing = bezier ? util.bezier.apply(util, bezier) : util.ease;\n }\n\n // store information on current easing\n this.ease = {\n start: (new Date()).getTime(),\n to: Math.pow(2, zoom),\n duration: duration,\n easing: easing\n };\n\n return easing;\n }\n}","path":"js/ui/easings.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/easings.js#L182-L184"},"params":[{"title":"param","description":null,"type":null,"name":"animOptions"}],"returns":[{"title":"returns","description":null,"type":{"type":"NameExpression","name":"this"}}],"name":"zoomOut","memberof":"Map","scope":"instance","members":{"instance":[],"static":[]},"path":["Map","zoomOut"]},{"description":"Zoom in by 1 level","tags":[{"title":"param","description":null,"type":null,"name":"animOptions"},{"title":"fires","description":"movestart"},{"title":"fires","description":"moveend"},{"title":"returns","description":null,"type":{"type":"NameExpression","name":"this"}},{"title":"name","name":"zoomIn"},{"title":"memberof","description":"Map"},{"title":"instance"}],"context":{"loc":{"start":{"line":170,"column":4},"end":{"line":172,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/easings.js","code":"{\n isEasing: function() {\n return !!this._abortFn;\n },\n\n /**\n * Stop current animation\n *\n * @returns {this}\n */\n stop: function() {\n if (this._abortFn) {\n this._abortFn.call(this);\n delete this._abortFn;\n\n this._finishFn.call(this);\n delete this._finishFn;\n }\n return this;\n },\n\n _ease: function(frame, finish, options) {\n this._finishFn = finish;\n this._abortFn = browser.timed(function (t) {\n frame.call(this, options.easing(t));\n if (t === 1) {\n delete this._abortFn;\n this._finishFn.call(this);\n delete this._finishFn;\n }\n }, options.animate === false ? 0 : options.duration, this);\n },\n\n /**\n * Pan by a certain number of pixels\n *\n * @param {Array} offset [x, y]\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n panBy: function(offset, options) {\n this.panTo(this.transform.center, util.extend({offset: Point.convert(offset).mult(-1)}, options));\n return this;\n },\n\n /**\n * Pan to a certain location with easing\n *\n * @param {Object} latlng a `LatLng` object\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n panTo: function(latlng, options) {\n this.stop();\n\n latlng = LatLng.convert(latlng);\n\n options = util.extend({\n duration: 500,\n easing: util.ease,\n offset: [0, 0]\n }, options);\n\n var tr = this.transform,\n offset = Point.convert(options.offset).rotate(-tr.angle),\n from = tr.point,\n to = tr.project(latlng).sub(offset);\n\n if (!options.noMoveStart) {\n this.fire('movestart');\n }\n\n this._ease(function(k) {\n tr.center = tr.unproject(from.add(to.sub(from).mult(k)));\n this._move();\n }, function() {\n this.fire('moveend');\n }, options);\n\n return this;\n },\n\n /**\n * Zooms to a certain zoom level with easing.\n *\n * @param {Number} zoom\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n zoomTo: function(zoom, options) {\n this.stop();\n\n options = util.extend({\n duration: 500\n }, options);\n\n options.easing = this._updateEasing(options.duration, zoom, options.easing);\n\n var tr = this.transform,\n around = tr.center,\n startZoom = tr.zoom;\n\n if (options.around) {\n around = LatLng.convert(options.around);\n } else if (options.offset) {\n around = tr.pointLocation(tr.centerPoint.add(Point.convert(options.offset)));\n }\n\n if (options.animate === false) options.duration = 0;\n\n if (!this.zooming) {\n this.zooming = true;\n this.fire('movestart');\n }\n\n this._ease(function(k) {\n tr.setZoomAround(interpolate(startZoom, zoom, k), around);\n this.animationLoop.set(300); // text fading\n this._move(true);\n }, function() {\n this.ease = null;\n if (options.duration >= 200) {\n this.zooming = false;\n this.fire('moveend');\n }\n }, options);\n\n if (options.duration < 200) {\n clearTimeout(this._onZoomEnd);\n this._onZoomEnd = setTimeout(function() {\n this.zooming = false;\n this._rerender();\n this.fire('moveend');\n }.bind(this), 200);\n }\n\n return this;\n },\n\n /**\n * Zoom in by 1 level\n *\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n zoomIn: function(options) {\n this.zoomTo(this.getZoom() + 1, options);\n },\n\n /**\n * Zoom out by 1 level\n *\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n zoomOut: function(options) {\n this.zoomTo(this.getZoom() - 1, options);\n },\n\n /**\n * Rotate bearing by a certain number of degrees with easing\n *\n * @param {Number} bearing\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n rotateTo: function(bearing, options) {\n this.stop();\n\n options = util.extend({\n duration: 500,\n easing: util.ease\n }, options);\n\n var tr = this.transform,\n start = this.getBearing(),\n around = tr.center;\n\n if (options.around) {\n around = LatLng.convert(options.around);\n } else if (options.offset) {\n around = tr.pointLocation(tr.centerPoint.add(Point.convert(options.offset)));\n }\n\n bearing = this._normalizeBearing(bearing, start);\n\n this.rotating = true;\n this.fire('movestart');\n\n this._ease(function(k) {\n tr.setBearingAround(interpolate(start, bearing, k), around);\n this._move(false, true);\n }, function() {\n this.rotating = false;\n this.fire('moveend');\n }, options);\n\n return this;\n },\n\n /**\n * Sets map bearing to 0 (north) with easing\n *\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n resetNorth: function(options) {\n return this.rotateTo(0, util.extend({duration: 1000}, options));\n },\n\n /**\n * Zoom to contain certain geographical bounds\n *\n * @param {Array} bounds [[minLat, minLng], [maxLat, maxLng]]\n * @param {Object} options\n * @param {Number} [options.speed=1.2] How fast animation occurs\n * @param {Number} [options.curve=1.42] How much zooming out occurs during animation\n * @param {Function} options.easing\n * @param {Number} options.padding how much padding there is around the given bounds on each side in pixels\n * @param {Number} options.maxZoom\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n fitBounds: function(bounds, options) {\n\n options = util.extend({\n padding: 0,\n offset: [0, 0],\n maxZoom: Infinity\n }, options);\n\n bounds = LatLngBounds.convert(bounds);\n\n var offset = Point.convert(options.offset),\n tr = this.transform,\n nw = tr.project(bounds.getNorthWest()),\n se = tr.project(bounds.getSouthEast()),\n size = se.sub(nw),\n center = tr.unproject(nw.add(se).div(2)),\n\n scaleX = (tr.width - options.padding * 2 - Math.abs(offset.x) * 2) / size.x,\n scaleY = (tr.height - options.padding * 2 - Math.abs(offset.y) * 2) / size.y,\n\n zoom = Math.min(tr.scaleZoom(tr.scale * Math.min(scaleX, scaleY)), options.maxZoom);\n\n return options.linear ?\n this.easeTo(center, zoom, 0, options) :\n this.flyTo(center, zoom, 0, options);\n },\n\n /**\n * Easing animation to a specified location/zoom/bearing\n *\n * @param {Object} latlng a `LatLng` object\n * @param {Number} zoom\n * @param {Number} bearing\n * @param {Number} pitch\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n easeTo: function(latlng, zoom, bearing, pitch, options) {\n this.stop();\n\n options = util.extend({\n offset: [0, 0],\n duration: 500,\n easing: util.ease\n }, options);\n\n var tr = this.transform,\n offset = Point.convert(options.offset).rotate(-tr.angle),\n startZoom = this.getZoom(),\n startBearing = this.getBearing(),\n startPitch = this.getPitch();\n\n latlng = LatLng.convert(latlng);\n zoom = zoom === undefined ? startZoom : zoom;\n bearing = bearing === undefined ? startBearing : this._normalizeBearing(bearing, startBearing);\n pitch = pitch === undefined ? startPitch : pitch;\n\n var scale = tr.zoomScale(zoom - startZoom),\n from = tr.point,\n to = latlng ? tr.project(latlng).sub(offset.div(scale)) : tr.point,\n around;\n\n if (zoom !== startZoom) {\n around = tr.pointLocation(tr.centerPoint.add(to.sub(from).div(1 - 1 / scale)));\n this.zooming = true;\n }\n if (startBearing !== bearing) this.rotating = true;\n\n this.fire('movestart');\n\n this._ease(function (k) {\n if (zoom !== startZoom) {\n tr.setZoomAround(interpolate(startZoom, zoom, k), around);\n } else {\n tr.center = tr.unproject(from.add(to.sub(from).mult(k)));\n }\n\n if (bearing !== startBearing) {\n tr.bearing = interpolate(startBearing, bearing, k);\n }\n\n if (pitch !== startPitch) {\n tr.pitch = interpolate(startPitch, pitch, k);\n }\n\n this.animationLoop.set(300); // text fading\n this._move(zoom !== startZoom, bearing !== startBearing);\n }, function() {\n this.zooming = false;\n this.rotating = false;\n this.fire('moveend');\n }, options);\n\n return this;\n },\n\n /**\n * Flying animation to a specified location/zoom/bearing with automatic curve\n *\n * @param {Object} latlng a `LatLng` object\n * @param {Number} zoom\n * @param {Number} bearing\n * @param {Object} options\n * @param {Number} [options.speed=1.2] How fast animation occurs\n * @param {Number} [options.curve=1.42] How much zooming out occurs during animation\n * @param {Function} options.easing\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n flyTo: function(latlng, zoom, bearing, options) {\n this.stop();\n\n options = util.extend({\n offset: [0, 0],\n speed: 1.2,\n curve: 1.42,\n easing: util.ease\n }, options);\n\n latlng = LatLng.convert(latlng);\n\n var offset = Point.convert(options.offset),\n tr = this.transform,\n startZoom = this.getZoom(),\n startBearing = this.getBearing();\n\n zoom = zoom === undefined ? startZoom : zoom;\n bearing = bearing === undefined ? startBearing : this._normalizeBearing(bearing, startBearing);\n\n var scale = tr.zoomScale(zoom - startZoom),\n from = tr.point,\n to = tr.project(latlng).sub(offset.div(scale));\n\n if (options.animate === false) {\n return this.setView(latlng, zoom, bearing, this.getPitch());\n }\n\n var startWorldSize = tr.worldSize,\n rho = options.curve,\n V = options.speed,\n\n w0 = Math.max(tr.width, tr.height),\n w1 = w0 / scale,\n u1 = to.sub(from).mag(),\n rho2 = rho * rho;\n\n function r(i) {\n var b = (w1 * w1 - w0 * w0 + (i ? -1 : 1) * rho2 * rho2 * u1 * u1) / (2 * (i ? w1 : w0) * rho2 * u1);\n return Math.log(Math.sqrt(b * b + 1) - b);\n }\n\n function sinh(n) { return (Math.exp(n) - Math.exp(-n)) / 2; }\n function cosh(n) { return (Math.exp(n) + Math.exp(-n)) / 2; }\n function tanh(n) { return sinh(n) / cosh(n); }\n\n var r0 = r(0),\n w = function (s) { return (cosh(r0) / cosh(r0 + rho * s)); },\n u = function (s) { return w0 * ((cosh(r0) * tanh(r0 + rho * s) - sinh(r0)) / rho2) / u1; },\n S = (r(1) - r0) / rho;\n\n if (Math.abs(u1) < 0.000001) {\n if (Math.abs(w0 - w1) < 0.000001) return this;\n\n var k = w1 < w0 ? -1 : 1;\n S = Math.abs(Math.log(w1 / w0)) / rho;\n\n u = function() { return 0; };\n w = function(s) { return Math.exp(k * rho * s); };\n }\n\n options.duration = 1000 * S / V;\n\n this.zooming = true;\n if (startBearing !== bearing) this.rotating = true;\n\n this.fire('movestart');\n\n this._ease(function (k) {\n var s = k * S,\n us = u(s);\n\n tr.zoom = startZoom + tr.scaleZoom(1 / w(s));\n tr.center = tr.unproject(from.add(to.sub(from).mult(us)), startWorldSize);\n\n if (bearing !== startBearing) {\n tr.bearing = interpolate(startBearing, bearing, k);\n }\n\n this.animationLoop.set(300); // text fading\n\n this._move(true, bearing !== startBearing);\n }, function() {\n this.zooming = false;\n this.rotating = false;\n this.fire('moveend');\n }, options);\n\n return this;\n },\n\n // convert bearing so that it's numerically close to the current one so that it interpolates properly\n _normalizeBearing: function(bearing, currentBearing) {\n bearing = util.wrap(bearing, -180, 180);\n var diff = Math.abs(bearing - currentBearing);\n if (Math.abs(bearing - 360 - currentBearing) < diff) bearing -= 360;\n if (Math.abs(bearing + 360 - currentBearing) < diff) bearing += 360;\n return bearing;\n },\n\n _updateEasing: function(duration, zoom, bezier) {\n var easing;\n\n if (this.ease) {\n var ease = this.ease,\n t = (Date.now() - ease.start) / ease.duration,\n speed = ease.easing(t + 0.01) - ease.easing(t),\n\n // Quick hack to make new bezier that is continuous with last\n x = 0.27 / Math.sqrt(speed * speed + 0.0001) * 0.01,\n y = Math.sqrt(0.27 * 0.27 - x * x);\n\n easing = util.bezier(x, y, 0.25, 1);\n } else {\n easing = bezier ? util.bezier.apply(util, bezier) : util.ease;\n }\n\n // store information on current easing\n this.ease = {\n start: (new Date()).getTime(),\n to: Math.pow(2, zoom),\n duration: duration,\n easing: easing\n };\n\n return easing;\n }\n}","path":"js/ui/easings.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/easings.js#L170-L172"},"params":[{"title":"param","description":null,"type":null,"name":"animOptions"}],"returns":[{"title":"returns","description":null,"type":{"type":"NameExpression","name":"this"}}],"name":"zoomIn","memberof":"Map","scope":"instance","members":{"instance":[],"static":[]},"path":["Map","zoomIn"]},{"description":"Update this map's style and re-render the map.","tags":[{"title":"param","description":"new style","type":{"type":"NameExpression","name":"Object"},"name":"updateStyle"},{"title":"returns","description":"this","type":{"type":"NameExpression","name":"Map"}},{"title":"name","name":"update"},{"title":"memberof","description":"Map"},{"title":"instance"}],"context":{"loc":{"start":{"line":667,"column":4},"end":{"line":676,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/map.js","code":"{\n\n options: {\n center: [0, 0],\n zoom: 0,\n bearing: 0,\n pitch: 0,\n\n minZoom: 0,\n maxZoom: 20,\n\n interactive: true,\n hash: false,\n\n attributionControl: true,\n\n failIfMajorPerformanceCaveat: false\n },\n\n addControl: function(control) {\n control.addTo(this);\n return this;\n },\n\n /**\n * Sets a map position\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @param {number} zoom Map zoom level\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setView: function(center, zoom, bearing, pitch) {\n this.stop();\n\n var tr = this.transform,\n zoomChanged = tr.zoom !== +zoom,\n bearingChanged = tr.bearing !== +bearing,\n pitchChanged = tr.pitch !== +pitch;\n\n tr.center = LatLng.convert(center);\n tr.zoom = +zoom;\n tr.bearing = +bearing;\n tr.pitch = +pitch;\n\n return this\n .fire('movestart')\n ._move(zoomChanged, bearingChanged, pitchChanged)\n .fire('moveend');\n },\n\n /**\n * Sets a map location\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setCenter: function(center) {\n this.setView(center, this.getZoom(), this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map zoom\n *\n * @param {number} zoom Map zoom level\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setZoom: function(zoom) {\n this.setView(this.getCenter(), zoom, this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map rotation\n *\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setBearing: function(bearing) {\n this.setView(this.getCenter(), this.getZoom(), bearing, this.getPitch());\n },\n\n /**\n * Sets a map angle\n *\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setPitch: function(pitch) {\n this.setView(this.getCenter(), this.getZoom(), this.getBearing(), pitch);\n },\n\n /**\n * Get the current view geographical point\n * @returns {LatLng}\n */\n getCenter: function() { return this.transform.center; },\n\n /**\n * Get the current zoom\n * @returns {number}\n */\n getZoom: function() { return this.transform.zoom; },\n\n /**\n * Get the current bearing in degrees\n * @returns {number}\n */\n getBearing: function() { return this.transform.bearing; },\n\n /**\n * Get the current angle in degrees\n * @returns {number}\n */\n getPitch: function() { return this.transform.pitch; },\n\n /**\n * @typedef {Object} [styleOptions]\n * @param {Boolean} [styleOptions.transition=true]\n */\n\n /**\n * Adds a style class to a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n addClass: function(klass, options) {\n if (this._classes[klass]) return;\n this._classes[klass] = true;\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Removes a style class from a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n removeClass: function(klass, options) {\n if (!this._classes[klass]) return;\n delete this._classes[klass];\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Helper method to add more than one class\n *\n * @param {Array} klasses An array of class names\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n setClasses: function(klasses, options) {\n this._classes = {};\n for (var i = 0; i < klasses.length; i++) {\n this._classes[klasses[i]] = true;\n }\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Check whether a style class is active\n *\n * @param {string} klass Name of style class\n * @returns {boolean}\n */\n hasClass: function(klass) {\n return !!this._classes[klass];\n },\n\n /**\n * Return an array of the current active style classes\n *\n * @returns {boolean}\n */\n getClasses: function() {\n return Object.keys(this._classes);\n },\n\n /**\n * Detect the map's new width and height and resize it.\n *\n * @returns {Map} `this`\n */\n resize: function() {\n var width = 0, height = 0;\n\n if (this._container) {\n width = this._container.offsetWidth || 400;\n height = this._container.offsetHeight || 300;\n }\n\n this._canvas.resize(width, height);\n\n this.transform.width = width;\n this.transform.height = height;\n this.transform._constrain();\n\n this.painter.resize(width, height);\n\n return this\n .fire('movestart')\n ._move()\n .fire('resize')\n .fire('moveend');\n },\n\n /**\n * Get the map's geographical bounds\n *\n * @returns {LatLngBounds}\n */\n getBounds: function() {\n return new LatLngBounds(\n this.transform.pointLocation(new Point(0, 0)),\n this.transform.pointLocation(this.transform.size));\n },\n\n /**\n * Get pixel coordinates (relative to map container) given a geographical location\n *\n * @param {LatLng} latlng\n * @returns {Object} `x` and `y` coordinates\n */\n project: function(latlng) {\n return this.transform.locationPoint(LatLng.convert(latlng));\n },\n\n /**\n * Get geographical coordinates given pixel coordinates\n *\n * @param {Array} point [x, y] pixel coordinates\n * @returns {LatLng}\n */\n unproject: function(point) {\n return this.transform.pointLocation(Point.convert(point));\n },\n\n /**\n * Get all features at a point ([x, y])\n *\n * @param {Array} point [x, y] pixel coordinates\n * @param {Object} params\n * @param {number} [params.radius=0] Optional. Radius in pixels to search in\n * @param {string} params.layer Optional. Only return features from a given layer\n * @param {string} params.type Optional. Either `raster` or `vector`\n * @param {featuresAtCallback} callback function that returns the response\n *\n * @callback featuresAtCallback\n * @param {Object|null} err Error _If any_\n * @param {Array} features Displays a JSON array of features given the passed parameters of `featuresAt`\n *\n * @returns {Map} `this`\n */\n featuresAt: function(point, params, callback) {\n var coord = this.transform.pointCoordinate(Point.convert(point));\n this.style.featuresAt(coord, params, callback);\n return this;\n },\n\n /**\n * Replaces the map's style object\n *\n * @param {Object} style A style object formatted as JSON\n * @returns {Map} `this`\n */\n setStyle: function(style) {\n if (this.style) {\n this.style\n .off('load', this._onStyleLoad)\n .off('error', this._forwardStyleEvent)\n .off('change', this._onStyleChange)\n .off('source.add', this._onSourceAdd)\n .off('source.remove', this._onSourceRemove)\n .off('source.load', this._onSourceUpdate)\n .off('source.error', this._forwardSourceEvent)\n .off('source.change', this._onSourceUpdate)\n .off('layer.add', this._forwardLayerEvent)\n .off('layer.remove', this._forwardLayerEvent)\n .off('tile.add', this._forwardTileEvent)\n .off('tile.remove', this._forwardTileEvent)\n .off('tile.load', this.update)\n .off('tile.error', this._forwardTileEvent)\n ._remove();\n\n this.off('rotate', this.style._redoPlacement);\n this.off('pitch', this.style._redoPlacement);\n }\n\n if (!style) {\n this.style = null;\n return this;\n } else if (style instanceof Style) {\n this.style = style;\n } else {\n this.style = new Style(style, this.animationLoop);\n }\n\n this.style\n .on('load', this._onStyleLoad)\n .on('error', this._forwardStyleEvent)\n .on('change', this._onStyleChange)\n .on('source.add', this._onSourceAdd)\n .on('source.remove', this._onSourceRemove)\n .on('source.load', this._onSourceUpdate)\n .on('source.error', this._forwardSourceEvent)\n .on('source.change', this._onSourceUpdate)\n .on('layer.add', this._forwardLayerEvent)\n .on('layer.remove', this._forwardLayerEvent)\n .on('tile.add', this._forwardTileEvent)\n .on('tile.remove', this._forwardTileEvent)\n .on('tile.load', this.update)\n .on('tile.error', this._forwardTileEvent);\n\n this.on('rotate', this.style._redoPlacement);\n this.on('pitch', this.style._redoPlacement);\n\n return this;\n },\n\n /**\n * Add a source to the map style.\n *\n * @param {string} id ID of the source. Must not be used by any existing source.\n * @param {Object} source source specification, following the\n * [Mapbox GL Style Reference](https://www.mapbox.com/mapbox-gl-style-spec/#sources)\n * @fires source.add\n * @returns {Map} `this`\n */\n addSource: function(id, source) {\n this.style.addSource(id, source);\n return this;\n },\n\n /**\n * Remove an existing source from the map style.\n *\n * @param {string} id ID of the source to remove\n * @fires source.remove\n * @returns {Map} `this`\n */\n removeSource: function(id) {\n this.style.removeSource(id);\n return this;\n },\n\n /**\n * Return the style source object with the given `id`.\n *\n * @param {string} id source ID\n * @returns {Object}\n */\n getSource: function(id) {\n return this.style.getSource(id);\n },\n\n /**\n * Add a layer to the map style. The layer will be inserted before the layer with\n * ID `before`, or appended if `before` is omitted.\n * @param {Layer} layer\n * @param {string=} before ID of an existing layer to insert before\n * @fires layer.add\n * @returns {Map} `this`\n */\n addLayer: function(layer, before) {\n this.style.addLayer(layer, before);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Remove the layer with the given `id` from the map. Any layers which refer to the\n * specified layer via a `ref` property are also removed.\n *\n * @param {string} id\n * @fires layer.remove\n * @returns {Map} this\n */\n removeLayer: function(id) {\n this.style.removeLayer(id);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Set the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {Array} filter filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n * @returns {Map} `this`\n */\n setFilter: function(layer, filter) {\n this.style.setFilter(layer, filter);\n return this;\n },\n\n /**\n * Get the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @returns {Array} filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n */\n getFilter: function(layer) {\n return this.style.getFilter(layer);\n },\n\n /**\n * Set the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {*} value value for the paint propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @param {string=} klass optional class specifier for the property\n * @returns {Map} `this`\n */\n setPaintProperty: function(layer, name, value, klass) {\n this.style.setPaintProperty(layer, name, value, klass);\n this.style._cascade(this._classes);\n this.update(true);\n return this;\n },\n\n /**\n * Get the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the paint propery\n */\n getPaintProperty: function(layer, name, klass) {\n return this.style.getPaintProperty(layer, name, klass);\n },\n\n /**\n * Set the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {*} value value for the layout propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @returns {Map} `this`\n */\n setLayoutProperty: function(layer, name, value) {\n this.style.setLayoutProperty(layer, name, value);\n return this;\n },\n\n /**\n * Get the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the layout propery\n */\n getLayoutProperty: function(layer, name) {\n return this.style.getLayoutProperty(layer, name);\n },\n\n /**\n * Get the Map's container as an HTML element\n * @returns {HTMLElement} container\n */\n getContainer: function() {\n return this._container;\n },\n\n /**\n * Get the Map's canvas as an HTML canvas\n * @returns {HTMLElement} canvas\n */\n getCanvas: function() {\n return this._canvas.getElement();\n },\n\n _move: function(zoom, rotate, pitch) {\n\n this.update(zoom).fire('move');\n\n if (zoom) this.fire('zoom');\n if (rotate) this.fire('rotate');\n if (pitch) this.fire('pitch');\n\n return this;\n },\n\n // map setup code\n _setupContainer: function() {\n var id = this.options.container;\n var container = this._container = typeof id === 'string' ? document.getElementById(id) : id;\n if (container) container.classList.add('mapboxgl-map');\n this._canvas = new Canvas(this, container);\n },\n\n _setupControlPos: function() {\n var corners = this._controlCorners = {};\n var prefix = 'mapboxgl-ctrl-';\n var container = this.getContainer();\n\n function createCorner(pos) {\n var className = prefix + pos;\n corners[pos] = DOM.create('div', className, container);\n }\n\n if (container && typeof document === 'object') {\n createCorner('top-left');\n createCorner('top-right');\n createCorner('bottom-left');\n createCorner('bottom-right');\n }\n },\n\n _setupPainter: function() {\n var gl = this._canvas.getWebGLContext(this.options.failIfMajorPerformanceCaveat);\n\n if (!gl) {\n console.error('Failed to initialize WebGL');\n return;\n }\n\n this.painter = new GLPainter(gl, this.transform);\n },\n\n _contextLost: function(event) {\n event.preventDefault();\n if (this._frameId) {\n browser.cancelFrame(this._frameId);\n }\n },\n\n _contextRestored: function() {\n this._setupPainter();\n this.resize();\n this.update();\n },\n\n /**\n * Is this map fully loaded? If the style isn't loaded\n * or it has a change to the sources or style that isn't\n * propagated to its style, return false.\n *\n * @returns {boolean} whether the map is loaded\n */\n loaded: function() {\n if (this._styleDirty || this._sourcesDirty)\n return false;\n if (this.style && !this.style.loaded())\n return false;\n return true;\n },\n\n /**\n * Update this map's style and re-render the map.\n *\n * @param {Object} updateStyle new style\n * @returns {Map} this\n */\n update: function(updateStyle) {\n if (!this.style) return this;\n\n this._styleDirty = this._styleDirty || updateStyle;\n this._sourcesDirty = true;\n\n this._rerender();\n\n return this;\n },\n\n /**\n * Call when a (re-)render of the map is required, e.g. when the\n * user panned or zoomed,f or new data is available.\n * @returns {Map} this\n */\n render: function() {\n if (this.style && this._styleDirty) {\n this._styleDirty = false;\n this.style._recalculate(this.transform.zoom);\n }\n\n if (this.style && this._sourcesDirty && !this._sourcesDirtyTimeout) {\n this._sourcesDirty = false;\n this._sourcesDirtyTimeout = setTimeout(function() {\n this._sourcesDirtyTimeout = null;\n }.bind(this), 50);\n this.style._updateSources(this.transform);\n }\n\n this.painter.render(this.style, {\n debug: this.debug,\n vertices: this.vertices,\n rotating: this.rotating,\n zooming: this.zooming\n });\n\n this.fire('render');\n\n if (this.loaded() && !this._loaded) {\n this._loaded = true;\n this.fire('load');\n }\n\n this._frameId = null;\n\n if (!this.animationLoop.stopped()) {\n this._styleDirty = true;\n }\n\n if (this._sourcesDirty || this._repaint || !this.animationLoop.stopped()) {\n this._rerender();\n }\n\n return this;\n },\n\n /**\n * Destroys the map's underlying resources, including web workers.\n * @returns {Map} this\n */\n remove: function() {\n if (this._hash) this._hash.remove();\n browser.cancelFrame(this._frameId);\n clearTimeout(this._sourcesDirtyTimeout);\n this.setStyle(null);\n return this;\n },\n\n _rerender: function() {\n if (this.style && !this._frameId) {\n this._frameId = browser.frame(this.render);\n }\n },\n\n _forwardStyleEvent: function(e) {\n this.fire('style.' + e.type, util.extend({style: e.target}, e));\n },\n\n _forwardSourceEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardLayerEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardTileEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _onStyleLoad: function(e) {\n this.style._cascade(this._classes, {transition: false});\n this._forwardStyleEvent(e);\n },\n\n _onStyleChange: function(e) {\n this.update(true);\n this._forwardStyleEvent(e);\n },\n\n _onSourceAdd: function(e) {\n var source = e.source;\n if (source.onAdd)\n source.onAdd(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceRemove: function(e) {\n var source = e.source;\n if (source.onRemove)\n source.onRemove(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceUpdate: function(e) {\n this.update();\n this._forwardSourceEvent(e);\n }\n}","path":"js/ui/map.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/map.js#L667-L676"},"params":[{"title":"param","description":"new style","type":{"type":"NameExpression","name":"Object"},"name":"updateStyle"}],"returns":[{"title":"returns","description":"this","type":{"type":"NameExpression","name":"Map"}}],"name":"update","memberof":"Map","scope":"instance","members":{"instance":[],"static":[]},"path":["Map","update"]},{"description":"Stop current animation","tags":[{"title":"returns","description":null,"type":{"type":"NameExpression","name":"this"}},{"title":"name","name":"stop"},{"title":"memberof","description":"Map"},{"title":"instance"}],"context":{"loc":{"start":{"line":27,"column":4},"end":{"line":36,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/easings.js","code":"{\n isEasing: function() {\n return !!this._abortFn;\n },\n\n /**\n * Stop current animation\n *\n * @returns {this}\n */\n stop: function() {\n if (this._abortFn) {\n this._abortFn.call(this);\n delete this._abortFn;\n\n this._finishFn.call(this);\n delete this._finishFn;\n }\n return this;\n },\n\n _ease: function(frame, finish, options) {\n this._finishFn = finish;\n this._abortFn = browser.timed(function (t) {\n frame.call(this, options.easing(t));\n if (t === 1) {\n delete this._abortFn;\n this._finishFn.call(this);\n delete this._finishFn;\n }\n }, options.animate === false ? 0 : options.duration, this);\n },\n\n /**\n * Pan by a certain number of pixels\n *\n * @param {Array} offset [x, y]\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n panBy: function(offset, options) {\n this.panTo(this.transform.center, util.extend({offset: Point.convert(offset).mult(-1)}, options));\n return this;\n },\n\n /**\n * Pan to a certain location with easing\n *\n * @param {Object} latlng a `LatLng` object\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n panTo: function(latlng, options) {\n this.stop();\n\n latlng = LatLng.convert(latlng);\n\n options = util.extend({\n duration: 500,\n easing: util.ease,\n offset: [0, 0]\n }, options);\n\n var tr = this.transform,\n offset = Point.convert(options.offset).rotate(-tr.angle),\n from = tr.point,\n to = tr.project(latlng).sub(offset);\n\n if (!options.noMoveStart) {\n this.fire('movestart');\n }\n\n this._ease(function(k) {\n tr.center = tr.unproject(from.add(to.sub(from).mult(k)));\n this._move();\n }, function() {\n this.fire('moveend');\n }, options);\n\n return this;\n },\n\n /**\n * Zooms to a certain zoom level with easing.\n *\n * @param {Number} zoom\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n zoomTo: function(zoom, options) {\n this.stop();\n\n options = util.extend({\n duration: 500\n }, options);\n\n options.easing = this._updateEasing(options.duration, zoom, options.easing);\n\n var tr = this.transform,\n around = tr.center,\n startZoom = tr.zoom;\n\n if (options.around) {\n around = LatLng.convert(options.around);\n } else if (options.offset) {\n around = tr.pointLocation(tr.centerPoint.add(Point.convert(options.offset)));\n }\n\n if (options.animate === false) options.duration = 0;\n\n if (!this.zooming) {\n this.zooming = true;\n this.fire('movestart');\n }\n\n this._ease(function(k) {\n tr.setZoomAround(interpolate(startZoom, zoom, k), around);\n this.animationLoop.set(300); // text fading\n this._move(true);\n }, function() {\n this.ease = null;\n if (options.duration >= 200) {\n this.zooming = false;\n this.fire('moveend');\n }\n }, options);\n\n if (options.duration < 200) {\n clearTimeout(this._onZoomEnd);\n this._onZoomEnd = setTimeout(function() {\n this.zooming = false;\n this._rerender();\n this.fire('moveend');\n }.bind(this), 200);\n }\n\n return this;\n },\n\n /**\n * Zoom in by 1 level\n *\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n zoomIn: function(options) {\n this.zoomTo(this.getZoom() + 1, options);\n },\n\n /**\n * Zoom out by 1 level\n *\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n zoomOut: function(options) {\n this.zoomTo(this.getZoom() - 1, options);\n },\n\n /**\n * Rotate bearing by a certain number of degrees with easing\n *\n * @param {Number} bearing\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n rotateTo: function(bearing, options) {\n this.stop();\n\n options = util.extend({\n duration: 500,\n easing: util.ease\n }, options);\n\n var tr = this.transform,\n start = this.getBearing(),\n around = tr.center;\n\n if (options.around) {\n around = LatLng.convert(options.around);\n } else if (options.offset) {\n around = tr.pointLocation(tr.centerPoint.add(Point.convert(options.offset)));\n }\n\n bearing = this._normalizeBearing(bearing, start);\n\n this.rotating = true;\n this.fire('movestart');\n\n this._ease(function(k) {\n tr.setBearingAround(interpolate(start, bearing, k), around);\n this._move(false, true);\n }, function() {\n this.rotating = false;\n this.fire('moveend');\n }, options);\n\n return this;\n },\n\n /**\n * Sets map bearing to 0 (north) with easing\n *\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n resetNorth: function(options) {\n return this.rotateTo(0, util.extend({duration: 1000}, options));\n },\n\n /**\n * Zoom to contain certain geographical bounds\n *\n * @param {Array} bounds [[minLat, minLng], [maxLat, maxLng]]\n * @param {Object} options\n * @param {Number} [options.speed=1.2] How fast animation occurs\n * @param {Number} [options.curve=1.42] How much zooming out occurs during animation\n * @param {Function} options.easing\n * @param {Number} options.padding how much padding there is around the given bounds on each side in pixels\n * @param {Number} options.maxZoom\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n fitBounds: function(bounds, options) {\n\n options = util.extend({\n padding: 0,\n offset: [0, 0],\n maxZoom: Infinity\n }, options);\n\n bounds = LatLngBounds.convert(bounds);\n\n var offset = Point.convert(options.offset),\n tr = this.transform,\n nw = tr.project(bounds.getNorthWest()),\n se = tr.project(bounds.getSouthEast()),\n size = se.sub(nw),\n center = tr.unproject(nw.add(se).div(2)),\n\n scaleX = (tr.width - options.padding * 2 - Math.abs(offset.x) * 2) / size.x,\n scaleY = (tr.height - options.padding * 2 - Math.abs(offset.y) * 2) / size.y,\n\n zoom = Math.min(tr.scaleZoom(tr.scale * Math.min(scaleX, scaleY)), options.maxZoom);\n\n return options.linear ?\n this.easeTo(center, zoom, 0, options) :\n this.flyTo(center, zoom, 0, options);\n },\n\n /**\n * Easing animation to a specified location/zoom/bearing\n *\n * @param {Object} latlng a `LatLng` object\n * @param {Number} zoom\n * @param {Number} bearing\n * @param {Number} pitch\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n easeTo: function(latlng, zoom, bearing, pitch, options) {\n this.stop();\n\n options = util.extend({\n offset: [0, 0],\n duration: 500,\n easing: util.ease\n }, options);\n\n var tr = this.transform,\n offset = Point.convert(options.offset).rotate(-tr.angle),\n startZoom = this.getZoom(),\n startBearing = this.getBearing(),\n startPitch = this.getPitch();\n\n latlng = LatLng.convert(latlng);\n zoom = zoom === undefined ? startZoom : zoom;\n bearing = bearing === undefined ? startBearing : this._normalizeBearing(bearing, startBearing);\n pitch = pitch === undefined ? startPitch : pitch;\n\n var scale = tr.zoomScale(zoom - startZoom),\n from = tr.point,\n to = latlng ? tr.project(latlng).sub(offset.div(scale)) : tr.point,\n around;\n\n if (zoom !== startZoom) {\n around = tr.pointLocation(tr.centerPoint.add(to.sub(from).div(1 - 1 / scale)));\n this.zooming = true;\n }\n if (startBearing !== bearing) this.rotating = true;\n\n this.fire('movestart');\n\n this._ease(function (k) {\n if (zoom !== startZoom) {\n tr.setZoomAround(interpolate(startZoom, zoom, k), around);\n } else {\n tr.center = tr.unproject(from.add(to.sub(from).mult(k)));\n }\n\n if (bearing !== startBearing) {\n tr.bearing = interpolate(startBearing, bearing, k);\n }\n\n if (pitch !== startPitch) {\n tr.pitch = interpolate(startPitch, pitch, k);\n }\n\n this.animationLoop.set(300); // text fading\n this._move(zoom !== startZoom, bearing !== startBearing);\n }, function() {\n this.zooming = false;\n this.rotating = false;\n this.fire('moveend');\n }, options);\n\n return this;\n },\n\n /**\n * Flying animation to a specified location/zoom/bearing with automatic curve\n *\n * @param {Object} latlng a `LatLng` object\n * @param {Number} zoom\n * @param {Number} bearing\n * @param {Object} options\n * @param {Number} [options.speed=1.2] How fast animation occurs\n * @param {Number} [options.curve=1.42] How much zooming out occurs during animation\n * @param {Function} options.easing\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n flyTo: function(latlng, zoom, bearing, options) {\n this.stop();\n\n options = util.extend({\n offset: [0, 0],\n speed: 1.2,\n curve: 1.42,\n easing: util.ease\n }, options);\n\n latlng = LatLng.convert(latlng);\n\n var offset = Point.convert(options.offset),\n tr = this.transform,\n startZoom = this.getZoom(),\n startBearing = this.getBearing();\n\n zoom = zoom === undefined ? startZoom : zoom;\n bearing = bearing === undefined ? startBearing : this._normalizeBearing(bearing, startBearing);\n\n var scale = tr.zoomScale(zoom - startZoom),\n from = tr.point,\n to = tr.project(latlng).sub(offset.div(scale));\n\n if (options.animate === false) {\n return this.setView(latlng, zoom, bearing, this.getPitch());\n }\n\n var startWorldSize = tr.worldSize,\n rho = options.curve,\n V = options.speed,\n\n w0 = Math.max(tr.width, tr.height),\n w1 = w0 / scale,\n u1 = to.sub(from).mag(),\n rho2 = rho * rho;\n\n function r(i) {\n var b = (w1 * w1 - w0 * w0 + (i ? -1 : 1) * rho2 * rho2 * u1 * u1) / (2 * (i ? w1 : w0) * rho2 * u1);\n return Math.log(Math.sqrt(b * b + 1) - b);\n }\n\n function sinh(n) { return (Math.exp(n) - Math.exp(-n)) / 2; }\n function cosh(n) { return (Math.exp(n) + Math.exp(-n)) / 2; }\n function tanh(n) { return sinh(n) / cosh(n); }\n\n var r0 = r(0),\n w = function (s) { return (cosh(r0) / cosh(r0 + rho * s)); },\n u = function (s) { return w0 * ((cosh(r0) * tanh(r0 + rho * s) - sinh(r0)) / rho2) / u1; },\n S = (r(1) - r0) / rho;\n\n if (Math.abs(u1) < 0.000001) {\n if (Math.abs(w0 - w1) < 0.000001) return this;\n\n var k = w1 < w0 ? -1 : 1;\n S = Math.abs(Math.log(w1 / w0)) / rho;\n\n u = function() { return 0; };\n w = function(s) { return Math.exp(k * rho * s); };\n }\n\n options.duration = 1000 * S / V;\n\n this.zooming = true;\n if (startBearing !== bearing) this.rotating = true;\n\n this.fire('movestart');\n\n this._ease(function (k) {\n var s = k * S,\n us = u(s);\n\n tr.zoom = startZoom + tr.scaleZoom(1 / w(s));\n tr.center = tr.unproject(from.add(to.sub(from).mult(us)), startWorldSize);\n\n if (bearing !== startBearing) {\n tr.bearing = interpolate(startBearing, bearing, k);\n }\n\n this.animationLoop.set(300); // text fading\n\n this._move(true, bearing !== startBearing);\n }, function() {\n this.zooming = false;\n this.rotating = false;\n this.fire('moveend');\n }, options);\n\n return this;\n },\n\n // convert bearing so that it's numerically close to the current one so that it interpolates properly\n _normalizeBearing: function(bearing, currentBearing) {\n bearing = util.wrap(bearing, -180, 180);\n var diff = Math.abs(bearing - currentBearing);\n if (Math.abs(bearing - 360 - currentBearing) < diff) bearing -= 360;\n if (Math.abs(bearing + 360 - currentBearing) < diff) bearing += 360;\n return bearing;\n },\n\n _updateEasing: function(duration, zoom, bezier) {\n var easing;\n\n if (this.ease) {\n var ease = this.ease,\n t = (Date.now() - ease.start) / ease.duration,\n speed = ease.easing(t + 0.01) - ease.easing(t),\n\n // Quick hack to make new bezier that is continuous with last\n x = 0.27 / Math.sqrt(speed * speed + 0.0001) * 0.01,\n y = Math.sqrt(0.27 * 0.27 - x * x);\n\n easing = util.bezier(x, y, 0.25, 1);\n } else {\n easing = bezier ? util.bezier.apply(util, bezier) : util.ease;\n }\n\n // store information on current easing\n this.ease = {\n start: (new Date()).getTime(),\n to: Math.pow(2, zoom),\n duration: duration,\n easing: easing\n };\n\n return easing;\n }\n}","path":"js/ui/easings.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/easings.js#L27-L36"},"returns":[{"title":"returns","description":null,"type":{"type":"NameExpression","name":"this"}}],"name":"stop","memberof":"Map","scope":"instance","members":{"instance":[],"static":[]},"path":["Map","stop"]},{"description":"Sets a map position","tags":[{"title":"param","description":"Latitude and longitude (passed as `[lat, lng]`)","type":{"type":"NameExpression","name":"Array"},"name":"center"},{"title":"param","description":"Map zoom level","type":{"type":"NameExpression","name":"number"},"name":"zoom"},{"title":"param","description":"Map rotation bearing in degrees counter-clockwise from north","type":{"type":"NameExpression","name":"number"},"name":"bearing"},{"title":"param","description":"The angle at which the camera is looking at the ground","type":{"type":"NameExpression","name":"number"},"name":"pitch"},{"title":"fires","description":"movestart"},{"title":"fires","description":"moveend"},{"title":"returns","description":"`this`","type":{"type":"NameExpression","name":"Map"}},{"title":"name","name":"setView"},{"title":"memberof","description":"Map"},{"title":"instance"}],"context":{"loc":{"start":{"line":130,"column":4},"end":{"line":147,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/map.js","code":"{\n\n options: {\n center: [0, 0],\n zoom: 0,\n bearing: 0,\n pitch: 0,\n\n minZoom: 0,\n maxZoom: 20,\n\n interactive: true,\n hash: false,\n\n attributionControl: true,\n\n failIfMajorPerformanceCaveat: false\n },\n\n addControl: function(control) {\n control.addTo(this);\n return this;\n },\n\n /**\n * Sets a map position\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @param {number} zoom Map zoom level\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setView: function(center, zoom, bearing, pitch) {\n this.stop();\n\n var tr = this.transform,\n zoomChanged = tr.zoom !== +zoom,\n bearingChanged = tr.bearing !== +bearing,\n pitchChanged = tr.pitch !== +pitch;\n\n tr.center = LatLng.convert(center);\n tr.zoom = +zoom;\n tr.bearing = +bearing;\n tr.pitch = +pitch;\n\n return this\n .fire('movestart')\n ._move(zoomChanged, bearingChanged, pitchChanged)\n .fire('moveend');\n },\n\n /**\n * Sets a map location\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setCenter: function(center) {\n this.setView(center, this.getZoom(), this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map zoom\n *\n * @param {number} zoom Map zoom level\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setZoom: function(zoom) {\n this.setView(this.getCenter(), zoom, this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map rotation\n *\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setBearing: function(bearing) {\n this.setView(this.getCenter(), this.getZoom(), bearing, this.getPitch());\n },\n\n /**\n * Sets a map angle\n *\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setPitch: function(pitch) {\n this.setView(this.getCenter(), this.getZoom(), this.getBearing(), pitch);\n },\n\n /**\n * Get the current view geographical point\n * @returns {LatLng}\n */\n getCenter: function() { return this.transform.center; },\n\n /**\n * Get the current zoom\n * @returns {number}\n */\n getZoom: function() { return this.transform.zoom; },\n\n /**\n * Get the current bearing in degrees\n * @returns {number}\n */\n getBearing: function() { return this.transform.bearing; },\n\n /**\n * Get the current angle in degrees\n * @returns {number}\n */\n getPitch: function() { return this.transform.pitch; },\n\n /**\n * @typedef {Object} [styleOptions]\n * @param {Boolean} [styleOptions.transition=true]\n */\n\n /**\n * Adds a style class to a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n addClass: function(klass, options) {\n if (this._classes[klass]) return;\n this._classes[klass] = true;\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Removes a style class from a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n removeClass: function(klass, options) {\n if (!this._classes[klass]) return;\n delete this._classes[klass];\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Helper method to add more than one class\n *\n * @param {Array} klasses An array of class names\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n setClasses: function(klasses, options) {\n this._classes = {};\n for (var i = 0; i < klasses.length; i++) {\n this._classes[klasses[i]] = true;\n }\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Check whether a style class is active\n *\n * @param {string} klass Name of style class\n * @returns {boolean}\n */\n hasClass: function(klass) {\n return !!this._classes[klass];\n },\n\n /**\n * Return an array of the current active style classes\n *\n * @returns {boolean}\n */\n getClasses: function() {\n return Object.keys(this._classes);\n },\n\n /**\n * Detect the map's new width and height and resize it.\n *\n * @returns {Map} `this`\n */\n resize: function() {\n var width = 0, height = 0;\n\n if (this._container) {\n width = this._container.offsetWidth || 400;\n height = this._container.offsetHeight || 300;\n }\n\n this._canvas.resize(width, height);\n\n this.transform.width = width;\n this.transform.height = height;\n this.transform._constrain();\n\n this.painter.resize(width, height);\n\n return this\n .fire('movestart')\n ._move()\n .fire('resize')\n .fire('moveend');\n },\n\n /**\n * Get the map's geographical bounds\n *\n * @returns {LatLngBounds}\n */\n getBounds: function() {\n return new LatLngBounds(\n this.transform.pointLocation(new Point(0, 0)),\n this.transform.pointLocation(this.transform.size));\n },\n\n /**\n * Get pixel coordinates (relative to map container) given a geographical location\n *\n * @param {LatLng} latlng\n * @returns {Object} `x` and `y` coordinates\n */\n project: function(latlng) {\n return this.transform.locationPoint(LatLng.convert(latlng));\n },\n\n /**\n * Get geographical coordinates given pixel coordinates\n *\n * @param {Array} point [x, y] pixel coordinates\n * @returns {LatLng}\n */\n unproject: function(point) {\n return this.transform.pointLocation(Point.convert(point));\n },\n\n /**\n * Get all features at a point ([x, y])\n *\n * @param {Array} point [x, y] pixel coordinates\n * @param {Object} params\n * @param {number} [params.radius=0] Optional. Radius in pixels to search in\n * @param {string} params.layer Optional. Only return features from a given layer\n * @param {string} params.type Optional. Either `raster` or `vector`\n * @param {featuresAtCallback} callback function that returns the response\n *\n * @callback featuresAtCallback\n * @param {Object|null} err Error _If any_\n * @param {Array} features Displays a JSON array of features given the passed parameters of `featuresAt`\n *\n * @returns {Map} `this`\n */\n featuresAt: function(point, params, callback) {\n var coord = this.transform.pointCoordinate(Point.convert(point));\n this.style.featuresAt(coord, params, callback);\n return this;\n },\n\n /**\n * Replaces the map's style object\n *\n * @param {Object} style A style object formatted as JSON\n * @returns {Map} `this`\n */\n setStyle: function(style) {\n if (this.style) {\n this.style\n .off('load', this._onStyleLoad)\n .off('error', this._forwardStyleEvent)\n .off('change', this._onStyleChange)\n .off('source.add', this._onSourceAdd)\n .off('source.remove', this._onSourceRemove)\n .off('source.load', this._onSourceUpdate)\n .off('source.error', this._forwardSourceEvent)\n .off('source.change', this._onSourceUpdate)\n .off('layer.add', this._forwardLayerEvent)\n .off('layer.remove', this._forwardLayerEvent)\n .off('tile.add', this._forwardTileEvent)\n .off('tile.remove', this._forwardTileEvent)\n .off('tile.load', this.update)\n .off('tile.error', this._forwardTileEvent)\n ._remove();\n\n this.off('rotate', this.style._redoPlacement);\n this.off('pitch', this.style._redoPlacement);\n }\n\n if (!style) {\n this.style = null;\n return this;\n } else if (style instanceof Style) {\n this.style = style;\n } else {\n this.style = new Style(style, this.animationLoop);\n }\n\n this.style\n .on('load', this._onStyleLoad)\n .on('error', this._forwardStyleEvent)\n .on('change', this._onStyleChange)\n .on('source.add', this._onSourceAdd)\n .on('source.remove', this._onSourceRemove)\n .on('source.load', this._onSourceUpdate)\n .on('source.error', this._forwardSourceEvent)\n .on('source.change', this._onSourceUpdate)\n .on('layer.add', this._forwardLayerEvent)\n .on('layer.remove', this._forwardLayerEvent)\n .on('tile.add', this._forwardTileEvent)\n .on('tile.remove', this._forwardTileEvent)\n .on('tile.load', this.update)\n .on('tile.error', this._forwardTileEvent);\n\n this.on('rotate', this.style._redoPlacement);\n this.on('pitch', this.style._redoPlacement);\n\n return this;\n },\n\n /**\n * Add a source to the map style.\n *\n * @param {string} id ID of the source. Must not be used by any existing source.\n * @param {Object} source source specification, following the\n * [Mapbox GL Style Reference](https://www.mapbox.com/mapbox-gl-style-spec/#sources)\n * @fires source.add\n * @returns {Map} `this`\n */\n addSource: function(id, source) {\n this.style.addSource(id, source);\n return this;\n },\n\n /**\n * Remove an existing source from the map style.\n *\n * @param {string} id ID of the source to remove\n * @fires source.remove\n * @returns {Map} `this`\n */\n removeSource: function(id) {\n this.style.removeSource(id);\n return this;\n },\n\n /**\n * Return the style source object with the given `id`.\n *\n * @param {string} id source ID\n * @returns {Object}\n */\n getSource: function(id) {\n return this.style.getSource(id);\n },\n\n /**\n * Add a layer to the map style. The layer will be inserted before the layer with\n * ID `before`, or appended if `before` is omitted.\n * @param {Layer} layer\n * @param {string=} before ID of an existing layer to insert before\n * @fires layer.add\n * @returns {Map} `this`\n */\n addLayer: function(layer, before) {\n this.style.addLayer(layer, before);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Remove the layer with the given `id` from the map. Any layers which refer to the\n * specified layer via a `ref` property are also removed.\n *\n * @param {string} id\n * @fires layer.remove\n * @returns {Map} this\n */\n removeLayer: function(id) {\n this.style.removeLayer(id);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Set the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {Array} filter filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n * @returns {Map} `this`\n */\n setFilter: function(layer, filter) {\n this.style.setFilter(layer, filter);\n return this;\n },\n\n /**\n * Get the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @returns {Array} filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n */\n getFilter: function(layer) {\n return this.style.getFilter(layer);\n },\n\n /**\n * Set the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {*} value value for the paint propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @param {string=} klass optional class specifier for the property\n * @returns {Map} `this`\n */\n setPaintProperty: function(layer, name, value, klass) {\n this.style.setPaintProperty(layer, name, value, klass);\n this.style._cascade(this._classes);\n this.update(true);\n return this;\n },\n\n /**\n * Get the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the paint propery\n */\n getPaintProperty: function(layer, name, klass) {\n return this.style.getPaintProperty(layer, name, klass);\n },\n\n /**\n * Set the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {*} value value for the layout propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @returns {Map} `this`\n */\n setLayoutProperty: function(layer, name, value) {\n this.style.setLayoutProperty(layer, name, value);\n return this;\n },\n\n /**\n * Get the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the layout propery\n */\n getLayoutProperty: function(layer, name) {\n return this.style.getLayoutProperty(layer, name);\n },\n\n /**\n * Get the Map's container as an HTML element\n * @returns {HTMLElement} container\n */\n getContainer: function() {\n return this._container;\n },\n\n /**\n * Get the Map's canvas as an HTML canvas\n * @returns {HTMLElement} canvas\n */\n getCanvas: function() {\n return this._canvas.getElement();\n },\n\n _move: function(zoom, rotate, pitch) {\n\n this.update(zoom).fire('move');\n\n if (zoom) this.fire('zoom');\n if (rotate) this.fire('rotate');\n if (pitch) this.fire('pitch');\n\n return this;\n },\n\n // map setup code\n _setupContainer: function() {\n var id = this.options.container;\n var container = this._container = typeof id === 'string' ? document.getElementById(id) : id;\n if (container) container.classList.add('mapboxgl-map');\n this._canvas = new Canvas(this, container);\n },\n\n _setupControlPos: function() {\n var corners = this._controlCorners = {};\n var prefix = 'mapboxgl-ctrl-';\n var container = this.getContainer();\n\n function createCorner(pos) {\n var className = prefix + pos;\n corners[pos] = DOM.create('div', className, container);\n }\n\n if (container && typeof document === 'object') {\n createCorner('top-left');\n createCorner('top-right');\n createCorner('bottom-left');\n createCorner('bottom-right');\n }\n },\n\n _setupPainter: function() {\n var gl = this._canvas.getWebGLContext(this.options.failIfMajorPerformanceCaveat);\n\n if (!gl) {\n console.error('Failed to initialize WebGL');\n return;\n }\n\n this.painter = new GLPainter(gl, this.transform);\n },\n\n _contextLost: function(event) {\n event.preventDefault();\n if (this._frameId) {\n browser.cancelFrame(this._frameId);\n }\n },\n\n _contextRestored: function() {\n this._setupPainter();\n this.resize();\n this.update();\n },\n\n /**\n * Is this map fully loaded? If the style isn't loaded\n * or it has a change to the sources or style that isn't\n * propagated to its style, return false.\n *\n * @returns {boolean} whether the map is loaded\n */\n loaded: function() {\n if (this._styleDirty || this._sourcesDirty)\n return false;\n if (this.style && !this.style.loaded())\n return false;\n return true;\n },\n\n /**\n * Update this map's style and re-render the map.\n *\n * @param {Object} updateStyle new style\n * @returns {Map} this\n */\n update: function(updateStyle) {\n if (!this.style) return this;\n\n this._styleDirty = this._styleDirty || updateStyle;\n this._sourcesDirty = true;\n\n this._rerender();\n\n return this;\n },\n\n /**\n * Call when a (re-)render of the map is required, e.g. when the\n * user panned or zoomed,f or new data is available.\n * @returns {Map} this\n */\n render: function() {\n if (this.style && this._styleDirty) {\n this._styleDirty = false;\n this.style._recalculate(this.transform.zoom);\n }\n\n if (this.style && this._sourcesDirty && !this._sourcesDirtyTimeout) {\n this._sourcesDirty = false;\n this._sourcesDirtyTimeout = setTimeout(function() {\n this._sourcesDirtyTimeout = null;\n }.bind(this), 50);\n this.style._updateSources(this.transform);\n }\n\n this.painter.render(this.style, {\n debug: this.debug,\n vertices: this.vertices,\n rotating: this.rotating,\n zooming: this.zooming\n });\n\n this.fire('render');\n\n if (this.loaded() && !this._loaded) {\n this._loaded = true;\n this.fire('load');\n }\n\n this._frameId = null;\n\n if (!this.animationLoop.stopped()) {\n this._styleDirty = true;\n }\n\n if (this._sourcesDirty || this._repaint || !this.animationLoop.stopped()) {\n this._rerender();\n }\n\n return this;\n },\n\n /**\n * Destroys the map's underlying resources, including web workers.\n * @returns {Map} this\n */\n remove: function() {\n if (this._hash) this._hash.remove();\n browser.cancelFrame(this._frameId);\n clearTimeout(this._sourcesDirtyTimeout);\n this.setStyle(null);\n return this;\n },\n\n _rerender: function() {\n if (this.style && !this._frameId) {\n this._frameId = browser.frame(this.render);\n }\n },\n\n _forwardStyleEvent: function(e) {\n this.fire('style.' + e.type, util.extend({style: e.target}, e));\n },\n\n _forwardSourceEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardLayerEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardTileEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _onStyleLoad: function(e) {\n this.style._cascade(this._classes, {transition: false});\n this._forwardStyleEvent(e);\n },\n\n _onStyleChange: function(e) {\n this.update(true);\n this._forwardStyleEvent(e);\n },\n\n _onSourceAdd: function(e) {\n var source = e.source;\n if (source.onAdd)\n source.onAdd(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceRemove: function(e) {\n var source = e.source;\n if (source.onRemove)\n source.onRemove(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceUpdate: function(e) {\n this.update();\n this._forwardSourceEvent(e);\n }\n}","path":"js/ui/map.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/map.js#L130-L147"},"params":[{"title":"param","description":"Latitude and longitude (passed as `[lat, lng]`)","type":{"type":"NameExpression","name":"Array"},"name":"center"},{"title":"param","description":"Map zoom level","type":{"type":"NameExpression","name":"number"},"name":"zoom"},{"title":"param","description":"Map rotation bearing in degrees counter-clockwise from north","type":{"type":"NameExpression","name":"number"},"name":"bearing"},{"title":"param","description":"The angle at which the camera is looking at the ground","type":{"type":"NameExpression","name":"number"},"name":"pitch"}],"returns":[{"title":"returns","description":"`this`","type":{"type":"NameExpression","name":"Map"}}],"name":"setView","memberof":"Map","scope":"instance","members":{"instance":[],"static":[]},"path":["Map","setView"]},{"description":"Sets a map zoom","tags":[{"title":"param","description":"Map zoom level","type":{"type":"NameExpression","name":"number"},"name":"zoom"},{"title":"fires","description":"movestart"},{"title":"fires","description":"moveend"},{"title":"returns","description":"`this`","type":{"type":"NameExpression","name":"Map"}},{"title":"name","name":"setZoom"},{"title":"memberof","description":"Map"},{"title":"instance"}],"context":{"loc":{"start":{"line":169,"column":4},"end":{"line":171,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/map.js","code":"{\n\n options: {\n center: [0, 0],\n zoom: 0,\n bearing: 0,\n pitch: 0,\n\n minZoom: 0,\n maxZoom: 20,\n\n interactive: true,\n hash: false,\n\n attributionControl: true,\n\n failIfMajorPerformanceCaveat: false\n },\n\n addControl: function(control) {\n control.addTo(this);\n return this;\n },\n\n /**\n * Sets a map position\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @param {number} zoom Map zoom level\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setView: function(center, zoom, bearing, pitch) {\n this.stop();\n\n var tr = this.transform,\n zoomChanged = tr.zoom !== +zoom,\n bearingChanged = tr.bearing !== +bearing,\n pitchChanged = tr.pitch !== +pitch;\n\n tr.center = LatLng.convert(center);\n tr.zoom = +zoom;\n tr.bearing = +bearing;\n tr.pitch = +pitch;\n\n return this\n .fire('movestart')\n ._move(zoomChanged, bearingChanged, pitchChanged)\n .fire('moveend');\n },\n\n /**\n * Sets a map location\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setCenter: function(center) {\n this.setView(center, this.getZoom(), this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map zoom\n *\n * @param {number} zoom Map zoom level\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setZoom: function(zoom) {\n this.setView(this.getCenter(), zoom, this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map rotation\n *\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setBearing: function(bearing) {\n this.setView(this.getCenter(), this.getZoom(), bearing, this.getPitch());\n },\n\n /**\n * Sets a map angle\n *\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setPitch: function(pitch) {\n this.setView(this.getCenter(), this.getZoom(), this.getBearing(), pitch);\n },\n\n /**\n * Get the current view geographical point\n * @returns {LatLng}\n */\n getCenter: function() { return this.transform.center; },\n\n /**\n * Get the current zoom\n * @returns {number}\n */\n getZoom: function() { return this.transform.zoom; },\n\n /**\n * Get the current bearing in degrees\n * @returns {number}\n */\n getBearing: function() { return this.transform.bearing; },\n\n /**\n * Get the current angle in degrees\n * @returns {number}\n */\n getPitch: function() { return this.transform.pitch; },\n\n /**\n * @typedef {Object} [styleOptions]\n * @param {Boolean} [styleOptions.transition=true]\n */\n\n /**\n * Adds a style class to a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n addClass: function(klass, options) {\n if (this._classes[klass]) return;\n this._classes[klass] = true;\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Removes a style class from a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n removeClass: function(klass, options) {\n if (!this._classes[klass]) return;\n delete this._classes[klass];\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Helper method to add more than one class\n *\n * @param {Array} klasses An array of class names\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n setClasses: function(klasses, options) {\n this._classes = {};\n for (var i = 0; i < klasses.length; i++) {\n this._classes[klasses[i]] = true;\n }\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Check whether a style class is active\n *\n * @param {string} klass Name of style class\n * @returns {boolean}\n */\n hasClass: function(klass) {\n return !!this._classes[klass];\n },\n\n /**\n * Return an array of the current active style classes\n *\n * @returns {boolean}\n */\n getClasses: function() {\n return Object.keys(this._classes);\n },\n\n /**\n * Detect the map's new width and height and resize it.\n *\n * @returns {Map} `this`\n */\n resize: function() {\n var width = 0, height = 0;\n\n if (this._container) {\n width = this._container.offsetWidth || 400;\n height = this._container.offsetHeight || 300;\n }\n\n this._canvas.resize(width, height);\n\n this.transform.width = width;\n this.transform.height = height;\n this.transform._constrain();\n\n this.painter.resize(width, height);\n\n return this\n .fire('movestart')\n ._move()\n .fire('resize')\n .fire('moveend');\n },\n\n /**\n * Get the map's geographical bounds\n *\n * @returns {LatLngBounds}\n */\n getBounds: function() {\n return new LatLngBounds(\n this.transform.pointLocation(new Point(0, 0)),\n this.transform.pointLocation(this.transform.size));\n },\n\n /**\n * Get pixel coordinates (relative to map container) given a geographical location\n *\n * @param {LatLng} latlng\n * @returns {Object} `x` and `y` coordinates\n */\n project: function(latlng) {\n return this.transform.locationPoint(LatLng.convert(latlng));\n },\n\n /**\n * Get geographical coordinates given pixel coordinates\n *\n * @param {Array} point [x, y] pixel coordinates\n * @returns {LatLng}\n */\n unproject: function(point) {\n return this.transform.pointLocation(Point.convert(point));\n },\n\n /**\n * Get all features at a point ([x, y])\n *\n * @param {Array} point [x, y] pixel coordinates\n * @param {Object} params\n * @param {number} [params.radius=0] Optional. Radius in pixels to search in\n * @param {string} params.layer Optional. Only return features from a given layer\n * @param {string} params.type Optional. Either `raster` or `vector`\n * @param {featuresAtCallback} callback function that returns the response\n *\n * @callback featuresAtCallback\n * @param {Object|null} err Error _If any_\n * @param {Array} features Displays a JSON array of features given the passed parameters of `featuresAt`\n *\n * @returns {Map} `this`\n */\n featuresAt: function(point, params, callback) {\n var coord = this.transform.pointCoordinate(Point.convert(point));\n this.style.featuresAt(coord, params, callback);\n return this;\n },\n\n /**\n * Replaces the map's style object\n *\n * @param {Object} style A style object formatted as JSON\n * @returns {Map} `this`\n */\n setStyle: function(style) {\n if (this.style) {\n this.style\n .off('load', this._onStyleLoad)\n .off('error', this._forwardStyleEvent)\n .off('change', this._onStyleChange)\n .off('source.add', this._onSourceAdd)\n .off('source.remove', this._onSourceRemove)\n .off('source.load', this._onSourceUpdate)\n .off('source.error', this._forwardSourceEvent)\n .off('source.change', this._onSourceUpdate)\n .off('layer.add', this._forwardLayerEvent)\n .off('layer.remove', this._forwardLayerEvent)\n .off('tile.add', this._forwardTileEvent)\n .off('tile.remove', this._forwardTileEvent)\n .off('tile.load', this.update)\n .off('tile.error', this._forwardTileEvent)\n ._remove();\n\n this.off('rotate', this.style._redoPlacement);\n this.off('pitch', this.style._redoPlacement);\n }\n\n if (!style) {\n this.style = null;\n return this;\n } else if (style instanceof Style) {\n this.style = style;\n } else {\n this.style = new Style(style, this.animationLoop);\n }\n\n this.style\n .on('load', this._onStyleLoad)\n .on('error', this._forwardStyleEvent)\n .on('change', this._onStyleChange)\n .on('source.add', this._onSourceAdd)\n .on('source.remove', this._onSourceRemove)\n .on('source.load', this._onSourceUpdate)\n .on('source.error', this._forwardSourceEvent)\n .on('source.change', this._onSourceUpdate)\n .on('layer.add', this._forwardLayerEvent)\n .on('layer.remove', this._forwardLayerEvent)\n .on('tile.add', this._forwardTileEvent)\n .on('tile.remove', this._forwardTileEvent)\n .on('tile.load', this.update)\n .on('tile.error', this._forwardTileEvent);\n\n this.on('rotate', this.style._redoPlacement);\n this.on('pitch', this.style._redoPlacement);\n\n return this;\n },\n\n /**\n * Add a source to the map style.\n *\n * @param {string} id ID of the source. Must not be used by any existing source.\n * @param {Object} source source specification, following the\n * [Mapbox GL Style Reference](https://www.mapbox.com/mapbox-gl-style-spec/#sources)\n * @fires source.add\n * @returns {Map} `this`\n */\n addSource: function(id, source) {\n this.style.addSource(id, source);\n return this;\n },\n\n /**\n * Remove an existing source from the map style.\n *\n * @param {string} id ID of the source to remove\n * @fires source.remove\n * @returns {Map} `this`\n */\n removeSource: function(id) {\n this.style.removeSource(id);\n return this;\n },\n\n /**\n * Return the style source object with the given `id`.\n *\n * @param {string} id source ID\n * @returns {Object}\n */\n getSource: function(id) {\n return this.style.getSource(id);\n },\n\n /**\n * Add a layer to the map style. The layer will be inserted before the layer with\n * ID `before`, or appended if `before` is omitted.\n * @param {Layer} layer\n * @param {string=} before ID of an existing layer to insert before\n * @fires layer.add\n * @returns {Map} `this`\n */\n addLayer: function(layer, before) {\n this.style.addLayer(layer, before);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Remove the layer with the given `id` from the map. Any layers which refer to the\n * specified layer via a `ref` property are also removed.\n *\n * @param {string} id\n * @fires layer.remove\n * @returns {Map} this\n */\n removeLayer: function(id) {\n this.style.removeLayer(id);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Set the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {Array} filter filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n * @returns {Map} `this`\n */\n setFilter: function(layer, filter) {\n this.style.setFilter(layer, filter);\n return this;\n },\n\n /**\n * Get the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @returns {Array} filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n */\n getFilter: function(layer) {\n return this.style.getFilter(layer);\n },\n\n /**\n * Set the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {*} value value for the paint propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @param {string=} klass optional class specifier for the property\n * @returns {Map} `this`\n */\n setPaintProperty: function(layer, name, value, klass) {\n this.style.setPaintProperty(layer, name, value, klass);\n this.style._cascade(this._classes);\n this.update(true);\n return this;\n },\n\n /**\n * Get the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the paint propery\n */\n getPaintProperty: function(layer, name, klass) {\n return this.style.getPaintProperty(layer, name, klass);\n },\n\n /**\n * Set the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {*} value value for the layout propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @returns {Map} `this`\n */\n setLayoutProperty: function(layer, name, value) {\n this.style.setLayoutProperty(layer, name, value);\n return this;\n },\n\n /**\n * Get the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the layout propery\n */\n getLayoutProperty: function(layer, name) {\n return this.style.getLayoutProperty(layer, name);\n },\n\n /**\n * Get the Map's container as an HTML element\n * @returns {HTMLElement} container\n */\n getContainer: function() {\n return this._container;\n },\n\n /**\n * Get the Map's canvas as an HTML canvas\n * @returns {HTMLElement} canvas\n */\n getCanvas: function() {\n return this._canvas.getElement();\n },\n\n _move: function(zoom, rotate, pitch) {\n\n this.update(zoom).fire('move');\n\n if (zoom) this.fire('zoom');\n if (rotate) this.fire('rotate');\n if (pitch) this.fire('pitch');\n\n return this;\n },\n\n // map setup code\n _setupContainer: function() {\n var id = this.options.container;\n var container = this._container = typeof id === 'string' ? document.getElementById(id) : id;\n if (container) container.classList.add('mapboxgl-map');\n this._canvas = new Canvas(this, container);\n },\n\n _setupControlPos: function() {\n var corners = this._controlCorners = {};\n var prefix = 'mapboxgl-ctrl-';\n var container = this.getContainer();\n\n function createCorner(pos) {\n var className = prefix + pos;\n corners[pos] = DOM.create('div', className, container);\n }\n\n if (container && typeof document === 'object') {\n createCorner('top-left');\n createCorner('top-right');\n createCorner('bottom-left');\n createCorner('bottom-right');\n }\n },\n\n _setupPainter: function() {\n var gl = this._canvas.getWebGLContext(this.options.failIfMajorPerformanceCaveat);\n\n if (!gl) {\n console.error('Failed to initialize WebGL');\n return;\n }\n\n this.painter = new GLPainter(gl, this.transform);\n },\n\n _contextLost: function(event) {\n event.preventDefault();\n if (this._frameId) {\n browser.cancelFrame(this._frameId);\n }\n },\n\n _contextRestored: function() {\n this._setupPainter();\n this.resize();\n this.update();\n },\n\n /**\n * Is this map fully loaded? If the style isn't loaded\n * or it has a change to the sources or style that isn't\n * propagated to its style, return false.\n *\n * @returns {boolean} whether the map is loaded\n */\n loaded: function() {\n if (this._styleDirty || this._sourcesDirty)\n return false;\n if (this.style && !this.style.loaded())\n return false;\n return true;\n },\n\n /**\n * Update this map's style and re-render the map.\n *\n * @param {Object} updateStyle new style\n * @returns {Map} this\n */\n update: function(updateStyle) {\n if (!this.style) return this;\n\n this._styleDirty = this._styleDirty || updateStyle;\n this._sourcesDirty = true;\n\n this._rerender();\n\n return this;\n },\n\n /**\n * Call when a (re-)render of the map is required, e.g. when the\n * user panned or zoomed,f or new data is available.\n * @returns {Map} this\n */\n render: function() {\n if (this.style && this._styleDirty) {\n this._styleDirty = false;\n this.style._recalculate(this.transform.zoom);\n }\n\n if (this.style && this._sourcesDirty && !this._sourcesDirtyTimeout) {\n this._sourcesDirty = false;\n this._sourcesDirtyTimeout = setTimeout(function() {\n this._sourcesDirtyTimeout = null;\n }.bind(this), 50);\n this.style._updateSources(this.transform);\n }\n\n this.painter.render(this.style, {\n debug: this.debug,\n vertices: this.vertices,\n rotating: this.rotating,\n zooming: this.zooming\n });\n\n this.fire('render');\n\n if (this.loaded() && !this._loaded) {\n this._loaded = true;\n this.fire('load');\n }\n\n this._frameId = null;\n\n if (!this.animationLoop.stopped()) {\n this._styleDirty = true;\n }\n\n if (this._sourcesDirty || this._repaint || !this.animationLoop.stopped()) {\n this._rerender();\n }\n\n return this;\n },\n\n /**\n * Destroys the map's underlying resources, including web workers.\n * @returns {Map} this\n */\n remove: function() {\n if (this._hash) this._hash.remove();\n browser.cancelFrame(this._frameId);\n clearTimeout(this._sourcesDirtyTimeout);\n this.setStyle(null);\n return this;\n },\n\n _rerender: function() {\n if (this.style && !this._frameId) {\n this._frameId = browser.frame(this.render);\n }\n },\n\n _forwardStyleEvent: function(e) {\n this.fire('style.' + e.type, util.extend({style: e.target}, e));\n },\n\n _forwardSourceEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardLayerEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardTileEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _onStyleLoad: function(e) {\n this.style._cascade(this._classes, {transition: false});\n this._forwardStyleEvent(e);\n },\n\n _onStyleChange: function(e) {\n this.update(true);\n this._forwardStyleEvent(e);\n },\n\n _onSourceAdd: function(e) {\n var source = e.source;\n if (source.onAdd)\n source.onAdd(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceRemove: function(e) {\n var source = e.source;\n if (source.onRemove)\n source.onRemove(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceUpdate: function(e) {\n this.update();\n this._forwardSourceEvent(e);\n }\n}","path":"js/ui/map.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/map.js#L169-L171"},"params":[{"title":"param","description":"Map zoom level","type":{"type":"NameExpression","name":"number"},"name":"zoom"}],"returns":[{"title":"returns","description":"`this`","type":{"type":"NameExpression","name":"Map"}}],"name":"setZoom","memberof":"Map","scope":"instance","members":{"instance":[],"static":[]},"path":["Map","setZoom"]},{"description":"Get geographical coordinates given pixel coordinates","tags":[{"title":"param","description":"[x, y] pixel coordinates","type":{"type":"TypeApplication","expression":{"type":"NameExpression","name":"Array"},"applications":[{"type":"NameExpression","name":"number"}]},"name":"point"},{"title":"returns","description":null,"type":{"type":"NameExpression","name":"LatLng"}},{"title":"name","name":"unproject"},{"title":"memberof","description":"Map"},{"title":"instance"}],"context":{"loc":{"start":{"line":344,"column":4},"end":{"line":346,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/map.js","code":"{\n\n options: {\n center: [0, 0],\n zoom: 0,\n bearing: 0,\n pitch: 0,\n\n minZoom: 0,\n maxZoom: 20,\n\n interactive: true,\n hash: false,\n\n attributionControl: true,\n\n failIfMajorPerformanceCaveat: false\n },\n\n addControl: function(control) {\n control.addTo(this);\n return this;\n },\n\n /**\n * Sets a map position\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @param {number} zoom Map zoom level\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setView: function(center, zoom, bearing, pitch) {\n this.stop();\n\n var tr = this.transform,\n zoomChanged = tr.zoom !== +zoom,\n bearingChanged = tr.bearing !== +bearing,\n pitchChanged = tr.pitch !== +pitch;\n\n tr.center = LatLng.convert(center);\n tr.zoom = +zoom;\n tr.bearing = +bearing;\n tr.pitch = +pitch;\n\n return this\n .fire('movestart')\n ._move(zoomChanged, bearingChanged, pitchChanged)\n .fire('moveend');\n },\n\n /**\n * Sets a map location\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setCenter: function(center) {\n this.setView(center, this.getZoom(), this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map zoom\n *\n * @param {number} zoom Map zoom level\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setZoom: function(zoom) {\n this.setView(this.getCenter(), zoom, this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map rotation\n *\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setBearing: function(bearing) {\n this.setView(this.getCenter(), this.getZoom(), bearing, this.getPitch());\n },\n\n /**\n * Sets a map angle\n *\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setPitch: function(pitch) {\n this.setView(this.getCenter(), this.getZoom(), this.getBearing(), pitch);\n },\n\n /**\n * Get the current view geographical point\n * @returns {LatLng}\n */\n getCenter: function() { return this.transform.center; },\n\n /**\n * Get the current zoom\n * @returns {number}\n */\n getZoom: function() { return this.transform.zoom; },\n\n /**\n * Get the current bearing in degrees\n * @returns {number}\n */\n getBearing: function() { return this.transform.bearing; },\n\n /**\n * Get the current angle in degrees\n * @returns {number}\n */\n getPitch: function() { return this.transform.pitch; },\n\n /**\n * @typedef {Object} [styleOptions]\n * @param {Boolean} [styleOptions.transition=true]\n */\n\n /**\n * Adds a style class to a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n addClass: function(klass, options) {\n if (this._classes[klass]) return;\n this._classes[klass] = true;\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Removes a style class from a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n removeClass: function(klass, options) {\n if (!this._classes[klass]) return;\n delete this._classes[klass];\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Helper method to add more than one class\n *\n * @param {Array} klasses An array of class names\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n setClasses: function(klasses, options) {\n this._classes = {};\n for (var i = 0; i < klasses.length; i++) {\n this._classes[klasses[i]] = true;\n }\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Check whether a style class is active\n *\n * @param {string} klass Name of style class\n * @returns {boolean}\n */\n hasClass: function(klass) {\n return !!this._classes[klass];\n },\n\n /**\n * Return an array of the current active style classes\n *\n * @returns {boolean}\n */\n getClasses: function() {\n return Object.keys(this._classes);\n },\n\n /**\n * Detect the map's new width and height and resize it.\n *\n * @returns {Map} `this`\n */\n resize: function() {\n var width = 0, height = 0;\n\n if (this._container) {\n width = this._container.offsetWidth || 400;\n height = this._container.offsetHeight || 300;\n }\n\n this._canvas.resize(width, height);\n\n this.transform.width = width;\n this.transform.height = height;\n this.transform._constrain();\n\n this.painter.resize(width, height);\n\n return this\n .fire('movestart')\n ._move()\n .fire('resize')\n .fire('moveend');\n },\n\n /**\n * Get the map's geographical bounds\n *\n * @returns {LatLngBounds}\n */\n getBounds: function() {\n return new LatLngBounds(\n this.transform.pointLocation(new Point(0, 0)),\n this.transform.pointLocation(this.transform.size));\n },\n\n /**\n * Get pixel coordinates (relative to map container) given a geographical location\n *\n * @param {LatLng} latlng\n * @returns {Object} `x` and `y` coordinates\n */\n project: function(latlng) {\n return this.transform.locationPoint(LatLng.convert(latlng));\n },\n\n /**\n * Get geographical coordinates given pixel coordinates\n *\n * @param {Array} point [x, y] pixel coordinates\n * @returns {LatLng}\n */\n unproject: function(point) {\n return this.transform.pointLocation(Point.convert(point));\n },\n\n /**\n * Get all features at a point ([x, y])\n *\n * @param {Array} point [x, y] pixel coordinates\n * @param {Object} params\n * @param {number} [params.radius=0] Optional. Radius in pixels to search in\n * @param {string} params.layer Optional. Only return features from a given layer\n * @param {string} params.type Optional. Either `raster` or `vector`\n * @param {featuresAtCallback} callback function that returns the response\n *\n * @callback featuresAtCallback\n * @param {Object|null} err Error _If any_\n * @param {Array} features Displays a JSON array of features given the passed parameters of `featuresAt`\n *\n * @returns {Map} `this`\n */\n featuresAt: function(point, params, callback) {\n var coord = this.transform.pointCoordinate(Point.convert(point));\n this.style.featuresAt(coord, params, callback);\n return this;\n },\n\n /**\n * Replaces the map's style object\n *\n * @param {Object} style A style object formatted as JSON\n * @returns {Map} `this`\n */\n setStyle: function(style) {\n if (this.style) {\n this.style\n .off('load', this._onStyleLoad)\n .off('error', this._forwardStyleEvent)\n .off('change', this._onStyleChange)\n .off('source.add', this._onSourceAdd)\n .off('source.remove', this._onSourceRemove)\n .off('source.load', this._onSourceUpdate)\n .off('source.error', this._forwardSourceEvent)\n .off('source.change', this._onSourceUpdate)\n .off('layer.add', this._forwardLayerEvent)\n .off('layer.remove', this._forwardLayerEvent)\n .off('tile.add', this._forwardTileEvent)\n .off('tile.remove', this._forwardTileEvent)\n .off('tile.load', this.update)\n .off('tile.error', this._forwardTileEvent)\n ._remove();\n\n this.off('rotate', this.style._redoPlacement);\n this.off('pitch', this.style._redoPlacement);\n }\n\n if (!style) {\n this.style = null;\n return this;\n } else if (style instanceof Style) {\n this.style = style;\n } else {\n this.style = new Style(style, this.animationLoop);\n }\n\n this.style\n .on('load', this._onStyleLoad)\n .on('error', this._forwardStyleEvent)\n .on('change', this._onStyleChange)\n .on('source.add', this._onSourceAdd)\n .on('source.remove', this._onSourceRemove)\n .on('source.load', this._onSourceUpdate)\n .on('source.error', this._forwardSourceEvent)\n .on('source.change', this._onSourceUpdate)\n .on('layer.add', this._forwardLayerEvent)\n .on('layer.remove', this._forwardLayerEvent)\n .on('tile.add', this._forwardTileEvent)\n .on('tile.remove', this._forwardTileEvent)\n .on('tile.load', this.update)\n .on('tile.error', this._forwardTileEvent);\n\n this.on('rotate', this.style._redoPlacement);\n this.on('pitch', this.style._redoPlacement);\n\n return this;\n },\n\n /**\n * Add a source to the map style.\n *\n * @param {string} id ID of the source. Must not be used by any existing source.\n * @param {Object} source source specification, following the\n * [Mapbox GL Style Reference](https://www.mapbox.com/mapbox-gl-style-spec/#sources)\n * @fires source.add\n * @returns {Map} `this`\n */\n addSource: function(id, source) {\n this.style.addSource(id, source);\n return this;\n },\n\n /**\n * Remove an existing source from the map style.\n *\n * @param {string} id ID of the source to remove\n * @fires source.remove\n * @returns {Map} `this`\n */\n removeSource: function(id) {\n this.style.removeSource(id);\n return this;\n },\n\n /**\n * Return the style source object with the given `id`.\n *\n * @param {string} id source ID\n * @returns {Object}\n */\n getSource: function(id) {\n return this.style.getSource(id);\n },\n\n /**\n * Add a layer to the map style. The layer will be inserted before the layer with\n * ID `before`, or appended if `before` is omitted.\n * @param {Layer} layer\n * @param {string=} before ID of an existing layer to insert before\n * @fires layer.add\n * @returns {Map} `this`\n */\n addLayer: function(layer, before) {\n this.style.addLayer(layer, before);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Remove the layer with the given `id` from the map. Any layers which refer to the\n * specified layer via a `ref` property are also removed.\n *\n * @param {string} id\n * @fires layer.remove\n * @returns {Map} this\n */\n removeLayer: function(id) {\n this.style.removeLayer(id);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Set the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {Array} filter filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n * @returns {Map} `this`\n */\n setFilter: function(layer, filter) {\n this.style.setFilter(layer, filter);\n return this;\n },\n\n /**\n * Get the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @returns {Array} filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n */\n getFilter: function(layer) {\n return this.style.getFilter(layer);\n },\n\n /**\n * Set the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {*} value value for the paint propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @param {string=} klass optional class specifier for the property\n * @returns {Map} `this`\n */\n setPaintProperty: function(layer, name, value, klass) {\n this.style.setPaintProperty(layer, name, value, klass);\n this.style._cascade(this._classes);\n this.update(true);\n return this;\n },\n\n /**\n * Get the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the paint propery\n */\n getPaintProperty: function(layer, name, klass) {\n return this.style.getPaintProperty(layer, name, klass);\n },\n\n /**\n * Set the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {*} value value for the layout propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @returns {Map} `this`\n */\n setLayoutProperty: function(layer, name, value) {\n this.style.setLayoutProperty(layer, name, value);\n return this;\n },\n\n /**\n * Get the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the layout propery\n */\n getLayoutProperty: function(layer, name) {\n return this.style.getLayoutProperty(layer, name);\n },\n\n /**\n * Get the Map's container as an HTML element\n * @returns {HTMLElement} container\n */\n getContainer: function() {\n return this._container;\n },\n\n /**\n * Get the Map's canvas as an HTML canvas\n * @returns {HTMLElement} canvas\n */\n getCanvas: function() {\n return this._canvas.getElement();\n },\n\n _move: function(zoom, rotate, pitch) {\n\n this.update(zoom).fire('move');\n\n if (zoom) this.fire('zoom');\n if (rotate) this.fire('rotate');\n if (pitch) this.fire('pitch');\n\n return this;\n },\n\n // map setup code\n _setupContainer: function() {\n var id = this.options.container;\n var container = this._container = typeof id === 'string' ? document.getElementById(id) : id;\n if (container) container.classList.add('mapboxgl-map');\n this._canvas = new Canvas(this, container);\n },\n\n _setupControlPos: function() {\n var corners = this._controlCorners = {};\n var prefix = 'mapboxgl-ctrl-';\n var container = this.getContainer();\n\n function createCorner(pos) {\n var className = prefix + pos;\n corners[pos] = DOM.create('div', className, container);\n }\n\n if (container && typeof document === 'object') {\n createCorner('top-left');\n createCorner('top-right');\n createCorner('bottom-left');\n createCorner('bottom-right');\n }\n },\n\n _setupPainter: function() {\n var gl = this._canvas.getWebGLContext(this.options.failIfMajorPerformanceCaveat);\n\n if (!gl) {\n console.error('Failed to initialize WebGL');\n return;\n }\n\n this.painter = new GLPainter(gl, this.transform);\n },\n\n _contextLost: function(event) {\n event.preventDefault();\n if (this._frameId) {\n browser.cancelFrame(this._frameId);\n }\n },\n\n _contextRestored: function() {\n this._setupPainter();\n this.resize();\n this.update();\n },\n\n /**\n * Is this map fully loaded? If the style isn't loaded\n * or it has a change to the sources or style that isn't\n * propagated to its style, return false.\n *\n * @returns {boolean} whether the map is loaded\n */\n loaded: function() {\n if (this._styleDirty || this._sourcesDirty)\n return false;\n if (this.style && !this.style.loaded())\n return false;\n return true;\n },\n\n /**\n * Update this map's style and re-render the map.\n *\n * @param {Object} updateStyle new style\n * @returns {Map} this\n */\n update: function(updateStyle) {\n if (!this.style) return this;\n\n this._styleDirty = this._styleDirty || updateStyle;\n this._sourcesDirty = true;\n\n this._rerender();\n\n return this;\n },\n\n /**\n * Call when a (re-)render of the map is required, e.g. when the\n * user panned or zoomed,f or new data is available.\n * @returns {Map} this\n */\n render: function() {\n if (this.style && this._styleDirty) {\n this._styleDirty = false;\n this.style._recalculate(this.transform.zoom);\n }\n\n if (this.style && this._sourcesDirty && !this._sourcesDirtyTimeout) {\n this._sourcesDirty = false;\n this._sourcesDirtyTimeout = setTimeout(function() {\n this._sourcesDirtyTimeout = null;\n }.bind(this), 50);\n this.style._updateSources(this.transform);\n }\n\n this.painter.render(this.style, {\n debug: this.debug,\n vertices: this.vertices,\n rotating: this.rotating,\n zooming: this.zooming\n });\n\n this.fire('render');\n\n if (this.loaded() && !this._loaded) {\n this._loaded = true;\n this.fire('load');\n }\n\n this._frameId = null;\n\n if (!this.animationLoop.stopped()) {\n this._styleDirty = true;\n }\n\n if (this._sourcesDirty || this._repaint || !this.animationLoop.stopped()) {\n this._rerender();\n }\n\n return this;\n },\n\n /**\n * Destroys the map's underlying resources, including web workers.\n * @returns {Map} this\n */\n remove: function() {\n if (this._hash) this._hash.remove();\n browser.cancelFrame(this._frameId);\n clearTimeout(this._sourcesDirtyTimeout);\n this.setStyle(null);\n return this;\n },\n\n _rerender: function() {\n if (this.style && !this._frameId) {\n this._frameId = browser.frame(this.render);\n }\n },\n\n _forwardStyleEvent: function(e) {\n this.fire('style.' + e.type, util.extend({style: e.target}, e));\n },\n\n _forwardSourceEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardLayerEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardTileEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _onStyleLoad: function(e) {\n this.style._cascade(this._classes, {transition: false});\n this._forwardStyleEvent(e);\n },\n\n _onStyleChange: function(e) {\n this.update(true);\n this._forwardStyleEvent(e);\n },\n\n _onSourceAdd: function(e) {\n var source = e.source;\n if (source.onAdd)\n source.onAdd(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceRemove: function(e) {\n var source = e.source;\n if (source.onRemove)\n source.onRemove(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceUpdate: function(e) {\n this.update();\n this._forwardSourceEvent(e);\n }\n}","path":"js/ui/map.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/map.js#L344-L346"},"params":[{"title":"param","description":"[x, y] pixel coordinates","type":{"type":"TypeApplication","expression":{"type":"NameExpression","name":"Array"},"applications":[{"type":"NameExpression","name":"number"}]},"name":"point"}],"returns":[{"title":"returns","description":null,"type":{"type":"NameExpression","name":"LatLng"}}],"name":"unproject","memberof":"Map","scope":"instance","members":{"instance":[],"static":[]},"path":["Map","unproject"]},{"description":"Set the value of a layout property in a given style layer.","tags":[{"title":"param","description":"ID of a layer","type":{"type":"NameExpression","name":"string"},"name":"layer"},{"title":"param","description":"name of a layout property","type":{"type":"NameExpression","name":"string"},"name":"name"},{"title":"param","description":"value for the layout propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)","type":{"type":"AllLiteral"},"name":"value"},{"title":"returns","description":"`this`","type":{"type":"NameExpression","name":"Map"}},{"title":"name","name":"setLayoutProperty"},{"title":"memberof","description":"Map"},{"title":"instance"}],"context":{"loc":{"start":{"line":552,"column":4},"end":{"line":555,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/map.js","code":"{\n\n options: {\n center: [0, 0],\n zoom: 0,\n bearing: 0,\n pitch: 0,\n\n minZoom: 0,\n maxZoom: 20,\n\n interactive: true,\n hash: false,\n\n attributionControl: true,\n\n failIfMajorPerformanceCaveat: false\n },\n\n addControl: function(control) {\n control.addTo(this);\n return this;\n },\n\n /**\n * Sets a map position\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @param {number} zoom Map zoom level\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setView: function(center, zoom, bearing, pitch) {\n this.stop();\n\n var tr = this.transform,\n zoomChanged = tr.zoom !== +zoom,\n bearingChanged = tr.bearing !== +bearing,\n pitchChanged = tr.pitch !== +pitch;\n\n tr.center = LatLng.convert(center);\n tr.zoom = +zoom;\n tr.bearing = +bearing;\n tr.pitch = +pitch;\n\n return this\n .fire('movestart')\n ._move(zoomChanged, bearingChanged, pitchChanged)\n .fire('moveend');\n },\n\n /**\n * Sets a map location\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setCenter: function(center) {\n this.setView(center, this.getZoom(), this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map zoom\n *\n * @param {number} zoom Map zoom level\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setZoom: function(zoom) {\n this.setView(this.getCenter(), zoom, this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map rotation\n *\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setBearing: function(bearing) {\n this.setView(this.getCenter(), this.getZoom(), bearing, this.getPitch());\n },\n\n /**\n * Sets a map angle\n *\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setPitch: function(pitch) {\n this.setView(this.getCenter(), this.getZoom(), this.getBearing(), pitch);\n },\n\n /**\n * Get the current view geographical point\n * @returns {LatLng}\n */\n getCenter: function() { return this.transform.center; },\n\n /**\n * Get the current zoom\n * @returns {number}\n */\n getZoom: function() { return this.transform.zoom; },\n\n /**\n * Get the current bearing in degrees\n * @returns {number}\n */\n getBearing: function() { return this.transform.bearing; },\n\n /**\n * Get the current angle in degrees\n * @returns {number}\n */\n getPitch: function() { return this.transform.pitch; },\n\n /**\n * @typedef {Object} [styleOptions]\n * @param {Boolean} [styleOptions.transition=true]\n */\n\n /**\n * Adds a style class to a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n addClass: function(klass, options) {\n if (this._classes[klass]) return;\n this._classes[klass] = true;\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Removes a style class from a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n removeClass: function(klass, options) {\n if (!this._classes[klass]) return;\n delete this._classes[klass];\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Helper method to add more than one class\n *\n * @param {Array} klasses An array of class names\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n setClasses: function(klasses, options) {\n this._classes = {};\n for (var i = 0; i < klasses.length; i++) {\n this._classes[klasses[i]] = true;\n }\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Check whether a style class is active\n *\n * @param {string} klass Name of style class\n * @returns {boolean}\n */\n hasClass: function(klass) {\n return !!this._classes[klass];\n },\n\n /**\n * Return an array of the current active style classes\n *\n * @returns {boolean}\n */\n getClasses: function() {\n return Object.keys(this._classes);\n },\n\n /**\n * Detect the map's new width and height and resize it.\n *\n * @returns {Map} `this`\n */\n resize: function() {\n var width = 0, height = 0;\n\n if (this._container) {\n width = this._container.offsetWidth || 400;\n height = this._container.offsetHeight || 300;\n }\n\n this._canvas.resize(width, height);\n\n this.transform.width = width;\n this.transform.height = height;\n this.transform._constrain();\n\n this.painter.resize(width, height);\n\n return this\n .fire('movestart')\n ._move()\n .fire('resize')\n .fire('moveend');\n },\n\n /**\n * Get the map's geographical bounds\n *\n * @returns {LatLngBounds}\n */\n getBounds: function() {\n return new LatLngBounds(\n this.transform.pointLocation(new Point(0, 0)),\n this.transform.pointLocation(this.transform.size));\n },\n\n /**\n * Get pixel coordinates (relative to map container) given a geographical location\n *\n * @param {LatLng} latlng\n * @returns {Object} `x` and `y` coordinates\n */\n project: function(latlng) {\n return this.transform.locationPoint(LatLng.convert(latlng));\n },\n\n /**\n * Get geographical coordinates given pixel coordinates\n *\n * @param {Array} point [x, y] pixel coordinates\n * @returns {LatLng}\n */\n unproject: function(point) {\n return this.transform.pointLocation(Point.convert(point));\n },\n\n /**\n * Get all features at a point ([x, y])\n *\n * @param {Array} point [x, y] pixel coordinates\n * @param {Object} params\n * @param {number} [params.radius=0] Optional. Radius in pixels to search in\n * @param {string} params.layer Optional. Only return features from a given layer\n * @param {string} params.type Optional. Either `raster` or `vector`\n * @param {featuresAtCallback} callback function that returns the response\n *\n * @callback featuresAtCallback\n * @param {Object|null} err Error _If any_\n * @param {Array} features Displays a JSON array of features given the passed parameters of `featuresAt`\n *\n * @returns {Map} `this`\n */\n featuresAt: function(point, params, callback) {\n var coord = this.transform.pointCoordinate(Point.convert(point));\n this.style.featuresAt(coord, params, callback);\n return this;\n },\n\n /**\n * Replaces the map's style object\n *\n * @param {Object} style A style object formatted as JSON\n * @returns {Map} `this`\n */\n setStyle: function(style) {\n if (this.style) {\n this.style\n .off('load', this._onStyleLoad)\n .off('error', this._forwardStyleEvent)\n .off('change', this._onStyleChange)\n .off('source.add', this._onSourceAdd)\n .off('source.remove', this._onSourceRemove)\n .off('source.load', this._onSourceUpdate)\n .off('source.error', this._forwardSourceEvent)\n .off('source.change', this._onSourceUpdate)\n .off('layer.add', this._forwardLayerEvent)\n .off('layer.remove', this._forwardLayerEvent)\n .off('tile.add', this._forwardTileEvent)\n .off('tile.remove', this._forwardTileEvent)\n .off('tile.load', this.update)\n .off('tile.error', this._forwardTileEvent)\n ._remove();\n\n this.off('rotate', this.style._redoPlacement);\n this.off('pitch', this.style._redoPlacement);\n }\n\n if (!style) {\n this.style = null;\n return this;\n } else if (style instanceof Style) {\n this.style = style;\n } else {\n this.style = new Style(style, this.animationLoop);\n }\n\n this.style\n .on('load', this._onStyleLoad)\n .on('error', this._forwardStyleEvent)\n .on('change', this._onStyleChange)\n .on('source.add', this._onSourceAdd)\n .on('source.remove', this._onSourceRemove)\n .on('source.load', this._onSourceUpdate)\n .on('source.error', this._forwardSourceEvent)\n .on('source.change', this._onSourceUpdate)\n .on('layer.add', this._forwardLayerEvent)\n .on('layer.remove', this._forwardLayerEvent)\n .on('tile.add', this._forwardTileEvent)\n .on('tile.remove', this._forwardTileEvent)\n .on('tile.load', this.update)\n .on('tile.error', this._forwardTileEvent);\n\n this.on('rotate', this.style._redoPlacement);\n this.on('pitch', this.style._redoPlacement);\n\n return this;\n },\n\n /**\n * Add a source to the map style.\n *\n * @param {string} id ID of the source. Must not be used by any existing source.\n * @param {Object} source source specification, following the\n * [Mapbox GL Style Reference](https://www.mapbox.com/mapbox-gl-style-spec/#sources)\n * @fires source.add\n * @returns {Map} `this`\n */\n addSource: function(id, source) {\n this.style.addSource(id, source);\n return this;\n },\n\n /**\n * Remove an existing source from the map style.\n *\n * @param {string} id ID of the source to remove\n * @fires source.remove\n * @returns {Map} `this`\n */\n removeSource: function(id) {\n this.style.removeSource(id);\n return this;\n },\n\n /**\n * Return the style source object with the given `id`.\n *\n * @param {string} id source ID\n * @returns {Object}\n */\n getSource: function(id) {\n return this.style.getSource(id);\n },\n\n /**\n * Add a layer to the map style. The layer will be inserted before the layer with\n * ID `before`, or appended if `before` is omitted.\n * @param {Layer} layer\n * @param {string=} before ID of an existing layer to insert before\n * @fires layer.add\n * @returns {Map} `this`\n */\n addLayer: function(layer, before) {\n this.style.addLayer(layer, before);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Remove the layer with the given `id` from the map. Any layers which refer to the\n * specified layer via a `ref` property are also removed.\n *\n * @param {string} id\n * @fires layer.remove\n * @returns {Map} this\n */\n removeLayer: function(id) {\n this.style.removeLayer(id);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Set the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {Array} filter filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n * @returns {Map} `this`\n */\n setFilter: function(layer, filter) {\n this.style.setFilter(layer, filter);\n return this;\n },\n\n /**\n * Get the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @returns {Array} filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n */\n getFilter: function(layer) {\n return this.style.getFilter(layer);\n },\n\n /**\n * Set the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {*} value value for the paint propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @param {string=} klass optional class specifier for the property\n * @returns {Map} `this`\n */\n setPaintProperty: function(layer, name, value, klass) {\n this.style.setPaintProperty(layer, name, value, klass);\n this.style._cascade(this._classes);\n this.update(true);\n return this;\n },\n\n /**\n * Get the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the paint propery\n */\n getPaintProperty: function(layer, name, klass) {\n return this.style.getPaintProperty(layer, name, klass);\n },\n\n /**\n * Set the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {*} value value for the layout propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @returns {Map} `this`\n */\n setLayoutProperty: function(layer, name, value) {\n this.style.setLayoutProperty(layer, name, value);\n return this;\n },\n\n /**\n * Get the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the layout propery\n */\n getLayoutProperty: function(layer, name) {\n return this.style.getLayoutProperty(layer, name);\n },\n\n /**\n * Get the Map's container as an HTML element\n * @returns {HTMLElement} container\n */\n getContainer: function() {\n return this._container;\n },\n\n /**\n * Get the Map's canvas as an HTML canvas\n * @returns {HTMLElement} canvas\n */\n getCanvas: function() {\n return this._canvas.getElement();\n },\n\n _move: function(zoom, rotate, pitch) {\n\n this.update(zoom).fire('move');\n\n if (zoom) this.fire('zoom');\n if (rotate) this.fire('rotate');\n if (pitch) this.fire('pitch');\n\n return this;\n },\n\n // map setup code\n _setupContainer: function() {\n var id = this.options.container;\n var container = this._container = typeof id === 'string' ? document.getElementById(id) : id;\n if (container) container.classList.add('mapboxgl-map');\n this._canvas = new Canvas(this, container);\n },\n\n _setupControlPos: function() {\n var corners = this._controlCorners = {};\n var prefix = 'mapboxgl-ctrl-';\n var container = this.getContainer();\n\n function createCorner(pos) {\n var className = prefix + pos;\n corners[pos] = DOM.create('div', className, container);\n }\n\n if (container && typeof document === 'object') {\n createCorner('top-left');\n createCorner('top-right');\n createCorner('bottom-left');\n createCorner('bottom-right');\n }\n },\n\n _setupPainter: function() {\n var gl = this._canvas.getWebGLContext(this.options.failIfMajorPerformanceCaveat);\n\n if (!gl) {\n console.error('Failed to initialize WebGL');\n return;\n }\n\n this.painter = new GLPainter(gl, this.transform);\n },\n\n _contextLost: function(event) {\n event.preventDefault();\n if (this._frameId) {\n browser.cancelFrame(this._frameId);\n }\n },\n\n _contextRestored: function() {\n this._setupPainter();\n this.resize();\n this.update();\n },\n\n /**\n * Is this map fully loaded? If the style isn't loaded\n * or it has a change to the sources or style that isn't\n * propagated to its style, return false.\n *\n * @returns {boolean} whether the map is loaded\n */\n loaded: function() {\n if (this._styleDirty || this._sourcesDirty)\n return false;\n if (this.style && !this.style.loaded())\n return false;\n return true;\n },\n\n /**\n * Update this map's style and re-render the map.\n *\n * @param {Object} updateStyle new style\n * @returns {Map} this\n */\n update: function(updateStyle) {\n if (!this.style) return this;\n\n this._styleDirty = this._styleDirty || updateStyle;\n this._sourcesDirty = true;\n\n this._rerender();\n\n return this;\n },\n\n /**\n * Call when a (re-)render of the map is required, e.g. when the\n * user panned or zoomed,f or new data is available.\n * @returns {Map} this\n */\n render: function() {\n if (this.style && this._styleDirty) {\n this._styleDirty = false;\n this.style._recalculate(this.transform.zoom);\n }\n\n if (this.style && this._sourcesDirty && !this._sourcesDirtyTimeout) {\n this._sourcesDirty = false;\n this._sourcesDirtyTimeout = setTimeout(function() {\n this._sourcesDirtyTimeout = null;\n }.bind(this), 50);\n this.style._updateSources(this.transform);\n }\n\n this.painter.render(this.style, {\n debug: this.debug,\n vertices: this.vertices,\n rotating: this.rotating,\n zooming: this.zooming\n });\n\n this.fire('render');\n\n if (this.loaded() && !this._loaded) {\n this._loaded = true;\n this.fire('load');\n }\n\n this._frameId = null;\n\n if (!this.animationLoop.stopped()) {\n this._styleDirty = true;\n }\n\n if (this._sourcesDirty || this._repaint || !this.animationLoop.stopped()) {\n this._rerender();\n }\n\n return this;\n },\n\n /**\n * Destroys the map's underlying resources, including web workers.\n * @returns {Map} this\n */\n remove: function() {\n if (this._hash) this._hash.remove();\n browser.cancelFrame(this._frameId);\n clearTimeout(this._sourcesDirtyTimeout);\n this.setStyle(null);\n return this;\n },\n\n _rerender: function() {\n if (this.style && !this._frameId) {\n this._frameId = browser.frame(this.render);\n }\n },\n\n _forwardStyleEvent: function(e) {\n this.fire('style.' + e.type, util.extend({style: e.target}, e));\n },\n\n _forwardSourceEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardLayerEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardTileEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _onStyleLoad: function(e) {\n this.style._cascade(this._classes, {transition: false});\n this._forwardStyleEvent(e);\n },\n\n _onStyleChange: function(e) {\n this.update(true);\n this._forwardStyleEvent(e);\n },\n\n _onSourceAdd: function(e) {\n var source = e.source;\n if (source.onAdd)\n source.onAdd(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceRemove: function(e) {\n var source = e.source;\n if (source.onRemove)\n source.onRemove(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceUpdate: function(e) {\n this.update();\n this._forwardSourceEvent(e);\n }\n}","path":"js/ui/map.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/map.js#L552-L555"},"params":[{"title":"param","description":"ID of a layer","type":{"type":"NameExpression","name":"string"},"name":"layer"},{"title":"param","description":"name of a layout property","type":{"type":"NameExpression","name":"string"},"name":"name"},{"title":"param","description":"value for the layout propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)","type":{"type":"AllLiteral"},"name":"value"}],"returns":[{"title":"returns","description":"`this`","type":{"type":"NameExpression","name":"Map"}}],"name":"setLayoutProperty","memberof":"Map","scope":"instance","members":{"instance":[],"static":[]},"path":["Map","setLayoutProperty"]},{"description":"Sets a map rotation","tags":[{"title":"param","description":"Map rotation bearing in degrees counter-clockwise from north","type":{"type":"NameExpression","name":"number"},"name":"bearing"},{"title":"fires","description":"movestart"},{"title":"fires","description":"moveend"},{"title":"returns","description":"`this`","type":{"type":"NameExpression","name":"Map"}},{"title":"name","name":"setBearing"},{"title":"memberof","description":"Map"},{"title":"instance"}],"context":{"loc":{"start":{"line":181,"column":4},"end":{"line":183,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/map.js","code":"{\n\n options: {\n center: [0, 0],\n zoom: 0,\n bearing: 0,\n pitch: 0,\n\n minZoom: 0,\n maxZoom: 20,\n\n interactive: true,\n hash: false,\n\n attributionControl: true,\n\n failIfMajorPerformanceCaveat: false\n },\n\n addControl: function(control) {\n control.addTo(this);\n return this;\n },\n\n /**\n * Sets a map position\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @param {number} zoom Map zoom level\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setView: function(center, zoom, bearing, pitch) {\n this.stop();\n\n var tr = this.transform,\n zoomChanged = tr.zoom !== +zoom,\n bearingChanged = tr.bearing !== +bearing,\n pitchChanged = tr.pitch !== +pitch;\n\n tr.center = LatLng.convert(center);\n tr.zoom = +zoom;\n tr.bearing = +bearing;\n tr.pitch = +pitch;\n\n return this\n .fire('movestart')\n ._move(zoomChanged, bearingChanged, pitchChanged)\n .fire('moveend');\n },\n\n /**\n * Sets a map location\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setCenter: function(center) {\n this.setView(center, this.getZoom(), this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map zoom\n *\n * @param {number} zoom Map zoom level\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setZoom: function(zoom) {\n this.setView(this.getCenter(), zoom, this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map rotation\n *\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setBearing: function(bearing) {\n this.setView(this.getCenter(), this.getZoom(), bearing, this.getPitch());\n },\n\n /**\n * Sets a map angle\n *\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setPitch: function(pitch) {\n this.setView(this.getCenter(), this.getZoom(), this.getBearing(), pitch);\n },\n\n /**\n * Get the current view geographical point\n * @returns {LatLng}\n */\n getCenter: function() { return this.transform.center; },\n\n /**\n * Get the current zoom\n * @returns {number}\n */\n getZoom: function() { return this.transform.zoom; },\n\n /**\n * Get the current bearing in degrees\n * @returns {number}\n */\n getBearing: function() { return this.transform.bearing; },\n\n /**\n * Get the current angle in degrees\n * @returns {number}\n */\n getPitch: function() { return this.transform.pitch; },\n\n /**\n * @typedef {Object} [styleOptions]\n * @param {Boolean} [styleOptions.transition=true]\n */\n\n /**\n * Adds a style class to a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n addClass: function(klass, options) {\n if (this._classes[klass]) return;\n this._classes[klass] = true;\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Removes a style class from a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n removeClass: function(klass, options) {\n if (!this._classes[klass]) return;\n delete this._classes[klass];\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Helper method to add more than one class\n *\n * @param {Array} klasses An array of class names\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n setClasses: function(klasses, options) {\n this._classes = {};\n for (var i = 0; i < klasses.length; i++) {\n this._classes[klasses[i]] = true;\n }\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Check whether a style class is active\n *\n * @param {string} klass Name of style class\n * @returns {boolean}\n */\n hasClass: function(klass) {\n return !!this._classes[klass];\n },\n\n /**\n * Return an array of the current active style classes\n *\n * @returns {boolean}\n */\n getClasses: function() {\n return Object.keys(this._classes);\n },\n\n /**\n * Detect the map's new width and height and resize it.\n *\n * @returns {Map} `this`\n */\n resize: function() {\n var width = 0, height = 0;\n\n if (this._container) {\n width = this._container.offsetWidth || 400;\n height = this._container.offsetHeight || 300;\n }\n\n this._canvas.resize(width, height);\n\n this.transform.width = width;\n this.transform.height = height;\n this.transform._constrain();\n\n this.painter.resize(width, height);\n\n return this\n .fire('movestart')\n ._move()\n .fire('resize')\n .fire('moveend');\n },\n\n /**\n * Get the map's geographical bounds\n *\n * @returns {LatLngBounds}\n */\n getBounds: function() {\n return new LatLngBounds(\n this.transform.pointLocation(new Point(0, 0)),\n this.transform.pointLocation(this.transform.size));\n },\n\n /**\n * Get pixel coordinates (relative to map container) given a geographical location\n *\n * @param {LatLng} latlng\n * @returns {Object} `x` and `y` coordinates\n */\n project: function(latlng) {\n return this.transform.locationPoint(LatLng.convert(latlng));\n },\n\n /**\n * Get geographical coordinates given pixel coordinates\n *\n * @param {Array} point [x, y] pixel coordinates\n * @returns {LatLng}\n */\n unproject: function(point) {\n return this.transform.pointLocation(Point.convert(point));\n },\n\n /**\n * Get all features at a point ([x, y])\n *\n * @param {Array} point [x, y] pixel coordinates\n * @param {Object} params\n * @param {number} [params.radius=0] Optional. Radius in pixels to search in\n * @param {string} params.layer Optional. Only return features from a given layer\n * @param {string} params.type Optional. Either `raster` or `vector`\n * @param {featuresAtCallback} callback function that returns the response\n *\n * @callback featuresAtCallback\n * @param {Object|null} err Error _If any_\n * @param {Array} features Displays a JSON array of features given the passed parameters of `featuresAt`\n *\n * @returns {Map} `this`\n */\n featuresAt: function(point, params, callback) {\n var coord = this.transform.pointCoordinate(Point.convert(point));\n this.style.featuresAt(coord, params, callback);\n return this;\n },\n\n /**\n * Replaces the map's style object\n *\n * @param {Object} style A style object formatted as JSON\n * @returns {Map} `this`\n */\n setStyle: function(style) {\n if (this.style) {\n this.style\n .off('load', this._onStyleLoad)\n .off('error', this._forwardStyleEvent)\n .off('change', this._onStyleChange)\n .off('source.add', this._onSourceAdd)\n .off('source.remove', this._onSourceRemove)\n .off('source.load', this._onSourceUpdate)\n .off('source.error', this._forwardSourceEvent)\n .off('source.change', this._onSourceUpdate)\n .off('layer.add', this._forwardLayerEvent)\n .off('layer.remove', this._forwardLayerEvent)\n .off('tile.add', this._forwardTileEvent)\n .off('tile.remove', this._forwardTileEvent)\n .off('tile.load', this.update)\n .off('tile.error', this._forwardTileEvent)\n ._remove();\n\n this.off('rotate', this.style._redoPlacement);\n this.off('pitch', this.style._redoPlacement);\n }\n\n if (!style) {\n this.style = null;\n return this;\n } else if (style instanceof Style) {\n this.style = style;\n } else {\n this.style = new Style(style, this.animationLoop);\n }\n\n this.style\n .on('load', this._onStyleLoad)\n .on('error', this._forwardStyleEvent)\n .on('change', this._onStyleChange)\n .on('source.add', this._onSourceAdd)\n .on('source.remove', this._onSourceRemove)\n .on('source.load', this._onSourceUpdate)\n .on('source.error', this._forwardSourceEvent)\n .on('source.change', this._onSourceUpdate)\n .on('layer.add', this._forwardLayerEvent)\n .on('layer.remove', this._forwardLayerEvent)\n .on('tile.add', this._forwardTileEvent)\n .on('tile.remove', this._forwardTileEvent)\n .on('tile.load', this.update)\n .on('tile.error', this._forwardTileEvent);\n\n this.on('rotate', this.style._redoPlacement);\n this.on('pitch', this.style._redoPlacement);\n\n return this;\n },\n\n /**\n * Add a source to the map style.\n *\n * @param {string} id ID of the source. Must not be used by any existing source.\n * @param {Object} source source specification, following the\n * [Mapbox GL Style Reference](https://www.mapbox.com/mapbox-gl-style-spec/#sources)\n * @fires source.add\n * @returns {Map} `this`\n */\n addSource: function(id, source) {\n this.style.addSource(id, source);\n return this;\n },\n\n /**\n * Remove an existing source from the map style.\n *\n * @param {string} id ID of the source to remove\n * @fires source.remove\n * @returns {Map} `this`\n */\n removeSource: function(id) {\n this.style.removeSource(id);\n return this;\n },\n\n /**\n * Return the style source object with the given `id`.\n *\n * @param {string} id source ID\n * @returns {Object}\n */\n getSource: function(id) {\n return this.style.getSource(id);\n },\n\n /**\n * Add a layer to the map style. The layer will be inserted before the layer with\n * ID `before`, or appended if `before` is omitted.\n * @param {Layer} layer\n * @param {string=} before ID of an existing layer to insert before\n * @fires layer.add\n * @returns {Map} `this`\n */\n addLayer: function(layer, before) {\n this.style.addLayer(layer, before);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Remove the layer with the given `id` from the map. Any layers which refer to the\n * specified layer via a `ref` property are also removed.\n *\n * @param {string} id\n * @fires layer.remove\n * @returns {Map} this\n */\n removeLayer: function(id) {\n this.style.removeLayer(id);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Set the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {Array} filter filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n * @returns {Map} `this`\n */\n setFilter: function(layer, filter) {\n this.style.setFilter(layer, filter);\n return this;\n },\n\n /**\n * Get the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @returns {Array} filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n */\n getFilter: function(layer) {\n return this.style.getFilter(layer);\n },\n\n /**\n * Set the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {*} value value for the paint propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @param {string=} klass optional class specifier for the property\n * @returns {Map} `this`\n */\n setPaintProperty: function(layer, name, value, klass) {\n this.style.setPaintProperty(layer, name, value, klass);\n this.style._cascade(this._classes);\n this.update(true);\n return this;\n },\n\n /**\n * Get the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the paint propery\n */\n getPaintProperty: function(layer, name, klass) {\n return this.style.getPaintProperty(layer, name, klass);\n },\n\n /**\n * Set the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {*} value value for the layout propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @returns {Map} `this`\n */\n setLayoutProperty: function(layer, name, value) {\n this.style.setLayoutProperty(layer, name, value);\n return this;\n },\n\n /**\n * Get the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the layout propery\n */\n getLayoutProperty: function(layer, name) {\n return this.style.getLayoutProperty(layer, name);\n },\n\n /**\n * Get the Map's container as an HTML element\n * @returns {HTMLElement} container\n */\n getContainer: function() {\n return this._container;\n },\n\n /**\n * Get the Map's canvas as an HTML canvas\n * @returns {HTMLElement} canvas\n */\n getCanvas: function() {\n return this._canvas.getElement();\n },\n\n _move: function(zoom, rotate, pitch) {\n\n this.update(zoom).fire('move');\n\n if (zoom) this.fire('zoom');\n if (rotate) this.fire('rotate');\n if (pitch) this.fire('pitch');\n\n return this;\n },\n\n // map setup code\n _setupContainer: function() {\n var id = this.options.container;\n var container = this._container = typeof id === 'string' ? document.getElementById(id) : id;\n if (container) container.classList.add('mapboxgl-map');\n this._canvas = new Canvas(this, container);\n },\n\n _setupControlPos: function() {\n var corners = this._controlCorners = {};\n var prefix = 'mapboxgl-ctrl-';\n var container = this.getContainer();\n\n function createCorner(pos) {\n var className = prefix + pos;\n corners[pos] = DOM.create('div', className, container);\n }\n\n if (container && typeof document === 'object') {\n createCorner('top-left');\n createCorner('top-right');\n createCorner('bottom-left');\n createCorner('bottom-right');\n }\n },\n\n _setupPainter: function() {\n var gl = this._canvas.getWebGLContext(this.options.failIfMajorPerformanceCaveat);\n\n if (!gl) {\n console.error('Failed to initialize WebGL');\n return;\n }\n\n this.painter = new GLPainter(gl, this.transform);\n },\n\n _contextLost: function(event) {\n event.preventDefault();\n if (this._frameId) {\n browser.cancelFrame(this._frameId);\n }\n },\n\n _contextRestored: function() {\n this._setupPainter();\n this.resize();\n this.update();\n },\n\n /**\n * Is this map fully loaded? If the style isn't loaded\n * or it has a change to the sources or style that isn't\n * propagated to its style, return false.\n *\n * @returns {boolean} whether the map is loaded\n */\n loaded: function() {\n if (this._styleDirty || this._sourcesDirty)\n return false;\n if (this.style && !this.style.loaded())\n return false;\n return true;\n },\n\n /**\n * Update this map's style and re-render the map.\n *\n * @param {Object} updateStyle new style\n * @returns {Map} this\n */\n update: function(updateStyle) {\n if (!this.style) return this;\n\n this._styleDirty = this._styleDirty || updateStyle;\n this._sourcesDirty = true;\n\n this._rerender();\n\n return this;\n },\n\n /**\n * Call when a (re-)render of the map is required, e.g. when the\n * user panned or zoomed,f or new data is available.\n * @returns {Map} this\n */\n render: function() {\n if (this.style && this._styleDirty) {\n this._styleDirty = false;\n this.style._recalculate(this.transform.zoom);\n }\n\n if (this.style && this._sourcesDirty && !this._sourcesDirtyTimeout) {\n this._sourcesDirty = false;\n this._sourcesDirtyTimeout = setTimeout(function() {\n this._sourcesDirtyTimeout = null;\n }.bind(this), 50);\n this.style._updateSources(this.transform);\n }\n\n this.painter.render(this.style, {\n debug: this.debug,\n vertices: this.vertices,\n rotating: this.rotating,\n zooming: this.zooming\n });\n\n this.fire('render');\n\n if (this.loaded() && !this._loaded) {\n this._loaded = true;\n this.fire('load');\n }\n\n this._frameId = null;\n\n if (!this.animationLoop.stopped()) {\n this._styleDirty = true;\n }\n\n if (this._sourcesDirty || this._repaint || !this.animationLoop.stopped()) {\n this._rerender();\n }\n\n return this;\n },\n\n /**\n * Destroys the map's underlying resources, including web workers.\n * @returns {Map} this\n */\n remove: function() {\n if (this._hash) this._hash.remove();\n browser.cancelFrame(this._frameId);\n clearTimeout(this._sourcesDirtyTimeout);\n this.setStyle(null);\n return this;\n },\n\n _rerender: function() {\n if (this.style && !this._frameId) {\n this._frameId = browser.frame(this.render);\n }\n },\n\n _forwardStyleEvent: function(e) {\n this.fire('style.' + e.type, util.extend({style: e.target}, e));\n },\n\n _forwardSourceEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardLayerEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardTileEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _onStyleLoad: function(e) {\n this.style._cascade(this._classes, {transition: false});\n this._forwardStyleEvent(e);\n },\n\n _onStyleChange: function(e) {\n this.update(true);\n this._forwardStyleEvent(e);\n },\n\n _onSourceAdd: function(e) {\n var source = e.source;\n if (source.onAdd)\n source.onAdd(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceRemove: function(e) {\n var source = e.source;\n if (source.onRemove)\n source.onRemove(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceUpdate: function(e) {\n this.update();\n this._forwardSourceEvent(e);\n }\n}","path":"js/ui/map.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/map.js#L181-L183"},"params":[{"title":"param","description":"Map rotation bearing in degrees counter-clockwise from north","type":{"type":"NameExpression","name":"number"},"name":"bearing"}],"returns":[{"title":"returns","description":"`this`","type":{"type":"NameExpression","name":"Map"}}],"name":"setBearing","memberof":"Map","scope":"instance","members":{"instance":[],"static":[]},"path":["Map","setBearing"]},{"description":"Set the value of a paint property in a given style layer.","tags":[{"title":"param","description":"ID of a layer","type":{"type":"NameExpression","name":"string"},"name":"layer"},{"title":"param","description":"name of a paint property","type":{"type":"NameExpression","name":"string"},"name":"name"},{"title":"param","description":"value for the paint propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)","type":{"type":"AllLiteral"},"name":"value"},{"title":"param","description":"optional class specifier for the property","type":{"type":"OptionalType","expression":{"type":"NameExpression","name":"string"}},"name":"klass"},{"title":"returns","description":"`this`","type":{"type":"NameExpression","name":"Map"}},{"title":"name","name":"setPaintProperty"},{"title":"memberof","description":"Map"},{"title":"instance"}],"context":{"loc":{"start":{"line":525,"column":4},"end":{"line":530,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/map.js","code":"{\n\n options: {\n center: [0, 0],\n zoom: 0,\n bearing: 0,\n pitch: 0,\n\n minZoom: 0,\n maxZoom: 20,\n\n interactive: true,\n hash: false,\n\n attributionControl: true,\n\n failIfMajorPerformanceCaveat: false\n },\n\n addControl: function(control) {\n control.addTo(this);\n return this;\n },\n\n /**\n * Sets a map position\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @param {number} zoom Map zoom level\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setView: function(center, zoom, bearing, pitch) {\n this.stop();\n\n var tr = this.transform,\n zoomChanged = tr.zoom !== +zoom,\n bearingChanged = tr.bearing !== +bearing,\n pitchChanged = tr.pitch !== +pitch;\n\n tr.center = LatLng.convert(center);\n tr.zoom = +zoom;\n tr.bearing = +bearing;\n tr.pitch = +pitch;\n\n return this\n .fire('movestart')\n ._move(zoomChanged, bearingChanged, pitchChanged)\n .fire('moveend');\n },\n\n /**\n * Sets a map location\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setCenter: function(center) {\n this.setView(center, this.getZoom(), this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map zoom\n *\n * @param {number} zoom Map zoom level\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setZoom: function(zoom) {\n this.setView(this.getCenter(), zoom, this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map rotation\n *\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setBearing: function(bearing) {\n this.setView(this.getCenter(), this.getZoom(), bearing, this.getPitch());\n },\n\n /**\n * Sets a map angle\n *\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setPitch: function(pitch) {\n this.setView(this.getCenter(), this.getZoom(), this.getBearing(), pitch);\n },\n\n /**\n * Get the current view geographical point\n * @returns {LatLng}\n */\n getCenter: function() { return this.transform.center; },\n\n /**\n * Get the current zoom\n * @returns {number}\n */\n getZoom: function() { return this.transform.zoom; },\n\n /**\n * Get the current bearing in degrees\n * @returns {number}\n */\n getBearing: function() { return this.transform.bearing; },\n\n /**\n * Get the current angle in degrees\n * @returns {number}\n */\n getPitch: function() { return this.transform.pitch; },\n\n /**\n * @typedef {Object} [styleOptions]\n * @param {Boolean} [styleOptions.transition=true]\n */\n\n /**\n * Adds a style class to a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n addClass: function(klass, options) {\n if (this._classes[klass]) return;\n this._classes[klass] = true;\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Removes a style class from a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n removeClass: function(klass, options) {\n if (!this._classes[klass]) return;\n delete this._classes[klass];\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Helper method to add more than one class\n *\n * @param {Array} klasses An array of class names\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n setClasses: function(klasses, options) {\n this._classes = {};\n for (var i = 0; i < klasses.length; i++) {\n this._classes[klasses[i]] = true;\n }\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Check whether a style class is active\n *\n * @param {string} klass Name of style class\n * @returns {boolean}\n */\n hasClass: function(klass) {\n return !!this._classes[klass];\n },\n\n /**\n * Return an array of the current active style classes\n *\n * @returns {boolean}\n */\n getClasses: function() {\n return Object.keys(this._classes);\n },\n\n /**\n * Detect the map's new width and height and resize it.\n *\n * @returns {Map} `this`\n */\n resize: function() {\n var width = 0, height = 0;\n\n if (this._container) {\n width = this._container.offsetWidth || 400;\n height = this._container.offsetHeight || 300;\n }\n\n this._canvas.resize(width, height);\n\n this.transform.width = width;\n this.transform.height = height;\n this.transform._constrain();\n\n this.painter.resize(width, height);\n\n return this\n .fire('movestart')\n ._move()\n .fire('resize')\n .fire('moveend');\n },\n\n /**\n * Get the map's geographical bounds\n *\n * @returns {LatLngBounds}\n */\n getBounds: function() {\n return new LatLngBounds(\n this.transform.pointLocation(new Point(0, 0)),\n this.transform.pointLocation(this.transform.size));\n },\n\n /**\n * Get pixel coordinates (relative to map container) given a geographical location\n *\n * @param {LatLng} latlng\n * @returns {Object} `x` and `y` coordinates\n */\n project: function(latlng) {\n return this.transform.locationPoint(LatLng.convert(latlng));\n },\n\n /**\n * Get geographical coordinates given pixel coordinates\n *\n * @param {Array} point [x, y] pixel coordinates\n * @returns {LatLng}\n */\n unproject: function(point) {\n return this.transform.pointLocation(Point.convert(point));\n },\n\n /**\n * Get all features at a point ([x, y])\n *\n * @param {Array} point [x, y] pixel coordinates\n * @param {Object} params\n * @param {number} [params.radius=0] Optional. Radius in pixels to search in\n * @param {string} params.layer Optional. Only return features from a given layer\n * @param {string} params.type Optional. Either `raster` or `vector`\n * @param {featuresAtCallback} callback function that returns the response\n *\n * @callback featuresAtCallback\n * @param {Object|null} err Error _If any_\n * @param {Array} features Displays a JSON array of features given the passed parameters of `featuresAt`\n *\n * @returns {Map} `this`\n */\n featuresAt: function(point, params, callback) {\n var coord = this.transform.pointCoordinate(Point.convert(point));\n this.style.featuresAt(coord, params, callback);\n return this;\n },\n\n /**\n * Replaces the map's style object\n *\n * @param {Object} style A style object formatted as JSON\n * @returns {Map} `this`\n */\n setStyle: function(style) {\n if (this.style) {\n this.style\n .off('load', this._onStyleLoad)\n .off('error', this._forwardStyleEvent)\n .off('change', this._onStyleChange)\n .off('source.add', this._onSourceAdd)\n .off('source.remove', this._onSourceRemove)\n .off('source.load', this._onSourceUpdate)\n .off('source.error', this._forwardSourceEvent)\n .off('source.change', this._onSourceUpdate)\n .off('layer.add', this._forwardLayerEvent)\n .off('layer.remove', this._forwardLayerEvent)\n .off('tile.add', this._forwardTileEvent)\n .off('tile.remove', this._forwardTileEvent)\n .off('tile.load', this.update)\n .off('tile.error', this._forwardTileEvent)\n ._remove();\n\n this.off('rotate', this.style._redoPlacement);\n this.off('pitch', this.style._redoPlacement);\n }\n\n if (!style) {\n this.style = null;\n return this;\n } else if (style instanceof Style) {\n this.style = style;\n } else {\n this.style = new Style(style, this.animationLoop);\n }\n\n this.style\n .on('load', this._onStyleLoad)\n .on('error', this._forwardStyleEvent)\n .on('change', this._onStyleChange)\n .on('source.add', this._onSourceAdd)\n .on('source.remove', this._onSourceRemove)\n .on('source.load', this._onSourceUpdate)\n .on('source.error', this._forwardSourceEvent)\n .on('source.change', this._onSourceUpdate)\n .on('layer.add', this._forwardLayerEvent)\n .on('layer.remove', this._forwardLayerEvent)\n .on('tile.add', this._forwardTileEvent)\n .on('tile.remove', this._forwardTileEvent)\n .on('tile.load', this.update)\n .on('tile.error', this._forwardTileEvent);\n\n this.on('rotate', this.style._redoPlacement);\n this.on('pitch', this.style._redoPlacement);\n\n return this;\n },\n\n /**\n * Add a source to the map style.\n *\n * @param {string} id ID of the source. Must not be used by any existing source.\n * @param {Object} source source specification, following the\n * [Mapbox GL Style Reference](https://www.mapbox.com/mapbox-gl-style-spec/#sources)\n * @fires source.add\n * @returns {Map} `this`\n */\n addSource: function(id, source) {\n this.style.addSource(id, source);\n return this;\n },\n\n /**\n * Remove an existing source from the map style.\n *\n * @param {string} id ID of the source to remove\n * @fires source.remove\n * @returns {Map} `this`\n */\n removeSource: function(id) {\n this.style.removeSource(id);\n return this;\n },\n\n /**\n * Return the style source object with the given `id`.\n *\n * @param {string} id source ID\n * @returns {Object}\n */\n getSource: function(id) {\n return this.style.getSource(id);\n },\n\n /**\n * Add a layer to the map style. The layer will be inserted before the layer with\n * ID `before`, or appended if `before` is omitted.\n * @param {Layer} layer\n * @param {string=} before ID of an existing layer to insert before\n * @fires layer.add\n * @returns {Map} `this`\n */\n addLayer: function(layer, before) {\n this.style.addLayer(layer, before);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Remove the layer with the given `id` from the map. Any layers which refer to the\n * specified layer via a `ref` property are also removed.\n *\n * @param {string} id\n * @fires layer.remove\n * @returns {Map} this\n */\n removeLayer: function(id) {\n this.style.removeLayer(id);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Set the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {Array} filter filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n * @returns {Map} `this`\n */\n setFilter: function(layer, filter) {\n this.style.setFilter(layer, filter);\n return this;\n },\n\n /**\n * Get the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @returns {Array} filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n */\n getFilter: function(layer) {\n return this.style.getFilter(layer);\n },\n\n /**\n * Set the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {*} value value for the paint propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @param {string=} klass optional class specifier for the property\n * @returns {Map} `this`\n */\n setPaintProperty: function(layer, name, value, klass) {\n this.style.setPaintProperty(layer, name, value, klass);\n this.style._cascade(this._classes);\n this.update(true);\n return this;\n },\n\n /**\n * Get the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the paint propery\n */\n getPaintProperty: function(layer, name, klass) {\n return this.style.getPaintProperty(layer, name, klass);\n },\n\n /**\n * Set the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {*} value value for the layout propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @returns {Map} `this`\n */\n setLayoutProperty: function(layer, name, value) {\n this.style.setLayoutProperty(layer, name, value);\n return this;\n },\n\n /**\n * Get the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the layout propery\n */\n getLayoutProperty: function(layer, name) {\n return this.style.getLayoutProperty(layer, name);\n },\n\n /**\n * Get the Map's container as an HTML element\n * @returns {HTMLElement} container\n */\n getContainer: function() {\n return this._container;\n },\n\n /**\n * Get the Map's canvas as an HTML canvas\n * @returns {HTMLElement} canvas\n */\n getCanvas: function() {\n return this._canvas.getElement();\n },\n\n _move: function(zoom, rotate, pitch) {\n\n this.update(zoom).fire('move');\n\n if (zoom) this.fire('zoom');\n if (rotate) this.fire('rotate');\n if (pitch) this.fire('pitch');\n\n return this;\n },\n\n // map setup code\n _setupContainer: function() {\n var id = this.options.container;\n var container = this._container = typeof id === 'string' ? document.getElementById(id) : id;\n if (container) container.classList.add('mapboxgl-map');\n this._canvas = new Canvas(this, container);\n },\n\n _setupControlPos: function() {\n var corners = this._controlCorners = {};\n var prefix = 'mapboxgl-ctrl-';\n var container = this.getContainer();\n\n function createCorner(pos) {\n var className = prefix + pos;\n corners[pos] = DOM.create('div', className, container);\n }\n\n if (container && typeof document === 'object') {\n createCorner('top-left');\n createCorner('top-right');\n createCorner('bottom-left');\n createCorner('bottom-right');\n }\n },\n\n _setupPainter: function() {\n var gl = this._canvas.getWebGLContext(this.options.failIfMajorPerformanceCaveat);\n\n if (!gl) {\n console.error('Failed to initialize WebGL');\n return;\n }\n\n this.painter = new GLPainter(gl, this.transform);\n },\n\n _contextLost: function(event) {\n event.preventDefault();\n if (this._frameId) {\n browser.cancelFrame(this._frameId);\n }\n },\n\n _contextRestored: function() {\n this._setupPainter();\n this.resize();\n this.update();\n },\n\n /**\n * Is this map fully loaded? If the style isn't loaded\n * or it has a change to the sources or style that isn't\n * propagated to its style, return false.\n *\n * @returns {boolean} whether the map is loaded\n */\n loaded: function() {\n if (this._styleDirty || this._sourcesDirty)\n return false;\n if (this.style && !this.style.loaded())\n return false;\n return true;\n },\n\n /**\n * Update this map's style and re-render the map.\n *\n * @param {Object} updateStyle new style\n * @returns {Map} this\n */\n update: function(updateStyle) {\n if (!this.style) return this;\n\n this._styleDirty = this._styleDirty || updateStyle;\n this._sourcesDirty = true;\n\n this._rerender();\n\n return this;\n },\n\n /**\n * Call when a (re-)render of the map is required, e.g. when the\n * user panned or zoomed,f or new data is available.\n * @returns {Map} this\n */\n render: function() {\n if (this.style && this._styleDirty) {\n this._styleDirty = false;\n this.style._recalculate(this.transform.zoom);\n }\n\n if (this.style && this._sourcesDirty && !this._sourcesDirtyTimeout) {\n this._sourcesDirty = false;\n this._sourcesDirtyTimeout = setTimeout(function() {\n this._sourcesDirtyTimeout = null;\n }.bind(this), 50);\n this.style._updateSources(this.transform);\n }\n\n this.painter.render(this.style, {\n debug: this.debug,\n vertices: this.vertices,\n rotating: this.rotating,\n zooming: this.zooming\n });\n\n this.fire('render');\n\n if (this.loaded() && !this._loaded) {\n this._loaded = true;\n this.fire('load');\n }\n\n this._frameId = null;\n\n if (!this.animationLoop.stopped()) {\n this._styleDirty = true;\n }\n\n if (this._sourcesDirty || this._repaint || !this.animationLoop.stopped()) {\n this._rerender();\n }\n\n return this;\n },\n\n /**\n * Destroys the map's underlying resources, including web workers.\n * @returns {Map} this\n */\n remove: function() {\n if (this._hash) this._hash.remove();\n browser.cancelFrame(this._frameId);\n clearTimeout(this._sourcesDirtyTimeout);\n this.setStyle(null);\n return this;\n },\n\n _rerender: function() {\n if (this.style && !this._frameId) {\n this._frameId = browser.frame(this.render);\n }\n },\n\n _forwardStyleEvent: function(e) {\n this.fire('style.' + e.type, util.extend({style: e.target}, e));\n },\n\n _forwardSourceEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardLayerEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardTileEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _onStyleLoad: function(e) {\n this.style._cascade(this._classes, {transition: false});\n this._forwardStyleEvent(e);\n },\n\n _onStyleChange: function(e) {\n this.update(true);\n this._forwardStyleEvent(e);\n },\n\n _onSourceAdd: function(e) {\n var source = e.source;\n if (source.onAdd)\n source.onAdd(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceRemove: function(e) {\n var source = e.source;\n if (source.onRemove)\n source.onRemove(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceUpdate: function(e) {\n this.update();\n this._forwardSourceEvent(e);\n }\n}","path":"js/ui/map.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/map.js#L525-L530"},"params":[{"title":"param","description":"ID of a layer","type":{"type":"NameExpression","name":"string"},"name":"layer"},{"title":"param","description":"name of a paint property","type":{"type":"NameExpression","name":"string"},"name":"name"},{"title":"param","description":"value for the paint propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)","type":{"type":"AllLiteral"},"name":"value"},{"title":"param","description":"optional class specifier for the property","type":{"type":"OptionalType","expression":{"type":"NameExpression","name":"string"}},"name":"klass"}],"returns":[{"title":"returns","description":"`this`","type":{"type":"NameExpression","name":"Map"}}],"name":"setPaintProperty","memberof":"Map","scope":"instance","members":{"instance":[],"static":[]},"path":["Map","setPaintProperty"]},{"description":"Sets a map location","tags":[{"title":"param","description":"Latitude and longitude (passed as `[lat, lng]`)","type":{"type":"NameExpression","name":"Array"},"name":"center"},{"title":"fires","description":"movestart"},{"title":"fires","description":"moveend"},{"title":"returns","description":"`this`","type":{"type":"NameExpression","name":"Map"}},{"title":"name","name":"setCenter"},{"title":"memberof","description":"Map"},{"title":"instance"}],"context":{"loc":{"start":{"line":157,"column":4},"end":{"line":159,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/map.js","code":"{\n\n options: {\n center: [0, 0],\n zoom: 0,\n bearing: 0,\n pitch: 0,\n\n minZoom: 0,\n maxZoom: 20,\n\n interactive: true,\n hash: false,\n\n attributionControl: true,\n\n failIfMajorPerformanceCaveat: false\n },\n\n addControl: function(control) {\n control.addTo(this);\n return this;\n },\n\n /**\n * Sets a map position\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @param {number} zoom Map zoom level\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setView: function(center, zoom, bearing, pitch) {\n this.stop();\n\n var tr = this.transform,\n zoomChanged = tr.zoom !== +zoom,\n bearingChanged = tr.bearing !== +bearing,\n pitchChanged = tr.pitch !== +pitch;\n\n tr.center = LatLng.convert(center);\n tr.zoom = +zoom;\n tr.bearing = +bearing;\n tr.pitch = +pitch;\n\n return this\n .fire('movestart')\n ._move(zoomChanged, bearingChanged, pitchChanged)\n .fire('moveend');\n },\n\n /**\n * Sets a map location\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setCenter: function(center) {\n this.setView(center, this.getZoom(), this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map zoom\n *\n * @param {number} zoom Map zoom level\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setZoom: function(zoom) {\n this.setView(this.getCenter(), zoom, this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map rotation\n *\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setBearing: function(bearing) {\n this.setView(this.getCenter(), this.getZoom(), bearing, this.getPitch());\n },\n\n /**\n * Sets a map angle\n *\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setPitch: function(pitch) {\n this.setView(this.getCenter(), this.getZoom(), this.getBearing(), pitch);\n },\n\n /**\n * Get the current view geographical point\n * @returns {LatLng}\n */\n getCenter: function() { return this.transform.center; },\n\n /**\n * Get the current zoom\n * @returns {number}\n */\n getZoom: function() { return this.transform.zoom; },\n\n /**\n * Get the current bearing in degrees\n * @returns {number}\n */\n getBearing: function() { return this.transform.bearing; },\n\n /**\n * Get the current angle in degrees\n * @returns {number}\n */\n getPitch: function() { return this.transform.pitch; },\n\n /**\n * @typedef {Object} [styleOptions]\n * @param {Boolean} [styleOptions.transition=true]\n */\n\n /**\n * Adds a style class to a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n addClass: function(klass, options) {\n if (this._classes[klass]) return;\n this._classes[klass] = true;\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Removes a style class from a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n removeClass: function(klass, options) {\n if (!this._classes[klass]) return;\n delete this._classes[klass];\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Helper method to add more than one class\n *\n * @param {Array} klasses An array of class names\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n setClasses: function(klasses, options) {\n this._classes = {};\n for (var i = 0; i < klasses.length; i++) {\n this._classes[klasses[i]] = true;\n }\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Check whether a style class is active\n *\n * @param {string} klass Name of style class\n * @returns {boolean}\n */\n hasClass: function(klass) {\n return !!this._classes[klass];\n },\n\n /**\n * Return an array of the current active style classes\n *\n * @returns {boolean}\n */\n getClasses: function() {\n return Object.keys(this._classes);\n },\n\n /**\n * Detect the map's new width and height and resize it.\n *\n * @returns {Map} `this`\n */\n resize: function() {\n var width = 0, height = 0;\n\n if (this._container) {\n width = this._container.offsetWidth || 400;\n height = this._container.offsetHeight || 300;\n }\n\n this._canvas.resize(width, height);\n\n this.transform.width = width;\n this.transform.height = height;\n this.transform._constrain();\n\n this.painter.resize(width, height);\n\n return this\n .fire('movestart')\n ._move()\n .fire('resize')\n .fire('moveend');\n },\n\n /**\n * Get the map's geographical bounds\n *\n * @returns {LatLngBounds}\n */\n getBounds: function() {\n return new LatLngBounds(\n this.transform.pointLocation(new Point(0, 0)),\n this.transform.pointLocation(this.transform.size));\n },\n\n /**\n * Get pixel coordinates (relative to map container) given a geographical location\n *\n * @param {LatLng} latlng\n * @returns {Object} `x` and `y` coordinates\n */\n project: function(latlng) {\n return this.transform.locationPoint(LatLng.convert(latlng));\n },\n\n /**\n * Get geographical coordinates given pixel coordinates\n *\n * @param {Array} point [x, y] pixel coordinates\n * @returns {LatLng}\n */\n unproject: function(point) {\n return this.transform.pointLocation(Point.convert(point));\n },\n\n /**\n * Get all features at a point ([x, y])\n *\n * @param {Array} point [x, y] pixel coordinates\n * @param {Object} params\n * @param {number} [params.radius=0] Optional. Radius in pixels to search in\n * @param {string} params.layer Optional. Only return features from a given layer\n * @param {string} params.type Optional. Either `raster` or `vector`\n * @param {featuresAtCallback} callback function that returns the response\n *\n * @callback featuresAtCallback\n * @param {Object|null} err Error _If any_\n * @param {Array} features Displays a JSON array of features given the passed parameters of `featuresAt`\n *\n * @returns {Map} `this`\n */\n featuresAt: function(point, params, callback) {\n var coord = this.transform.pointCoordinate(Point.convert(point));\n this.style.featuresAt(coord, params, callback);\n return this;\n },\n\n /**\n * Replaces the map's style object\n *\n * @param {Object} style A style object formatted as JSON\n * @returns {Map} `this`\n */\n setStyle: function(style) {\n if (this.style) {\n this.style\n .off('load', this._onStyleLoad)\n .off('error', this._forwardStyleEvent)\n .off('change', this._onStyleChange)\n .off('source.add', this._onSourceAdd)\n .off('source.remove', this._onSourceRemove)\n .off('source.load', this._onSourceUpdate)\n .off('source.error', this._forwardSourceEvent)\n .off('source.change', this._onSourceUpdate)\n .off('layer.add', this._forwardLayerEvent)\n .off('layer.remove', this._forwardLayerEvent)\n .off('tile.add', this._forwardTileEvent)\n .off('tile.remove', this._forwardTileEvent)\n .off('tile.load', this.update)\n .off('tile.error', this._forwardTileEvent)\n ._remove();\n\n this.off('rotate', this.style._redoPlacement);\n this.off('pitch', this.style._redoPlacement);\n }\n\n if (!style) {\n this.style = null;\n return this;\n } else if (style instanceof Style) {\n this.style = style;\n } else {\n this.style = new Style(style, this.animationLoop);\n }\n\n this.style\n .on('load', this._onStyleLoad)\n .on('error', this._forwardStyleEvent)\n .on('change', this._onStyleChange)\n .on('source.add', this._onSourceAdd)\n .on('source.remove', this._onSourceRemove)\n .on('source.load', this._onSourceUpdate)\n .on('source.error', this._forwardSourceEvent)\n .on('source.change', this._onSourceUpdate)\n .on('layer.add', this._forwardLayerEvent)\n .on('layer.remove', this._forwardLayerEvent)\n .on('tile.add', this._forwardTileEvent)\n .on('tile.remove', this._forwardTileEvent)\n .on('tile.load', this.update)\n .on('tile.error', this._forwardTileEvent);\n\n this.on('rotate', this.style._redoPlacement);\n this.on('pitch', this.style._redoPlacement);\n\n return this;\n },\n\n /**\n * Add a source to the map style.\n *\n * @param {string} id ID of the source. Must not be used by any existing source.\n * @param {Object} source source specification, following the\n * [Mapbox GL Style Reference](https://www.mapbox.com/mapbox-gl-style-spec/#sources)\n * @fires source.add\n * @returns {Map} `this`\n */\n addSource: function(id, source) {\n this.style.addSource(id, source);\n return this;\n },\n\n /**\n * Remove an existing source from the map style.\n *\n * @param {string} id ID of the source to remove\n * @fires source.remove\n * @returns {Map} `this`\n */\n removeSource: function(id) {\n this.style.removeSource(id);\n return this;\n },\n\n /**\n * Return the style source object with the given `id`.\n *\n * @param {string} id source ID\n * @returns {Object}\n */\n getSource: function(id) {\n return this.style.getSource(id);\n },\n\n /**\n * Add a layer to the map style. The layer will be inserted before the layer with\n * ID `before`, or appended if `before` is omitted.\n * @param {Layer} layer\n * @param {string=} before ID of an existing layer to insert before\n * @fires layer.add\n * @returns {Map} `this`\n */\n addLayer: function(layer, before) {\n this.style.addLayer(layer, before);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Remove the layer with the given `id` from the map. Any layers which refer to the\n * specified layer via a `ref` property are also removed.\n *\n * @param {string} id\n * @fires layer.remove\n * @returns {Map} this\n */\n removeLayer: function(id) {\n this.style.removeLayer(id);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Set the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {Array} filter filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n * @returns {Map} `this`\n */\n setFilter: function(layer, filter) {\n this.style.setFilter(layer, filter);\n return this;\n },\n\n /**\n * Get the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @returns {Array} filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n */\n getFilter: function(layer) {\n return this.style.getFilter(layer);\n },\n\n /**\n * Set the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {*} value value for the paint propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @param {string=} klass optional class specifier for the property\n * @returns {Map} `this`\n */\n setPaintProperty: function(layer, name, value, klass) {\n this.style.setPaintProperty(layer, name, value, klass);\n this.style._cascade(this._classes);\n this.update(true);\n return this;\n },\n\n /**\n * Get the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the paint propery\n */\n getPaintProperty: function(layer, name, klass) {\n return this.style.getPaintProperty(layer, name, klass);\n },\n\n /**\n * Set the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {*} value value for the layout propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @returns {Map} `this`\n */\n setLayoutProperty: function(layer, name, value) {\n this.style.setLayoutProperty(layer, name, value);\n return this;\n },\n\n /**\n * Get the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the layout propery\n */\n getLayoutProperty: function(layer, name) {\n return this.style.getLayoutProperty(layer, name);\n },\n\n /**\n * Get the Map's container as an HTML element\n * @returns {HTMLElement} container\n */\n getContainer: function() {\n return this._container;\n },\n\n /**\n * Get the Map's canvas as an HTML canvas\n * @returns {HTMLElement} canvas\n */\n getCanvas: function() {\n return this._canvas.getElement();\n },\n\n _move: function(zoom, rotate, pitch) {\n\n this.update(zoom).fire('move');\n\n if (zoom) this.fire('zoom');\n if (rotate) this.fire('rotate');\n if (pitch) this.fire('pitch');\n\n return this;\n },\n\n // map setup code\n _setupContainer: function() {\n var id = this.options.container;\n var container = this._container = typeof id === 'string' ? document.getElementById(id) : id;\n if (container) container.classList.add('mapboxgl-map');\n this._canvas = new Canvas(this, container);\n },\n\n _setupControlPos: function() {\n var corners = this._controlCorners = {};\n var prefix = 'mapboxgl-ctrl-';\n var container = this.getContainer();\n\n function createCorner(pos) {\n var className = prefix + pos;\n corners[pos] = DOM.create('div', className, container);\n }\n\n if (container && typeof document === 'object') {\n createCorner('top-left');\n createCorner('top-right');\n createCorner('bottom-left');\n createCorner('bottom-right');\n }\n },\n\n _setupPainter: function() {\n var gl = this._canvas.getWebGLContext(this.options.failIfMajorPerformanceCaveat);\n\n if (!gl) {\n console.error('Failed to initialize WebGL');\n return;\n }\n\n this.painter = new GLPainter(gl, this.transform);\n },\n\n _contextLost: function(event) {\n event.preventDefault();\n if (this._frameId) {\n browser.cancelFrame(this._frameId);\n }\n },\n\n _contextRestored: function() {\n this._setupPainter();\n this.resize();\n this.update();\n },\n\n /**\n * Is this map fully loaded? If the style isn't loaded\n * or it has a change to the sources or style that isn't\n * propagated to its style, return false.\n *\n * @returns {boolean} whether the map is loaded\n */\n loaded: function() {\n if (this._styleDirty || this._sourcesDirty)\n return false;\n if (this.style && !this.style.loaded())\n return false;\n return true;\n },\n\n /**\n * Update this map's style and re-render the map.\n *\n * @param {Object} updateStyle new style\n * @returns {Map} this\n */\n update: function(updateStyle) {\n if (!this.style) return this;\n\n this._styleDirty = this._styleDirty || updateStyle;\n this._sourcesDirty = true;\n\n this._rerender();\n\n return this;\n },\n\n /**\n * Call when a (re-)render of the map is required, e.g. when the\n * user panned or zoomed,f or new data is available.\n * @returns {Map} this\n */\n render: function() {\n if (this.style && this._styleDirty) {\n this._styleDirty = false;\n this.style._recalculate(this.transform.zoom);\n }\n\n if (this.style && this._sourcesDirty && !this._sourcesDirtyTimeout) {\n this._sourcesDirty = false;\n this._sourcesDirtyTimeout = setTimeout(function() {\n this._sourcesDirtyTimeout = null;\n }.bind(this), 50);\n this.style._updateSources(this.transform);\n }\n\n this.painter.render(this.style, {\n debug: this.debug,\n vertices: this.vertices,\n rotating: this.rotating,\n zooming: this.zooming\n });\n\n this.fire('render');\n\n if (this.loaded() && !this._loaded) {\n this._loaded = true;\n this.fire('load');\n }\n\n this._frameId = null;\n\n if (!this.animationLoop.stopped()) {\n this._styleDirty = true;\n }\n\n if (this._sourcesDirty || this._repaint || !this.animationLoop.stopped()) {\n this._rerender();\n }\n\n return this;\n },\n\n /**\n * Destroys the map's underlying resources, including web workers.\n * @returns {Map} this\n */\n remove: function() {\n if (this._hash) this._hash.remove();\n browser.cancelFrame(this._frameId);\n clearTimeout(this._sourcesDirtyTimeout);\n this.setStyle(null);\n return this;\n },\n\n _rerender: function() {\n if (this.style && !this._frameId) {\n this._frameId = browser.frame(this.render);\n }\n },\n\n _forwardStyleEvent: function(e) {\n this.fire('style.' + e.type, util.extend({style: e.target}, e));\n },\n\n _forwardSourceEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardLayerEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardTileEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _onStyleLoad: function(e) {\n this.style._cascade(this._classes, {transition: false});\n this._forwardStyleEvent(e);\n },\n\n _onStyleChange: function(e) {\n this.update(true);\n this._forwardStyleEvent(e);\n },\n\n _onSourceAdd: function(e) {\n var source = e.source;\n if (source.onAdd)\n source.onAdd(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceRemove: function(e) {\n var source = e.source;\n if (source.onRemove)\n source.onRemove(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceUpdate: function(e) {\n this.update();\n this._forwardSourceEvent(e);\n }\n}","path":"js/ui/map.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/map.js#L157-L159"},"params":[{"title":"param","description":"Latitude and longitude (passed as `[lat, lng]`)","type":{"type":"NameExpression","name":"Array"},"name":"center"}],"returns":[{"title":"returns","description":"`this`","type":{"type":"NameExpression","name":"Map"}}],"name":"setCenter","memberof":"Map","scope":"instance","members":{"instance":[],"static":[]},"path":["Map","setCenter"]},{"description":"Set the filter for a given style layer.","tags":[{"title":"param","description":"ID of a layer","type":{"type":"NameExpression","name":"string"},"name":"layer"},{"title":"param","description":"filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)","type":{"type":"NameExpression","name":"Array"},"name":"filter"},{"title":"returns","description":"`this`","type":{"type":"NameExpression","name":"Map"}},{"title":"name","name":"setFilter"},{"title":"memberof","description":"Map"},{"title":"instance"}],"context":{"loc":{"start":{"line":501,"column":4},"end":{"line":504,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/map.js","code":"{\n\n options: {\n center: [0, 0],\n zoom: 0,\n bearing: 0,\n pitch: 0,\n\n minZoom: 0,\n maxZoom: 20,\n\n interactive: true,\n hash: false,\n\n attributionControl: true,\n\n failIfMajorPerformanceCaveat: false\n },\n\n addControl: function(control) {\n control.addTo(this);\n return this;\n },\n\n /**\n * Sets a map position\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @param {number} zoom Map zoom level\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setView: function(center, zoom, bearing, pitch) {\n this.stop();\n\n var tr = this.transform,\n zoomChanged = tr.zoom !== +zoom,\n bearingChanged = tr.bearing !== +bearing,\n pitchChanged = tr.pitch !== +pitch;\n\n tr.center = LatLng.convert(center);\n tr.zoom = +zoom;\n tr.bearing = +bearing;\n tr.pitch = +pitch;\n\n return this\n .fire('movestart')\n ._move(zoomChanged, bearingChanged, pitchChanged)\n .fire('moveend');\n },\n\n /**\n * Sets a map location\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setCenter: function(center) {\n this.setView(center, this.getZoom(), this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map zoom\n *\n * @param {number} zoom Map zoom level\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setZoom: function(zoom) {\n this.setView(this.getCenter(), zoom, this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map rotation\n *\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setBearing: function(bearing) {\n this.setView(this.getCenter(), this.getZoom(), bearing, this.getPitch());\n },\n\n /**\n * Sets a map angle\n *\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setPitch: function(pitch) {\n this.setView(this.getCenter(), this.getZoom(), this.getBearing(), pitch);\n },\n\n /**\n * Get the current view geographical point\n * @returns {LatLng}\n */\n getCenter: function() { return this.transform.center; },\n\n /**\n * Get the current zoom\n * @returns {number}\n */\n getZoom: function() { return this.transform.zoom; },\n\n /**\n * Get the current bearing in degrees\n * @returns {number}\n */\n getBearing: function() { return this.transform.bearing; },\n\n /**\n * Get the current angle in degrees\n * @returns {number}\n */\n getPitch: function() { return this.transform.pitch; },\n\n /**\n * @typedef {Object} [styleOptions]\n * @param {Boolean} [styleOptions.transition=true]\n */\n\n /**\n * Adds a style class to a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n addClass: function(klass, options) {\n if (this._classes[klass]) return;\n this._classes[klass] = true;\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Removes a style class from a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n removeClass: function(klass, options) {\n if (!this._classes[klass]) return;\n delete this._classes[klass];\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Helper method to add more than one class\n *\n * @param {Array} klasses An array of class names\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n setClasses: function(klasses, options) {\n this._classes = {};\n for (var i = 0; i < klasses.length; i++) {\n this._classes[klasses[i]] = true;\n }\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Check whether a style class is active\n *\n * @param {string} klass Name of style class\n * @returns {boolean}\n */\n hasClass: function(klass) {\n return !!this._classes[klass];\n },\n\n /**\n * Return an array of the current active style classes\n *\n * @returns {boolean}\n */\n getClasses: function() {\n return Object.keys(this._classes);\n },\n\n /**\n * Detect the map's new width and height and resize it.\n *\n * @returns {Map} `this`\n */\n resize: function() {\n var width = 0, height = 0;\n\n if (this._container) {\n width = this._container.offsetWidth || 400;\n height = this._container.offsetHeight || 300;\n }\n\n this._canvas.resize(width, height);\n\n this.transform.width = width;\n this.transform.height = height;\n this.transform._constrain();\n\n this.painter.resize(width, height);\n\n return this\n .fire('movestart')\n ._move()\n .fire('resize')\n .fire('moveend');\n },\n\n /**\n * Get the map's geographical bounds\n *\n * @returns {LatLngBounds}\n */\n getBounds: function() {\n return new LatLngBounds(\n this.transform.pointLocation(new Point(0, 0)),\n this.transform.pointLocation(this.transform.size));\n },\n\n /**\n * Get pixel coordinates (relative to map container) given a geographical location\n *\n * @param {LatLng} latlng\n * @returns {Object} `x` and `y` coordinates\n */\n project: function(latlng) {\n return this.transform.locationPoint(LatLng.convert(latlng));\n },\n\n /**\n * Get geographical coordinates given pixel coordinates\n *\n * @param {Array} point [x, y] pixel coordinates\n * @returns {LatLng}\n */\n unproject: function(point) {\n return this.transform.pointLocation(Point.convert(point));\n },\n\n /**\n * Get all features at a point ([x, y])\n *\n * @param {Array} point [x, y] pixel coordinates\n * @param {Object} params\n * @param {number} [params.radius=0] Optional. Radius in pixels to search in\n * @param {string} params.layer Optional. Only return features from a given layer\n * @param {string} params.type Optional. Either `raster` or `vector`\n * @param {featuresAtCallback} callback function that returns the response\n *\n * @callback featuresAtCallback\n * @param {Object|null} err Error _If any_\n * @param {Array} features Displays a JSON array of features given the passed parameters of `featuresAt`\n *\n * @returns {Map} `this`\n */\n featuresAt: function(point, params, callback) {\n var coord = this.transform.pointCoordinate(Point.convert(point));\n this.style.featuresAt(coord, params, callback);\n return this;\n },\n\n /**\n * Replaces the map's style object\n *\n * @param {Object} style A style object formatted as JSON\n * @returns {Map} `this`\n */\n setStyle: function(style) {\n if (this.style) {\n this.style\n .off('load', this._onStyleLoad)\n .off('error', this._forwardStyleEvent)\n .off('change', this._onStyleChange)\n .off('source.add', this._onSourceAdd)\n .off('source.remove', this._onSourceRemove)\n .off('source.load', this._onSourceUpdate)\n .off('source.error', this._forwardSourceEvent)\n .off('source.change', this._onSourceUpdate)\n .off('layer.add', this._forwardLayerEvent)\n .off('layer.remove', this._forwardLayerEvent)\n .off('tile.add', this._forwardTileEvent)\n .off('tile.remove', this._forwardTileEvent)\n .off('tile.load', this.update)\n .off('tile.error', this._forwardTileEvent)\n ._remove();\n\n this.off('rotate', this.style._redoPlacement);\n this.off('pitch', this.style._redoPlacement);\n }\n\n if (!style) {\n this.style = null;\n return this;\n } else if (style instanceof Style) {\n this.style = style;\n } else {\n this.style = new Style(style, this.animationLoop);\n }\n\n this.style\n .on('load', this._onStyleLoad)\n .on('error', this._forwardStyleEvent)\n .on('change', this._onStyleChange)\n .on('source.add', this._onSourceAdd)\n .on('source.remove', this._onSourceRemove)\n .on('source.load', this._onSourceUpdate)\n .on('source.error', this._forwardSourceEvent)\n .on('source.change', this._onSourceUpdate)\n .on('layer.add', this._forwardLayerEvent)\n .on('layer.remove', this._forwardLayerEvent)\n .on('tile.add', this._forwardTileEvent)\n .on('tile.remove', this._forwardTileEvent)\n .on('tile.load', this.update)\n .on('tile.error', this._forwardTileEvent);\n\n this.on('rotate', this.style._redoPlacement);\n this.on('pitch', this.style._redoPlacement);\n\n return this;\n },\n\n /**\n * Add a source to the map style.\n *\n * @param {string} id ID of the source. Must not be used by any existing source.\n * @param {Object} source source specification, following the\n * [Mapbox GL Style Reference](https://www.mapbox.com/mapbox-gl-style-spec/#sources)\n * @fires source.add\n * @returns {Map} `this`\n */\n addSource: function(id, source) {\n this.style.addSource(id, source);\n return this;\n },\n\n /**\n * Remove an existing source from the map style.\n *\n * @param {string} id ID of the source to remove\n * @fires source.remove\n * @returns {Map} `this`\n */\n removeSource: function(id) {\n this.style.removeSource(id);\n return this;\n },\n\n /**\n * Return the style source object with the given `id`.\n *\n * @param {string} id source ID\n * @returns {Object}\n */\n getSource: function(id) {\n return this.style.getSource(id);\n },\n\n /**\n * Add a layer to the map style. The layer will be inserted before the layer with\n * ID `before`, or appended if `before` is omitted.\n * @param {Layer} layer\n * @param {string=} before ID of an existing layer to insert before\n * @fires layer.add\n * @returns {Map} `this`\n */\n addLayer: function(layer, before) {\n this.style.addLayer(layer, before);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Remove the layer with the given `id` from the map. Any layers which refer to the\n * specified layer via a `ref` property are also removed.\n *\n * @param {string} id\n * @fires layer.remove\n * @returns {Map} this\n */\n removeLayer: function(id) {\n this.style.removeLayer(id);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Set the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {Array} filter filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n * @returns {Map} `this`\n */\n setFilter: function(layer, filter) {\n this.style.setFilter(layer, filter);\n return this;\n },\n\n /**\n * Get the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @returns {Array} filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n */\n getFilter: function(layer) {\n return this.style.getFilter(layer);\n },\n\n /**\n * Set the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {*} value value for the paint propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @param {string=} klass optional class specifier for the property\n * @returns {Map} `this`\n */\n setPaintProperty: function(layer, name, value, klass) {\n this.style.setPaintProperty(layer, name, value, klass);\n this.style._cascade(this._classes);\n this.update(true);\n return this;\n },\n\n /**\n * Get the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the paint propery\n */\n getPaintProperty: function(layer, name, klass) {\n return this.style.getPaintProperty(layer, name, klass);\n },\n\n /**\n * Set the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {*} value value for the layout propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @returns {Map} `this`\n */\n setLayoutProperty: function(layer, name, value) {\n this.style.setLayoutProperty(layer, name, value);\n return this;\n },\n\n /**\n * Get the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the layout propery\n */\n getLayoutProperty: function(layer, name) {\n return this.style.getLayoutProperty(layer, name);\n },\n\n /**\n * Get the Map's container as an HTML element\n * @returns {HTMLElement} container\n */\n getContainer: function() {\n return this._container;\n },\n\n /**\n * Get the Map's canvas as an HTML canvas\n * @returns {HTMLElement} canvas\n */\n getCanvas: function() {\n return this._canvas.getElement();\n },\n\n _move: function(zoom, rotate, pitch) {\n\n this.update(zoom).fire('move');\n\n if (zoom) this.fire('zoom');\n if (rotate) this.fire('rotate');\n if (pitch) this.fire('pitch');\n\n return this;\n },\n\n // map setup code\n _setupContainer: function() {\n var id = this.options.container;\n var container = this._container = typeof id === 'string' ? document.getElementById(id) : id;\n if (container) container.classList.add('mapboxgl-map');\n this._canvas = new Canvas(this, container);\n },\n\n _setupControlPos: function() {\n var corners = this._controlCorners = {};\n var prefix = 'mapboxgl-ctrl-';\n var container = this.getContainer();\n\n function createCorner(pos) {\n var className = prefix + pos;\n corners[pos] = DOM.create('div', className, container);\n }\n\n if (container && typeof document === 'object') {\n createCorner('top-left');\n createCorner('top-right');\n createCorner('bottom-left');\n createCorner('bottom-right');\n }\n },\n\n _setupPainter: function() {\n var gl = this._canvas.getWebGLContext(this.options.failIfMajorPerformanceCaveat);\n\n if (!gl) {\n console.error('Failed to initialize WebGL');\n return;\n }\n\n this.painter = new GLPainter(gl, this.transform);\n },\n\n _contextLost: function(event) {\n event.preventDefault();\n if (this._frameId) {\n browser.cancelFrame(this._frameId);\n }\n },\n\n _contextRestored: function() {\n this._setupPainter();\n this.resize();\n this.update();\n },\n\n /**\n * Is this map fully loaded? If the style isn't loaded\n * or it has a change to the sources or style that isn't\n * propagated to its style, return false.\n *\n * @returns {boolean} whether the map is loaded\n */\n loaded: function() {\n if (this._styleDirty || this._sourcesDirty)\n return false;\n if (this.style && !this.style.loaded())\n return false;\n return true;\n },\n\n /**\n * Update this map's style and re-render the map.\n *\n * @param {Object} updateStyle new style\n * @returns {Map} this\n */\n update: function(updateStyle) {\n if (!this.style) return this;\n\n this._styleDirty = this._styleDirty || updateStyle;\n this._sourcesDirty = true;\n\n this._rerender();\n\n return this;\n },\n\n /**\n * Call when a (re-)render of the map is required, e.g. when the\n * user panned or zoomed,f or new data is available.\n * @returns {Map} this\n */\n render: function() {\n if (this.style && this._styleDirty) {\n this._styleDirty = false;\n this.style._recalculate(this.transform.zoom);\n }\n\n if (this.style && this._sourcesDirty && !this._sourcesDirtyTimeout) {\n this._sourcesDirty = false;\n this._sourcesDirtyTimeout = setTimeout(function() {\n this._sourcesDirtyTimeout = null;\n }.bind(this), 50);\n this.style._updateSources(this.transform);\n }\n\n this.painter.render(this.style, {\n debug: this.debug,\n vertices: this.vertices,\n rotating: this.rotating,\n zooming: this.zooming\n });\n\n this.fire('render');\n\n if (this.loaded() && !this._loaded) {\n this._loaded = true;\n this.fire('load');\n }\n\n this._frameId = null;\n\n if (!this.animationLoop.stopped()) {\n this._styleDirty = true;\n }\n\n if (this._sourcesDirty || this._repaint || !this.animationLoop.stopped()) {\n this._rerender();\n }\n\n return this;\n },\n\n /**\n * Destroys the map's underlying resources, including web workers.\n * @returns {Map} this\n */\n remove: function() {\n if (this._hash) this._hash.remove();\n browser.cancelFrame(this._frameId);\n clearTimeout(this._sourcesDirtyTimeout);\n this.setStyle(null);\n return this;\n },\n\n _rerender: function() {\n if (this.style && !this._frameId) {\n this._frameId = browser.frame(this.render);\n }\n },\n\n _forwardStyleEvent: function(e) {\n this.fire('style.' + e.type, util.extend({style: e.target}, e));\n },\n\n _forwardSourceEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardLayerEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardTileEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _onStyleLoad: function(e) {\n this.style._cascade(this._classes, {transition: false});\n this._forwardStyleEvent(e);\n },\n\n _onStyleChange: function(e) {\n this.update(true);\n this._forwardStyleEvent(e);\n },\n\n _onSourceAdd: function(e) {\n var source = e.source;\n if (source.onAdd)\n source.onAdd(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceRemove: function(e) {\n var source = e.source;\n if (source.onRemove)\n source.onRemove(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceUpdate: function(e) {\n this.update();\n this._forwardSourceEvent(e);\n }\n}","path":"js/ui/map.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/map.js#L501-L504"},"params":[{"title":"param","description":"ID of a layer","type":{"type":"NameExpression","name":"string"},"name":"layer"},{"title":"param","description":"filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)","type":{"type":"NameExpression","name":"Array"},"name":"filter"}],"returns":[{"title":"returns","description":"`this`","type":{"type":"NameExpression","name":"Map"}}],"name":"setFilter","memberof":"Map","scope":"instance","members":{"instance":[],"static":[]},"path":["Map","setFilter"]},{"description":"Helper method to add more than one class","tags":[{"title":"param","description":"An array of class names","type":{"type":"TypeApplication","expression":{"type":"NameExpression","name":"Array"},"applications":[{"type":"NameExpression","name":"string"}]},"name":"klasses"},{"title":"param","description":null,"type":{"type":"NameExpression","name":"styleOptions"},"name":"options"},{"title":"fires","description":"change"},{"title":"returns","description":"`this`","type":{"type":"NameExpression","name":"Map"}},{"title":"name","name":"setClasses"},{"title":"memberof","description":"Map"},{"title":"instance"}],"context":{"loc":{"start":{"line":262,"column":4},"end":{"line":268,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/map.js","code":"{\n\n options: {\n center: [0, 0],\n zoom: 0,\n bearing: 0,\n pitch: 0,\n\n minZoom: 0,\n maxZoom: 20,\n\n interactive: true,\n hash: false,\n\n attributionControl: true,\n\n failIfMajorPerformanceCaveat: false\n },\n\n addControl: function(control) {\n control.addTo(this);\n return this;\n },\n\n /**\n * Sets a map position\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @param {number} zoom Map zoom level\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setView: function(center, zoom, bearing, pitch) {\n this.stop();\n\n var tr = this.transform,\n zoomChanged = tr.zoom !== +zoom,\n bearingChanged = tr.bearing !== +bearing,\n pitchChanged = tr.pitch !== +pitch;\n\n tr.center = LatLng.convert(center);\n tr.zoom = +zoom;\n tr.bearing = +bearing;\n tr.pitch = +pitch;\n\n return this\n .fire('movestart')\n ._move(zoomChanged, bearingChanged, pitchChanged)\n .fire('moveend');\n },\n\n /**\n * Sets a map location\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setCenter: function(center) {\n this.setView(center, this.getZoom(), this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map zoom\n *\n * @param {number} zoom Map zoom level\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setZoom: function(zoom) {\n this.setView(this.getCenter(), zoom, this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map rotation\n *\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setBearing: function(bearing) {\n this.setView(this.getCenter(), this.getZoom(), bearing, this.getPitch());\n },\n\n /**\n * Sets a map angle\n *\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setPitch: function(pitch) {\n this.setView(this.getCenter(), this.getZoom(), this.getBearing(), pitch);\n },\n\n /**\n * Get the current view geographical point\n * @returns {LatLng}\n */\n getCenter: function() { return this.transform.center; },\n\n /**\n * Get the current zoom\n * @returns {number}\n */\n getZoom: function() { return this.transform.zoom; },\n\n /**\n * Get the current bearing in degrees\n * @returns {number}\n */\n getBearing: function() { return this.transform.bearing; },\n\n /**\n * Get the current angle in degrees\n * @returns {number}\n */\n getPitch: function() { return this.transform.pitch; },\n\n /**\n * @typedef {Object} [styleOptions]\n * @param {Boolean} [styleOptions.transition=true]\n */\n\n /**\n * Adds a style class to a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n addClass: function(klass, options) {\n if (this._classes[klass]) return;\n this._classes[klass] = true;\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Removes a style class from a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n removeClass: function(klass, options) {\n if (!this._classes[klass]) return;\n delete this._classes[klass];\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Helper method to add more than one class\n *\n * @param {Array} klasses An array of class names\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n setClasses: function(klasses, options) {\n this._classes = {};\n for (var i = 0; i < klasses.length; i++) {\n this._classes[klasses[i]] = true;\n }\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Check whether a style class is active\n *\n * @param {string} klass Name of style class\n * @returns {boolean}\n */\n hasClass: function(klass) {\n return !!this._classes[klass];\n },\n\n /**\n * Return an array of the current active style classes\n *\n * @returns {boolean}\n */\n getClasses: function() {\n return Object.keys(this._classes);\n },\n\n /**\n * Detect the map's new width and height and resize it.\n *\n * @returns {Map} `this`\n */\n resize: function() {\n var width = 0, height = 0;\n\n if (this._container) {\n width = this._container.offsetWidth || 400;\n height = this._container.offsetHeight || 300;\n }\n\n this._canvas.resize(width, height);\n\n this.transform.width = width;\n this.transform.height = height;\n this.transform._constrain();\n\n this.painter.resize(width, height);\n\n return this\n .fire('movestart')\n ._move()\n .fire('resize')\n .fire('moveend');\n },\n\n /**\n * Get the map's geographical bounds\n *\n * @returns {LatLngBounds}\n */\n getBounds: function() {\n return new LatLngBounds(\n this.transform.pointLocation(new Point(0, 0)),\n this.transform.pointLocation(this.transform.size));\n },\n\n /**\n * Get pixel coordinates (relative to map container) given a geographical location\n *\n * @param {LatLng} latlng\n * @returns {Object} `x` and `y` coordinates\n */\n project: function(latlng) {\n return this.transform.locationPoint(LatLng.convert(latlng));\n },\n\n /**\n * Get geographical coordinates given pixel coordinates\n *\n * @param {Array} point [x, y] pixel coordinates\n * @returns {LatLng}\n */\n unproject: function(point) {\n return this.transform.pointLocation(Point.convert(point));\n },\n\n /**\n * Get all features at a point ([x, y])\n *\n * @param {Array} point [x, y] pixel coordinates\n * @param {Object} params\n * @param {number} [params.radius=0] Optional. Radius in pixels to search in\n * @param {string} params.layer Optional. Only return features from a given layer\n * @param {string} params.type Optional. Either `raster` or `vector`\n * @param {featuresAtCallback} callback function that returns the response\n *\n * @callback featuresAtCallback\n * @param {Object|null} err Error _If any_\n * @param {Array} features Displays a JSON array of features given the passed parameters of `featuresAt`\n *\n * @returns {Map} `this`\n */\n featuresAt: function(point, params, callback) {\n var coord = this.transform.pointCoordinate(Point.convert(point));\n this.style.featuresAt(coord, params, callback);\n return this;\n },\n\n /**\n * Replaces the map's style object\n *\n * @param {Object} style A style object formatted as JSON\n * @returns {Map} `this`\n */\n setStyle: function(style) {\n if (this.style) {\n this.style\n .off('load', this._onStyleLoad)\n .off('error', this._forwardStyleEvent)\n .off('change', this._onStyleChange)\n .off('source.add', this._onSourceAdd)\n .off('source.remove', this._onSourceRemove)\n .off('source.load', this._onSourceUpdate)\n .off('source.error', this._forwardSourceEvent)\n .off('source.change', this._onSourceUpdate)\n .off('layer.add', this._forwardLayerEvent)\n .off('layer.remove', this._forwardLayerEvent)\n .off('tile.add', this._forwardTileEvent)\n .off('tile.remove', this._forwardTileEvent)\n .off('tile.load', this.update)\n .off('tile.error', this._forwardTileEvent)\n ._remove();\n\n this.off('rotate', this.style._redoPlacement);\n this.off('pitch', this.style._redoPlacement);\n }\n\n if (!style) {\n this.style = null;\n return this;\n } else if (style instanceof Style) {\n this.style = style;\n } else {\n this.style = new Style(style, this.animationLoop);\n }\n\n this.style\n .on('load', this._onStyleLoad)\n .on('error', this._forwardStyleEvent)\n .on('change', this._onStyleChange)\n .on('source.add', this._onSourceAdd)\n .on('source.remove', this._onSourceRemove)\n .on('source.load', this._onSourceUpdate)\n .on('source.error', this._forwardSourceEvent)\n .on('source.change', this._onSourceUpdate)\n .on('layer.add', this._forwardLayerEvent)\n .on('layer.remove', this._forwardLayerEvent)\n .on('tile.add', this._forwardTileEvent)\n .on('tile.remove', this._forwardTileEvent)\n .on('tile.load', this.update)\n .on('tile.error', this._forwardTileEvent);\n\n this.on('rotate', this.style._redoPlacement);\n this.on('pitch', this.style._redoPlacement);\n\n return this;\n },\n\n /**\n * Add a source to the map style.\n *\n * @param {string} id ID of the source. Must not be used by any existing source.\n * @param {Object} source source specification, following the\n * [Mapbox GL Style Reference](https://www.mapbox.com/mapbox-gl-style-spec/#sources)\n * @fires source.add\n * @returns {Map} `this`\n */\n addSource: function(id, source) {\n this.style.addSource(id, source);\n return this;\n },\n\n /**\n * Remove an existing source from the map style.\n *\n * @param {string} id ID of the source to remove\n * @fires source.remove\n * @returns {Map} `this`\n */\n removeSource: function(id) {\n this.style.removeSource(id);\n return this;\n },\n\n /**\n * Return the style source object with the given `id`.\n *\n * @param {string} id source ID\n * @returns {Object}\n */\n getSource: function(id) {\n return this.style.getSource(id);\n },\n\n /**\n * Add a layer to the map style. The layer will be inserted before the layer with\n * ID `before`, or appended if `before` is omitted.\n * @param {Layer} layer\n * @param {string=} before ID of an existing layer to insert before\n * @fires layer.add\n * @returns {Map} `this`\n */\n addLayer: function(layer, before) {\n this.style.addLayer(layer, before);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Remove the layer with the given `id` from the map. Any layers which refer to the\n * specified layer via a `ref` property are also removed.\n *\n * @param {string} id\n * @fires layer.remove\n * @returns {Map} this\n */\n removeLayer: function(id) {\n this.style.removeLayer(id);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Set the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {Array} filter filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n * @returns {Map} `this`\n */\n setFilter: function(layer, filter) {\n this.style.setFilter(layer, filter);\n return this;\n },\n\n /**\n * Get the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @returns {Array} filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n */\n getFilter: function(layer) {\n return this.style.getFilter(layer);\n },\n\n /**\n * Set the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {*} value value for the paint propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @param {string=} klass optional class specifier for the property\n * @returns {Map} `this`\n */\n setPaintProperty: function(layer, name, value, klass) {\n this.style.setPaintProperty(layer, name, value, klass);\n this.style._cascade(this._classes);\n this.update(true);\n return this;\n },\n\n /**\n * Get the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the paint propery\n */\n getPaintProperty: function(layer, name, klass) {\n return this.style.getPaintProperty(layer, name, klass);\n },\n\n /**\n * Set the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {*} value value for the layout propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @returns {Map} `this`\n */\n setLayoutProperty: function(layer, name, value) {\n this.style.setLayoutProperty(layer, name, value);\n return this;\n },\n\n /**\n * Get the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the layout propery\n */\n getLayoutProperty: function(layer, name) {\n return this.style.getLayoutProperty(layer, name);\n },\n\n /**\n * Get the Map's container as an HTML element\n * @returns {HTMLElement} container\n */\n getContainer: function() {\n return this._container;\n },\n\n /**\n * Get the Map's canvas as an HTML canvas\n * @returns {HTMLElement} canvas\n */\n getCanvas: function() {\n return this._canvas.getElement();\n },\n\n _move: function(zoom, rotate, pitch) {\n\n this.update(zoom).fire('move');\n\n if (zoom) this.fire('zoom');\n if (rotate) this.fire('rotate');\n if (pitch) this.fire('pitch');\n\n return this;\n },\n\n // map setup code\n _setupContainer: function() {\n var id = this.options.container;\n var container = this._container = typeof id === 'string' ? document.getElementById(id) : id;\n if (container) container.classList.add('mapboxgl-map');\n this._canvas = new Canvas(this, container);\n },\n\n _setupControlPos: function() {\n var corners = this._controlCorners = {};\n var prefix = 'mapboxgl-ctrl-';\n var container = this.getContainer();\n\n function createCorner(pos) {\n var className = prefix + pos;\n corners[pos] = DOM.create('div', className, container);\n }\n\n if (container && typeof document === 'object') {\n createCorner('top-left');\n createCorner('top-right');\n createCorner('bottom-left');\n createCorner('bottom-right');\n }\n },\n\n _setupPainter: function() {\n var gl = this._canvas.getWebGLContext(this.options.failIfMajorPerformanceCaveat);\n\n if (!gl) {\n console.error('Failed to initialize WebGL');\n return;\n }\n\n this.painter = new GLPainter(gl, this.transform);\n },\n\n _contextLost: function(event) {\n event.preventDefault();\n if (this._frameId) {\n browser.cancelFrame(this._frameId);\n }\n },\n\n _contextRestored: function() {\n this._setupPainter();\n this.resize();\n this.update();\n },\n\n /**\n * Is this map fully loaded? If the style isn't loaded\n * or it has a change to the sources or style that isn't\n * propagated to its style, return false.\n *\n * @returns {boolean} whether the map is loaded\n */\n loaded: function() {\n if (this._styleDirty || this._sourcesDirty)\n return false;\n if (this.style && !this.style.loaded())\n return false;\n return true;\n },\n\n /**\n * Update this map's style and re-render the map.\n *\n * @param {Object} updateStyle new style\n * @returns {Map} this\n */\n update: function(updateStyle) {\n if (!this.style) return this;\n\n this._styleDirty = this._styleDirty || updateStyle;\n this._sourcesDirty = true;\n\n this._rerender();\n\n return this;\n },\n\n /**\n * Call when a (re-)render of the map is required, e.g. when the\n * user panned or zoomed,f or new data is available.\n * @returns {Map} this\n */\n render: function() {\n if (this.style && this._styleDirty) {\n this._styleDirty = false;\n this.style._recalculate(this.transform.zoom);\n }\n\n if (this.style && this._sourcesDirty && !this._sourcesDirtyTimeout) {\n this._sourcesDirty = false;\n this._sourcesDirtyTimeout = setTimeout(function() {\n this._sourcesDirtyTimeout = null;\n }.bind(this), 50);\n this.style._updateSources(this.transform);\n }\n\n this.painter.render(this.style, {\n debug: this.debug,\n vertices: this.vertices,\n rotating: this.rotating,\n zooming: this.zooming\n });\n\n this.fire('render');\n\n if (this.loaded() && !this._loaded) {\n this._loaded = true;\n this.fire('load');\n }\n\n this._frameId = null;\n\n if (!this.animationLoop.stopped()) {\n this._styleDirty = true;\n }\n\n if (this._sourcesDirty || this._repaint || !this.animationLoop.stopped()) {\n this._rerender();\n }\n\n return this;\n },\n\n /**\n * Destroys the map's underlying resources, including web workers.\n * @returns {Map} this\n */\n remove: function() {\n if (this._hash) this._hash.remove();\n browser.cancelFrame(this._frameId);\n clearTimeout(this._sourcesDirtyTimeout);\n this.setStyle(null);\n return this;\n },\n\n _rerender: function() {\n if (this.style && !this._frameId) {\n this._frameId = browser.frame(this.render);\n }\n },\n\n _forwardStyleEvent: function(e) {\n this.fire('style.' + e.type, util.extend({style: e.target}, e));\n },\n\n _forwardSourceEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardLayerEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardTileEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _onStyleLoad: function(e) {\n this.style._cascade(this._classes, {transition: false});\n this._forwardStyleEvent(e);\n },\n\n _onStyleChange: function(e) {\n this.update(true);\n this._forwardStyleEvent(e);\n },\n\n _onSourceAdd: function(e) {\n var source = e.source;\n if (source.onAdd)\n source.onAdd(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceRemove: function(e) {\n var source = e.source;\n if (source.onRemove)\n source.onRemove(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceUpdate: function(e) {\n this.update();\n this._forwardSourceEvent(e);\n }\n}","path":"js/ui/map.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/map.js#L262-L268"},"params":[{"title":"param","description":"An array of class names","type":{"type":"TypeApplication","expression":{"type":"NameExpression","name":"Array"},"applications":[{"type":"NameExpression","name":"string"}]},"name":"klasses"},{"title":"param","description":null,"type":{"type":"NameExpression","name":"styleOptions"},"name":"options"}],"returns":[{"title":"returns","description":"`this`","type":{"type":"NameExpression","name":"Map"}}],"name":"setClasses","memberof":"Map","scope":"instance","members":{"instance":[],"static":[]},"path":["Map","setClasses"]},{"description":"Rotate bearing by a certain number of degrees with easing","tags":[{"title":"param","description":null,"type":{"type":"NameExpression","name":"Number"},"name":"bearing"},{"title":"param","description":null,"type":null,"name":"animOptions"},{"title":"fires","description":"movestart"},{"title":"fires","description":"moveend"},{"title":"returns","description":null,"type":{"type":"NameExpression","name":"this"}},{"title":"name","name":"rotateTo"},{"title":"memberof","description":"Map"},{"title":"instance"}],"context":{"loc":{"start":{"line":195,"column":4},"end":{"line":227,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/easings.js","code":"{\n isEasing: function() {\n return !!this._abortFn;\n },\n\n /**\n * Stop current animation\n *\n * @returns {this}\n */\n stop: function() {\n if (this._abortFn) {\n this._abortFn.call(this);\n delete this._abortFn;\n\n this._finishFn.call(this);\n delete this._finishFn;\n }\n return this;\n },\n\n _ease: function(frame, finish, options) {\n this._finishFn = finish;\n this._abortFn = browser.timed(function (t) {\n frame.call(this, options.easing(t));\n if (t === 1) {\n delete this._abortFn;\n this._finishFn.call(this);\n delete this._finishFn;\n }\n }, options.animate === false ? 0 : options.duration, this);\n },\n\n /**\n * Pan by a certain number of pixels\n *\n * @param {Array} offset [x, y]\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n panBy: function(offset, options) {\n this.panTo(this.transform.center, util.extend({offset: Point.convert(offset).mult(-1)}, options));\n return this;\n },\n\n /**\n * Pan to a certain location with easing\n *\n * @param {Object} latlng a `LatLng` object\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n panTo: function(latlng, options) {\n this.stop();\n\n latlng = LatLng.convert(latlng);\n\n options = util.extend({\n duration: 500,\n easing: util.ease,\n offset: [0, 0]\n }, options);\n\n var tr = this.transform,\n offset = Point.convert(options.offset).rotate(-tr.angle),\n from = tr.point,\n to = tr.project(latlng).sub(offset);\n\n if (!options.noMoveStart) {\n this.fire('movestart');\n }\n\n this._ease(function(k) {\n tr.center = tr.unproject(from.add(to.sub(from).mult(k)));\n this._move();\n }, function() {\n this.fire('moveend');\n }, options);\n\n return this;\n },\n\n /**\n * Zooms to a certain zoom level with easing.\n *\n * @param {Number} zoom\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n zoomTo: function(zoom, options) {\n this.stop();\n\n options = util.extend({\n duration: 500\n }, options);\n\n options.easing = this._updateEasing(options.duration, zoom, options.easing);\n\n var tr = this.transform,\n around = tr.center,\n startZoom = tr.zoom;\n\n if (options.around) {\n around = LatLng.convert(options.around);\n } else if (options.offset) {\n around = tr.pointLocation(tr.centerPoint.add(Point.convert(options.offset)));\n }\n\n if (options.animate === false) options.duration = 0;\n\n if (!this.zooming) {\n this.zooming = true;\n this.fire('movestart');\n }\n\n this._ease(function(k) {\n tr.setZoomAround(interpolate(startZoom, zoom, k), around);\n this.animationLoop.set(300); // text fading\n this._move(true);\n }, function() {\n this.ease = null;\n if (options.duration >= 200) {\n this.zooming = false;\n this.fire('moveend');\n }\n }, options);\n\n if (options.duration < 200) {\n clearTimeout(this._onZoomEnd);\n this._onZoomEnd = setTimeout(function() {\n this.zooming = false;\n this._rerender();\n this.fire('moveend');\n }.bind(this), 200);\n }\n\n return this;\n },\n\n /**\n * Zoom in by 1 level\n *\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n zoomIn: function(options) {\n this.zoomTo(this.getZoom() + 1, options);\n },\n\n /**\n * Zoom out by 1 level\n *\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n zoomOut: function(options) {\n this.zoomTo(this.getZoom() - 1, options);\n },\n\n /**\n * Rotate bearing by a certain number of degrees with easing\n *\n * @param {Number} bearing\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n rotateTo: function(bearing, options) {\n this.stop();\n\n options = util.extend({\n duration: 500,\n easing: util.ease\n }, options);\n\n var tr = this.transform,\n start = this.getBearing(),\n around = tr.center;\n\n if (options.around) {\n around = LatLng.convert(options.around);\n } else if (options.offset) {\n around = tr.pointLocation(tr.centerPoint.add(Point.convert(options.offset)));\n }\n\n bearing = this._normalizeBearing(bearing, start);\n\n this.rotating = true;\n this.fire('movestart');\n\n this._ease(function(k) {\n tr.setBearingAround(interpolate(start, bearing, k), around);\n this._move(false, true);\n }, function() {\n this.rotating = false;\n this.fire('moveend');\n }, options);\n\n return this;\n },\n\n /**\n * Sets map bearing to 0 (north) with easing\n *\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n resetNorth: function(options) {\n return this.rotateTo(0, util.extend({duration: 1000}, options));\n },\n\n /**\n * Zoom to contain certain geographical bounds\n *\n * @param {Array} bounds [[minLat, minLng], [maxLat, maxLng]]\n * @param {Object} options\n * @param {Number} [options.speed=1.2] How fast animation occurs\n * @param {Number} [options.curve=1.42] How much zooming out occurs during animation\n * @param {Function} options.easing\n * @param {Number} options.padding how much padding there is around the given bounds on each side in pixels\n * @param {Number} options.maxZoom\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n fitBounds: function(bounds, options) {\n\n options = util.extend({\n padding: 0,\n offset: [0, 0],\n maxZoom: Infinity\n }, options);\n\n bounds = LatLngBounds.convert(bounds);\n\n var offset = Point.convert(options.offset),\n tr = this.transform,\n nw = tr.project(bounds.getNorthWest()),\n se = tr.project(bounds.getSouthEast()),\n size = se.sub(nw),\n center = tr.unproject(nw.add(se).div(2)),\n\n scaleX = (tr.width - options.padding * 2 - Math.abs(offset.x) * 2) / size.x,\n scaleY = (tr.height - options.padding * 2 - Math.abs(offset.y) * 2) / size.y,\n\n zoom = Math.min(tr.scaleZoom(tr.scale * Math.min(scaleX, scaleY)), options.maxZoom);\n\n return options.linear ?\n this.easeTo(center, zoom, 0, options) :\n this.flyTo(center, zoom, 0, options);\n },\n\n /**\n * Easing animation to a specified location/zoom/bearing\n *\n * @param {Object} latlng a `LatLng` object\n * @param {Number} zoom\n * @param {Number} bearing\n * @param {Number} pitch\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n easeTo: function(latlng, zoom, bearing, pitch, options) {\n this.stop();\n\n options = util.extend({\n offset: [0, 0],\n duration: 500,\n easing: util.ease\n }, options);\n\n var tr = this.transform,\n offset = Point.convert(options.offset).rotate(-tr.angle),\n startZoom = this.getZoom(),\n startBearing = this.getBearing(),\n startPitch = this.getPitch();\n\n latlng = LatLng.convert(latlng);\n zoom = zoom === undefined ? startZoom : zoom;\n bearing = bearing === undefined ? startBearing : this._normalizeBearing(bearing, startBearing);\n pitch = pitch === undefined ? startPitch : pitch;\n\n var scale = tr.zoomScale(zoom - startZoom),\n from = tr.point,\n to = latlng ? tr.project(latlng).sub(offset.div(scale)) : tr.point,\n around;\n\n if (zoom !== startZoom) {\n around = tr.pointLocation(tr.centerPoint.add(to.sub(from).div(1 - 1 / scale)));\n this.zooming = true;\n }\n if (startBearing !== bearing) this.rotating = true;\n\n this.fire('movestart');\n\n this._ease(function (k) {\n if (zoom !== startZoom) {\n tr.setZoomAround(interpolate(startZoom, zoom, k), around);\n } else {\n tr.center = tr.unproject(from.add(to.sub(from).mult(k)));\n }\n\n if (bearing !== startBearing) {\n tr.bearing = interpolate(startBearing, bearing, k);\n }\n\n if (pitch !== startPitch) {\n tr.pitch = interpolate(startPitch, pitch, k);\n }\n\n this.animationLoop.set(300); // text fading\n this._move(zoom !== startZoom, bearing !== startBearing);\n }, function() {\n this.zooming = false;\n this.rotating = false;\n this.fire('moveend');\n }, options);\n\n return this;\n },\n\n /**\n * Flying animation to a specified location/zoom/bearing with automatic curve\n *\n * @param {Object} latlng a `LatLng` object\n * @param {Number} zoom\n * @param {Number} bearing\n * @param {Object} options\n * @param {Number} [options.speed=1.2] How fast animation occurs\n * @param {Number} [options.curve=1.42] How much zooming out occurs during animation\n * @param {Function} options.easing\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n flyTo: function(latlng, zoom, bearing, options) {\n this.stop();\n\n options = util.extend({\n offset: [0, 0],\n speed: 1.2,\n curve: 1.42,\n easing: util.ease\n }, options);\n\n latlng = LatLng.convert(latlng);\n\n var offset = Point.convert(options.offset),\n tr = this.transform,\n startZoom = this.getZoom(),\n startBearing = this.getBearing();\n\n zoom = zoom === undefined ? startZoom : zoom;\n bearing = bearing === undefined ? startBearing : this._normalizeBearing(bearing, startBearing);\n\n var scale = tr.zoomScale(zoom - startZoom),\n from = tr.point,\n to = tr.project(latlng).sub(offset.div(scale));\n\n if (options.animate === false) {\n return this.setView(latlng, zoom, bearing, this.getPitch());\n }\n\n var startWorldSize = tr.worldSize,\n rho = options.curve,\n V = options.speed,\n\n w0 = Math.max(tr.width, tr.height),\n w1 = w0 / scale,\n u1 = to.sub(from).mag(),\n rho2 = rho * rho;\n\n function r(i) {\n var b = (w1 * w1 - w0 * w0 + (i ? -1 : 1) * rho2 * rho2 * u1 * u1) / (2 * (i ? w1 : w0) * rho2 * u1);\n return Math.log(Math.sqrt(b * b + 1) - b);\n }\n\n function sinh(n) { return (Math.exp(n) - Math.exp(-n)) / 2; }\n function cosh(n) { return (Math.exp(n) + Math.exp(-n)) / 2; }\n function tanh(n) { return sinh(n) / cosh(n); }\n\n var r0 = r(0),\n w = function (s) { return (cosh(r0) / cosh(r0 + rho * s)); },\n u = function (s) { return w0 * ((cosh(r0) * tanh(r0 + rho * s) - sinh(r0)) / rho2) / u1; },\n S = (r(1) - r0) / rho;\n\n if (Math.abs(u1) < 0.000001) {\n if (Math.abs(w0 - w1) < 0.000001) return this;\n\n var k = w1 < w0 ? -1 : 1;\n S = Math.abs(Math.log(w1 / w0)) / rho;\n\n u = function() { return 0; };\n w = function(s) { return Math.exp(k * rho * s); };\n }\n\n options.duration = 1000 * S / V;\n\n this.zooming = true;\n if (startBearing !== bearing) this.rotating = true;\n\n this.fire('movestart');\n\n this._ease(function (k) {\n var s = k * S,\n us = u(s);\n\n tr.zoom = startZoom + tr.scaleZoom(1 / w(s));\n tr.center = tr.unproject(from.add(to.sub(from).mult(us)), startWorldSize);\n\n if (bearing !== startBearing) {\n tr.bearing = interpolate(startBearing, bearing, k);\n }\n\n this.animationLoop.set(300); // text fading\n\n this._move(true, bearing !== startBearing);\n }, function() {\n this.zooming = false;\n this.rotating = false;\n this.fire('moveend');\n }, options);\n\n return this;\n },\n\n // convert bearing so that it's numerically close to the current one so that it interpolates properly\n _normalizeBearing: function(bearing, currentBearing) {\n bearing = util.wrap(bearing, -180, 180);\n var diff = Math.abs(bearing - currentBearing);\n if (Math.abs(bearing - 360 - currentBearing) < diff) bearing -= 360;\n if (Math.abs(bearing + 360 - currentBearing) < diff) bearing += 360;\n return bearing;\n },\n\n _updateEasing: function(duration, zoom, bezier) {\n var easing;\n\n if (this.ease) {\n var ease = this.ease,\n t = (Date.now() - ease.start) / ease.duration,\n speed = ease.easing(t + 0.01) - ease.easing(t),\n\n // Quick hack to make new bezier that is continuous with last\n x = 0.27 / Math.sqrt(speed * speed + 0.0001) * 0.01,\n y = Math.sqrt(0.27 * 0.27 - x * x);\n\n easing = util.bezier(x, y, 0.25, 1);\n } else {\n easing = bezier ? util.bezier.apply(util, bezier) : util.ease;\n }\n\n // store information on current easing\n this.ease = {\n start: (new Date()).getTime(),\n to: Math.pow(2, zoom),\n duration: duration,\n easing: easing\n };\n\n return easing;\n }\n}","path":"js/ui/easings.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/easings.js#L195-L227"},"params":[{"title":"param","description":null,"type":{"type":"NameExpression","name":"Number"},"name":"bearing"},{"title":"param","description":null,"type":null,"name":"animOptions"}],"returns":[{"title":"returns","description":null,"type":{"type":"NameExpression","name":"this"}}],"name":"rotateTo","memberof":"Map","scope":"instance","members":{"instance":[],"static":[]},"path":["Map","rotateTo"]},{"description":"Replaces the map's style object","tags":[{"title":"param","description":"A style object formatted as JSON","type":{"type":"NameExpression","name":"Object"},"name":"style"},{"title":"returns","description":"`this`","type":{"type":"NameExpression","name":"Map"}},{"title":"name","name":"setStyle"},{"title":"memberof","description":"Map"},{"title":"instance"}],"context":{"loc":{"start":{"line":376,"column":4},"end":{"line":428,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/map.js","code":"{\n\n options: {\n center: [0, 0],\n zoom: 0,\n bearing: 0,\n pitch: 0,\n\n minZoom: 0,\n maxZoom: 20,\n\n interactive: true,\n hash: false,\n\n attributionControl: true,\n\n failIfMajorPerformanceCaveat: false\n },\n\n addControl: function(control) {\n control.addTo(this);\n return this;\n },\n\n /**\n * Sets a map position\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @param {number} zoom Map zoom level\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setView: function(center, zoom, bearing, pitch) {\n this.stop();\n\n var tr = this.transform,\n zoomChanged = tr.zoom !== +zoom,\n bearingChanged = tr.bearing !== +bearing,\n pitchChanged = tr.pitch !== +pitch;\n\n tr.center = LatLng.convert(center);\n tr.zoom = +zoom;\n tr.bearing = +bearing;\n tr.pitch = +pitch;\n\n return this\n .fire('movestart')\n ._move(zoomChanged, bearingChanged, pitchChanged)\n .fire('moveend');\n },\n\n /**\n * Sets a map location\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setCenter: function(center) {\n this.setView(center, this.getZoom(), this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map zoom\n *\n * @param {number} zoom Map zoom level\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setZoom: function(zoom) {\n this.setView(this.getCenter(), zoom, this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map rotation\n *\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setBearing: function(bearing) {\n this.setView(this.getCenter(), this.getZoom(), bearing, this.getPitch());\n },\n\n /**\n * Sets a map angle\n *\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setPitch: function(pitch) {\n this.setView(this.getCenter(), this.getZoom(), this.getBearing(), pitch);\n },\n\n /**\n * Get the current view geographical point\n * @returns {LatLng}\n */\n getCenter: function() { return this.transform.center; },\n\n /**\n * Get the current zoom\n * @returns {number}\n */\n getZoom: function() { return this.transform.zoom; },\n\n /**\n * Get the current bearing in degrees\n * @returns {number}\n */\n getBearing: function() { return this.transform.bearing; },\n\n /**\n * Get the current angle in degrees\n * @returns {number}\n */\n getPitch: function() { return this.transform.pitch; },\n\n /**\n * @typedef {Object} [styleOptions]\n * @param {Boolean} [styleOptions.transition=true]\n */\n\n /**\n * Adds a style class to a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n addClass: function(klass, options) {\n if (this._classes[klass]) return;\n this._classes[klass] = true;\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Removes a style class from a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n removeClass: function(klass, options) {\n if (!this._classes[klass]) return;\n delete this._classes[klass];\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Helper method to add more than one class\n *\n * @param {Array} klasses An array of class names\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n setClasses: function(klasses, options) {\n this._classes = {};\n for (var i = 0; i < klasses.length; i++) {\n this._classes[klasses[i]] = true;\n }\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Check whether a style class is active\n *\n * @param {string} klass Name of style class\n * @returns {boolean}\n */\n hasClass: function(klass) {\n return !!this._classes[klass];\n },\n\n /**\n * Return an array of the current active style classes\n *\n * @returns {boolean}\n */\n getClasses: function() {\n return Object.keys(this._classes);\n },\n\n /**\n * Detect the map's new width and height and resize it.\n *\n * @returns {Map} `this`\n */\n resize: function() {\n var width = 0, height = 0;\n\n if (this._container) {\n width = this._container.offsetWidth || 400;\n height = this._container.offsetHeight || 300;\n }\n\n this._canvas.resize(width, height);\n\n this.transform.width = width;\n this.transform.height = height;\n this.transform._constrain();\n\n this.painter.resize(width, height);\n\n return this\n .fire('movestart')\n ._move()\n .fire('resize')\n .fire('moveend');\n },\n\n /**\n * Get the map's geographical bounds\n *\n * @returns {LatLngBounds}\n */\n getBounds: function() {\n return new LatLngBounds(\n this.transform.pointLocation(new Point(0, 0)),\n this.transform.pointLocation(this.transform.size));\n },\n\n /**\n * Get pixel coordinates (relative to map container) given a geographical location\n *\n * @param {LatLng} latlng\n * @returns {Object} `x` and `y` coordinates\n */\n project: function(latlng) {\n return this.transform.locationPoint(LatLng.convert(latlng));\n },\n\n /**\n * Get geographical coordinates given pixel coordinates\n *\n * @param {Array} point [x, y] pixel coordinates\n * @returns {LatLng}\n */\n unproject: function(point) {\n return this.transform.pointLocation(Point.convert(point));\n },\n\n /**\n * Get all features at a point ([x, y])\n *\n * @param {Array} point [x, y] pixel coordinates\n * @param {Object} params\n * @param {number} [params.radius=0] Optional. Radius in pixels to search in\n * @param {string} params.layer Optional. Only return features from a given layer\n * @param {string} params.type Optional. Either `raster` or `vector`\n * @param {featuresAtCallback} callback function that returns the response\n *\n * @callback featuresAtCallback\n * @param {Object|null} err Error _If any_\n * @param {Array} features Displays a JSON array of features given the passed parameters of `featuresAt`\n *\n * @returns {Map} `this`\n */\n featuresAt: function(point, params, callback) {\n var coord = this.transform.pointCoordinate(Point.convert(point));\n this.style.featuresAt(coord, params, callback);\n return this;\n },\n\n /**\n * Replaces the map's style object\n *\n * @param {Object} style A style object formatted as JSON\n * @returns {Map} `this`\n */\n setStyle: function(style) {\n if (this.style) {\n this.style\n .off('load', this._onStyleLoad)\n .off('error', this._forwardStyleEvent)\n .off('change', this._onStyleChange)\n .off('source.add', this._onSourceAdd)\n .off('source.remove', this._onSourceRemove)\n .off('source.load', this._onSourceUpdate)\n .off('source.error', this._forwardSourceEvent)\n .off('source.change', this._onSourceUpdate)\n .off('layer.add', this._forwardLayerEvent)\n .off('layer.remove', this._forwardLayerEvent)\n .off('tile.add', this._forwardTileEvent)\n .off('tile.remove', this._forwardTileEvent)\n .off('tile.load', this.update)\n .off('tile.error', this._forwardTileEvent)\n ._remove();\n\n this.off('rotate', this.style._redoPlacement);\n this.off('pitch', this.style._redoPlacement);\n }\n\n if (!style) {\n this.style = null;\n return this;\n } else if (style instanceof Style) {\n this.style = style;\n } else {\n this.style = new Style(style, this.animationLoop);\n }\n\n this.style\n .on('load', this._onStyleLoad)\n .on('error', this._forwardStyleEvent)\n .on('change', this._onStyleChange)\n .on('source.add', this._onSourceAdd)\n .on('source.remove', this._onSourceRemove)\n .on('source.load', this._onSourceUpdate)\n .on('source.error', this._forwardSourceEvent)\n .on('source.change', this._onSourceUpdate)\n .on('layer.add', this._forwardLayerEvent)\n .on('layer.remove', this._forwardLayerEvent)\n .on('tile.add', this._forwardTileEvent)\n .on('tile.remove', this._forwardTileEvent)\n .on('tile.load', this.update)\n .on('tile.error', this._forwardTileEvent);\n\n this.on('rotate', this.style._redoPlacement);\n this.on('pitch', this.style._redoPlacement);\n\n return this;\n },\n\n /**\n * Add a source to the map style.\n *\n * @param {string} id ID of the source. Must not be used by any existing source.\n * @param {Object} source source specification, following the\n * [Mapbox GL Style Reference](https://www.mapbox.com/mapbox-gl-style-spec/#sources)\n * @fires source.add\n * @returns {Map} `this`\n */\n addSource: function(id, source) {\n this.style.addSource(id, source);\n return this;\n },\n\n /**\n * Remove an existing source from the map style.\n *\n * @param {string} id ID of the source to remove\n * @fires source.remove\n * @returns {Map} `this`\n */\n removeSource: function(id) {\n this.style.removeSource(id);\n return this;\n },\n\n /**\n * Return the style source object with the given `id`.\n *\n * @param {string} id source ID\n * @returns {Object}\n */\n getSource: function(id) {\n return this.style.getSource(id);\n },\n\n /**\n * Add a layer to the map style. The layer will be inserted before the layer with\n * ID `before`, or appended if `before` is omitted.\n * @param {Layer} layer\n * @param {string=} before ID of an existing layer to insert before\n * @fires layer.add\n * @returns {Map} `this`\n */\n addLayer: function(layer, before) {\n this.style.addLayer(layer, before);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Remove the layer with the given `id` from the map. Any layers which refer to the\n * specified layer via a `ref` property are also removed.\n *\n * @param {string} id\n * @fires layer.remove\n * @returns {Map} this\n */\n removeLayer: function(id) {\n this.style.removeLayer(id);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Set the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {Array} filter filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n * @returns {Map} `this`\n */\n setFilter: function(layer, filter) {\n this.style.setFilter(layer, filter);\n return this;\n },\n\n /**\n * Get the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @returns {Array} filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n */\n getFilter: function(layer) {\n return this.style.getFilter(layer);\n },\n\n /**\n * Set the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {*} value value for the paint propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @param {string=} klass optional class specifier for the property\n * @returns {Map} `this`\n */\n setPaintProperty: function(layer, name, value, klass) {\n this.style.setPaintProperty(layer, name, value, klass);\n this.style._cascade(this._classes);\n this.update(true);\n return this;\n },\n\n /**\n * Get the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the paint propery\n */\n getPaintProperty: function(layer, name, klass) {\n return this.style.getPaintProperty(layer, name, klass);\n },\n\n /**\n * Set the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {*} value value for the layout propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @returns {Map} `this`\n */\n setLayoutProperty: function(layer, name, value) {\n this.style.setLayoutProperty(layer, name, value);\n return this;\n },\n\n /**\n * Get the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the layout propery\n */\n getLayoutProperty: function(layer, name) {\n return this.style.getLayoutProperty(layer, name);\n },\n\n /**\n * Get the Map's container as an HTML element\n * @returns {HTMLElement} container\n */\n getContainer: function() {\n return this._container;\n },\n\n /**\n * Get the Map's canvas as an HTML canvas\n * @returns {HTMLElement} canvas\n */\n getCanvas: function() {\n return this._canvas.getElement();\n },\n\n _move: function(zoom, rotate, pitch) {\n\n this.update(zoom).fire('move');\n\n if (zoom) this.fire('zoom');\n if (rotate) this.fire('rotate');\n if (pitch) this.fire('pitch');\n\n return this;\n },\n\n // map setup code\n _setupContainer: function() {\n var id = this.options.container;\n var container = this._container = typeof id === 'string' ? document.getElementById(id) : id;\n if (container) container.classList.add('mapboxgl-map');\n this._canvas = new Canvas(this, container);\n },\n\n _setupControlPos: function() {\n var corners = this._controlCorners = {};\n var prefix = 'mapboxgl-ctrl-';\n var container = this.getContainer();\n\n function createCorner(pos) {\n var className = prefix + pos;\n corners[pos] = DOM.create('div', className, container);\n }\n\n if (container && typeof document === 'object') {\n createCorner('top-left');\n createCorner('top-right');\n createCorner('bottom-left');\n createCorner('bottom-right');\n }\n },\n\n _setupPainter: function() {\n var gl = this._canvas.getWebGLContext(this.options.failIfMajorPerformanceCaveat);\n\n if (!gl) {\n console.error('Failed to initialize WebGL');\n return;\n }\n\n this.painter = new GLPainter(gl, this.transform);\n },\n\n _contextLost: function(event) {\n event.preventDefault();\n if (this._frameId) {\n browser.cancelFrame(this._frameId);\n }\n },\n\n _contextRestored: function() {\n this._setupPainter();\n this.resize();\n this.update();\n },\n\n /**\n * Is this map fully loaded? If the style isn't loaded\n * or it has a change to the sources or style that isn't\n * propagated to its style, return false.\n *\n * @returns {boolean} whether the map is loaded\n */\n loaded: function() {\n if (this._styleDirty || this._sourcesDirty)\n return false;\n if (this.style && !this.style.loaded())\n return false;\n return true;\n },\n\n /**\n * Update this map's style and re-render the map.\n *\n * @param {Object} updateStyle new style\n * @returns {Map} this\n */\n update: function(updateStyle) {\n if (!this.style) return this;\n\n this._styleDirty = this._styleDirty || updateStyle;\n this._sourcesDirty = true;\n\n this._rerender();\n\n return this;\n },\n\n /**\n * Call when a (re-)render of the map is required, e.g. when the\n * user panned or zoomed,f or new data is available.\n * @returns {Map} this\n */\n render: function() {\n if (this.style && this._styleDirty) {\n this._styleDirty = false;\n this.style._recalculate(this.transform.zoom);\n }\n\n if (this.style && this._sourcesDirty && !this._sourcesDirtyTimeout) {\n this._sourcesDirty = false;\n this._sourcesDirtyTimeout = setTimeout(function() {\n this._sourcesDirtyTimeout = null;\n }.bind(this), 50);\n this.style._updateSources(this.transform);\n }\n\n this.painter.render(this.style, {\n debug: this.debug,\n vertices: this.vertices,\n rotating: this.rotating,\n zooming: this.zooming\n });\n\n this.fire('render');\n\n if (this.loaded() && !this._loaded) {\n this._loaded = true;\n this.fire('load');\n }\n\n this._frameId = null;\n\n if (!this.animationLoop.stopped()) {\n this._styleDirty = true;\n }\n\n if (this._sourcesDirty || this._repaint || !this.animationLoop.stopped()) {\n this._rerender();\n }\n\n return this;\n },\n\n /**\n * Destroys the map's underlying resources, including web workers.\n * @returns {Map} this\n */\n remove: function() {\n if (this._hash) this._hash.remove();\n browser.cancelFrame(this._frameId);\n clearTimeout(this._sourcesDirtyTimeout);\n this.setStyle(null);\n return this;\n },\n\n _rerender: function() {\n if (this.style && !this._frameId) {\n this._frameId = browser.frame(this.render);\n }\n },\n\n _forwardStyleEvent: function(e) {\n this.fire('style.' + e.type, util.extend({style: e.target}, e));\n },\n\n _forwardSourceEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardLayerEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardTileEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _onStyleLoad: function(e) {\n this.style._cascade(this._classes, {transition: false});\n this._forwardStyleEvent(e);\n },\n\n _onStyleChange: function(e) {\n this.update(true);\n this._forwardStyleEvent(e);\n },\n\n _onSourceAdd: function(e) {\n var source = e.source;\n if (source.onAdd)\n source.onAdd(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceRemove: function(e) {\n var source = e.source;\n if (source.onRemove)\n source.onRemove(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceUpdate: function(e) {\n this.update();\n this._forwardSourceEvent(e);\n }\n}","path":"js/ui/map.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/map.js#L376-L428"},"params":[{"title":"param","description":"A style object formatted as JSON","type":{"type":"NameExpression","name":"Object"},"name":"style"}],"returns":[{"title":"returns","description":"`this`","type":{"type":"NameExpression","name":"Map"}}],"name":"setStyle","memberof":"Map","scope":"instance","members":{"instance":[],"static":[]},"path":["Map","setStyle"]},{"description":"Remove an existing source from the map style.","tags":[{"title":"param","description":"ID of the source to remove","type":{"type":"NameExpression","name":"string"},"name":"id"},{"title":"fires","description":"source.remove"},{"title":"returns","description":"`this`","type":{"type":"NameExpression","name":"Map"}},{"title":"name","name":"removeSource"},{"title":"memberof","description":"Map"},{"title":"instance"}],"context":{"loc":{"start":{"line":451,"column":4},"end":{"line":454,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/map.js","code":"{\n\n options: {\n center: [0, 0],\n zoom: 0,\n bearing: 0,\n pitch: 0,\n\n minZoom: 0,\n maxZoom: 20,\n\n interactive: true,\n hash: false,\n\n attributionControl: true,\n\n failIfMajorPerformanceCaveat: false\n },\n\n addControl: function(control) {\n control.addTo(this);\n return this;\n },\n\n /**\n * Sets a map position\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @param {number} zoom Map zoom level\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setView: function(center, zoom, bearing, pitch) {\n this.stop();\n\n var tr = this.transform,\n zoomChanged = tr.zoom !== +zoom,\n bearingChanged = tr.bearing !== +bearing,\n pitchChanged = tr.pitch !== +pitch;\n\n tr.center = LatLng.convert(center);\n tr.zoom = +zoom;\n tr.bearing = +bearing;\n tr.pitch = +pitch;\n\n return this\n .fire('movestart')\n ._move(zoomChanged, bearingChanged, pitchChanged)\n .fire('moveend');\n },\n\n /**\n * Sets a map location\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setCenter: function(center) {\n this.setView(center, this.getZoom(), this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map zoom\n *\n * @param {number} zoom Map zoom level\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setZoom: function(zoom) {\n this.setView(this.getCenter(), zoom, this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map rotation\n *\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setBearing: function(bearing) {\n this.setView(this.getCenter(), this.getZoom(), bearing, this.getPitch());\n },\n\n /**\n * Sets a map angle\n *\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setPitch: function(pitch) {\n this.setView(this.getCenter(), this.getZoom(), this.getBearing(), pitch);\n },\n\n /**\n * Get the current view geographical point\n * @returns {LatLng}\n */\n getCenter: function() { return this.transform.center; },\n\n /**\n * Get the current zoom\n * @returns {number}\n */\n getZoom: function() { return this.transform.zoom; },\n\n /**\n * Get the current bearing in degrees\n * @returns {number}\n */\n getBearing: function() { return this.transform.bearing; },\n\n /**\n * Get the current angle in degrees\n * @returns {number}\n */\n getPitch: function() { return this.transform.pitch; },\n\n /**\n * @typedef {Object} [styleOptions]\n * @param {Boolean} [styleOptions.transition=true]\n */\n\n /**\n * Adds a style class to a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n addClass: function(klass, options) {\n if (this._classes[klass]) return;\n this._classes[klass] = true;\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Removes a style class from a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n removeClass: function(klass, options) {\n if (!this._classes[klass]) return;\n delete this._classes[klass];\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Helper method to add more than one class\n *\n * @param {Array} klasses An array of class names\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n setClasses: function(klasses, options) {\n this._classes = {};\n for (var i = 0; i < klasses.length; i++) {\n this._classes[klasses[i]] = true;\n }\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Check whether a style class is active\n *\n * @param {string} klass Name of style class\n * @returns {boolean}\n */\n hasClass: function(klass) {\n return !!this._classes[klass];\n },\n\n /**\n * Return an array of the current active style classes\n *\n * @returns {boolean}\n */\n getClasses: function() {\n return Object.keys(this._classes);\n },\n\n /**\n * Detect the map's new width and height and resize it.\n *\n * @returns {Map} `this`\n */\n resize: function() {\n var width = 0, height = 0;\n\n if (this._container) {\n width = this._container.offsetWidth || 400;\n height = this._container.offsetHeight || 300;\n }\n\n this._canvas.resize(width, height);\n\n this.transform.width = width;\n this.transform.height = height;\n this.transform._constrain();\n\n this.painter.resize(width, height);\n\n return this\n .fire('movestart')\n ._move()\n .fire('resize')\n .fire('moveend');\n },\n\n /**\n * Get the map's geographical bounds\n *\n * @returns {LatLngBounds}\n */\n getBounds: function() {\n return new LatLngBounds(\n this.transform.pointLocation(new Point(0, 0)),\n this.transform.pointLocation(this.transform.size));\n },\n\n /**\n * Get pixel coordinates (relative to map container) given a geographical location\n *\n * @param {LatLng} latlng\n * @returns {Object} `x` and `y` coordinates\n */\n project: function(latlng) {\n return this.transform.locationPoint(LatLng.convert(latlng));\n },\n\n /**\n * Get geographical coordinates given pixel coordinates\n *\n * @param {Array} point [x, y] pixel coordinates\n * @returns {LatLng}\n */\n unproject: function(point) {\n return this.transform.pointLocation(Point.convert(point));\n },\n\n /**\n * Get all features at a point ([x, y])\n *\n * @param {Array} point [x, y] pixel coordinates\n * @param {Object} params\n * @param {number} [params.radius=0] Optional. Radius in pixels to search in\n * @param {string} params.layer Optional. Only return features from a given layer\n * @param {string} params.type Optional. Either `raster` or `vector`\n * @param {featuresAtCallback} callback function that returns the response\n *\n * @callback featuresAtCallback\n * @param {Object|null} err Error _If any_\n * @param {Array} features Displays a JSON array of features given the passed parameters of `featuresAt`\n *\n * @returns {Map} `this`\n */\n featuresAt: function(point, params, callback) {\n var coord = this.transform.pointCoordinate(Point.convert(point));\n this.style.featuresAt(coord, params, callback);\n return this;\n },\n\n /**\n * Replaces the map's style object\n *\n * @param {Object} style A style object formatted as JSON\n * @returns {Map} `this`\n */\n setStyle: function(style) {\n if (this.style) {\n this.style\n .off('load', this._onStyleLoad)\n .off('error', this._forwardStyleEvent)\n .off('change', this._onStyleChange)\n .off('source.add', this._onSourceAdd)\n .off('source.remove', this._onSourceRemove)\n .off('source.load', this._onSourceUpdate)\n .off('source.error', this._forwardSourceEvent)\n .off('source.change', this._onSourceUpdate)\n .off('layer.add', this._forwardLayerEvent)\n .off('layer.remove', this._forwardLayerEvent)\n .off('tile.add', this._forwardTileEvent)\n .off('tile.remove', this._forwardTileEvent)\n .off('tile.load', this.update)\n .off('tile.error', this._forwardTileEvent)\n ._remove();\n\n this.off('rotate', this.style._redoPlacement);\n this.off('pitch', this.style._redoPlacement);\n }\n\n if (!style) {\n this.style = null;\n return this;\n } else if (style instanceof Style) {\n this.style = style;\n } else {\n this.style = new Style(style, this.animationLoop);\n }\n\n this.style\n .on('load', this._onStyleLoad)\n .on('error', this._forwardStyleEvent)\n .on('change', this._onStyleChange)\n .on('source.add', this._onSourceAdd)\n .on('source.remove', this._onSourceRemove)\n .on('source.load', this._onSourceUpdate)\n .on('source.error', this._forwardSourceEvent)\n .on('source.change', this._onSourceUpdate)\n .on('layer.add', this._forwardLayerEvent)\n .on('layer.remove', this._forwardLayerEvent)\n .on('tile.add', this._forwardTileEvent)\n .on('tile.remove', this._forwardTileEvent)\n .on('tile.load', this.update)\n .on('tile.error', this._forwardTileEvent);\n\n this.on('rotate', this.style._redoPlacement);\n this.on('pitch', this.style._redoPlacement);\n\n return this;\n },\n\n /**\n * Add a source to the map style.\n *\n * @param {string} id ID of the source. Must not be used by any existing source.\n * @param {Object} source source specification, following the\n * [Mapbox GL Style Reference](https://www.mapbox.com/mapbox-gl-style-spec/#sources)\n * @fires source.add\n * @returns {Map} `this`\n */\n addSource: function(id, source) {\n this.style.addSource(id, source);\n return this;\n },\n\n /**\n * Remove an existing source from the map style.\n *\n * @param {string} id ID of the source to remove\n * @fires source.remove\n * @returns {Map} `this`\n */\n removeSource: function(id) {\n this.style.removeSource(id);\n return this;\n },\n\n /**\n * Return the style source object with the given `id`.\n *\n * @param {string} id source ID\n * @returns {Object}\n */\n getSource: function(id) {\n return this.style.getSource(id);\n },\n\n /**\n * Add a layer to the map style. The layer will be inserted before the layer with\n * ID `before`, or appended if `before` is omitted.\n * @param {Layer} layer\n * @param {string=} before ID of an existing layer to insert before\n * @fires layer.add\n * @returns {Map} `this`\n */\n addLayer: function(layer, before) {\n this.style.addLayer(layer, before);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Remove the layer with the given `id` from the map. Any layers which refer to the\n * specified layer via a `ref` property are also removed.\n *\n * @param {string} id\n * @fires layer.remove\n * @returns {Map} this\n */\n removeLayer: function(id) {\n this.style.removeLayer(id);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Set the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {Array} filter filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n * @returns {Map} `this`\n */\n setFilter: function(layer, filter) {\n this.style.setFilter(layer, filter);\n return this;\n },\n\n /**\n * Get the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @returns {Array} filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n */\n getFilter: function(layer) {\n return this.style.getFilter(layer);\n },\n\n /**\n * Set the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {*} value value for the paint propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @param {string=} klass optional class specifier for the property\n * @returns {Map} `this`\n */\n setPaintProperty: function(layer, name, value, klass) {\n this.style.setPaintProperty(layer, name, value, klass);\n this.style._cascade(this._classes);\n this.update(true);\n return this;\n },\n\n /**\n * Get the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the paint propery\n */\n getPaintProperty: function(layer, name, klass) {\n return this.style.getPaintProperty(layer, name, klass);\n },\n\n /**\n * Set the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {*} value value for the layout propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @returns {Map} `this`\n */\n setLayoutProperty: function(layer, name, value) {\n this.style.setLayoutProperty(layer, name, value);\n return this;\n },\n\n /**\n * Get the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the layout propery\n */\n getLayoutProperty: function(layer, name) {\n return this.style.getLayoutProperty(layer, name);\n },\n\n /**\n * Get the Map's container as an HTML element\n * @returns {HTMLElement} container\n */\n getContainer: function() {\n return this._container;\n },\n\n /**\n * Get the Map's canvas as an HTML canvas\n * @returns {HTMLElement} canvas\n */\n getCanvas: function() {\n return this._canvas.getElement();\n },\n\n _move: function(zoom, rotate, pitch) {\n\n this.update(zoom).fire('move');\n\n if (zoom) this.fire('zoom');\n if (rotate) this.fire('rotate');\n if (pitch) this.fire('pitch');\n\n return this;\n },\n\n // map setup code\n _setupContainer: function() {\n var id = this.options.container;\n var container = this._container = typeof id === 'string' ? document.getElementById(id) : id;\n if (container) container.classList.add('mapboxgl-map');\n this._canvas = new Canvas(this, container);\n },\n\n _setupControlPos: function() {\n var corners = this._controlCorners = {};\n var prefix = 'mapboxgl-ctrl-';\n var container = this.getContainer();\n\n function createCorner(pos) {\n var className = prefix + pos;\n corners[pos] = DOM.create('div', className, container);\n }\n\n if (container && typeof document === 'object') {\n createCorner('top-left');\n createCorner('top-right');\n createCorner('bottom-left');\n createCorner('bottom-right');\n }\n },\n\n _setupPainter: function() {\n var gl = this._canvas.getWebGLContext(this.options.failIfMajorPerformanceCaveat);\n\n if (!gl) {\n console.error('Failed to initialize WebGL');\n return;\n }\n\n this.painter = new GLPainter(gl, this.transform);\n },\n\n _contextLost: function(event) {\n event.preventDefault();\n if (this._frameId) {\n browser.cancelFrame(this._frameId);\n }\n },\n\n _contextRestored: function() {\n this._setupPainter();\n this.resize();\n this.update();\n },\n\n /**\n * Is this map fully loaded? If the style isn't loaded\n * or it has a change to the sources or style that isn't\n * propagated to its style, return false.\n *\n * @returns {boolean} whether the map is loaded\n */\n loaded: function() {\n if (this._styleDirty || this._sourcesDirty)\n return false;\n if (this.style && !this.style.loaded())\n return false;\n return true;\n },\n\n /**\n * Update this map's style and re-render the map.\n *\n * @param {Object} updateStyle new style\n * @returns {Map} this\n */\n update: function(updateStyle) {\n if (!this.style) return this;\n\n this._styleDirty = this._styleDirty || updateStyle;\n this._sourcesDirty = true;\n\n this._rerender();\n\n return this;\n },\n\n /**\n * Call when a (re-)render of the map is required, e.g. when the\n * user panned or zoomed,f or new data is available.\n * @returns {Map} this\n */\n render: function() {\n if (this.style && this._styleDirty) {\n this._styleDirty = false;\n this.style._recalculate(this.transform.zoom);\n }\n\n if (this.style && this._sourcesDirty && !this._sourcesDirtyTimeout) {\n this._sourcesDirty = false;\n this._sourcesDirtyTimeout = setTimeout(function() {\n this._sourcesDirtyTimeout = null;\n }.bind(this), 50);\n this.style._updateSources(this.transform);\n }\n\n this.painter.render(this.style, {\n debug: this.debug,\n vertices: this.vertices,\n rotating: this.rotating,\n zooming: this.zooming\n });\n\n this.fire('render');\n\n if (this.loaded() && !this._loaded) {\n this._loaded = true;\n this.fire('load');\n }\n\n this._frameId = null;\n\n if (!this.animationLoop.stopped()) {\n this._styleDirty = true;\n }\n\n if (this._sourcesDirty || this._repaint || !this.animationLoop.stopped()) {\n this._rerender();\n }\n\n return this;\n },\n\n /**\n * Destroys the map's underlying resources, including web workers.\n * @returns {Map} this\n */\n remove: function() {\n if (this._hash) this._hash.remove();\n browser.cancelFrame(this._frameId);\n clearTimeout(this._sourcesDirtyTimeout);\n this.setStyle(null);\n return this;\n },\n\n _rerender: function() {\n if (this.style && !this._frameId) {\n this._frameId = browser.frame(this.render);\n }\n },\n\n _forwardStyleEvent: function(e) {\n this.fire('style.' + e.type, util.extend({style: e.target}, e));\n },\n\n _forwardSourceEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardLayerEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardTileEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _onStyleLoad: function(e) {\n this.style._cascade(this._classes, {transition: false});\n this._forwardStyleEvent(e);\n },\n\n _onStyleChange: function(e) {\n this.update(true);\n this._forwardStyleEvent(e);\n },\n\n _onSourceAdd: function(e) {\n var source = e.source;\n if (source.onAdd)\n source.onAdd(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceRemove: function(e) {\n var source = e.source;\n if (source.onRemove)\n source.onRemove(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceUpdate: function(e) {\n this.update();\n this._forwardSourceEvent(e);\n }\n}","path":"js/ui/map.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/map.js#L451-L454"},"params":[{"title":"param","description":"ID of the source to remove","type":{"type":"NameExpression","name":"string"},"name":"id"}],"returns":[{"title":"returns","description":"`this`","type":{"type":"NameExpression","name":"Map"}}],"name":"removeSource","memberof":"Map","scope":"instance","members":{"instance":[],"static":[]},"path":["Map","removeSource"]},{"description":"Return the style source object with the given `id`.","tags":[{"title":"param","description":"source ID","type":{"type":"NameExpression","name":"string"},"name":"id"},{"title":"returns","description":null,"type":{"type":"NameExpression","name":"Object"}},{"title":"name","name":"getSource"},{"title":"memberof","description":"Map"},{"title":"instance"}],"context":{"loc":{"start":{"line":462,"column":4},"end":{"line":464,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/map.js","code":"{\n\n options: {\n center: [0, 0],\n zoom: 0,\n bearing: 0,\n pitch: 0,\n\n minZoom: 0,\n maxZoom: 20,\n\n interactive: true,\n hash: false,\n\n attributionControl: true,\n\n failIfMajorPerformanceCaveat: false\n },\n\n addControl: function(control) {\n control.addTo(this);\n return this;\n },\n\n /**\n * Sets a map position\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @param {number} zoom Map zoom level\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setView: function(center, zoom, bearing, pitch) {\n this.stop();\n\n var tr = this.transform,\n zoomChanged = tr.zoom !== +zoom,\n bearingChanged = tr.bearing !== +bearing,\n pitchChanged = tr.pitch !== +pitch;\n\n tr.center = LatLng.convert(center);\n tr.zoom = +zoom;\n tr.bearing = +bearing;\n tr.pitch = +pitch;\n\n return this\n .fire('movestart')\n ._move(zoomChanged, bearingChanged, pitchChanged)\n .fire('moveend');\n },\n\n /**\n * Sets a map location\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setCenter: function(center) {\n this.setView(center, this.getZoom(), this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map zoom\n *\n * @param {number} zoom Map zoom level\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setZoom: function(zoom) {\n this.setView(this.getCenter(), zoom, this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map rotation\n *\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setBearing: function(bearing) {\n this.setView(this.getCenter(), this.getZoom(), bearing, this.getPitch());\n },\n\n /**\n * Sets a map angle\n *\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setPitch: function(pitch) {\n this.setView(this.getCenter(), this.getZoom(), this.getBearing(), pitch);\n },\n\n /**\n * Get the current view geographical point\n * @returns {LatLng}\n */\n getCenter: function() { return this.transform.center; },\n\n /**\n * Get the current zoom\n * @returns {number}\n */\n getZoom: function() { return this.transform.zoom; },\n\n /**\n * Get the current bearing in degrees\n * @returns {number}\n */\n getBearing: function() { return this.transform.bearing; },\n\n /**\n * Get the current angle in degrees\n * @returns {number}\n */\n getPitch: function() { return this.transform.pitch; },\n\n /**\n * @typedef {Object} [styleOptions]\n * @param {Boolean} [styleOptions.transition=true]\n */\n\n /**\n * Adds a style class to a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n addClass: function(klass, options) {\n if (this._classes[klass]) return;\n this._classes[klass] = true;\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Removes a style class from a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n removeClass: function(klass, options) {\n if (!this._classes[klass]) return;\n delete this._classes[klass];\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Helper method to add more than one class\n *\n * @param {Array} klasses An array of class names\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n setClasses: function(klasses, options) {\n this._classes = {};\n for (var i = 0; i < klasses.length; i++) {\n this._classes[klasses[i]] = true;\n }\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Check whether a style class is active\n *\n * @param {string} klass Name of style class\n * @returns {boolean}\n */\n hasClass: function(klass) {\n return !!this._classes[klass];\n },\n\n /**\n * Return an array of the current active style classes\n *\n * @returns {boolean}\n */\n getClasses: function() {\n return Object.keys(this._classes);\n },\n\n /**\n * Detect the map's new width and height and resize it.\n *\n * @returns {Map} `this`\n */\n resize: function() {\n var width = 0, height = 0;\n\n if (this._container) {\n width = this._container.offsetWidth || 400;\n height = this._container.offsetHeight || 300;\n }\n\n this._canvas.resize(width, height);\n\n this.transform.width = width;\n this.transform.height = height;\n this.transform._constrain();\n\n this.painter.resize(width, height);\n\n return this\n .fire('movestart')\n ._move()\n .fire('resize')\n .fire('moveend');\n },\n\n /**\n * Get the map's geographical bounds\n *\n * @returns {LatLngBounds}\n */\n getBounds: function() {\n return new LatLngBounds(\n this.transform.pointLocation(new Point(0, 0)),\n this.transform.pointLocation(this.transform.size));\n },\n\n /**\n * Get pixel coordinates (relative to map container) given a geographical location\n *\n * @param {LatLng} latlng\n * @returns {Object} `x` and `y` coordinates\n */\n project: function(latlng) {\n return this.transform.locationPoint(LatLng.convert(latlng));\n },\n\n /**\n * Get geographical coordinates given pixel coordinates\n *\n * @param {Array} point [x, y] pixel coordinates\n * @returns {LatLng}\n */\n unproject: function(point) {\n return this.transform.pointLocation(Point.convert(point));\n },\n\n /**\n * Get all features at a point ([x, y])\n *\n * @param {Array} point [x, y] pixel coordinates\n * @param {Object} params\n * @param {number} [params.radius=0] Optional. Radius in pixels to search in\n * @param {string} params.layer Optional. Only return features from a given layer\n * @param {string} params.type Optional. Either `raster` or `vector`\n * @param {featuresAtCallback} callback function that returns the response\n *\n * @callback featuresAtCallback\n * @param {Object|null} err Error _If any_\n * @param {Array} features Displays a JSON array of features given the passed parameters of `featuresAt`\n *\n * @returns {Map} `this`\n */\n featuresAt: function(point, params, callback) {\n var coord = this.transform.pointCoordinate(Point.convert(point));\n this.style.featuresAt(coord, params, callback);\n return this;\n },\n\n /**\n * Replaces the map's style object\n *\n * @param {Object} style A style object formatted as JSON\n * @returns {Map} `this`\n */\n setStyle: function(style) {\n if (this.style) {\n this.style\n .off('load', this._onStyleLoad)\n .off('error', this._forwardStyleEvent)\n .off('change', this._onStyleChange)\n .off('source.add', this._onSourceAdd)\n .off('source.remove', this._onSourceRemove)\n .off('source.load', this._onSourceUpdate)\n .off('source.error', this._forwardSourceEvent)\n .off('source.change', this._onSourceUpdate)\n .off('layer.add', this._forwardLayerEvent)\n .off('layer.remove', this._forwardLayerEvent)\n .off('tile.add', this._forwardTileEvent)\n .off('tile.remove', this._forwardTileEvent)\n .off('tile.load', this.update)\n .off('tile.error', this._forwardTileEvent)\n ._remove();\n\n this.off('rotate', this.style._redoPlacement);\n this.off('pitch', this.style._redoPlacement);\n }\n\n if (!style) {\n this.style = null;\n return this;\n } else if (style instanceof Style) {\n this.style = style;\n } else {\n this.style = new Style(style, this.animationLoop);\n }\n\n this.style\n .on('load', this._onStyleLoad)\n .on('error', this._forwardStyleEvent)\n .on('change', this._onStyleChange)\n .on('source.add', this._onSourceAdd)\n .on('source.remove', this._onSourceRemove)\n .on('source.load', this._onSourceUpdate)\n .on('source.error', this._forwardSourceEvent)\n .on('source.change', this._onSourceUpdate)\n .on('layer.add', this._forwardLayerEvent)\n .on('layer.remove', this._forwardLayerEvent)\n .on('tile.add', this._forwardTileEvent)\n .on('tile.remove', this._forwardTileEvent)\n .on('tile.load', this.update)\n .on('tile.error', this._forwardTileEvent);\n\n this.on('rotate', this.style._redoPlacement);\n this.on('pitch', this.style._redoPlacement);\n\n return this;\n },\n\n /**\n * Add a source to the map style.\n *\n * @param {string} id ID of the source. Must not be used by any existing source.\n * @param {Object} source source specification, following the\n * [Mapbox GL Style Reference](https://www.mapbox.com/mapbox-gl-style-spec/#sources)\n * @fires source.add\n * @returns {Map} `this`\n */\n addSource: function(id, source) {\n this.style.addSource(id, source);\n return this;\n },\n\n /**\n * Remove an existing source from the map style.\n *\n * @param {string} id ID of the source to remove\n * @fires source.remove\n * @returns {Map} `this`\n */\n removeSource: function(id) {\n this.style.removeSource(id);\n return this;\n },\n\n /**\n * Return the style source object with the given `id`.\n *\n * @param {string} id source ID\n * @returns {Object}\n */\n getSource: function(id) {\n return this.style.getSource(id);\n },\n\n /**\n * Add a layer to the map style. The layer will be inserted before the layer with\n * ID `before`, or appended if `before` is omitted.\n * @param {Layer} layer\n * @param {string=} before ID of an existing layer to insert before\n * @fires layer.add\n * @returns {Map} `this`\n */\n addLayer: function(layer, before) {\n this.style.addLayer(layer, before);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Remove the layer with the given `id` from the map. Any layers which refer to the\n * specified layer via a `ref` property are also removed.\n *\n * @param {string} id\n * @fires layer.remove\n * @returns {Map} this\n */\n removeLayer: function(id) {\n this.style.removeLayer(id);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Set the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {Array} filter filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n * @returns {Map} `this`\n */\n setFilter: function(layer, filter) {\n this.style.setFilter(layer, filter);\n return this;\n },\n\n /**\n * Get the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @returns {Array} filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n */\n getFilter: function(layer) {\n return this.style.getFilter(layer);\n },\n\n /**\n * Set the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {*} value value for the paint propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @param {string=} klass optional class specifier for the property\n * @returns {Map} `this`\n */\n setPaintProperty: function(layer, name, value, klass) {\n this.style.setPaintProperty(layer, name, value, klass);\n this.style._cascade(this._classes);\n this.update(true);\n return this;\n },\n\n /**\n * Get the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the paint propery\n */\n getPaintProperty: function(layer, name, klass) {\n return this.style.getPaintProperty(layer, name, klass);\n },\n\n /**\n * Set the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {*} value value for the layout propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @returns {Map} `this`\n */\n setLayoutProperty: function(layer, name, value) {\n this.style.setLayoutProperty(layer, name, value);\n return this;\n },\n\n /**\n * Get the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the layout propery\n */\n getLayoutProperty: function(layer, name) {\n return this.style.getLayoutProperty(layer, name);\n },\n\n /**\n * Get the Map's container as an HTML element\n * @returns {HTMLElement} container\n */\n getContainer: function() {\n return this._container;\n },\n\n /**\n * Get the Map's canvas as an HTML canvas\n * @returns {HTMLElement} canvas\n */\n getCanvas: function() {\n return this._canvas.getElement();\n },\n\n _move: function(zoom, rotate, pitch) {\n\n this.update(zoom).fire('move');\n\n if (zoom) this.fire('zoom');\n if (rotate) this.fire('rotate');\n if (pitch) this.fire('pitch');\n\n return this;\n },\n\n // map setup code\n _setupContainer: function() {\n var id = this.options.container;\n var container = this._container = typeof id === 'string' ? document.getElementById(id) : id;\n if (container) container.classList.add('mapboxgl-map');\n this._canvas = new Canvas(this, container);\n },\n\n _setupControlPos: function() {\n var corners = this._controlCorners = {};\n var prefix = 'mapboxgl-ctrl-';\n var container = this.getContainer();\n\n function createCorner(pos) {\n var className = prefix + pos;\n corners[pos] = DOM.create('div', className, container);\n }\n\n if (container && typeof document === 'object') {\n createCorner('top-left');\n createCorner('top-right');\n createCorner('bottom-left');\n createCorner('bottom-right');\n }\n },\n\n _setupPainter: function() {\n var gl = this._canvas.getWebGLContext(this.options.failIfMajorPerformanceCaveat);\n\n if (!gl) {\n console.error('Failed to initialize WebGL');\n return;\n }\n\n this.painter = new GLPainter(gl, this.transform);\n },\n\n _contextLost: function(event) {\n event.preventDefault();\n if (this._frameId) {\n browser.cancelFrame(this._frameId);\n }\n },\n\n _contextRestored: function() {\n this._setupPainter();\n this.resize();\n this.update();\n },\n\n /**\n * Is this map fully loaded? If the style isn't loaded\n * or it has a change to the sources or style that isn't\n * propagated to its style, return false.\n *\n * @returns {boolean} whether the map is loaded\n */\n loaded: function() {\n if (this._styleDirty || this._sourcesDirty)\n return false;\n if (this.style && !this.style.loaded())\n return false;\n return true;\n },\n\n /**\n * Update this map's style and re-render the map.\n *\n * @param {Object} updateStyle new style\n * @returns {Map} this\n */\n update: function(updateStyle) {\n if (!this.style) return this;\n\n this._styleDirty = this._styleDirty || updateStyle;\n this._sourcesDirty = true;\n\n this._rerender();\n\n return this;\n },\n\n /**\n * Call when a (re-)render of the map is required, e.g. when the\n * user panned or zoomed,f or new data is available.\n * @returns {Map} this\n */\n render: function() {\n if (this.style && this._styleDirty) {\n this._styleDirty = false;\n this.style._recalculate(this.transform.zoom);\n }\n\n if (this.style && this._sourcesDirty && !this._sourcesDirtyTimeout) {\n this._sourcesDirty = false;\n this._sourcesDirtyTimeout = setTimeout(function() {\n this._sourcesDirtyTimeout = null;\n }.bind(this), 50);\n this.style._updateSources(this.transform);\n }\n\n this.painter.render(this.style, {\n debug: this.debug,\n vertices: this.vertices,\n rotating: this.rotating,\n zooming: this.zooming\n });\n\n this.fire('render');\n\n if (this.loaded() && !this._loaded) {\n this._loaded = true;\n this.fire('load');\n }\n\n this._frameId = null;\n\n if (!this.animationLoop.stopped()) {\n this._styleDirty = true;\n }\n\n if (this._sourcesDirty || this._repaint || !this.animationLoop.stopped()) {\n this._rerender();\n }\n\n return this;\n },\n\n /**\n * Destroys the map's underlying resources, including web workers.\n * @returns {Map} this\n */\n remove: function() {\n if (this._hash) this._hash.remove();\n browser.cancelFrame(this._frameId);\n clearTimeout(this._sourcesDirtyTimeout);\n this.setStyle(null);\n return this;\n },\n\n _rerender: function() {\n if (this.style && !this._frameId) {\n this._frameId = browser.frame(this.render);\n }\n },\n\n _forwardStyleEvent: function(e) {\n this.fire('style.' + e.type, util.extend({style: e.target}, e));\n },\n\n _forwardSourceEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardLayerEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardTileEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _onStyleLoad: function(e) {\n this.style._cascade(this._classes, {transition: false});\n this._forwardStyleEvent(e);\n },\n\n _onStyleChange: function(e) {\n this.update(true);\n this._forwardStyleEvent(e);\n },\n\n _onSourceAdd: function(e) {\n var source = e.source;\n if (source.onAdd)\n source.onAdd(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceRemove: function(e) {\n var source = e.source;\n if (source.onRemove)\n source.onRemove(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceUpdate: function(e) {\n this.update();\n this._forwardSourceEvent(e);\n }\n}","path":"js/ui/map.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/map.js#L462-L464"},"params":[{"title":"param","description":"source ID","type":{"type":"NameExpression","name":"string"},"name":"id"}],"returns":[{"title":"returns","description":null,"type":{"type":"NameExpression","name":"Object"}}],"name":"getSource","memberof":"Map","scope":"instance","members":{"instance":[],"static":[]},"path":["Map","getSource"]},{"description":"Get pixel coordinates (relative to map container) given a geographical location","tags":[{"title":"param","description":null,"type":{"type":"NameExpression","name":"LatLng"},"name":"latlng"},{"title":"returns","description":"`x` and `y` coordinates","type":{"type":"NameExpression","name":"Object"}},{"title":"name","name":"project"},{"title":"memberof","description":"Map"},{"title":"instance"}],"context":{"loc":{"start":{"line":334,"column":4},"end":{"line":336,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/map.js","code":"{\n\n options: {\n center: [0, 0],\n zoom: 0,\n bearing: 0,\n pitch: 0,\n\n minZoom: 0,\n maxZoom: 20,\n\n interactive: true,\n hash: false,\n\n attributionControl: true,\n\n failIfMajorPerformanceCaveat: false\n },\n\n addControl: function(control) {\n control.addTo(this);\n return this;\n },\n\n /**\n * Sets a map position\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @param {number} zoom Map zoom level\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setView: function(center, zoom, bearing, pitch) {\n this.stop();\n\n var tr = this.transform,\n zoomChanged = tr.zoom !== +zoom,\n bearingChanged = tr.bearing !== +bearing,\n pitchChanged = tr.pitch !== +pitch;\n\n tr.center = LatLng.convert(center);\n tr.zoom = +zoom;\n tr.bearing = +bearing;\n tr.pitch = +pitch;\n\n return this\n .fire('movestart')\n ._move(zoomChanged, bearingChanged, pitchChanged)\n .fire('moveend');\n },\n\n /**\n * Sets a map location\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setCenter: function(center) {\n this.setView(center, this.getZoom(), this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map zoom\n *\n * @param {number} zoom Map zoom level\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setZoom: function(zoom) {\n this.setView(this.getCenter(), zoom, this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map rotation\n *\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setBearing: function(bearing) {\n this.setView(this.getCenter(), this.getZoom(), bearing, this.getPitch());\n },\n\n /**\n * Sets a map angle\n *\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setPitch: function(pitch) {\n this.setView(this.getCenter(), this.getZoom(), this.getBearing(), pitch);\n },\n\n /**\n * Get the current view geographical point\n * @returns {LatLng}\n */\n getCenter: function() { return this.transform.center; },\n\n /**\n * Get the current zoom\n * @returns {number}\n */\n getZoom: function() { return this.transform.zoom; },\n\n /**\n * Get the current bearing in degrees\n * @returns {number}\n */\n getBearing: function() { return this.transform.bearing; },\n\n /**\n * Get the current angle in degrees\n * @returns {number}\n */\n getPitch: function() { return this.transform.pitch; },\n\n /**\n * @typedef {Object} [styleOptions]\n * @param {Boolean} [styleOptions.transition=true]\n */\n\n /**\n * Adds a style class to a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n addClass: function(klass, options) {\n if (this._classes[klass]) return;\n this._classes[klass] = true;\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Removes a style class from a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n removeClass: function(klass, options) {\n if (!this._classes[klass]) return;\n delete this._classes[klass];\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Helper method to add more than one class\n *\n * @param {Array} klasses An array of class names\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n setClasses: function(klasses, options) {\n this._classes = {};\n for (var i = 0; i < klasses.length; i++) {\n this._classes[klasses[i]] = true;\n }\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Check whether a style class is active\n *\n * @param {string} klass Name of style class\n * @returns {boolean}\n */\n hasClass: function(klass) {\n return !!this._classes[klass];\n },\n\n /**\n * Return an array of the current active style classes\n *\n * @returns {boolean}\n */\n getClasses: function() {\n return Object.keys(this._classes);\n },\n\n /**\n * Detect the map's new width and height and resize it.\n *\n * @returns {Map} `this`\n */\n resize: function() {\n var width = 0, height = 0;\n\n if (this._container) {\n width = this._container.offsetWidth || 400;\n height = this._container.offsetHeight || 300;\n }\n\n this._canvas.resize(width, height);\n\n this.transform.width = width;\n this.transform.height = height;\n this.transform._constrain();\n\n this.painter.resize(width, height);\n\n return this\n .fire('movestart')\n ._move()\n .fire('resize')\n .fire('moveend');\n },\n\n /**\n * Get the map's geographical bounds\n *\n * @returns {LatLngBounds}\n */\n getBounds: function() {\n return new LatLngBounds(\n this.transform.pointLocation(new Point(0, 0)),\n this.transform.pointLocation(this.transform.size));\n },\n\n /**\n * Get pixel coordinates (relative to map container) given a geographical location\n *\n * @param {LatLng} latlng\n * @returns {Object} `x` and `y` coordinates\n */\n project: function(latlng) {\n return this.transform.locationPoint(LatLng.convert(latlng));\n },\n\n /**\n * Get geographical coordinates given pixel coordinates\n *\n * @param {Array} point [x, y] pixel coordinates\n * @returns {LatLng}\n */\n unproject: function(point) {\n return this.transform.pointLocation(Point.convert(point));\n },\n\n /**\n * Get all features at a point ([x, y])\n *\n * @param {Array} point [x, y] pixel coordinates\n * @param {Object} params\n * @param {number} [params.radius=0] Optional. Radius in pixels to search in\n * @param {string} params.layer Optional. Only return features from a given layer\n * @param {string} params.type Optional. Either `raster` or `vector`\n * @param {featuresAtCallback} callback function that returns the response\n *\n * @callback featuresAtCallback\n * @param {Object|null} err Error _If any_\n * @param {Array} features Displays a JSON array of features given the passed parameters of `featuresAt`\n *\n * @returns {Map} `this`\n */\n featuresAt: function(point, params, callback) {\n var coord = this.transform.pointCoordinate(Point.convert(point));\n this.style.featuresAt(coord, params, callback);\n return this;\n },\n\n /**\n * Replaces the map's style object\n *\n * @param {Object} style A style object formatted as JSON\n * @returns {Map} `this`\n */\n setStyle: function(style) {\n if (this.style) {\n this.style\n .off('load', this._onStyleLoad)\n .off('error', this._forwardStyleEvent)\n .off('change', this._onStyleChange)\n .off('source.add', this._onSourceAdd)\n .off('source.remove', this._onSourceRemove)\n .off('source.load', this._onSourceUpdate)\n .off('source.error', this._forwardSourceEvent)\n .off('source.change', this._onSourceUpdate)\n .off('layer.add', this._forwardLayerEvent)\n .off('layer.remove', this._forwardLayerEvent)\n .off('tile.add', this._forwardTileEvent)\n .off('tile.remove', this._forwardTileEvent)\n .off('tile.load', this.update)\n .off('tile.error', this._forwardTileEvent)\n ._remove();\n\n this.off('rotate', this.style._redoPlacement);\n this.off('pitch', this.style._redoPlacement);\n }\n\n if (!style) {\n this.style = null;\n return this;\n } else if (style instanceof Style) {\n this.style = style;\n } else {\n this.style = new Style(style, this.animationLoop);\n }\n\n this.style\n .on('load', this._onStyleLoad)\n .on('error', this._forwardStyleEvent)\n .on('change', this._onStyleChange)\n .on('source.add', this._onSourceAdd)\n .on('source.remove', this._onSourceRemove)\n .on('source.load', this._onSourceUpdate)\n .on('source.error', this._forwardSourceEvent)\n .on('source.change', this._onSourceUpdate)\n .on('layer.add', this._forwardLayerEvent)\n .on('layer.remove', this._forwardLayerEvent)\n .on('tile.add', this._forwardTileEvent)\n .on('tile.remove', this._forwardTileEvent)\n .on('tile.load', this.update)\n .on('tile.error', this._forwardTileEvent);\n\n this.on('rotate', this.style._redoPlacement);\n this.on('pitch', this.style._redoPlacement);\n\n return this;\n },\n\n /**\n * Add a source to the map style.\n *\n * @param {string} id ID of the source. Must not be used by any existing source.\n * @param {Object} source source specification, following the\n * [Mapbox GL Style Reference](https://www.mapbox.com/mapbox-gl-style-spec/#sources)\n * @fires source.add\n * @returns {Map} `this`\n */\n addSource: function(id, source) {\n this.style.addSource(id, source);\n return this;\n },\n\n /**\n * Remove an existing source from the map style.\n *\n * @param {string} id ID of the source to remove\n * @fires source.remove\n * @returns {Map} `this`\n */\n removeSource: function(id) {\n this.style.removeSource(id);\n return this;\n },\n\n /**\n * Return the style source object with the given `id`.\n *\n * @param {string} id source ID\n * @returns {Object}\n */\n getSource: function(id) {\n return this.style.getSource(id);\n },\n\n /**\n * Add a layer to the map style. The layer will be inserted before the layer with\n * ID `before`, or appended if `before` is omitted.\n * @param {Layer} layer\n * @param {string=} before ID of an existing layer to insert before\n * @fires layer.add\n * @returns {Map} `this`\n */\n addLayer: function(layer, before) {\n this.style.addLayer(layer, before);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Remove the layer with the given `id` from the map. Any layers which refer to the\n * specified layer via a `ref` property are also removed.\n *\n * @param {string} id\n * @fires layer.remove\n * @returns {Map} this\n */\n removeLayer: function(id) {\n this.style.removeLayer(id);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Set the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {Array} filter filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n * @returns {Map} `this`\n */\n setFilter: function(layer, filter) {\n this.style.setFilter(layer, filter);\n return this;\n },\n\n /**\n * Get the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @returns {Array} filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n */\n getFilter: function(layer) {\n return this.style.getFilter(layer);\n },\n\n /**\n * Set the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {*} value value for the paint propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @param {string=} klass optional class specifier for the property\n * @returns {Map} `this`\n */\n setPaintProperty: function(layer, name, value, klass) {\n this.style.setPaintProperty(layer, name, value, klass);\n this.style._cascade(this._classes);\n this.update(true);\n return this;\n },\n\n /**\n * Get the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the paint propery\n */\n getPaintProperty: function(layer, name, klass) {\n return this.style.getPaintProperty(layer, name, klass);\n },\n\n /**\n * Set the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {*} value value for the layout propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @returns {Map} `this`\n */\n setLayoutProperty: function(layer, name, value) {\n this.style.setLayoutProperty(layer, name, value);\n return this;\n },\n\n /**\n * Get the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the layout propery\n */\n getLayoutProperty: function(layer, name) {\n return this.style.getLayoutProperty(layer, name);\n },\n\n /**\n * Get the Map's container as an HTML element\n * @returns {HTMLElement} container\n */\n getContainer: function() {\n return this._container;\n },\n\n /**\n * Get the Map's canvas as an HTML canvas\n * @returns {HTMLElement} canvas\n */\n getCanvas: function() {\n return this._canvas.getElement();\n },\n\n _move: function(zoom, rotate, pitch) {\n\n this.update(zoom).fire('move');\n\n if (zoom) this.fire('zoom');\n if (rotate) this.fire('rotate');\n if (pitch) this.fire('pitch');\n\n return this;\n },\n\n // map setup code\n _setupContainer: function() {\n var id = this.options.container;\n var container = this._container = typeof id === 'string' ? document.getElementById(id) : id;\n if (container) container.classList.add('mapboxgl-map');\n this._canvas = new Canvas(this, container);\n },\n\n _setupControlPos: function() {\n var corners = this._controlCorners = {};\n var prefix = 'mapboxgl-ctrl-';\n var container = this.getContainer();\n\n function createCorner(pos) {\n var className = prefix + pos;\n corners[pos] = DOM.create('div', className, container);\n }\n\n if (container && typeof document === 'object') {\n createCorner('top-left');\n createCorner('top-right');\n createCorner('bottom-left');\n createCorner('bottom-right');\n }\n },\n\n _setupPainter: function() {\n var gl = this._canvas.getWebGLContext(this.options.failIfMajorPerformanceCaveat);\n\n if (!gl) {\n console.error('Failed to initialize WebGL');\n return;\n }\n\n this.painter = new GLPainter(gl, this.transform);\n },\n\n _contextLost: function(event) {\n event.preventDefault();\n if (this._frameId) {\n browser.cancelFrame(this._frameId);\n }\n },\n\n _contextRestored: function() {\n this._setupPainter();\n this.resize();\n this.update();\n },\n\n /**\n * Is this map fully loaded? If the style isn't loaded\n * or it has a change to the sources or style that isn't\n * propagated to its style, return false.\n *\n * @returns {boolean} whether the map is loaded\n */\n loaded: function() {\n if (this._styleDirty || this._sourcesDirty)\n return false;\n if (this.style && !this.style.loaded())\n return false;\n return true;\n },\n\n /**\n * Update this map's style and re-render the map.\n *\n * @param {Object} updateStyle new style\n * @returns {Map} this\n */\n update: function(updateStyle) {\n if (!this.style) return this;\n\n this._styleDirty = this._styleDirty || updateStyle;\n this._sourcesDirty = true;\n\n this._rerender();\n\n return this;\n },\n\n /**\n * Call when a (re-)render of the map is required, e.g. when the\n * user panned or zoomed,f or new data is available.\n * @returns {Map} this\n */\n render: function() {\n if (this.style && this._styleDirty) {\n this._styleDirty = false;\n this.style._recalculate(this.transform.zoom);\n }\n\n if (this.style && this._sourcesDirty && !this._sourcesDirtyTimeout) {\n this._sourcesDirty = false;\n this._sourcesDirtyTimeout = setTimeout(function() {\n this._sourcesDirtyTimeout = null;\n }.bind(this), 50);\n this.style._updateSources(this.transform);\n }\n\n this.painter.render(this.style, {\n debug: this.debug,\n vertices: this.vertices,\n rotating: this.rotating,\n zooming: this.zooming\n });\n\n this.fire('render');\n\n if (this.loaded() && !this._loaded) {\n this._loaded = true;\n this.fire('load');\n }\n\n this._frameId = null;\n\n if (!this.animationLoop.stopped()) {\n this._styleDirty = true;\n }\n\n if (this._sourcesDirty || this._repaint || !this.animationLoop.stopped()) {\n this._rerender();\n }\n\n return this;\n },\n\n /**\n * Destroys the map's underlying resources, including web workers.\n * @returns {Map} this\n */\n remove: function() {\n if (this._hash) this._hash.remove();\n browser.cancelFrame(this._frameId);\n clearTimeout(this._sourcesDirtyTimeout);\n this.setStyle(null);\n return this;\n },\n\n _rerender: function() {\n if (this.style && !this._frameId) {\n this._frameId = browser.frame(this.render);\n }\n },\n\n _forwardStyleEvent: function(e) {\n this.fire('style.' + e.type, util.extend({style: e.target}, e));\n },\n\n _forwardSourceEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardLayerEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardTileEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _onStyleLoad: function(e) {\n this.style._cascade(this._classes, {transition: false});\n this._forwardStyleEvent(e);\n },\n\n _onStyleChange: function(e) {\n this.update(true);\n this._forwardStyleEvent(e);\n },\n\n _onSourceAdd: function(e) {\n var source = e.source;\n if (source.onAdd)\n source.onAdd(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceRemove: function(e) {\n var source = e.source;\n if (source.onRemove)\n source.onRemove(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceUpdate: function(e) {\n this.update();\n this._forwardSourceEvent(e);\n }\n}","path":"js/ui/map.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/map.js#L334-L336"},"params":[{"title":"param","description":null,"type":{"type":"NameExpression","name":"LatLng"},"name":"latlng"}],"returns":[{"title":"returns","description":"`x` and `y` coordinates","type":{"type":"NameExpression","name":"Object"}}],"name":"project","memberof":"Map","scope":"instance","members":{"instance":[],"static":[]},"path":["Map","project"]},{"description":"Check whether a style class is active","tags":[{"title":"param","description":"Name of style class","type":{"type":"NameExpression","name":"string"},"name":"klass"},{"title":"returns","description":null,"type":{"type":"NameExpression","name":"boolean"}},{"title":"name","name":"hasClass"},{"title":"memberof","description":"Map"},{"title":"instance"}],"context":{"loc":{"start":{"line":276,"column":4},"end":{"line":278,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/map.js","code":"{\n\n options: {\n center: [0, 0],\n zoom: 0,\n bearing: 0,\n pitch: 0,\n\n minZoom: 0,\n maxZoom: 20,\n\n interactive: true,\n hash: false,\n\n attributionControl: true,\n\n failIfMajorPerformanceCaveat: false\n },\n\n addControl: function(control) {\n control.addTo(this);\n return this;\n },\n\n /**\n * Sets a map position\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @param {number} zoom Map zoom level\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setView: function(center, zoom, bearing, pitch) {\n this.stop();\n\n var tr = this.transform,\n zoomChanged = tr.zoom !== +zoom,\n bearingChanged = tr.bearing !== +bearing,\n pitchChanged = tr.pitch !== +pitch;\n\n tr.center = LatLng.convert(center);\n tr.zoom = +zoom;\n tr.bearing = +bearing;\n tr.pitch = +pitch;\n\n return this\n .fire('movestart')\n ._move(zoomChanged, bearingChanged, pitchChanged)\n .fire('moveend');\n },\n\n /**\n * Sets a map location\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setCenter: function(center) {\n this.setView(center, this.getZoom(), this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map zoom\n *\n * @param {number} zoom Map zoom level\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setZoom: function(zoom) {\n this.setView(this.getCenter(), zoom, this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map rotation\n *\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setBearing: function(bearing) {\n this.setView(this.getCenter(), this.getZoom(), bearing, this.getPitch());\n },\n\n /**\n * Sets a map angle\n *\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setPitch: function(pitch) {\n this.setView(this.getCenter(), this.getZoom(), this.getBearing(), pitch);\n },\n\n /**\n * Get the current view geographical point\n * @returns {LatLng}\n */\n getCenter: function() { return this.transform.center; },\n\n /**\n * Get the current zoom\n * @returns {number}\n */\n getZoom: function() { return this.transform.zoom; },\n\n /**\n * Get the current bearing in degrees\n * @returns {number}\n */\n getBearing: function() { return this.transform.bearing; },\n\n /**\n * Get the current angle in degrees\n * @returns {number}\n */\n getPitch: function() { return this.transform.pitch; },\n\n /**\n * @typedef {Object} [styleOptions]\n * @param {Boolean} [styleOptions.transition=true]\n */\n\n /**\n * Adds a style class to a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n addClass: function(klass, options) {\n if (this._classes[klass]) return;\n this._classes[klass] = true;\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Removes a style class from a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n removeClass: function(klass, options) {\n if (!this._classes[klass]) return;\n delete this._classes[klass];\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Helper method to add more than one class\n *\n * @param {Array} klasses An array of class names\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n setClasses: function(klasses, options) {\n this._classes = {};\n for (var i = 0; i < klasses.length; i++) {\n this._classes[klasses[i]] = true;\n }\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Check whether a style class is active\n *\n * @param {string} klass Name of style class\n * @returns {boolean}\n */\n hasClass: function(klass) {\n return !!this._classes[klass];\n },\n\n /**\n * Return an array of the current active style classes\n *\n * @returns {boolean}\n */\n getClasses: function() {\n return Object.keys(this._classes);\n },\n\n /**\n * Detect the map's new width and height and resize it.\n *\n * @returns {Map} `this`\n */\n resize: function() {\n var width = 0, height = 0;\n\n if (this._container) {\n width = this._container.offsetWidth || 400;\n height = this._container.offsetHeight || 300;\n }\n\n this._canvas.resize(width, height);\n\n this.transform.width = width;\n this.transform.height = height;\n this.transform._constrain();\n\n this.painter.resize(width, height);\n\n return this\n .fire('movestart')\n ._move()\n .fire('resize')\n .fire('moveend');\n },\n\n /**\n * Get the map's geographical bounds\n *\n * @returns {LatLngBounds}\n */\n getBounds: function() {\n return new LatLngBounds(\n this.transform.pointLocation(new Point(0, 0)),\n this.transform.pointLocation(this.transform.size));\n },\n\n /**\n * Get pixel coordinates (relative to map container) given a geographical location\n *\n * @param {LatLng} latlng\n * @returns {Object} `x` and `y` coordinates\n */\n project: function(latlng) {\n return this.transform.locationPoint(LatLng.convert(latlng));\n },\n\n /**\n * Get geographical coordinates given pixel coordinates\n *\n * @param {Array} point [x, y] pixel coordinates\n * @returns {LatLng}\n */\n unproject: function(point) {\n return this.transform.pointLocation(Point.convert(point));\n },\n\n /**\n * Get all features at a point ([x, y])\n *\n * @param {Array} point [x, y] pixel coordinates\n * @param {Object} params\n * @param {number} [params.radius=0] Optional. Radius in pixels to search in\n * @param {string} params.layer Optional. Only return features from a given layer\n * @param {string} params.type Optional. Either `raster` or `vector`\n * @param {featuresAtCallback} callback function that returns the response\n *\n * @callback featuresAtCallback\n * @param {Object|null} err Error _If any_\n * @param {Array} features Displays a JSON array of features given the passed parameters of `featuresAt`\n *\n * @returns {Map} `this`\n */\n featuresAt: function(point, params, callback) {\n var coord = this.transform.pointCoordinate(Point.convert(point));\n this.style.featuresAt(coord, params, callback);\n return this;\n },\n\n /**\n * Replaces the map's style object\n *\n * @param {Object} style A style object formatted as JSON\n * @returns {Map} `this`\n */\n setStyle: function(style) {\n if (this.style) {\n this.style\n .off('load', this._onStyleLoad)\n .off('error', this._forwardStyleEvent)\n .off('change', this._onStyleChange)\n .off('source.add', this._onSourceAdd)\n .off('source.remove', this._onSourceRemove)\n .off('source.load', this._onSourceUpdate)\n .off('source.error', this._forwardSourceEvent)\n .off('source.change', this._onSourceUpdate)\n .off('layer.add', this._forwardLayerEvent)\n .off('layer.remove', this._forwardLayerEvent)\n .off('tile.add', this._forwardTileEvent)\n .off('tile.remove', this._forwardTileEvent)\n .off('tile.load', this.update)\n .off('tile.error', this._forwardTileEvent)\n ._remove();\n\n this.off('rotate', this.style._redoPlacement);\n this.off('pitch', this.style._redoPlacement);\n }\n\n if (!style) {\n this.style = null;\n return this;\n } else if (style instanceof Style) {\n this.style = style;\n } else {\n this.style = new Style(style, this.animationLoop);\n }\n\n this.style\n .on('load', this._onStyleLoad)\n .on('error', this._forwardStyleEvent)\n .on('change', this._onStyleChange)\n .on('source.add', this._onSourceAdd)\n .on('source.remove', this._onSourceRemove)\n .on('source.load', this._onSourceUpdate)\n .on('source.error', this._forwardSourceEvent)\n .on('source.change', this._onSourceUpdate)\n .on('layer.add', this._forwardLayerEvent)\n .on('layer.remove', this._forwardLayerEvent)\n .on('tile.add', this._forwardTileEvent)\n .on('tile.remove', this._forwardTileEvent)\n .on('tile.load', this.update)\n .on('tile.error', this._forwardTileEvent);\n\n this.on('rotate', this.style._redoPlacement);\n this.on('pitch', this.style._redoPlacement);\n\n return this;\n },\n\n /**\n * Add a source to the map style.\n *\n * @param {string} id ID of the source. Must not be used by any existing source.\n * @param {Object} source source specification, following the\n * [Mapbox GL Style Reference](https://www.mapbox.com/mapbox-gl-style-spec/#sources)\n * @fires source.add\n * @returns {Map} `this`\n */\n addSource: function(id, source) {\n this.style.addSource(id, source);\n return this;\n },\n\n /**\n * Remove an existing source from the map style.\n *\n * @param {string} id ID of the source to remove\n * @fires source.remove\n * @returns {Map} `this`\n */\n removeSource: function(id) {\n this.style.removeSource(id);\n return this;\n },\n\n /**\n * Return the style source object with the given `id`.\n *\n * @param {string} id source ID\n * @returns {Object}\n */\n getSource: function(id) {\n return this.style.getSource(id);\n },\n\n /**\n * Add a layer to the map style. The layer will be inserted before the layer with\n * ID `before`, or appended if `before` is omitted.\n * @param {Layer} layer\n * @param {string=} before ID of an existing layer to insert before\n * @fires layer.add\n * @returns {Map} `this`\n */\n addLayer: function(layer, before) {\n this.style.addLayer(layer, before);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Remove the layer with the given `id` from the map. Any layers which refer to the\n * specified layer via a `ref` property are also removed.\n *\n * @param {string} id\n * @fires layer.remove\n * @returns {Map} this\n */\n removeLayer: function(id) {\n this.style.removeLayer(id);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Set the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {Array} filter filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n * @returns {Map} `this`\n */\n setFilter: function(layer, filter) {\n this.style.setFilter(layer, filter);\n return this;\n },\n\n /**\n * Get the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @returns {Array} filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n */\n getFilter: function(layer) {\n return this.style.getFilter(layer);\n },\n\n /**\n * Set the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {*} value value for the paint propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @param {string=} klass optional class specifier for the property\n * @returns {Map} `this`\n */\n setPaintProperty: function(layer, name, value, klass) {\n this.style.setPaintProperty(layer, name, value, klass);\n this.style._cascade(this._classes);\n this.update(true);\n return this;\n },\n\n /**\n * Get the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the paint propery\n */\n getPaintProperty: function(layer, name, klass) {\n return this.style.getPaintProperty(layer, name, klass);\n },\n\n /**\n * Set the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {*} value value for the layout propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @returns {Map} `this`\n */\n setLayoutProperty: function(layer, name, value) {\n this.style.setLayoutProperty(layer, name, value);\n return this;\n },\n\n /**\n * Get the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the layout propery\n */\n getLayoutProperty: function(layer, name) {\n return this.style.getLayoutProperty(layer, name);\n },\n\n /**\n * Get the Map's container as an HTML element\n * @returns {HTMLElement} container\n */\n getContainer: function() {\n return this._container;\n },\n\n /**\n * Get the Map's canvas as an HTML canvas\n * @returns {HTMLElement} canvas\n */\n getCanvas: function() {\n return this._canvas.getElement();\n },\n\n _move: function(zoom, rotate, pitch) {\n\n this.update(zoom).fire('move');\n\n if (zoom) this.fire('zoom');\n if (rotate) this.fire('rotate');\n if (pitch) this.fire('pitch');\n\n return this;\n },\n\n // map setup code\n _setupContainer: function() {\n var id = this.options.container;\n var container = this._container = typeof id === 'string' ? document.getElementById(id) : id;\n if (container) container.classList.add('mapboxgl-map');\n this._canvas = new Canvas(this, container);\n },\n\n _setupControlPos: function() {\n var corners = this._controlCorners = {};\n var prefix = 'mapboxgl-ctrl-';\n var container = this.getContainer();\n\n function createCorner(pos) {\n var className = prefix + pos;\n corners[pos] = DOM.create('div', className, container);\n }\n\n if (container && typeof document === 'object') {\n createCorner('top-left');\n createCorner('top-right');\n createCorner('bottom-left');\n createCorner('bottom-right');\n }\n },\n\n _setupPainter: function() {\n var gl = this._canvas.getWebGLContext(this.options.failIfMajorPerformanceCaveat);\n\n if (!gl) {\n console.error('Failed to initialize WebGL');\n return;\n }\n\n this.painter = new GLPainter(gl, this.transform);\n },\n\n _contextLost: function(event) {\n event.preventDefault();\n if (this._frameId) {\n browser.cancelFrame(this._frameId);\n }\n },\n\n _contextRestored: function() {\n this._setupPainter();\n this.resize();\n this.update();\n },\n\n /**\n * Is this map fully loaded? If the style isn't loaded\n * or it has a change to the sources or style that isn't\n * propagated to its style, return false.\n *\n * @returns {boolean} whether the map is loaded\n */\n loaded: function() {\n if (this._styleDirty || this._sourcesDirty)\n return false;\n if (this.style && !this.style.loaded())\n return false;\n return true;\n },\n\n /**\n * Update this map's style and re-render the map.\n *\n * @param {Object} updateStyle new style\n * @returns {Map} this\n */\n update: function(updateStyle) {\n if (!this.style) return this;\n\n this._styleDirty = this._styleDirty || updateStyle;\n this._sourcesDirty = true;\n\n this._rerender();\n\n return this;\n },\n\n /**\n * Call when a (re-)render of the map is required, e.g. when the\n * user panned or zoomed,f or new data is available.\n * @returns {Map} this\n */\n render: function() {\n if (this.style && this._styleDirty) {\n this._styleDirty = false;\n this.style._recalculate(this.transform.zoom);\n }\n\n if (this.style && this._sourcesDirty && !this._sourcesDirtyTimeout) {\n this._sourcesDirty = false;\n this._sourcesDirtyTimeout = setTimeout(function() {\n this._sourcesDirtyTimeout = null;\n }.bind(this), 50);\n this.style._updateSources(this.transform);\n }\n\n this.painter.render(this.style, {\n debug: this.debug,\n vertices: this.vertices,\n rotating: this.rotating,\n zooming: this.zooming\n });\n\n this.fire('render');\n\n if (this.loaded() && !this._loaded) {\n this._loaded = true;\n this.fire('load');\n }\n\n this._frameId = null;\n\n if (!this.animationLoop.stopped()) {\n this._styleDirty = true;\n }\n\n if (this._sourcesDirty || this._repaint || !this.animationLoop.stopped()) {\n this._rerender();\n }\n\n return this;\n },\n\n /**\n * Destroys the map's underlying resources, including web workers.\n * @returns {Map} this\n */\n remove: function() {\n if (this._hash) this._hash.remove();\n browser.cancelFrame(this._frameId);\n clearTimeout(this._sourcesDirtyTimeout);\n this.setStyle(null);\n return this;\n },\n\n _rerender: function() {\n if (this.style && !this._frameId) {\n this._frameId = browser.frame(this.render);\n }\n },\n\n _forwardStyleEvent: function(e) {\n this.fire('style.' + e.type, util.extend({style: e.target}, e));\n },\n\n _forwardSourceEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardLayerEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardTileEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _onStyleLoad: function(e) {\n this.style._cascade(this._classes, {transition: false});\n this._forwardStyleEvent(e);\n },\n\n _onStyleChange: function(e) {\n this.update(true);\n this._forwardStyleEvent(e);\n },\n\n _onSourceAdd: function(e) {\n var source = e.source;\n if (source.onAdd)\n source.onAdd(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceRemove: function(e) {\n var source = e.source;\n if (source.onRemove)\n source.onRemove(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceUpdate: function(e) {\n this.update();\n this._forwardSourceEvent(e);\n }\n}","path":"js/ui/map.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/map.js#L276-L278"},"params":[{"title":"param","description":"Name of style class","type":{"type":"NameExpression","name":"string"},"name":"klass"}],"returns":[{"title":"returns","description":null,"type":{"type":"NameExpression","name":"boolean"}}],"name":"hasClass","memberof":"Map","scope":"instance","members":{"instance":[],"static":[]},"path":["Map","hasClass"]},{"description":"Remove the layer with the given `id` from the map. Any layers which refer to the\nspecified layer via a `ref` property are also removed.","tags":[{"title":"param","description":null,"type":{"type":"NameExpression","name":"string"},"name":"id"},{"title":"fires","description":"layer.remove"},{"title":"returns","description":"this","type":{"type":"NameExpression","name":"Map"}},{"title":"name","name":"removeLayer"},{"title":"memberof","description":"Map"},{"title":"instance"}],"context":{"loc":{"start":{"line":488,"column":4},"end":{"line":492,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/map.js","code":"{\n\n options: {\n center: [0, 0],\n zoom: 0,\n bearing: 0,\n pitch: 0,\n\n minZoom: 0,\n maxZoom: 20,\n\n interactive: true,\n hash: false,\n\n attributionControl: true,\n\n failIfMajorPerformanceCaveat: false\n },\n\n addControl: function(control) {\n control.addTo(this);\n return this;\n },\n\n /**\n * Sets a map position\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @param {number} zoom Map zoom level\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setView: function(center, zoom, bearing, pitch) {\n this.stop();\n\n var tr = this.transform,\n zoomChanged = tr.zoom !== +zoom,\n bearingChanged = tr.bearing !== +bearing,\n pitchChanged = tr.pitch !== +pitch;\n\n tr.center = LatLng.convert(center);\n tr.zoom = +zoom;\n tr.bearing = +bearing;\n tr.pitch = +pitch;\n\n return this\n .fire('movestart')\n ._move(zoomChanged, bearingChanged, pitchChanged)\n .fire('moveend');\n },\n\n /**\n * Sets a map location\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setCenter: function(center) {\n this.setView(center, this.getZoom(), this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map zoom\n *\n * @param {number} zoom Map zoom level\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setZoom: function(zoom) {\n this.setView(this.getCenter(), zoom, this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map rotation\n *\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setBearing: function(bearing) {\n this.setView(this.getCenter(), this.getZoom(), bearing, this.getPitch());\n },\n\n /**\n * Sets a map angle\n *\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setPitch: function(pitch) {\n this.setView(this.getCenter(), this.getZoom(), this.getBearing(), pitch);\n },\n\n /**\n * Get the current view geographical point\n * @returns {LatLng}\n */\n getCenter: function() { return this.transform.center; },\n\n /**\n * Get the current zoom\n * @returns {number}\n */\n getZoom: function() { return this.transform.zoom; },\n\n /**\n * Get the current bearing in degrees\n * @returns {number}\n */\n getBearing: function() { return this.transform.bearing; },\n\n /**\n * Get the current angle in degrees\n * @returns {number}\n */\n getPitch: function() { return this.transform.pitch; },\n\n /**\n * @typedef {Object} [styleOptions]\n * @param {Boolean} [styleOptions.transition=true]\n */\n\n /**\n * Adds a style class to a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n addClass: function(klass, options) {\n if (this._classes[klass]) return;\n this._classes[klass] = true;\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Removes a style class from a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n removeClass: function(klass, options) {\n if (!this._classes[klass]) return;\n delete this._classes[klass];\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Helper method to add more than one class\n *\n * @param {Array} klasses An array of class names\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n setClasses: function(klasses, options) {\n this._classes = {};\n for (var i = 0; i < klasses.length; i++) {\n this._classes[klasses[i]] = true;\n }\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Check whether a style class is active\n *\n * @param {string} klass Name of style class\n * @returns {boolean}\n */\n hasClass: function(klass) {\n return !!this._classes[klass];\n },\n\n /**\n * Return an array of the current active style classes\n *\n * @returns {boolean}\n */\n getClasses: function() {\n return Object.keys(this._classes);\n },\n\n /**\n * Detect the map's new width and height and resize it.\n *\n * @returns {Map} `this`\n */\n resize: function() {\n var width = 0, height = 0;\n\n if (this._container) {\n width = this._container.offsetWidth || 400;\n height = this._container.offsetHeight || 300;\n }\n\n this._canvas.resize(width, height);\n\n this.transform.width = width;\n this.transform.height = height;\n this.transform._constrain();\n\n this.painter.resize(width, height);\n\n return this\n .fire('movestart')\n ._move()\n .fire('resize')\n .fire('moveend');\n },\n\n /**\n * Get the map's geographical bounds\n *\n * @returns {LatLngBounds}\n */\n getBounds: function() {\n return new LatLngBounds(\n this.transform.pointLocation(new Point(0, 0)),\n this.transform.pointLocation(this.transform.size));\n },\n\n /**\n * Get pixel coordinates (relative to map container) given a geographical location\n *\n * @param {LatLng} latlng\n * @returns {Object} `x` and `y` coordinates\n */\n project: function(latlng) {\n return this.transform.locationPoint(LatLng.convert(latlng));\n },\n\n /**\n * Get geographical coordinates given pixel coordinates\n *\n * @param {Array} point [x, y] pixel coordinates\n * @returns {LatLng}\n */\n unproject: function(point) {\n return this.transform.pointLocation(Point.convert(point));\n },\n\n /**\n * Get all features at a point ([x, y])\n *\n * @param {Array} point [x, y] pixel coordinates\n * @param {Object} params\n * @param {number} [params.radius=0] Optional. Radius in pixels to search in\n * @param {string} params.layer Optional. Only return features from a given layer\n * @param {string} params.type Optional. Either `raster` or `vector`\n * @param {featuresAtCallback} callback function that returns the response\n *\n * @callback featuresAtCallback\n * @param {Object|null} err Error _If any_\n * @param {Array} features Displays a JSON array of features given the passed parameters of `featuresAt`\n *\n * @returns {Map} `this`\n */\n featuresAt: function(point, params, callback) {\n var coord = this.transform.pointCoordinate(Point.convert(point));\n this.style.featuresAt(coord, params, callback);\n return this;\n },\n\n /**\n * Replaces the map's style object\n *\n * @param {Object} style A style object formatted as JSON\n * @returns {Map} `this`\n */\n setStyle: function(style) {\n if (this.style) {\n this.style\n .off('load', this._onStyleLoad)\n .off('error', this._forwardStyleEvent)\n .off('change', this._onStyleChange)\n .off('source.add', this._onSourceAdd)\n .off('source.remove', this._onSourceRemove)\n .off('source.load', this._onSourceUpdate)\n .off('source.error', this._forwardSourceEvent)\n .off('source.change', this._onSourceUpdate)\n .off('layer.add', this._forwardLayerEvent)\n .off('layer.remove', this._forwardLayerEvent)\n .off('tile.add', this._forwardTileEvent)\n .off('tile.remove', this._forwardTileEvent)\n .off('tile.load', this.update)\n .off('tile.error', this._forwardTileEvent)\n ._remove();\n\n this.off('rotate', this.style._redoPlacement);\n this.off('pitch', this.style._redoPlacement);\n }\n\n if (!style) {\n this.style = null;\n return this;\n } else if (style instanceof Style) {\n this.style = style;\n } else {\n this.style = new Style(style, this.animationLoop);\n }\n\n this.style\n .on('load', this._onStyleLoad)\n .on('error', this._forwardStyleEvent)\n .on('change', this._onStyleChange)\n .on('source.add', this._onSourceAdd)\n .on('source.remove', this._onSourceRemove)\n .on('source.load', this._onSourceUpdate)\n .on('source.error', this._forwardSourceEvent)\n .on('source.change', this._onSourceUpdate)\n .on('layer.add', this._forwardLayerEvent)\n .on('layer.remove', this._forwardLayerEvent)\n .on('tile.add', this._forwardTileEvent)\n .on('tile.remove', this._forwardTileEvent)\n .on('tile.load', this.update)\n .on('tile.error', this._forwardTileEvent);\n\n this.on('rotate', this.style._redoPlacement);\n this.on('pitch', this.style._redoPlacement);\n\n return this;\n },\n\n /**\n * Add a source to the map style.\n *\n * @param {string} id ID of the source. Must not be used by any existing source.\n * @param {Object} source source specification, following the\n * [Mapbox GL Style Reference](https://www.mapbox.com/mapbox-gl-style-spec/#sources)\n * @fires source.add\n * @returns {Map} `this`\n */\n addSource: function(id, source) {\n this.style.addSource(id, source);\n return this;\n },\n\n /**\n * Remove an existing source from the map style.\n *\n * @param {string} id ID of the source to remove\n * @fires source.remove\n * @returns {Map} `this`\n */\n removeSource: function(id) {\n this.style.removeSource(id);\n return this;\n },\n\n /**\n * Return the style source object with the given `id`.\n *\n * @param {string} id source ID\n * @returns {Object}\n */\n getSource: function(id) {\n return this.style.getSource(id);\n },\n\n /**\n * Add a layer to the map style. The layer will be inserted before the layer with\n * ID `before`, or appended if `before` is omitted.\n * @param {Layer} layer\n * @param {string=} before ID of an existing layer to insert before\n * @fires layer.add\n * @returns {Map} `this`\n */\n addLayer: function(layer, before) {\n this.style.addLayer(layer, before);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Remove the layer with the given `id` from the map. Any layers which refer to the\n * specified layer via a `ref` property are also removed.\n *\n * @param {string} id\n * @fires layer.remove\n * @returns {Map} this\n */\n removeLayer: function(id) {\n this.style.removeLayer(id);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Set the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {Array} filter filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n * @returns {Map} `this`\n */\n setFilter: function(layer, filter) {\n this.style.setFilter(layer, filter);\n return this;\n },\n\n /**\n * Get the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @returns {Array} filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n */\n getFilter: function(layer) {\n return this.style.getFilter(layer);\n },\n\n /**\n * Set the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {*} value value for the paint propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @param {string=} klass optional class specifier for the property\n * @returns {Map} `this`\n */\n setPaintProperty: function(layer, name, value, klass) {\n this.style.setPaintProperty(layer, name, value, klass);\n this.style._cascade(this._classes);\n this.update(true);\n return this;\n },\n\n /**\n * Get the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the paint propery\n */\n getPaintProperty: function(layer, name, klass) {\n return this.style.getPaintProperty(layer, name, klass);\n },\n\n /**\n * Set the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {*} value value for the layout propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @returns {Map} `this`\n */\n setLayoutProperty: function(layer, name, value) {\n this.style.setLayoutProperty(layer, name, value);\n return this;\n },\n\n /**\n * Get the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the layout propery\n */\n getLayoutProperty: function(layer, name) {\n return this.style.getLayoutProperty(layer, name);\n },\n\n /**\n * Get the Map's container as an HTML element\n * @returns {HTMLElement} container\n */\n getContainer: function() {\n return this._container;\n },\n\n /**\n * Get the Map's canvas as an HTML canvas\n * @returns {HTMLElement} canvas\n */\n getCanvas: function() {\n return this._canvas.getElement();\n },\n\n _move: function(zoom, rotate, pitch) {\n\n this.update(zoom).fire('move');\n\n if (zoom) this.fire('zoom');\n if (rotate) this.fire('rotate');\n if (pitch) this.fire('pitch');\n\n return this;\n },\n\n // map setup code\n _setupContainer: function() {\n var id = this.options.container;\n var container = this._container = typeof id === 'string' ? document.getElementById(id) : id;\n if (container) container.classList.add('mapboxgl-map');\n this._canvas = new Canvas(this, container);\n },\n\n _setupControlPos: function() {\n var corners = this._controlCorners = {};\n var prefix = 'mapboxgl-ctrl-';\n var container = this.getContainer();\n\n function createCorner(pos) {\n var className = prefix + pos;\n corners[pos] = DOM.create('div', className, container);\n }\n\n if (container && typeof document === 'object') {\n createCorner('top-left');\n createCorner('top-right');\n createCorner('bottom-left');\n createCorner('bottom-right');\n }\n },\n\n _setupPainter: function() {\n var gl = this._canvas.getWebGLContext(this.options.failIfMajorPerformanceCaveat);\n\n if (!gl) {\n console.error('Failed to initialize WebGL');\n return;\n }\n\n this.painter = new GLPainter(gl, this.transform);\n },\n\n _contextLost: function(event) {\n event.preventDefault();\n if (this._frameId) {\n browser.cancelFrame(this._frameId);\n }\n },\n\n _contextRestored: function() {\n this._setupPainter();\n this.resize();\n this.update();\n },\n\n /**\n * Is this map fully loaded? If the style isn't loaded\n * or it has a change to the sources or style that isn't\n * propagated to its style, return false.\n *\n * @returns {boolean} whether the map is loaded\n */\n loaded: function() {\n if (this._styleDirty || this._sourcesDirty)\n return false;\n if (this.style && !this.style.loaded())\n return false;\n return true;\n },\n\n /**\n * Update this map's style and re-render the map.\n *\n * @param {Object} updateStyle new style\n * @returns {Map} this\n */\n update: function(updateStyle) {\n if (!this.style) return this;\n\n this._styleDirty = this._styleDirty || updateStyle;\n this._sourcesDirty = true;\n\n this._rerender();\n\n return this;\n },\n\n /**\n * Call when a (re-)render of the map is required, e.g. when the\n * user panned or zoomed,f or new data is available.\n * @returns {Map} this\n */\n render: function() {\n if (this.style && this._styleDirty) {\n this._styleDirty = false;\n this.style._recalculate(this.transform.zoom);\n }\n\n if (this.style && this._sourcesDirty && !this._sourcesDirtyTimeout) {\n this._sourcesDirty = false;\n this._sourcesDirtyTimeout = setTimeout(function() {\n this._sourcesDirtyTimeout = null;\n }.bind(this), 50);\n this.style._updateSources(this.transform);\n }\n\n this.painter.render(this.style, {\n debug: this.debug,\n vertices: this.vertices,\n rotating: this.rotating,\n zooming: this.zooming\n });\n\n this.fire('render');\n\n if (this.loaded() && !this._loaded) {\n this._loaded = true;\n this.fire('load');\n }\n\n this._frameId = null;\n\n if (!this.animationLoop.stopped()) {\n this._styleDirty = true;\n }\n\n if (this._sourcesDirty || this._repaint || !this.animationLoop.stopped()) {\n this._rerender();\n }\n\n return this;\n },\n\n /**\n * Destroys the map's underlying resources, including web workers.\n * @returns {Map} this\n */\n remove: function() {\n if (this._hash) this._hash.remove();\n browser.cancelFrame(this._frameId);\n clearTimeout(this._sourcesDirtyTimeout);\n this.setStyle(null);\n return this;\n },\n\n _rerender: function() {\n if (this.style && !this._frameId) {\n this._frameId = browser.frame(this.render);\n }\n },\n\n _forwardStyleEvent: function(e) {\n this.fire('style.' + e.type, util.extend({style: e.target}, e));\n },\n\n _forwardSourceEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardLayerEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardTileEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _onStyleLoad: function(e) {\n this.style._cascade(this._classes, {transition: false});\n this._forwardStyleEvent(e);\n },\n\n _onStyleChange: function(e) {\n this.update(true);\n this._forwardStyleEvent(e);\n },\n\n _onSourceAdd: function(e) {\n var source = e.source;\n if (source.onAdd)\n source.onAdd(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceRemove: function(e) {\n var source = e.source;\n if (source.onRemove)\n source.onRemove(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceUpdate: function(e) {\n this.update();\n this._forwardSourceEvent(e);\n }\n}","path":"js/ui/map.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/map.js#L488-L492"},"params":[{"title":"param","description":null,"type":{"type":"NameExpression","name":"string"},"name":"id"}],"returns":[{"title":"returns","description":"this","type":{"type":"NameExpression","name":"Map"}}],"name":"removeLayer","memberof":"Map","scope":"instance","members":{"instance":[],"static":[]},"path":["Map","removeLayer"]},{"description":"Removes a style class from a map","tags":[{"title":"param","description":"name of style class","type":{"type":"NameExpression","name":"string"},"name":"klass"},{"title":"param","description":null,"type":{"type":"NameExpression","name":"styleOptions"},"name":"options"},{"title":"fires","description":"change"},{"title":"returns","description":"`this`","type":{"type":"NameExpression","name":"Map"}},{"title":"name","name":"removeClass"},{"title":"memberof","description":"Map"},{"title":"instance"}],"context":{"loc":{"start":{"line":248,"column":4},"end":{"line":252,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/map.js","code":"{\n\n options: {\n center: [0, 0],\n zoom: 0,\n bearing: 0,\n pitch: 0,\n\n minZoom: 0,\n maxZoom: 20,\n\n interactive: true,\n hash: false,\n\n attributionControl: true,\n\n failIfMajorPerformanceCaveat: false\n },\n\n addControl: function(control) {\n control.addTo(this);\n return this;\n },\n\n /**\n * Sets a map position\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @param {number} zoom Map zoom level\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setView: function(center, zoom, bearing, pitch) {\n this.stop();\n\n var tr = this.transform,\n zoomChanged = tr.zoom !== +zoom,\n bearingChanged = tr.bearing !== +bearing,\n pitchChanged = tr.pitch !== +pitch;\n\n tr.center = LatLng.convert(center);\n tr.zoom = +zoom;\n tr.bearing = +bearing;\n tr.pitch = +pitch;\n\n return this\n .fire('movestart')\n ._move(zoomChanged, bearingChanged, pitchChanged)\n .fire('moveend');\n },\n\n /**\n * Sets a map location\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setCenter: function(center) {\n this.setView(center, this.getZoom(), this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map zoom\n *\n * @param {number} zoom Map zoom level\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setZoom: function(zoom) {\n this.setView(this.getCenter(), zoom, this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map rotation\n *\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setBearing: function(bearing) {\n this.setView(this.getCenter(), this.getZoom(), bearing, this.getPitch());\n },\n\n /**\n * Sets a map angle\n *\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setPitch: function(pitch) {\n this.setView(this.getCenter(), this.getZoom(), this.getBearing(), pitch);\n },\n\n /**\n * Get the current view geographical point\n * @returns {LatLng}\n */\n getCenter: function() { return this.transform.center; },\n\n /**\n * Get the current zoom\n * @returns {number}\n */\n getZoom: function() { return this.transform.zoom; },\n\n /**\n * Get the current bearing in degrees\n * @returns {number}\n */\n getBearing: function() { return this.transform.bearing; },\n\n /**\n * Get the current angle in degrees\n * @returns {number}\n */\n getPitch: function() { return this.transform.pitch; },\n\n /**\n * @typedef {Object} [styleOptions]\n * @param {Boolean} [styleOptions.transition=true]\n */\n\n /**\n * Adds a style class to a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n addClass: function(klass, options) {\n if (this._classes[klass]) return;\n this._classes[klass] = true;\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Removes a style class from a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n removeClass: function(klass, options) {\n if (!this._classes[klass]) return;\n delete this._classes[klass];\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Helper method to add more than one class\n *\n * @param {Array} klasses An array of class names\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n setClasses: function(klasses, options) {\n this._classes = {};\n for (var i = 0; i < klasses.length; i++) {\n this._classes[klasses[i]] = true;\n }\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Check whether a style class is active\n *\n * @param {string} klass Name of style class\n * @returns {boolean}\n */\n hasClass: function(klass) {\n return !!this._classes[klass];\n },\n\n /**\n * Return an array of the current active style classes\n *\n * @returns {boolean}\n */\n getClasses: function() {\n return Object.keys(this._classes);\n },\n\n /**\n * Detect the map's new width and height and resize it.\n *\n * @returns {Map} `this`\n */\n resize: function() {\n var width = 0, height = 0;\n\n if (this._container) {\n width = this._container.offsetWidth || 400;\n height = this._container.offsetHeight || 300;\n }\n\n this._canvas.resize(width, height);\n\n this.transform.width = width;\n this.transform.height = height;\n this.transform._constrain();\n\n this.painter.resize(width, height);\n\n return this\n .fire('movestart')\n ._move()\n .fire('resize')\n .fire('moveend');\n },\n\n /**\n * Get the map's geographical bounds\n *\n * @returns {LatLngBounds}\n */\n getBounds: function() {\n return new LatLngBounds(\n this.transform.pointLocation(new Point(0, 0)),\n this.transform.pointLocation(this.transform.size));\n },\n\n /**\n * Get pixel coordinates (relative to map container) given a geographical location\n *\n * @param {LatLng} latlng\n * @returns {Object} `x` and `y` coordinates\n */\n project: function(latlng) {\n return this.transform.locationPoint(LatLng.convert(latlng));\n },\n\n /**\n * Get geographical coordinates given pixel coordinates\n *\n * @param {Array} point [x, y] pixel coordinates\n * @returns {LatLng}\n */\n unproject: function(point) {\n return this.transform.pointLocation(Point.convert(point));\n },\n\n /**\n * Get all features at a point ([x, y])\n *\n * @param {Array} point [x, y] pixel coordinates\n * @param {Object} params\n * @param {number} [params.radius=0] Optional. Radius in pixels to search in\n * @param {string} params.layer Optional. Only return features from a given layer\n * @param {string} params.type Optional. Either `raster` or `vector`\n * @param {featuresAtCallback} callback function that returns the response\n *\n * @callback featuresAtCallback\n * @param {Object|null} err Error _If any_\n * @param {Array} features Displays a JSON array of features given the passed parameters of `featuresAt`\n *\n * @returns {Map} `this`\n */\n featuresAt: function(point, params, callback) {\n var coord = this.transform.pointCoordinate(Point.convert(point));\n this.style.featuresAt(coord, params, callback);\n return this;\n },\n\n /**\n * Replaces the map's style object\n *\n * @param {Object} style A style object formatted as JSON\n * @returns {Map} `this`\n */\n setStyle: function(style) {\n if (this.style) {\n this.style\n .off('load', this._onStyleLoad)\n .off('error', this._forwardStyleEvent)\n .off('change', this._onStyleChange)\n .off('source.add', this._onSourceAdd)\n .off('source.remove', this._onSourceRemove)\n .off('source.load', this._onSourceUpdate)\n .off('source.error', this._forwardSourceEvent)\n .off('source.change', this._onSourceUpdate)\n .off('layer.add', this._forwardLayerEvent)\n .off('layer.remove', this._forwardLayerEvent)\n .off('tile.add', this._forwardTileEvent)\n .off('tile.remove', this._forwardTileEvent)\n .off('tile.load', this.update)\n .off('tile.error', this._forwardTileEvent)\n ._remove();\n\n this.off('rotate', this.style._redoPlacement);\n this.off('pitch', this.style._redoPlacement);\n }\n\n if (!style) {\n this.style = null;\n return this;\n } else if (style instanceof Style) {\n this.style = style;\n } else {\n this.style = new Style(style, this.animationLoop);\n }\n\n this.style\n .on('load', this._onStyleLoad)\n .on('error', this._forwardStyleEvent)\n .on('change', this._onStyleChange)\n .on('source.add', this._onSourceAdd)\n .on('source.remove', this._onSourceRemove)\n .on('source.load', this._onSourceUpdate)\n .on('source.error', this._forwardSourceEvent)\n .on('source.change', this._onSourceUpdate)\n .on('layer.add', this._forwardLayerEvent)\n .on('layer.remove', this._forwardLayerEvent)\n .on('tile.add', this._forwardTileEvent)\n .on('tile.remove', this._forwardTileEvent)\n .on('tile.load', this.update)\n .on('tile.error', this._forwardTileEvent);\n\n this.on('rotate', this.style._redoPlacement);\n this.on('pitch', this.style._redoPlacement);\n\n return this;\n },\n\n /**\n * Add a source to the map style.\n *\n * @param {string} id ID of the source. Must not be used by any existing source.\n * @param {Object} source source specification, following the\n * [Mapbox GL Style Reference](https://www.mapbox.com/mapbox-gl-style-spec/#sources)\n * @fires source.add\n * @returns {Map} `this`\n */\n addSource: function(id, source) {\n this.style.addSource(id, source);\n return this;\n },\n\n /**\n * Remove an existing source from the map style.\n *\n * @param {string} id ID of the source to remove\n * @fires source.remove\n * @returns {Map} `this`\n */\n removeSource: function(id) {\n this.style.removeSource(id);\n return this;\n },\n\n /**\n * Return the style source object with the given `id`.\n *\n * @param {string} id source ID\n * @returns {Object}\n */\n getSource: function(id) {\n return this.style.getSource(id);\n },\n\n /**\n * Add a layer to the map style. The layer will be inserted before the layer with\n * ID `before`, or appended if `before` is omitted.\n * @param {Layer} layer\n * @param {string=} before ID of an existing layer to insert before\n * @fires layer.add\n * @returns {Map} `this`\n */\n addLayer: function(layer, before) {\n this.style.addLayer(layer, before);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Remove the layer with the given `id` from the map. Any layers which refer to the\n * specified layer via a `ref` property are also removed.\n *\n * @param {string} id\n * @fires layer.remove\n * @returns {Map} this\n */\n removeLayer: function(id) {\n this.style.removeLayer(id);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Set the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {Array} filter filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n * @returns {Map} `this`\n */\n setFilter: function(layer, filter) {\n this.style.setFilter(layer, filter);\n return this;\n },\n\n /**\n * Get the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @returns {Array} filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n */\n getFilter: function(layer) {\n return this.style.getFilter(layer);\n },\n\n /**\n * Set the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {*} value value for the paint propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @param {string=} klass optional class specifier for the property\n * @returns {Map} `this`\n */\n setPaintProperty: function(layer, name, value, klass) {\n this.style.setPaintProperty(layer, name, value, klass);\n this.style._cascade(this._classes);\n this.update(true);\n return this;\n },\n\n /**\n * Get the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the paint propery\n */\n getPaintProperty: function(layer, name, klass) {\n return this.style.getPaintProperty(layer, name, klass);\n },\n\n /**\n * Set the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {*} value value for the layout propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @returns {Map} `this`\n */\n setLayoutProperty: function(layer, name, value) {\n this.style.setLayoutProperty(layer, name, value);\n return this;\n },\n\n /**\n * Get the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the layout propery\n */\n getLayoutProperty: function(layer, name) {\n return this.style.getLayoutProperty(layer, name);\n },\n\n /**\n * Get the Map's container as an HTML element\n * @returns {HTMLElement} container\n */\n getContainer: function() {\n return this._container;\n },\n\n /**\n * Get the Map's canvas as an HTML canvas\n * @returns {HTMLElement} canvas\n */\n getCanvas: function() {\n return this._canvas.getElement();\n },\n\n _move: function(zoom, rotate, pitch) {\n\n this.update(zoom).fire('move');\n\n if (zoom) this.fire('zoom');\n if (rotate) this.fire('rotate');\n if (pitch) this.fire('pitch');\n\n return this;\n },\n\n // map setup code\n _setupContainer: function() {\n var id = this.options.container;\n var container = this._container = typeof id === 'string' ? document.getElementById(id) : id;\n if (container) container.classList.add('mapboxgl-map');\n this._canvas = new Canvas(this, container);\n },\n\n _setupControlPos: function() {\n var corners = this._controlCorners = {};\n var prefix = 'mapboxgl-ctrl-';\n var container = this.getContainer();\n\n function createCorner(pos) {\n var className = prefix + pos;\n corners[pos] = DOM.create('div', className, container);\n }\n\n if (container && typeof document === 'object') {\n createCorner('top-left');\n createCorner('top-right');\n createCorner('bottom-left');\n createCorner('bottom-right');\n }\n },\n\n _setupPainter: function() {\n var gl = this._canvas.getWebGLContext(this.options.failIfMajorPerformanceCaveat);\n\n if (!gl) {\n console.error('Failed to initialize WebGL');\n return;\n }\n\n this.painter = new GLPainter(gl, this.transform);\n },\n\n _contextLost: function(event) {\n event.preventDefault();\n if (this._frameId) {\n browser.cancelFrame(this._frameId);\n }\n },\n\n _contextRestored: function() {\n this._setupPainter();\n this.resize();\n this.update();\n },\n\n /**\n * Is this map fully loaded? If the style isn't loaded\n * or it has a change to the sources or style that isn't\n * propagated to its style, return false.\n *\n * @returns {boolean} whether the map is loaded\n */\n loaded: function() {\n if (this._styleDirty || this._sourcesDirty)\n return false;\n if (this.style && !this.style.loaded())\n return false;\n return true;\n },\n\n /**\n * Update this map's style and re-render the map.\n *\n * @param {Object} updateStyle new style\n * @returns {Map} this\n */\n update: function(updateStyle) {\n if (!this.style) return this;\n\n this._styleDirty = this._styleDirty || updateStyle;\n this._sourcesDirty = true;\n\n this._rerender();\n\n return this;\n },\n\n /**\n * Call when a (re-)render of the map is required, e.g. when the\n * user panned or zoomed,f or new data is available.\n * @returns {Map} this\n */\n render: function() {\n if (this.style && this._styleDirty) {\n this._styleDirty = false;\n this.style._recalculate(this.transform.zoom);\n }\n\n if (this.style && this._sourcesDirty && !this._sourcesDirtyTimeout) {\n this._sourcesDirty = false;\n this._sourcesDirtyTimeout = setTimeout(function() {\n this._sourcesDirtyTimeout = null;\n }.bind(this), 50);\n this.style._updateSources(this.transform);\n }\n\n this.painter.render(this.style, {\n debug: this.debug,\n vertices: this.vertices,\n rotating: this.rotating,\n zooming: this.zooming\n });\n\n this.fire('render');\n\n if (this.loaded() && !this._loaded) {\n this._loaded = true;\n this.fire('load');\n }\n\n this._frameId = null;\n\n if (!this.animationLoop.stopped()) {\n this._styleDirty = true;\n }\n\n if (this._sourcesDirty || this._repaint || !this.animationLoop.stopped()) {\n this._rerender();\n }\n\n return this;\n },\n\n /**\n * Destroys the map's underlying resources, including web workers.\n * @returns {Map} this\n */\n remove: function() {\n if (this._hash) this._hash.remove();\n browser.cancelFrame(this._frameId);\n clearTimeout(this._sourcesDirtyTimeout);\n this.setStyle(null);\n return this;\n },\n\n _rerender: function() {\n if (this.style && !this._frameId) {\n this._frameId = browser.frame(this.render);\n }\n },\n\n _forwardStyleEvent: function(e) {\n this.fire('style.' + e.type, util.extend({style: e.target}, e));\n },\n\n _forwardSourceEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardLayerEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardTileEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _onStyleLoad: function(e) {\n this.style._cascade(this._classes, {transition: false});\n this._forwardStyleEvent(e);\n },\n\n _onStyleChange: function(e) {\n this.update(true);\n this._forwardStyleEvent(e);\n },\n\n _onSourceAdd: function(e) {\n var source = e.source;\n if (source.onAdd)\n source.onAdd(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceRemove: function(e) {\n var source = e.source;\n if (source.onRemove)\n source.onRemove(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceUpdate: function(e) {\n this.update();\n this._forwardSourceEvent(e);\n }\n}","path":"js/ui/map.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/map.js#L248-L252"},"params":[{"title":"param","description":"name of style class","type":{"type":"NameExpression","name":"string"},"name":"klass"},{"title":"param","description":null,"type":{"type":"NameExpression","name":"styleOptions"},"name":"options"}],"returns":[{"title":"returns","description":"`this`","type":{"type":"NameExpression","name":"Map"}}],"name":"removeClass","memberof":"Map","scope":"instance","members":{"instance":[],"static":[]},"path":["Map","removeClass"]},{"description":"Get the current angle in degrees","tags":[{"title":"returns","description":null,"type":{"type":"NameExpression","name":"number"}},{"title":"name","name":"getPitch"},{"title":"memberof","description":"Map"},{"title":"instance"}],"context":{"loc":{"start":{"line":219,"column":4},"end":{"line":219,"column":57}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/map.js","code":"{\n\n options: {\n center: [0, 0],\n zoom: 0,\n bearing: 0,\n pitch: 0,\n\n minZoom: 0,\n maxZoom: 20,\n\n interactive: true,\n hash: false,\n\n attributionControl: true,\n\n failIfMajorPerformanceCaveat: false\n },\n\n addControl: function(control) {\n control.addTo(this);\n return this;\n },\n\n /**\n * Sets a map position\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @param {number} zoom Map zoom level\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setView: function(center, zoom, bearing, pitch) {\n this.stop();\n\n var tr = this.transform,\n zoomChanged = tr.zoom !== +zoom,\n bearingChanged = tr.bearing !== +bearing,\n pitchChanged = tr.pitch !== +pitch;\n\n tr.center = LatLng.convert(center);\n tr.zoom = +zoom;\n tr.bearing = +bearing;\n tr.pitch = +pitch;\n\n return this\n .fire('movestart')\n ._move(zoomChanged, bearingChanged, pitchChanged)\n .fire('moveend');\n },\n\n /**\n * Sets a map location\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setCenter: function(center) {\n this.setView(center, this.getZoom(), this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map zoom\n *\n * @param {number} zoom Map zoom level\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setZoom: function(zoom) {\n this.setView(this.getCenter(), zoom, this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map rotation\n *\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setBearing: function(bearing) {\n this.setView(this.getCenter(), this.getZoom(), bearing, this.getPitch());\n },\n\n /**\n * Sets a map angle\n *\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setPitch: function(pitch) {\n this.setView(this.getCenter(), this.getZoom(), this.getBearing(), pitch);\n },\n\n /**\n * Get the current view geographical point\n * @returns {LatLng}\n */\n getCenter: function() { return this.transform.center; },\n\n /**\n * Get the current zoom\n * @returns {number}\n */\n getZoom: function() { return this.transform.zoom; },\n\n /**\n * Get the current bearing in degrees\n * @returns {number}\n */\n getBearing: function() { return this.transform.bearing; },\n\n /**\n * Get the current angle in degrees\n * @returns {number}\n */\n getPitch: function() { return this.transform.pitch; },\n\n /**\n * @typedef {Object} [styleOptions]\n * @param {Boolean} [styleOptions.transition=true]\n */\n\n /**\n * Adds a style class to a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n addClass: function(klass, options) {\n if (this._classes[klass]) return;\n this._classes[klass] = true;\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Removes a style class from a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n removeClass: function(klass, options) {\n if (!this._classes[klass]) return;\n delete this._classes[klass];\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Helper method to add more than one class\n *\n * @param {Array} klasses An array of class names\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n setClasses: function(klasses, options) {\n this._classes = {};\n for (var i = 0; i < klasses.length; i++) {\n this._classes[klasses[i]] = true;\n }\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Check whether a style class is active\n *\n * @param {string} klass Name of style class\n * @returns {boolean}\n */\n hasClass: function(klass) {\n return !!this._classes[klass];\n },\n\n /**\n * Return an array of the current active style classes\n *\n * @returns {boolean}\n */\n getClasses: function() {\n return Object.keys(this._classes);\n },\n\n /**\n * Detect the map's new width and height and resize it.\n *\n * @returns {Map} `this`\n */\n resize: function() {\n var width = 0, height = 0;\n\n if (this._container) {\n width = this._container.offsetWidth || 400;\n height = this._container.offsetHeight || 300;\n }\n\n this._canvas.resize(width, height);\n\n this.transform.width = width;\n this.transform.height = height;\n this.transform._constrain();\n\n this.painter.resize(width, height);\n\n return this\n .fire('movestart')\n ._move()\n .fire('resize')\n .fire('moveend');\n },\n\n /**\n * Get the map's geographical bounds\n *\n * @returns {LatLngBounds}\n */\n getBounds: function() {\n return new LatLngBounds(\n this.transform.pointLocation(new Point(0, 0)),\n this.transform.pointLocation(this.transform.size));\n },\n\n /**\n * Get pixel coordinates (relative to map container) given a geographical location\n *\n * @param {LatLng} latlng\n * @returns {Object} `x` and `y` coordinates\n */\n project: function(latlng) {\n return this.transform.locationPoint(LatLng.convert(latlng));\n },\n\n /**\n * Get geographical coordinates given pixel coordinates\n *\n * @param {Array} point [x, y] pixel coordinates\n * @returns {LatLng}\n */\n unproject: function(point) {\n return this.transform.pointLocation(Point.convert(point));\n },\n\n /**\n * Get all features at a point ([x, y])\n *\n * @param {Array} point [x, y] pixel coordinates\n * @param {Object} params\n * @param {number} [params.radius=0] Optional. Radius in pixels to search in\n * @param {string} params.layer Optional. Only return features from a given layer\n * @param {string} params.type Optional. Either `raster` or `vector`\n * @param {featuresAtCallback} callback function that returns the response\n *\n * @callback featuresAtCallback\n * @param {Object|null} err Error _If any_\n * @param {Array} features Displays a JSON array of features given the passed parameters of `featuresAt`\n *\n * @returns {Map} `this`\n */\n featuresAt: function(point, params, callback) {\n var coord = this.transform.pointCoordinate(Point.convert(point));\n this.style.featuresAt(coord, params, callback);\n return this;\n },\n\n /**\n * Replaces the map's style object\n *\n * @param {Object} style A style object formatted as JSON\n * @returns {Map} `this`\n */\n setStyle: function(style) {\n if (this.style) {\n this.style\n .off('load', this._onStyleLoad)\n .off('error', this._forwardStyleEvent)\n .off('change', this._onStyleChange)\n .off('source.add', this._onSourceAdd)\n .off('source.remove', this._onSourceRemove)\n .off('source.load', this._onSourceUpdate)\n .off('source.error', this._forwardSourceEvent)\n .off('source.change', this._onSourceUpdate)\n .off('layer.add', this._forwardLayerEvent)\n .off('layer.remove', this._forwardLayerEvent)\n .off('tile.add', this._forwardTileEvent)\n .off('tile.remove', this._forwardTileEvent)\n .off('tile.load', this.update)\n .off('tile.error', this._forwardTileEvent)\n ._remove();\n\n this.off('rotate', this.style._redoPlacement);\n this.off('pitch', this.style._redoPlacement);\n }\n\n if (!style) {\n this.style = null;\n return this;\n } else if (style instanceof Style) {\n this.style = style;\n } else {\n this.style = new Style(style, this.animationLoop);\n }\n\n this.style\n .on('load', this._onStyleLoad)\n .on('error', this._forwardStyleEvent)\n .on('change', this._onStyleChange)\n .on('source.add', this._onSourceAdd)\n .on('source.remove', this._onSourceRemove)\n .on('source.load', this._onSourceUpdate)\n .on('source.error', this._forwardSourceEvent)\n .on('source.change', this._onSourceUpdate)\n .on('layer.add', this._forwardLayerEvent)\n .on('layer.remove', this._forwardLayerEvent)\n .on('tile.add', this._forwardTileEvent)\n .on('tile.remove', this._forwardTileEvent)\n .on('tile.load', this.update)\n .on('tile.error', this._forwardTileEvent);\n\n this.on('rotate', this.style._redoPlacement);\n this.on('pitch', this.style._redoPlacement);\n\n return this;\n },\n\n /**\n * Add a source to the map style.\n *\n * @param {string} id ID of the source. Must not be used by any existing source.\n * @param {Object} source source specification, following the\n * [Mapbox GL Style Reference](https://www.mapbox.com/mapbox-gl-style-spec/#sources)\n * @fires source.add\n * @returns {Map} `this`\n */\n addSource: function(id, source) {\n this.style.addSource(id, source);\n return this;\n },\n\n /**\n * Remove an existing source from the map style.\n *\n * @param {string} id ID of the source to remove\n * @fires source.remove\n * @returns {Map} `this`\n */\n removeSource: function(id) {\n this.style.removeSource(id);\n return this;\n },\n\n /**\n * Return the style source object with the given `id`.\n *\n * @param {string} id source ID\n * @returns {Object}\n */\n getSource: function(id) {\n return this.style.getSource(id);\n },\n\n /**\n * Add a layer to the map style. The layer will be inserted before the layer with\n * ID `before`, or appended if `before` is omitted.\n * @param {Layer} layer\n * @param {string=} before ID of an existing layer to insert before\n * @fires layer.add\n * @returns {Map} `this`\n */\n addLayer: function(layer, before) {\n this.style.addLayer(layer, before);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Remove the layer with the given `id` from the map. Any layers which refer to the\n * specified layer via a `ref` property are also removed.\n *\n * @param {string} id\n * @fires layer.remove\n * @returns {Map} this\n */\n removeLayer: function(id) {\n this.style.removeLayer(id);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Set the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {Array} filter filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n * @returns {Map} `this`\n */\n setFilter: function(layer, filter) {\n this.style.setFilter(layer, filter);\n return this;\n },\n\n /**\n * Get the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @returns {Array} filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n */\n getFilter: function(layer) {\n return this.style.getFilter(layer);\n },\n\n /**\n * Set the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {*} value value for the paint propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @param {string=} klass optional class specifier for the property\n * @returns {Map} `this`\n */\n setPaintProperty: function(layer, name, value, klass) {\n this.style.setPaintProperty(layer, name, value, klass);\n this.style._cascade(this._classes);\n this.update(true);\n return this;\n },\n\n /**\n * Get the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the paint propery\n */\n getPaintProperty: function(layer, name, klass) {\n return this.style.getPaintProperty(layer, name, klass);\n },\n\n /**\n * Set the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {*} value value for the layout propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @returns {Map} `this`\n */\n setLayoutProperty: function(layer, name, value) {\n this.style.setLayoutProperty(layer, name, value);\n return this;\n },\n\n /**\n * Get the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the layout propery\n */\n getLayoutProperty: function(layer, name) {\n return this.style.getLayoutProperty(layer, name);\n },\n\n /**\n * Get the Map's container as an HTML element\n * @returns {HTMLElement} container\n */\n getContainer: function() {\n return this._container;\n },\n\n /**\n * Get the Map's canvas as an HTML canvas\n * @returns {HTMLElement} canvas\n */\n getCanvas: function() {\n return this._canvas.getElement();\n },\n\n _move: function(zoom, rotate, pitch) {\n\n this.update(zoom).fire('move');\n\n if (zoom) this.fire('zoom');\n if (rotate) this.fire('rotate');\n if (pitch) this.fire('pitch');\n\n return this;\n },\n\n // map setup code\n _setupContainer: function() {\n var id = this.options.container;\n var container = this._container = typeof id === 'string' ? document.getElementById(id) : id;\n if (container) container.classList.add('mapboxgl-map');\n this._canvas = new Canvas(this, container);\n },\n\n _setupControlPos: function() {\n var corners = this._controlCorners = {};\n var prefix = 'mapboxgl-ctrl-';\n var container = this.getContainer();\n\n function createCorner(pos) {\n var className = prefix + pos;\n corners[pos] = DOM.create('div', className, container);\n }\n\n if (container && typeof document === 'object') {\n createCorner('top-left');\n createCorner('top-right');\n createCorner('bottom-left');\n createCorner('bottom-right');\n }\n },\n\n _setupPainter: function() {\n var gl = this._canvas.getWebGLContext(this.options.failIfMajorPerformanceCaveat);\n\n if (!gl) {\n console.error('Failed to initialize WebGL');\n return;\n }\n\n this.painter = new GLPainter(gl, this.transform);\n },\n\n _contextLost: function(event) {\n event.preventDefault();\n if (this._frameId) {\n browser.cancelFrame(this._frameId);\n }\n },\n\n _contextRestored: function() {\n this._setupPainter();\n this.resize();\n this.update();\n },\n\n /**\n * Is this map fully loaded? If the style isn't loaded\n * or it has a change to the sources or style that isn't\n * propagated to its style, return false.\n *\n * @returns {boolean} whether the map is loaded\n */\n loaded: function() {\n if (this._styleDirty || this._sourcesDirty)\n return false;\n if (this.style && !this.style.loaded())\n return false;\n return true;\n },\n\n /**\n * Update this map's style and re-render the map.\n *\n * @param {Object} updateStyle new style\n * @returns {Map} this\n */\n update: function(updateStyle) {\n if (!this.style) return this;\n\n this._styleDirty = this._styleDirty || updateStyle;\n this._sourcesDirty = true;\n\n this._rerender();\n\n return this;\n },\n\n /**\n * Call when a (re-)render of the map is required, e.g. when the\n * user panned or zoomed,f or new data is available.\n * @returns {Map} this\n */\n render: function() {\n if (this.style && this._styleDirty) {\n this._styleDirty = false;\n this.style._recalculate(this.transform.zoom);\n }\n\n if (this.style && this._sourcesDirty && !this._sourcesDirtyTimeout) {\n this._sourcesDirty = false;\n this._sourcesDirtyTimeout = setTimeout(function() {\n this._sourcesDirtyTimeout = null;\n }.bind(this), 50);\n this.style._updateSources(this.transform);\n }\n\n this.painter.render(this.style, {\n debug: this.debug,\n vertices: this.vertices,\n rotating: this.rotating,\n zooming: this.zooming\n });\n\n this.fire('render');\n\n if (this.loaded() && !this._loaded) {\n this._loaded = true;\n this.fire('load');\n }\n\n this._frameId = null;\n\n if (!this.animationLoop.stopped()) {\n this._styleDirty = true;\n }\n\n if (this._sourcesDirty || this._repaint || !this.animationLoop.stopped()) {\n this._rerender();\n }\n\n return this;\n },\n\n /**\n * Destroys the map's underlying resources, including web workers.\n * @returns {Map} this\n */\n remove: function() {\n if (this._hash) this._hash.remove();\n browser.cancelFrame(this._frameId);\n clearTimeout(this._sourcesDirtyTimeout);\n this.setStyle(null);\n return this;\n },\n\n _rerender: function() {\n if (this.style && !this._frameId) {\n this._frameId = browser.frame(this.render);\n }\n },\n\n _forwardStyleEvent: function(e) {\n this.fire('style.' + e.type, util.extend({style: e.target}, e));\n },\n\n _forwardSourceEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardLayerEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardTileEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _onStyleLoad: function(e) {\n this.style._cascade(this._classes, {transition: false});\n this._forwardStyleEvent(e);\n },\n\n _onStyleChange: function(e) {\n this.update(true);\n this._forwardStyleEvent(e);\n },\n\n _onSourceAdd: function(e) {\n var source = e.source;\n if (source.onAdd)\n source.onAdd(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceRemove: function(e) {\n var source = e.source;\n if (source.onRemove)\n source.onRemove(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceUpdate: function(e) {\n this.update();\n this._forwardSourceEvent(e);\n }\n}","path":"js/ui/map.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/map.js#L219-L219"},"returns":[{"title":"returns","description":null,"type":{"type":"NameExpression","name":"number"}}],"name":"getPitch","memberof":"Map","scope":"instance","members":{"instance":[],"static":[]},"path":["Map","getPitch"]},{"description":"Get the value of a paint property in a given style layer.","tags":[{"title":"param","description":"ID of a layer","type":{"type":"NameExpression","name":"string"},"name":"layer"},{"title":"param","description":"name of a paint property","type":{"type":"NameExpression","name":"string"},"name":"name"},{"title":"param","description":"optional class specifier for the property","type":{"type":"OptionalType","expression":{"type":"NameExpression","name":"string"}},"name":"klass"},{"title":"returns","description":"value for the paint propery","type":{"type":"AllLiteral"}},{"title":"name","name":"getPaintProperty"},{"title":"memberof","description":"Map"},{"title":"instance"}],"context":{"loc":{"start":{"line":540,"column":4},"end":{"line":542,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/map.js","code":"{\n\n options: {\n center: [0, 0],\n zoom: 0,\n bearing: 0,\n pitch: 0,\n\n minZoom: 0,\n maxZoom: 20,\n\n interactive: true,\n hash: false,\n\n attributionControl: true,\n\n failIfMajorPerformanceCaveat: false\n },\n\n addControl: function(control) {\n control.addTo(this);\n return this;\n },\n\n /**\n * Sets a map position\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @param {number} zoom Map zoom level\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setView: function(center, zoom, bearing, pitch) {\n this.stop();\n\n var tr = this.transform,\n zoomChanged = tr.zoom !== +zoom,\n bearingChanged = tr.bearing !== +bearing,\n pitchChanged = tr.pitch !== +pitch;\n\n tr.center = LatLng.convert(center);\n tr.zoom = +zoom;\n tr.bearing = +bearing;\n tr.pitch = +pitch;\n\n return this\n .fire('movestart')\n ._move(zoomChanged, bearingChanged, pitchChanged)\n .fire('moveend');\n },\n\n /**\n * Sets a map location\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setCenter: function(center) {\n this.setView(center, this.getZoom(), this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map zoom\n *\n * @param {number} zoom Map zoom level\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setZoom: function(zoom) {\n this.setView(this.getCenter(), zoom, this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map rotation\n *\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setBearing: function(bearing) {\n this.setView(this.getCenter(), this.getZoom(), bearing, this.getPitch());\n },\n\n /**\n * Sets a map angle\n *\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setPitch: function(pitch) {\n this.setView(this.getCenter(), this.getZoom(), this.getBearing(), pitch);\n },\n\n /**\n * Get the current view geographical point\n * @returns {LatLng}\n */\n getCenter: function() { return this.transform.center; },\n\n /**\n * Get the current zoom\n * @returns {number}\n */\n getZoom: function() { return this.transform.zoom; },\n\n /**\n * Get the current bearing in degrees\n * @returns {number}\n */\n getBearing: function() { return this.transform.bearing; },\n\n /**\n * Get the current angle in degrees\n * @returns {number}\n */\n getPitch: function() { return this.transform.pitch; },\n\n /**\n * @typedef {Object} [styleOptions]\n * @param {Boolean} [styleOptions.transition=true]\n */\n\n /**\n * Adds a style class to a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n addClass: function(klass, options) {\n if (this._classes[klass]) return;\n this._classes[klass] = true;\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Removes a style class from a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n removeClass: function(klass, options) {\n if (!this._classes[klass]) return;\n delete this._classes[klass];\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Helper method to add more than one class\n *\n * @param {Array} klasses An array of class names\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n setClasses: function(klasses, options) {\n this._classes = {};\n for (var i = 0; i < klasses.length; i++) {\n this._classes[klasses[i]] = true;\n }\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Check whether a style class is active\n *\n * @param {string} klass Name of style class\n * @returns {boolean}\n */\n hasClass: function(klass) {\n return !!this._classes[klass];\n },\n\n /**\n * Return an array of the current active style classes\n *\n * @returns {boolean}\n */\n getClasses: function() {\n return Object.keys(this._classes);\n },\n\n /**\n * Detect the map's new width and height and resize it.\n *\n * @returns {Map} `this`\n */\n resize: function() {\n var width = 0, height = 0;\n\n if (this._container) {\n width = this._container.offsetWidth || 400;\n height = this._container.offsetHeight || 300;\n }\n\n this._canvas.resize(width, height);\n\n this.transform.width = width;\n this.transform.height = height;\n this.transform._constrain();\n\n this.painter.resize(width, height);\n\n return this\n .fire('movestart')\n ._move()\n .fire('resize')\n .fire('moveend');\n },\n\n /**\n * Get the map's geographical bounds\n *\n * @returns {LatLngBounds}\n */\n getBounds: function() {\n return new LatLngBounds(\n this.transform.pointLocation(new Point(0, 0)),\n this.transform.pointLocation(this.transform.size));\n },\n\n /**\n * Get pixel coordinates (relative to map container) given a geographical location\n *\n * @param {LatLng} latlng\n * @returns {Object} `x` and `y` coordinates\n */\n project: function(latlng) {\n return this.transform.locationPoint(LatLng.convert(latlng));\n },\n\n /**\n * Get geographical coordinates given pixel coordinates\n *\n * @param {Array} point [x, y] pixel coordinates\n * @returns {LatLng}\n */\n unproject: function(point) {\n return this.transform.pointLocation(Point.convert(point));\n },\n\n /**\n * Get all features at a point ([x, y])\n *\n * @param {Array} point [x, y] pixel coordinates\n * @param {Object} params\n * @param {number} [params.radius=0] Optional. Radius in pixels to search in\n * @param {string} params.layer Optional. Only return features from a given layer\n * @param {string} params.type Optional. Either `raster` or `vector`\n * @param {featuresAtCallback} callback function that returns the response\n *\n * @callback featuresAtCallback\n * @param {Object|null} err Error _If any_\n * @param {Array} features Displays a JSON array of features given the passed parameters of `featuresAt`\n *\n * @returns {Map} `this`\n */\n featuresAt: function(point, params, callback) {\n var coord = this.transform.pointCoordinate(Point.convert(point));\n this.style.featuresAt(coord, params, callback);\n return this;\n },\n\n /**\n * Replaces the map's style object\n *\n * @param {Object} style A style object formatted as JSON\n * @returns {Map} `this`\n */\n setStyle: function(style) {\n if (this.style) {\n this.style\n .off('load', this._onStyleLoad)\n .off('error', this._forwardStyleEvent)\n .off('change', this._onStyleChange)\n .off('source.add', this._onSourceAdd)\n .off('source.remove', this._onSourceRemove)\n .off('source.load', this._onSourceUpdate)\n .off('source.error', this._forwardSourceEvent)\n .off('source.change', this._onSourceUpdate)\n .off('layer.add', this._forwardLayerEvent)\n .off('layer.remove', this._forwardLayerEvent)\n .off('tile.add', this._forwardTileEvent)\n .off('tile.remove', this._forwardTileEvent)\n .off('tile.load', this.update)\n .off('tile.error', this._forwardTileEvent)\n ._remove();\n\n this.off('rotate', this.style._redoPlacement);\n this.off('pitch', this.style._redoPlacement);\n }\n\n if (!style) {\n this.style = null;\n return this;\n } else if (style instanceof Style) {\n this.style = style;\n } else {\n this.style = new Style(style, this.animationLoop);\n }\n\n this.style\n .on('load', this._onStyleLoad)\n .on('error', this._forwardStyleEvent)\n .on('change', this._onStyleChange)\n .on('source.add', this._onSourceAdd)\n .on('source.remove', this._onSourceRemove)\n .on('source.load', this._onSourceUpdate)\n .on('source.error', this._forwardSourceEvent)\n .on('source.change', this._onSourceUpdate)\n .on('layer.add', this._forwardLayerEvent)\n .on('layer.remove', this._forwardLayerEvent)\n .on('tile.add', this._forwardTileEvent)\n .on('tile.remove', this._forwardTileEvent)\n .on('tile.load', this.update)\n .on('tile.error', this._forwardTileEvent);\n\n this.on('rotate', this.style._redoPlacement);\n this.on('pitch', this.style._redoPlacement);\n\n return this;\n },\n\n /**\n * Add a source to the map style.\n *\n * @param {string} id ID of the source. Must not be used by any existing source.\n * @param {Object} source source specification, following the\n * [Mapbox GL Style Reference](https://www.mapbox.com/mapbox-gl-style-spec/#sources)\n * @fires source.add\n * @returns {Map} `this`\n */\n addSource: function(id, source) {\n this.style.addSource(id, source);\n return this;\n },\n\n /**\n * Remove an existing source from the map style.\n *\n * @param {string} id ID of the source to remove\n * @fires source.remove\n * @returns {Map} `this`\n */\n removeSource: function(id) {\n this.style.removeSource(id);\n return this;\n },\n\n /**\n * Return the style source object with the given `id`.\n *\n * @param {string} id source ID\n * @returns {Object}\n */\n getSource: function(id) {\n return this.style.getSource(id);\n },\n\n /**\n * Add a layer to the map style. The layer will be inserted before the layer with\n * ID `before`, or appended if `before` is omitted.\n * @param {Layer} layer\n * @param {string=} before ID of an existing layer to insert before\n * @fires layer.add\n * @returns {Map} `this`\n */\n addLayer: function(layer, before) {\n this.style.addLayer(layer, before);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Remove the layer with the given `id` from the map. Any layers which refer to the\n * specified layer via a `ref` property are also removed.\n *\n * @param {string} id\n * @fires layer.remove\n * @returns {Map} this\n */\n removeLayer: function(id) {\n this.style.removeLayer(id);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Set the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {Array} filter filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n * @returns {Map} `this`\n */\n setFilter: function(layer, filter) {\n this.style.setFilter(layer, filter);\n return this;\n },\n\n /**\n * Get the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @returns {Array} filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n */\n getFilter: function(layer) {\n return this.style.getFilter(layer);\n },\n\n /**\n * Set the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {*} value value for the paint propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @param {string=} klass optional class specifier for the property\n * @returns {Map} `this`\n */\n setPaintProperty: function(layer, name, value, klass) {\n this.style.setPaintProperty(layer, name, value, klass);\n this.style._cascade(this._classes);\n this.update(true);\n return this;\n },\n\n /**\n * Get the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the paint propery\n */\n getPaintProperty: function(layer, name, klass) {\n return this.style.getPaintProperty(layer, name, klass);\n },\n\n /**\n * Set the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {*} value value for the layout propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @returns {Map} `this`\n */\n setLayoutProperty: function(layer, name, value) {\n this.style.setLayoutProperty(layer, name, value);\n return this;\n },\n\n /**\n * Get the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the layout propery\n */\n getLayoutProperty: function(layer, name) {\n return this.style.getLayoutProperty(layer, name);\n },\n\n /**\n * Get the Map's container as an HTML element\n * @returns {HTMLElement} container\n */\n getContainer: function() {\n return this._container;\n },\n\n /**\n * Get the Map's canvas as an HTML canvas\n * @returns {HTMLElement} canvas\n */\n getCanvas: function() {\n return this._canvas.getElement();\n },\n\n _move: function(zoom, rotate, pitch) {\n\n this.update(zoom).fire('move');\n\n if (zoom) this.fire('zoom');\n if (rotate) this.fire('rotate');\n if (pitch) this.fire('pitch');\n\n return this;\n },\n\n // map setup code\n _setupContainer: function() {\n var id = this.options.container;\n var container = this._container = typeof id === 'string' ? document.getElementById(id) : id;\n if (container) container.classList.add('mapboxgl-map');\n this._canvas = new Canvas(this, container);\n },\n\n _setupControlPos: function() {\n var corners = this._controlCorners = {};\n var prefix = 'mapboxgl-ctrl-';\n var container = this.getContainer();\n\n function createCorner(pos) {\n var className = prefix + pos;\n corners[pos] = DOM.create('div', className, container);\n }\n\n if (container && typeof document === 'object') {\n createCorner('top-left');\n createCorner('top-right');\n createCorner('bottom-left');\n createCorner('bottom-right');\n }\n },\n\n _setupPainter: function() {\n var gl = this._canvas.getWebGLContext(this.options.failIfMajorPerformanceCaveat);\n\n if (!gl) {\n console.error('Failed to initialize WebGL');\n return;\n }\n\n this.painter = new GLPainter(gl, this.transform);\n },\n\n _contextLost: function(event) {\n event.preventDefault();\n if (this._frameId) {\n browser.cancelFrame(this._frameId);\n }\n },\n\n _contextRestored: function() {\n this._setupPainter();\n this.resize();\n this.update();\n },\n\n /**\n * Is this map fully loaded? If the style isn't loaded\n * or it has a change to the sources or style that isn't\n * propagated to its style, return false.\n *\n * @returns {boolean} whether the map is loaded\n */\n loaded: function() {\n if (this._styleDirty || this._sourcesDirty)\n return false;\n if (this.style && !this.style.loaded())\n return false;\n return true;\n },\n\n /**\n * Update this map's style and re-render the map.\n *\n * @param {Object} updateStyle new style\n * @returns {Map} this\n */\n update: function(updateStyle) {\n if (!this.style) return this;\n\n this._styleDirty = this._styleDirty || updateStyle;\n this._sourcesDirty = true;\n\n this._rerender();\n\n return this;\n },\n\n /**\n * Call when a (re-)render of the map is required, e.g. when the\n * user panned or zoomed,f or new data is available.\n * @returns {Map} this\n */\n render: function() {\n if (this.style && this._styleDirty) {\n this._styleDirty = false;\n this.style._recalculate(this.transform.zoom);\n }\n\n if (this.style && this._sourcesDirty && !this._sourcesDirtyTimeout) {\n this._sourcesDirty = false;\n this._sourcesDirtyTimeout = setTimeout(function() {\n this._sourcesDirtyTimeout = null;\n }.bind(this), 50);\n this.style._updateSources(this.transform);\n }\n\n this.painter.render(this.style, {\n debug: this.debug,\n vertices: this.vertices,\n rotating: this.rotating,\n zooming: this.zooming\n });\n\n this.fire('render');\n\n if (this.loaded() && !this._loaded) {\n this._loaded = true;\n this.fire('load');\n }\n\n this._frameId = null;\n\n if (!this.animationLoop.stopped()) {\n this._styleDirty = true;\n }\n\n if (this._sourcesDirty || this._repaint || !this.animationLoop.stopped()) {\n this._rerender();\n }\n\n return this;\n },\n\n /**\n * Destroys the map's underlying resources, including web workers.\n * @returns {Map} this\n */\n remove: function() {\n if (this._hash) this._hash.remove();\n browser.cancelFrame(this._frameId);\n clearTimeout(this._sourcesDirtyTimeout);\n this.setStyle(null);\n return this;\n },\n\n _rerender: function() {\n if (this.style && !this._frameId) {\n this._frameId = browser.frame(this.render);\n }\n },\n\n _forwardStyleEvent: function(e) {\n this.fire('style.' + e.type, util.extend({style: e.target}, e));\n },\n\n _forwardSourceEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardLayerEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardTileEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _onStyleLoad: function(e) {\n this.style._cascade(this._classes, {transition: false});\n this._forwardStyleEvent(e);\n },\n\n _onStyleChange: function(e) {\n this.update(true);\n this._forwardStyleEvent(e);\n },\n\n _onSourceAdd: function(e) {\n var source = e.source;\n if (source.onAdd)\n source.onAdd(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceRemove: function(e) {\n var source = e.source;\n if (source.onRemove)\n source.onRemove(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceUpdate: function(e) {\n this.update();\n this._forwardSourceEvent(e);\n }\n}","path":"js/ui/map.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/map.js#L540-L542"},"params":[{"title":"param","description":"ID of a layer","type":{"type":"NameExpression","name":"string"},"name":"layer"},{"title":"param","description":"name of a paint property","type":{"type":"NameExpression","name":"string"},"name":"name"},{"title":"param","description":"optional class specifier for the property","type":{"type":"OptionalType","expression":{"type":"NameExpression","name":"string"}},"name":"klass"}],"returns":[{"title":"returns","description":"value for the paint propery","type":{"type":"AllLiteral"}}],"name":"getPaintProperty","memberof":"Map","scope":"instance","members":{"instance":[],"static":[]},"path":["Map","getPaintProperty"]},{"description":"Get the current zoom","tags":[{"title":"returns","description":null,"type":{"type":"NameExpression","name":"number"}},{"title":"name","name":"getZoom"},{"title":"memberof","description":"Map"},{"title":"instance"}],"context":{"loc":{"start":{"line":207,"column":4},"end":{"line":207,"column":55}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/map.js","code":"{\n\n options: {\n center: [0, 0],\n zoom: 0,\n bearing: 0,\n pitch: 0,\n\n minZoom: 0,\n maxZoom: 20,\n\n interactive: true,\n hash: false,\n\n attributionControl: true,\n\n failIfMajorPerformanceCaveat: false\n },\n\n addControl: function(control) {\n control.addTo(this);\n return this;\n },\n\n /**\n * Sets a map position\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @param {number} zoom Map zoom level\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setView: function(center, zoom, bearing, pitch) {\n this.stop();\n\n var tr = this.transform,\n zoomChanged = tr.zoom !== +zoom,\n bearingChanged = tr.bearing !== +bearing,\n pitchChanged = tr.pitch !== +pitch;\n\n tr.center = LatLng.convert(center);\n tr.zoom = +zoom;\n tr.bearing = +bearing;\n tr.pitch = +pitch;\n\n return this\n .fire('movestart')\n ._move(zoomChanged, bearingChanged, pitchChanged)\n .fire('moveend');\n },\n\n /**\n * Sets a map location\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setCenter: function(center) {\n this.setView(center, this.getZoom(), this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map zoom\n *\n * @param {number} zoom Map zoom level\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setZoom: function(zoom) {\n this.setView(this.getCenter(), zoom, this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map rotation\n *\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setBearing: function(bearing) {\n this.setView(this.getCenter(), this.getZoom(), bearing, this.getPitch());\n },\n\n /**\n * Sets a map angle\n *\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setPitch: function(pitch) {\n this.setView(this.getCenter(), this.getZoom(), this.getBearing(), pitch);\n },\n\n /**\n * Get the current view geographical point\n * @returns {LatLng}\n */\n getCenter: function() { return this.transform.center; },\n\n /**\n * Get the current zoom\n * @returns {number}\n */\n getZoom: function() { return this.transform.zoom; },\n\n /**\n * Get the current bearing in degrees\n * @returns {number}\n */\n getBearing: function() { return this.transform.bearing; },\n\n /**\n * Get the current angle in degrees\n * @returns {number}\n */\n getPitch: function() { return this.transform.pitch; },\n\n /**\n * @typedef {Object} [styleOptions]\n * @param {Boolean} [styleOptions.transition=true]\n */\n\n /**\n * Adds a style class to a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n addClass: function(klass, options) {\n if (this._classes[klass]) return;\n this._classes[klass] = true;\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Removes a style class from a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n removeClass: function(klass, options) {\n if (!this._classes[klass]) return;\n delete this._classes[klass];\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Helper method to add more than one class\n *\n * @param {Array} klasses An array of class names\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n setClasses: function(klasses, options) {\n this._classes = {};\n for (var i = 0; i < klasses.length; i++) {\n this._classes[klasses[i]] = true;\n }\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Check whether a style class is active\n *\n * @param {string} klass Name of style class\n * @returns {boolean}\n */\n hasClass: function(klass) {\n return !!this._classes[klass];\n },\n\n /**\n * Return an array of the current active style classes\n *\n * @returns {boolean}\n */\n getClasses: function() {\n return Object.keys(this._classes);\n },\n\n /**\n * Detect the map's new width and height and resize it.\n *\n * @returns {Map} `this`\n */\n resize: function() {\n var width = 0, height = 0;\n\n if (this._container) {\n width = this._container.offsetWidth || 400;\n height = this._container.offsetHeight || 300;\n }\n\n this._canvas.resize(width, height);\n\n this.transform.width = width;\n this.transform.height = height;\n this.transform._constrain();\n\n this.painter.resize(width, height);\n\n return this\n .fire('movestart')\n ._move()\n .fire('resize')\n .fire('moveend');\n },\n\n /**\n * Get the map's geographical bounds\n *\n * @returns {LatLngBounds}\n */\n getBounds: function() {\n return new LatLngBounds(\n this.transform.pointLocation(new Point(0, 0)),\n this.transform.pointLocation(this.transform.size));\n },\n\n /**\n * Get pixel coordinates (relative to map container) given a geographical location\n *\n * @param {LatLng} latlng\n * @returns {Object} `x` and `y` coordinates\n */\n project: function(latlng) {\n return this.transform.locationPoint(LatLng.convert(latlng));\n },\n\n /**\n * Get geographical coordinates given pixel coordinates\n *\n * @param {Array} point [x, y] pixel coordinates\n * @returns {LatLng}\n */\n unproject: function(point) {\n return this.transform.pointLocation(Point.convert(point));\n },\n\n /**\n * Get all features at a point ([x, y])\n *\n * @param {Array} point [x, y] pixel coordinates\n * @param {Object} params\n * @param {number} [params.radius=0] Optional. Radius in pixels to search in\n * @param {string} params.layer Optional. Only return features from a given layer\n * @param {string} params.type Optional. Either `raster` or `vector`\n * @param {featuresAtCallback} callback function that returns the response\n *\n * @callback featuresAtCallback\n * @param {Object|null} err Error _If any_\n * @param {Array} features Displays a JSON array of features given the passed parameters of `featuresAt`\n *\n * @returns {Map} `this`\n */\n featuresAt: function(point, params, callback) {\n var coord = this.transform.pointCoordinate(Point.convert(point));\n this.style.featuresAt(coord, params, callback);\n return this;\n },\n\n /**\n * Replaces the map's style object\n *\n * @param {Object} style A style object formatted as JSON\n * @returns {Map} `this`\n */\n setStyle: function(style) {\n if (this.style) {\n this.style\n .off('load', this._onStyleLoad)\n .off('error', this._forwardStyleEvent)\n .off('change', this._onStyleChange)\n .off('source.add', this._onSourceAdd)\n .off('source.remove', this._onSourceRemove)\n .off('source.load', this._onSourceUpdate)\n .off('source.error', this._forwardSourceEvent)\n .off('source.change', this._onSourceUpdate)\n .off('layer.add', this._forwardLayerEvent)\n .off('layer.remove', this._forwardLayerEvent)\n .off('tile.add', this._forwardTileEvent)\n .off('tile.remove', this._forwardTileEvent)\n .off('tile.load', this.update)\n .off('tile.error', this._forwardTileEvent)\n ._remove();\n\n this.off('rotate', this.style._redoPlacement);\n this.off('pitch', this.style._redoPlacement);\n }\n\n if (!style) {\n this.style = null;\n return this;\n } else if (style instanceof Style) {\n this.style = style;\n } else {\n this.style = new Style(style, this.animationLoop);\n }\n\n this.style\n .on('load', this._onStyleLoad)\n .on('error', this._forwardStyleEvent)\n .on('change', this._onStyleChange)\n .on('source.add', this._onSourceAdd)\n .on('source.remove', this._onSourceRemove)\n .on('source.load', this._onSourceUpdate)\n .on('source.error', this._forwardSourceEvent)\n .on('source.change', this._onSourceUpdate)\n .on('layer.add', this._forwardLayerEvent)\n .on('layer.remove', this._forwardLayerEvent)\n .on('tile.add', this._forwardTileEvent)\n .on('tile.remove', this._forwardTileEvent)\n .on('tile.load', this.update)\n .on('tile.error', this._forwardTileEvent);\n\n this.on('rotate', this.style._redoPlacement);\n this.on('pitch', this.style._redoPlacement);\n\n return this;\n },\n\n /**\n * Add a source to the map style.\n *\n * @param {string} id ID of the source. Must not be used by any existing source.\n * @param {Object} source source specification, following the\n * [Mapbox GL Style Reference](https://www.mapbox.com/mapbox-gl-style-spec/#sources)\n * @fires source.add\n * @returns {Map} `this`\n */\n addSource: function(id, source) {\n this.style.addSource(id, source);\n return this;\n },\n\n /**\n * Remove an existing source from the map style.\n *\n * @param {string} id ID of the source to remove\n * @fires source.remove\n * @returns {Map} `this`\n */\n removeSource: function(id) {\n this.style.removeSource(id);\n return this;\n },\n\n /**\n * Return the style source object with the given `id`.\n *\n * @param {string} id source ID\n * @returns {Object}\n */\n getSource: function(id) {\n return this.style.getSource(id);\n },\n\n /**\n * Add a layer to the map style. The layer will be inserted before the layer with\n * ID `before`, or appended if `before` is omitted.\n * @param {Layer} layer\n * @param {string=} before ID of an existing layer to insert before\n * @fires layer.add\n * @returns {Map} `this`\n */\n addLayer: function(layer, before) {\n this.style.addLayer(layer, before);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Remove the layer with the given `id` from the map. Any layers which refer to the\n * specified layer via a `ref` property are also removed.\n *\n * @param {string} id\n * @fires layer.remove\n * @returns {Map} this\n */\n removeLayer: function(id) {\n this.style.removeLayer(id);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Set the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {Array} filter filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n * @returns {Map} `this`\n */\n setFilter: function(layer, filter) {\n this.style.setFilter(layer, filter);\n return this;\n },\n\n /**\n * Get the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @returns {Array} filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n */\n getFilter: function(layer) {\n return this.style.getFilter(layer);\n },\n\n /**\n * Set the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {*} value value for the paint propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @param {string=} klass optional class specifier for the property\n * @returns {Map} `this`\n */\n setPaintProperty: function(layer, name, value, klass) {\n this.style.setPaintProperty(layer, name, value, klass);\n this.style._cascade(this._classes);\n this.update(true);\n return this;\n },\n\n /**\n * Get the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the paint propery\n */\n getPaintProperty: function(layer, name, klass) {\n return this.style.getPaintProperty(layer, name, klass);\n },\n\n /**\n * Set the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {*} value value for the layout propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @returns {Map} `this`\n */\n setLayoutProperty: function(layer, name, value) {\n this.style.setLayoutProperty(layer, name, value);\n return this;\n },\n\n /**\n * Get the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the layout propery\n */\n getLayoutProperty: function(layer, name) {\n return this.style.getLayoutProperty(layer, name);\n },\n\n /**\n * Get the Map's container as an HTML element\n * @returns {HTMLElement} container\n */\n getContainer: function() {\n return this._container;\n },\n\n /**\n * Get the Map's canvas as an HTML canvas\n * @returns {HTMLElement} canvas\n */\n getCanvas: function() {\n return this._canvas.getElement();\n },\n\n _move: function(zoom, rotate, pitch) {\n\n this.update(zoom).fire('move');\n\n if (zoom) this.fire('zoom');\n if (rotate) this.fire('rotate');\n if (pitch) this.fire('pitch');\n\n return this;\n },\n\n // map setup code\n _setupContainer: function() {\n var id = this.options.container;\n var container = this._container = typeof id === 'string' ? document.getElementById(id) : id;\n if (container) container.classList.add('mapboxgl-map');\n this._canvas = new Canvas(this, container);\n },\n\n _setupControlPos: function() {\n var corners = this._controlCorners = {};\n var prefix = 'mapboxgl-ctrl-';\n var container = this.getContainer();\n\n function createCorner(pos) {\n var className = prefix + pos;\n corners[pos] = DOM.create('div', className, container);\n }\n\n if (container && typeof document === 'object') {\n createCorner('top-left');\n createCorner('top-right');\n createCorner('bottom-left');\n createCorner('bottom-right');\n }\n },\n\n _setupPainter: function() {\n var gl = this._canvas.getWebGLContext(this.options.failIfMajorPerformanceCaveat);\n\n if (!gl) {\n console.error('Failed to initialize WebGL');\n return;\n }\n\n this.painter = new GLPainter(gl, this.transform);\n },\n\n _contextLost: function(event) {\n event.preventDefault();\n if (this._frameId) {\n browser.cancelFrame(this._frameId);\n }\n },\n\n _contextRestored: function() {\n this._setupPainter();\n this.resize();\n this.update();\n },\n\n /**\n * Is this map fully loaded? If the style isn't loaded\n * or it has a change to the sources or style that isn't\n * propagated to its style, return false.\n *\n * @returns {boolean} whether the map is loaded\n */\n loaded: function() {\n if (this._styleDirty || this._sourcesDirty)\n return false;\n if (this.style && !this.style.loaded())\n return false;\n return true;\n },\n\n /**\n * Update this map's style and re-render the map.\n *\n * @param {Object} updateStyle new style\n * @returns {Map} this\n */\n update: function(updateStyle) {\n if (!this.style) return this;\n\n this._styleDirty = this._styleDirty || updateStyle;\n this._sourcesDirty = true;\n\n this._rerender();\n\n return this;\n },\n\n /**\n * Call when a (re-)render of the map is required, e.g. when the\n * user panned or zoomed,f or new data is available.\n * @returns {Map} this\n */\n render: function() {\n if (this.style && this._styleDirty) {\n this._styleDirty = false;\n this.style._recalculate(this.transform.zoom);\n }\n\n if (this.style && this._sourcesDirty && !this._sourcesDirtyTimeout) {\n this._sourcesDirty = false;\n this._sourcesDirtyTimeout = setTimeout(function() {\n this._sourcesDirtyTimeout = null;\n }.bind(this), 50);\n this.style._updateSources(this.transform);\n }\n\n this.painter.render(this.style, {\n debug: this.debug,\n vertices: this.vertices,\n rotating: this.rotating,\n zooming: this.zooming\n });\n\n this.fire('render');\n\n if (this.loaded() && !this._loaded) {\n this._loaded = true;\n this.fire('load');\n }\n\n this._frameId = null;\n\n if (!this.animationLoop.stopped()) {\n this._styleDirty = true;\n }\n\n if (this._sourcesDirty || this._repaint || !this.animationLoop.stopped()) {\n this._rerender();\n }\n\n return this;\n },\n\n /**\n * Destroys the map's underlying resources, including web workers.\n * @returns {Map} this\n */\n remove: function() {\n if (this._hash) this._hash.remove();\n browser.cancelFrame(this._frameId);\n clearTimeout(this._sourcesDirtyTimeout);\n this.setStyle(null);\n return this;\n },\n\n _rerender: function() {\n if (this.style && !this._frameId) {\n this._frameId = browser.frame(this.render);\n }\n },\n\n _forwardStyleEvent: function(e) {\n this.fire('style.' + e.type, util.extend({style: e.target}, e));\n },\n\n _forwardSourceEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardLayerEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardTileEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _onStyleLoad: function(e) {\n this.style._cascade(this._classes, {transition: false});\n this._forwardStyleEvent(e);\n },\n\n _onStyleChange: function(e) {\n this.update(true);\n this._forwardStyleEvent(e);\n },\n\n _onSourceAdd: function(e) {\n var source = e.source;\n if (source.onAdd)\n source.onAdd(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceRemove: function(e) {\n var source = e.source;\n if (source.onRemove)\n source.onRemove(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceUpdate: function(e) {\n this.update();\n this._forwardSourceEvent(e);\n }\n}","path":"js/ui/map.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/map.js#L207-L207"},"returns":[{"title":"returns","description":null,"type":{"type":"NameExpression","name":"number"}}],"name":"getZoom","memberof":"Map","scope":"instance","members":{"instance":[],"static":[]},"path":["Map","getZoom"]},{"description":"Pan by a certain number of pixels","tags":[{"title":"param","description":"[x, y]","type":{"type":"NameExpression","name":"Array"},"name":"offset"},{"title":"param","description":null,"type":null,"name":"animOptions"},{"title":"fires","description":"movestart"},{"title":"fires","description":"moveend"},{"title":"returns","description":null,"type":{"type":"NameExpression","name":"this"}},{"title":"name","name":"panBy"},{"title":"memberof","description":"Map"},{"title":"instance"}],"context":{"loc":{"start":{"line":59,"column":4},"end":{"line":62,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/easings.js","code":"{\n isEasing: function() {\n return !!this._abortFn;\n },\n\n /**\n * Stop current animation\n *\n * @returns {this}\n */\n stop: function() {\n if (this._abortFn) {\n this._abortFn.call(this);\n delete this._abortFn;\n\n this._finishFn.call(this);\n delete this._finishFn;\n }\n return this;\n },\n\n _ease: function(frame, finish, options) {\n this._finishFn = finish;\n this._abortFn = browser.timed(function (t) {\n frame.call(this, options.easing(t));\n if (t === 1) {\n delete this._abortFn;\n this._finishFn.call(this);\n delete this._finishFn;\n }\n }, options.animate === false ? 0 : options.duration, this);\n },\n\n /**\n * Pan by a certain number of pixels\n *\n * @param {Array} offset [x, y]\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n panBy: function(offset, options) {\n this.panTo(this.transform.center, util.extend({offset: Point.convert(offset).mult(-1)}, options));\n return this;\n },\n\n /**\n * Pan to a certain location with easing\n *\n * @param {Object} latlng a `LatLng` object\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n panTo: function(latlng, options) {\n this.stop();\n\n latlng = LatLng.convert(latlng);\n\n options = util.extend({\n duration: 500,\n easing: util.ease,\n offset: [0, 0]\n }, options);\n\n var tr = this.transform,\n offset = Point.convert(options.offset).rotate(-tr.angle),\n from = tr.point,\n to = tr.project(latlng).sub(offset);\n\n if (!options.noMoveStart) {\n this.fire('movestart');\n }\n\n this._ease(function(k) {\n tr.center = tr.unproject(from.add(to.sub(from).mult(k)));\n this._move();\n }, function() {\n this.fire('moveend');\n }, options);\n\n return this;\n },\n\n /**\n * Zooms to a certain zoom level with easing.\n *\n * @param {Number} zoom\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n zoomTo: function(zoom, options) {\n this.stop();\n\n options = util.extend({\n duration: 500\n }, options);\n\n options.easing = this._updateEasing(options.duration, zoom, options.easing);\n\n var tr = this.transform,\n around = tr.center,\n startZoom = tr.zoom;\n\n if (options.around) {\n around = LatLng.convert(options.around);\n } else if (options.offset) {\n around = tr.pointLocation(tr.centerPoint.add(Point.convert(options.offset)));\n }\n\n if (options.animate === false) options.duration = 0;\n\n if (!this.zooming) {\n this.zooming = true;\n this.fire('movestart');\n }\n\n this._ease(function(k) {\n tr.setZoomAround(interpolate(startZoom, zoom, k), around);\n this.animationLoop.set(300); // text fading\n this._move(true);\n }, function() {\n this.ease = null;\n if (options.duration >= 200) {\n this.zooming = false;\n this.fire('moveend');\n }\n }, options);\n\n if (options.duration < 200) {\n clearTimeout(this._onZoomEnd);\n this._onZoomEnd = setTimeout(function() {\n this.zooming = false;\n this._rerender();\n this.fire('moveend');\n }.bind(this), 200);\n }\n\n return this;\n },\n\n /**\n * Zoom in by 1 level\n *\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n zoomIn: function(options) {\n this.zoomTo(this.getZoom() + 1, options);\n },\n\n /**\n * Zoom out by 1 level\n *\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n zoomOut: function(options) {\n this.zoomTo(this.getZoom() - 1, options);\n },\n\n /**\n * Rotate bearing by a certain number of degrees with easing\n *\n * @param {Number} bearing\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n rotateTo: function(bearing, options) {\n this.stop();\n\n options = util.extend({\n duration: 500,\n easing: util.ease\n }, options);\n\n var tr = this.transform,\n start = this.getBearing(),\n around = tr.center;\n\n if (options.around) {\n around = LatLng.convert(options.around);\n } else if (options.offset) {\n around = tr.pointLocation(tr.centerPoint.add(Point.convert(options.offset)));\n }\n\n bearing = this._normalizeBearing(bearing, start);\n\n this.rotating = true;\n this.fire('movestart');\n\n this._ease(function(k) {\n tr.setBearingAround(interpolate(start, bearing, k), around);\n this._move(false, true);\n }, function() {\n this.rotating = false;\n this.fire('moveend');\n }, options);\n\n return this;\n },\n\n /**\n * Sets map bearing to 0 (north) with easing\n *\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n resetNorth: function(options) {\n return this.rotateTo(0, util.extend({duration: 1000}, options));\n },\n\n /**\n * Zoom to contain certain geographical bounds\n *\n * @param {Array} bounds [[minLat, minLng], [maxLat, maxLng]]\n * @param {Object} options\n * @param {Number} [options.speed=1.2] How fast animation occurs\n * @param {Number} [options.curve=1.42] How much zooming out occurs during animation\n * @param {Function} options.easing\n * @param {Number} options.padding how much padding there is around the given bounds on each side in pixels\n * @param {Number} options.maxZoom\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n fitBounds: function(bounds, options) {\n\n options = util.extend({\n padding: 0,\n offset: [0, 0],\n maxZoom: Infinity\n }, options);\n\n bounds = LatLngBounds.convert(bounds);\n\n var offset = Point.convert(options.offset),\n tr = this.transform,\n nw = tr.project(bounds.getNorthWest()),\n se = tr.project(bounds.getSouthEast()),\n size = se.sub(nw),\n center = tr.unproject(nw.add(se).div(2)),\n\n scaleX = (tr.width - options.padding * 2 - Math.abs(offset.x) * 2) / size.x,\n scaleY = (tr.height - options.padding * 2 - Math.abs(offset.y) * 2) / size.y,\n\n zoom = Math.min(tr.scaleZoom(tr.scale * Math.min(scaleX, scaleY)), options.maxZoom);\n\n return options.linear ?\n this.easeTo(center, zoom, 0, options) :\n this.flyTo(center, zoom, 0, options);\n },\n\n /**\n * Easing animation to a specified location/zoom/bearing\n *\n * @param {Object} latlng a `LatLng` object\n * @param {Number} zoom\n * @param {Number} bearing\n * @param {Number} pitch\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n easeTo: function(latlng, zoom, bearing, pitch, options) {\n this.stop();\n\n options = util.extend({\n offset: [0, 0],\n duration: 500,\n easing: util.ease\n }, options);\n\n var tr = this.transform,\n offset = Point.convert(options.offset).rotate(-tr.angle),\n startZoom = this.getZoom(),\n startBearing = this.getBearing(),\n startPitch = this.getPitch();\n\n latlng = LatLng.convert(latlng);\n zoom = zoom === undefined ? startZoom : zoom;\n bearing = bearing === undefined ? startBearing : this._normalizeBearing(bearing, startBearing);\n pitch = pitch === undefined ? startPitch : pitch;\n\n var scale = tr.zoomScale(zoom - startZoom),\n from = tr.point,\n to = latlng ? tr.project(latlng).sub(offset.div(scale)) : tr.point,\n around;\n\n if (zoom !== startZoom) {\n around = tr.pointLocation(tr.centerPoint.add(to.sub(from).div(1 - 1 / scale)));\n this.zooming = true;\n }\n if (startBearing !== bearing) this.rotating = true;\n\n this.fire('movestart');\n\n this._ease(function (k) {\n if (zoom !== startZoom) {\n tr.setZoomAround(interpolate(startZoom, zoom, k), around);\n } else {\n tr.center = tr.unproject(from.add(to.sub(from).mult(k)));\n }\n\n if (bearing !== startBearing) {\n tr.bearing = interpolate(startBearing, bearing, k);\n }\n\n if (pitch !== startPitch) {\n tr.pitch = interpolate(startPitch, pitch, k);\n }\n\n this.animationLoop.set(300); // text fading\n this._move(zoom !== startZoom, bearing !== startBearing);\n }, function() {\n this.zooming = false;\n this.rotating = false;\n this.fire('moveend');\n }, options);\n\n return this;\n },\n\n /**\n * Flying animation to a specified location/zoom/bearing with automatic curve\n *\n * @param {Object} latlng a `LatLng` object\n * @param {Number} zoom\n * @param {Number} bearing\n * @param {Object} options\n * @param {Number} [options.speed=1.2] How fast animation occurs\n * @param {Number} [options.curve=1.42] How much zooming out occurs during animation\n * @param {Function} options.easing\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n flyTo: function(latlng, zoom, bearing, options) {\n this.stop();\n\n options = util.extend({\n offset: [0, 0],\n speed: 1.2,\n curve: 1.42,\n easing: util.ease\n }, options);\n\n latlng = LatLng.convert(latlng);\n\n var offset = Point.convert(options.offset),\n tr = this.transform,\n startZoom = this.getZoom(),\n startBearing = this.getBearing();\n\n zoom = zoom === undefined ? startZoom : zoom;\n bearing = bearing === undefined ? startBearing : this._normalizeBearing(bearing, startBearing);\n\n var scale = tr.zoomScale(zoom - startZoom),\n from = tr.point,\n to = tr.project(latlng).sub(offset.div(scale));\n\n if (options.animate === false) {\n return this.setView(latlng, zoom, bearing, this.getPitch());\n }\n\n var startWorldSize = tr.worldSize,\n rho = options.curve,\n V = options.speed,\n\n w0 = Math.max(tr.width, tr.height),\n w1 = w0 / scale,\n u1 = to.sub(from).mag(),\n rho2 = rho * rho;\n\n function r(i) {\n var b = (w1 * w1 - w0 * w0 + (i ? -1 : 1) * rho2 * rho2 * u1 * u1) / (2 * (i ? w1 : w0) * rho2 * u1);\n return Math.log(Math.sqrt(b * b + 1) - b);\n }\n\n function sinh(n) { return (Math.exp(n) - Math.exp(-n)) / 2; }\n function cosh(n) { return (Math.exp(n) + Math.exp(-n)) / 2; }\n function tanh(n) { return sinh(n) / cosh(n); }\n\n var r0 = r(0),\n w = function (s) { return (cosh(r0) / cosh(r0 + rho * s)); },\n u = function (s) { return w0 * ((cosh(r0) * tanh(r0 + rho * s) - sinh(r0)) / rho2) / u1; },\n S = (r(1) - r0) / rho;\n\n if (Math.abs(u1) < 0.000001) {\n if (Math.abs(w0 - w1) < 0.000001) return this;\n\n var k = w1 < w0 ? -1 : 1;\n S = Math.abs(Math.log(w1 / w0)) / rho;\n\n u = function() { return 0; };\n w = function(s) { return Math.exp(k * rho * s); };\n }\n\n options.duration = 1000 * S / V;\n\n this.zooming = true;\n if (startBearing !== bearing) this.rotating = true;\n\n this.fire('movestart');\n\n this._ease(function (k) {\n var s = k * S,\n us = u(s);\n\n tr.zoom = startZoom + tr.scaleZoom(1 / w(s));\n tr.center = tr.unproject(from.add(to.sub(from).mult(us)), startWorldSize);\n\n if (bearing !== startBearing) {\n tr.bearing = interpolate(startBearing, bearing, k);\n }\n\n this.animationLoop.set(300); // text fading\n\n this._move(true, bearing !== startBearing);\n }, function() {\n this.zooming = false;\n this.rotating = false;\n this.fire('moveend');\n }, options);\n\n return this;\n },\n\n // convert bearing so that it's numerically close to the current one so that it interpolates properly\n _normalizeBearing: function(bearing, currentBearing) {\n bearing = util.wrap(bearing, -180, 180);\n var diff = Math.abs(bearing - currentBearing);\n if (Math.abs(bearing - 360 - currentBearing) < diff) bearing -= 360;\n if (Math.abs(bearing + 360 - currentBearing) < diff) bearing += 360;\n return bearing;\n },\n\n _updateEasing: function(duration, zoom, bezier) {\n var easing;\n\n if (this.ease) {\n var ease = this.ease,\n t = (Date.now() - ease.start) / ease.duration,\n speed = ease.easing(t + 0.01) - ease.easing(t),\n\n // Quick hack to make new bezier that is continuous with last\n x = 0.27 / Math.sqrt(speed * speed + 0.0001) * 0.01,\n y = Math.sqrt(0.27 * 0.27 - x * x);\n\n easing = util.bezier(x, y, 0.25, 1);\n } else {\n easing = bezier ? util.bezier.apply(util, bezier) : util.ease;\n }\n\n // store information on current easing\n this.ease = {\n start: (new Date()).getTime(),\n to: Math.pow(2, zoom),\n duration: duration,\n easing: easing\n };\n\n return easing;\n }\n}","path":"js/ui/easings.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/easings.js#L59-L62"},"params":[{"title":"param","description":"[x, y]","type":{"type":"NameExpression","name":"Array"},"name":"offset"},{"title":"param","description":null,"type":null,"name":"animOptions"}],"returns":[{"title":"returns","description":null,"type":{"type":"NameExpression","name":"this"}}],"name":"panBy","memberof":"Map","scope":"instance","members":{"instance":[],"static":[]},"path":["Map","panBy"]},{"description":"Is this map fully loaded? If the style isn't loaded\nor it has a change to the sources or style that isn't\npropagated to its style, return false.","tags":[{"title":"returns","description":"whether the map is loaded","type":{"type":"NameExpression","name":"boolean"}},{"title":"name","name":"loaded"},{"title":"memberof","description":"Map"},{"title":"instance"}],"context":{"loc":{"start":{"line":653,"column":4},"end":{"line":659,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/map.js","code":"{\n\n options: {\n center: [0, 0],\n zoom: 0,\n bearing: 0,\n pitch: 0,\n\n minZoom: 0,\n maxZoom: 20,\n\n interactive: true,\n hash: false,\n\n attributionControl: true,\n\n failIfMajorPerformanceCaveat: false\n },\n\n addControl: function(control) {\n control.addTo(this);\n return this;\n },\n\n /**\n * Sets a map position\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @param {number} zoom Map zoom level\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setView: function(center, zoom, bearing, pitch) {\n this.stop();\n\n var tr = this.transform,\n zoomChanged = tr.zoom !== +zoom,\n bearingChanged = tr.bearing !== +bearing,\n pitchChanged = tr.pitch !== +pitch;\n\n tr.center = LatLng.convert(center);\n tr.zoom = +zoom;\n tr.bearing = +bearing;\n tr.pitch = +pitch;\n\n return this\n .fire('movestart')\n ._move(zoomChanged, bearingChanged, pitchChanged)\n .fire('moveend');\n },\n\n /**\n * Sets a map location\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setCenter: function(center) {\n this.setView(center, this.getZoom(), this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map zoom\n *\n * @param {number} zoom Map zoom level\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setZoom: function(zoom) {\n this.setView(this.getCenter(), zoom, this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map rotation\n *\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setBearing: function(bearing) {\n this.setView(this.getCenter(), this.getZoom(), bearing, this.getPitch());\n },\n\n /**\n * Sets a map angle\n *\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setPitch: function(pitch) {\n this.setView(this.getCenter(), this.getZoom(), this.getBearing(), pitch);\n },\n\n /**\n * Get the current view geographical point\n * @returns {LatLng}\n */\n getCenter: function() { return this.transform.center; },\n\n /**\n * Get the current zoom\n * @returns {number}\n */\n getZoom: function() { return this.transform.zoom; },\n\n /**\n * Get the current bearing in degrees\n * @returns {number}\n */\n getBearing: function() { return this.transform.bearing; },\n\n /**\n * Get the current angle in degrees\n * @returns {number}\n */\n getPitch: function() { return this.transform.pitch; },\n\n /**\n * @typedef {Object} [styleOptions]\n * @param {Boolean} [styleOptions.transition=true]\n */\n\n /**\n * Adds a style class to a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n addClass: function(klass, options) {\n if (this._classes[klass]) return;\n this._classes[klass] = true;\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Removes a style class from a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n removeClass: function(klass, options) {\n if (!this._classes[klass]) return;\n delete this._classes[klass];\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Helper method to add more than one class\n *\n * @param {Array} klasses An array of class names\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n setClasses: function(klasses, options) {\n this._classes = {};\n for (var i = 0; i < klasses.length; i++) {\n this._classes[klasses[i]] = true;\n }\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Check whether a style class is active\n *\n * @param {string} klass Name of style class\n * @returns {boolean}\n */\n hasClass: function(klass) {\n return !!this._classes[klass];\n },\n\n /**\n * Return an array of the current active style classes\n *\n * @returns {boolean}\n */\n getClasses: function() {\n return Object.keys(this._classes);\n },\n\n /**\n * Detect the map's new width and height and resize it.\n *\n * @returns {Map} `this`\n */\n resize: function() {\n var width = 0, height = 0;\n\n if (this._container) {\n width = this._container.offsetWidth || 400;\n height = this._container.offsetHeight || 300;\n }\n\n this._canvas.resize(width, height);\n\n this.transform.width = width;\n this.transform.height = height;\n this.transform._constrain();\n\n this.painter.resize(width, height);\n\n return this\n .fire('movestart')\n ._move()\n .fire('resize')\n .fire('moveend');\n },\n\n /**\n * Get the map's geographical bounds\n *\n * @returns {LatLngBounds}\n */\n getBounds: function() {\n return new LatLngBounds(\n this.transform.pointLocation(new Point(0, 0)),\n this.transform.pointLocation(this.transform.size));\n },\n\n /**\n * Get pixel coordinates (relative to map container) given a geographical location\n *\n * @param {LatLng} latlng\n * @returns {Object} `x` and `y` coordinates\n */\n project: function(latlng) {\n return this.transform.locationPoint(LatLng.convert(latlng));\n },\n\n /**\n * Get geographical coordinates given pixel coordinates\n *\n * @param {Array} point [x, y] pixel coordinates\n * @returns {LatLng}\n */\n unproject: function(point) {\n return this.transform.pointLocation(Point.convert(point));\n },\n\n /**\n * Get all features at a point ([x, y])\n *\n * @param {Array} point [x, y] pixel coordinates\n * @param {Object} params\n * @param {number} [params.radius=0] Optional. Radius in pixels to search in\n * @param {string} params.layer Optional. Only return features from a given layer\n * @param {string} params.type Optional. Either `raster` or `vector`\n * @param {featuresAtCallback} callback function that returns the response\n *\n * @callback featuresAtCallback\n * @param {Object|null} err Error _If any_\n * @param {Array} features Displays a JSON array of features given the passed parameters of `featuresAt`\n *\n * @returns {Map} `this`\n */\n featuresAt: function(point, params, callback) {\n var coord = this.transform.pointCoordinate(Point.convert(point));\n this.style.featuresAt(coord, params, callback);\n return this;\n },\n\n /**\n * Replaces the map's style object\n *\n * @param {Object} style A style object formatted as JSON\n * @returns {Map} `this`\n */\n setStyle: function(style) {\n if (this.style) {\n this.style\n .off('load', this._onStyleLoad)\n .off('error', this._forwardStyleEvent)\n .off('change', this._onStyleChange)\n .off('source.add', this._onSourceAdd)\n .off('source.remove', this._onSourceRemove)\n .off('source.load', this._onSourceUpdate)\n .off('source.error', this._forwardSourceEvent)\n .off('source.change', this._onSourceUpdate)\n .off('layer.add', this._forwardLayerEvent)\n .off('layer.remove', this._forwardLayerEvent)\n .off('tile.add', this._forwardTileEvent)\n .off('tile.remove', this._forwardTileEvent)\n .off('tile.load', this.update)\n .off('tile.error', this._forwardTileEvent)\n ._remove();\n\n this.off('rotate', this.style._redoPlacement);\n this.off('pitch', this.style._redoPlacement);\n }\n\n if (!style) {\n this.style = null;\n return this;\n } else if (style instanceof Style) {\n this.style = style;\n } else {\n this.style = new Style(style, this.animationLoop);\n }\n\n this.style\n .on('load', this._onStyleLoad)\n .on('error', this._forwardStyleEvent)\n .on('change', this._onStyleChange)\n .on('source.add', this._onSourceAdd)\n .on('source.remove', this._onSourceRemove)\n .on('source.load', this._onSourceUpdate)\n .on('source.error', this._forwardSourceEvent)\n .on('source.change', this._onSourceUpdate)\n .on('layer.add', this._forwardLayerEvent)\n .on('layer.remove', this._forwardLayerEvent)\n .on('tile.add', this._forwardTileEvent)\n .on('tile.remove', this._forwardTileEvent)\n .on('tile.load', this.update)\n .on('tile.error', this._forwardTileEvent);\n\n this.on('rotate', this.style._redoPlacement);\n this.on('pitch', this.style._redoPlacement);\n\n return this;\n },\n\n /**\n * Add a source to the map style.\n *\n * @param {string} id ID of the source. Must not be used by any existing source.\n * @param {Object} source source specification, following the\n * [Mapbox GL Style Reference](https://www.mapbox.com/mapbox-gl-style-spec/#sources)\n * @fires source.add\n * @returns {Map} `this`\n */\n addSource: function(id, source) {\n this.style.addSource(id, source);\n return this;\n },\n\n /**\n * Remove an existing source from the map style.\n *\n * @param {string} id ID of the source to remove\n * @fires source.remove\n * @returns {Map} `this`\n */\n removeSource: function(id) {\n this.style.removeSource(id);\n return this;\n },\n\n /**\n * Return the style source object with the given `id`.\n *\n * @param {string} id source ID\n * @returns {Object}\n */\n getSource: function(id) {\n return this.style.getSource(id);\n },\n\n /**\n * Add a layer to the map style. The layer will be inserted before the layer with\n * ID `before`, or appended if `before` is omitted.\n * @param {Layer} layer\n * @param {string=} before ID of an existing layer to insert before\n * @fires layer.add\n * @returns {Map} `this`\n */\n addLayer: function(layer, before) {\n this.style.addLayer(layer, before);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Remove the layer with the given `id` from the map. Any layers which refer to the\n * specified layer via a `ref` property are also removed.\n *\n * @param {string} id\n * @fires layer.remove\n * @returns {Map} this\n */\n removeLayer: function(id) {\n this.style.removeLayer(id);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Set the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {Array} filter filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n * @returns {Map} `this`\n */\n setFilter: function(layer, filter) {\n this.style.setFilter(layer, filter);\n return this;\n },\n\n /**\n * Get the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @returns {Array} filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n */\n getFilter: function(layer) {\n return this.style.getFilter(layer);\n },\n\n /**\n * Set the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {*} value value for the paint propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @param {string=} klass optional class specifier for the property\n * @returns {Map} `this`\n */\n setPaintProperty: function(layer, name, value, klass) {\n this.style.setPaintProperty(layer, name, value, klass);\n this.style._cascade(this._classes);\n this.update(true);\n return this;\n },\n\n /**\n * Get the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the paint propery\n */\n getPaintProperty: function(layer, name, klass) {\n return this.style.getPaintProperty(layer, name, klass);\n },\n\n /**\n * Set the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {*} value value for the layout propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @returns {Map} `this`\n */\n setLayoutProperty: function(layer, name, value) {\n this.style.setLayoutProperty(layer, name, value);\n return this;\n },\n\n /**\n * Get the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the layout propery\n */\n getLayoutProperty: function(layer, name) {\n return this.style.getLayoutProperty(layer, name);\n },\n\n /**\n * Get the Map's container as an HTML element\n * @returns {HTMLElement} container\n */\n getContainer: function() {\n return this._container;\n },\n\n /**\n * Get the Map's canvas as an HTML canvas\n * @returns {HTMLElement} canvas\n */\n getCanvas: function() {\n return this._canvas.getElement();\n },\n\n _move: function(zoom, rotate, pitch) {\n\n this.update(zoom).fire('move');\n\n if (zoom) this.fire('zoom');\n if (rotate) this.fire('rotate');\n if (pitch) this.fire('pitch');\n\n return this;\n },\n\n // map setup code\n _setupContainer: function() {\n var id = this.options.container;\n var container = this._container = typeof id === 'string' ? document.getElementById(id) : id;\n if (container) container.classList.add('mapboxgl-map');\n this._canvas = new Canvas(this, container);\n },\n\n _setupControlPos: function() {\n var corners = this._controlCorners = {};\n var prefix = 'mapboxgl-ctrl-';\n var container = this.getContainer();\n\n function createCorner(pos) {\n var className = prefix + pos;\n corners[pos] = DOM.create('div', className, container);\n }\n\n if (container && typeof document === 'object') {\n createCorner('top-left');\n createCorner('top-right');\n createCorner('bottom-left');\n createCorner('bottom-right');\n }\n },\n\n _setupPainter: function() {\n var gl = this._canvas.getWebGLContext(this.options.failIfMajorPerformanceCaveat);\n\n if (!gl) {\n console.error('Failed to initialize WebGL');\n return;\n }\n\n this.painter = new GLPainter(gl, this.transform);\n },\n\n _contextLost: function(event) {\n event.preventDefault();\n if (this._frameId) {\n browser.cancelFrame(this._frameId);\n }\n },\n\n _contextRestored: function() {\n this._setupPainter();\n this.resize();\n this.update();\n },\n\n /**\n * Is this map fully loaded? If the style isn't loaded\n * or it has a change to the sources or style that isn't\n * propagated to its style, return false.\n *\n * @returns {boolean} whether the map is loaded\n */\n loaded: function() {\n if (this._styleDirty || this._sourcesDirty)\n return false;\n if (this.style && !this.style.loaded())\n return false;\n return true;\n },\n\n /**\n * Update this map's style and re-render the map.\n *\n * @param {Object} updateStyle new style\n * @returns {Map} this\n */\n update: function(updateStyle) {\n if (!this.style) return this;\n\n this._styleDirty = this._styleDirty || updateStyle;\n this._sourcesDirty = true;\n\n this._rerender();\n\n return this;\n },\n\n /**\n * Call when a (re-)render of the map is required, e.g. when the\n * user panned or zoomed,f or new data is available.\n * @returns {Map} this\n */\n render: function() {\n if (this.style && this._styleDirty) {\n this._styleDirty = false;\n this.style._recalculate(this.transform.zoom);\n }\n\n if (this.style && this._sourcesDirty && !this._sourcesDirtyTimeout) {\n this._sourcesDirty = false;\n this._sourcesDirtyTimeout = setTimeout(function() {\n this._sourcesDirtyTimeout = null;\n }.bind(this), 50);\n this.style._updateSources(this.transform);\n }\n\n this.painter.render(this.style, {\n debug: this.debug,\n vertices: this.vertices,\n rotating: this.rotating,\n zooming: this.zooming\n });\n\n this.fire('render');\n\n if (this.loaded() && !this._loaded) {\n this._loaded = true;\n this.fire('load');\n }\n\n this._frameId = null;\n\n if (!this.animationLoop.stopped()) {\n this._styleDirty = true;\n }\n\n if (this._sourcesDirty || this._repaint || !this.animationLoop.stopped()) {\n this._rerender();\n }\n\n return this;\n },\n\n /**\n * Destroys the map's underlying resources, including web workers.\n * @returns {Map} this\n */\n remove: function() {\n if (this._hash) this._hash.remove();\n browser.cancelFrame(this._frameId);\n clearTimeout(this._sourcesDirtyTimeout);\n this.setStyle(null);\n return this;\n },\n\n _rerender: function() {\n if (this.style && !this._frameId) {\n this._frameId = browser.frame(this.render);\n }\n },\n\n _forwardStyleEvent: function(e) {\n this.fire('style.' + e.type, util.extend({style: e.target}, e));\n },\n\n _forwardSourceEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardLayerEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardTileEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _onStyleLoad: function(e) {\n this.style._cascade(this._classes, {transition: false});\n this._forwardStyleEvent(e);\n },\n\n _onStyleChange: function(e) {\n this.update(true);\n this._forwardStyleEvent(e);\n },\n\n _onSourceAdd: function(e) {\n var source = e.source;\n if (source.onAdd)\n source.onAdd(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceRemove: function(e) {\n var source = e.source;\n if (source.onRemove)\n source.onRemove(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceUpdate: function(e) {\n this.update();\n this._forwardSourceEvent(e);\n }\n}","path":"js/ui/map.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/map.js#L653-L659"},"returns":[{"title":"returns","description":"whether the map is loaded","type":{"type":"NameExpression","name":"boolean"}}],"name":"loaded","memberof":"Map","scope":"instance","members":{"instance":[],"static":[]},"path":["Map","loaded"]},{"description":"Call when a (re-)render of the map is required, e.g. when the\nuser panned or zoomed,f or new data is available.","tags":[{"title":"returns","description":"this","type":{"type":"NameExpression","name":"Map"}},{"title":"name","name":"render"},{"title":"memberof","description":"Map"},{"title":"instance"}],"context":{"loc":{"start":{"line":683,"column":4},"end":{"line":722,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/map.js","code":"{\n\n options: {\n center: [0, 0],\n zoom: 0,\n bearing: 0,\n pitch: 0,\n\n minZoom: 0,\n maxZoom: 20,\n\n interactive: true,\n hash: false,\n\n attributionControl: true,\n\n failIfMajorPerformanceCaveat: false\n },\n\n addControl: function(control) {\n control.addTo(this);\n return this;\n },\n\n /**\n * Sets a map position\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @param {number} zoom Map zoom level\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setView: function(center, zoom, bearing, pitch) {\n this.stop();\n\n var tr = this.transform,\n zoomChanged = tr.zoom !== +zoom,\n bearingChanged = tr.bearing !== +bearing,\n pitchChanged = tr.pitch !== +pitch;\n\n tr.center = LatLng.convert(center);\n tr.zoom = +zoom;\n tr.bearing = +bearing;\n tr.pitch = +pitch;\n\n return this\n .fire('movestart')\n ._move(zoomChanged, bearingChanged, pitchChanged)\n .fire('moveend');\n },\n\n /**\n * Sets a map location\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setCenter: function(center) {\n this.setView(center, this.getZoom(), this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map zoom\n *\n * @param {number} zoom Map zoom level\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setZoom: function(zoom) {\n this.setView(this.getCenter(), zoom, this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map rotation\n *\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setBearing: function(bearing) {\n this.setView(this.getCenter(), this.getZoom(), bearing, this.getPitch());\n },\n\n /**\n * Sets a map angle\n *\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setPitch: function(pitch) {\n this.setView(this.getCenter(), this.getZoom(), this.getBearing(), pitch);\n },\n\n /**\n * Get the current view geographical point\n * @returns {LatLng}\n */\n getCenter: function() { return this.transform.center; },\n\n /**\n * Get the current zoom\n * @returns {number}\n */\n getZoom: function() { return this.transform.zoom; },\n\n /**\n * Get the current bearing in degrees\n * @returns {number}\n */\n getBearing: function() { return this.transform.bearing; },\n\n /**\n * Get the current angle in degrees\n * @returns {number}\n */\n getPitch: function() { return this.transform.pitch; },\n\n /**\n * @typedef {Object} [styleOptions]\n * @param {Boolean} [styleOptions.transition=true]\n */\n\n /**\n * Adds a style class to a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n addClass: function(klass, options) {\n if (this._classes[klass]) return;\n this._classes[klass] = true;\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Removes a style class from a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n removeClass: function(klass, options) {\n if (!this._classes[klass]) return;\n delete this._classes[klass];\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Helper method to add more than one class\n *\n * @param {Array} klasses An array of class names\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n setClasses: function(klasses, options) {\n this._classes = {};\n for (var i = 0; i < klasses.length; i++) {\n this._classes[klasses[i]] = true;\n }\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Check whether a style class is active\n *\n * @param {string} klass Name of style class\n * @returns {boolean}\n */\n hasClass: function(klass) {\n return !!this._classes[klass];\n },\n\n /**\n * Return an array of the current active style classes\n *\n * @returns {boolean}\n */\n getClasses: function() {\n return Object.keys(this._classes);\n },\n\n /**\n * Detect the map's new width and height and resize it.\n *\n * @returns {Map} `this`\n */\n resize: function() {\n var width = 0, height = 0;\n\n if (this._container) {\n width = this._container.offsetWidth || 400;\n height = this._container.offsetHeight || 300;\n }\n\n this._canvas.resize(width, height);\n\n this.transform.width = width;\n this.transform.height = height;\n this.transform._constrain();\n\n this.painter.resize(width, height);\n\n return this\n .fire('movestart')\n ._move()\n .fire('resize')\n .fire('moveend');\n },\n\n /**\n * Get the map's geographical bounds\n *\n * @returns {LatLngBounds}\n */\n getBounds: function() {\n return new LatLngBounds(\n this.transform.pointLocation(new Point(0, 0)),\n this.transform.pointLocation(this.transform.size));\n },\n\n /**\n * Get pixel coordinates (relative to map container) given a geographical location\n *\n * @param {LatLng} latlng\n * @returns {Object} `x` and `y` coordinates\n */\n project: function(latlng) {\n return this.transform.locationPoint(LatLng.convert(latlng));\n },\n\n /**\n * Get geographical coordinates given pixel coordinates\n *\n * @param {Array} point [x, y] pixel coordinates\n * @returns {LatLng}\n */\n unproject: function(point) {\n return this.transform.pointLocation(Point.convert(point));\n },\n\n /**\n * Get all features at a point ([x, y])\n *\n * @param {Array} point [x, y] pixel coordinates\n * @param {Object} params\n * @param {number} [params.radius=0] Optional. Radius in pixels to search in\n * @param {string} params.layer Optional. Only return features from a given layer\n * @param {string} params.type Optional. Either `raster` or `vector`\n * @param {featuresAtCallback} callback function that returns the response\n *\n * @callback featuresAtCallback\n * @param {Object|null} err Error _If any_\n * @param {Array} features Displays a JSON array of features given the passed parameters of `featuresAt`\n *\n * @returns {Map} `this`\n */\n featuresAt: function(point, params, callback) {\n var coord = this.transform.pointCoordinate(Point.convert(point));\n this.style.featuresAt(coord, params, callback);\n return this;\n },\n\n /**\n * Replaces the map's style object\n *\n * @param {Object} style A style object formatted as JSON\n * @returns {Map} `this`\n */\n setStyle: function(style) {\n if (this.style) {\n this.style\n .off('load', this._onStyleLoad)\n .off('error', this._forwardStyleEvent)\n .off('change', this._onStyleChange)\n .off('source.add', this._onSourceAdd)\n .off('source.remove', this._onSourceRemove)\n .off('source.load', this._onSourceUpdate)\n .off('source.error', this._forwardSourceEvent)\n .off('source.change', this._onSourceUpdate)\n .off('layer.add', this._forwardLayerEvent)\n .off('layer.remove', this._forwardLayerEvent)\n .off('tile.add', this._forwardTileEvent)\n .off('tile.remove', this._forwardTileEvent)\n .off('tile.load', this.update)\n .off('tile.error', this._forwardTileEvent)\n ._remove();\n\n this.off('rotate', this.style._redoPlacement);\n this.off('pitch', this.style._redoPlacement);\n }\n\n if (!style) {\n this.style = null;\n return this;\n } else if (style instanceof Style) {\n this.style = style;\n } else {\n this.style = new Style(style, this.animationLoop);\n }\n\n this.style\n .on('load', this._onStyleLoad)\n .on('error', this._forwardStyleEvent)\n .on('change', this._onStyleChange)\n .on('source.add', this._onSourceAdd)\n .on('source.remove', this._onSourceRemove)\n .on('source.load', this._onSourceUpdate)\n .on('source.error', this._forwardSourceEvent)\n .on('source.change', this._onSourceUpdate)\n .on('layer.add', this._forwardLayerEvent)\n .on('layer.remove', this._forwardLayerEvent)\n .on('tile.add', this._forwardTileEvent)\n .on('tile.remove', this._forwardTileEvent)\n .on('tile.load', this.update)\n .on('tile.error', this._forwardTileEvent);\n\n this.on('rotate', this.style._redoPlacement);\n this.on('pitch', this.style._redoPlacement);\n\n return this;\n },\n\n /**\n * Add a source to the map style.\n *\n * @param {string} id ID of the source. Must not be used by any existing source.\n * @param {Object} source source specification, following the\n * [Mapbox GL Style Reference](https://www.mapbox.com/mapbox-gl-style-spec/#sources)\n * @fires source.add\n * @returns {Map} `this`\n */\n addSource: function(id, source) {\n this.style.addSource(id, source);\n return this;\n },\n\n /**\n * Remove an existing source from the map style.\n *\n * @param {string} id ID of the source to remove\n * @fires source.remove\n * @returns {Map} `this`\n */\n removeSource: function(id) {\n this.style.removeSource(id);\n return this;\n },\n\n /**\n * Return the style source object with the given `id`.\n *\n * @param {string} id source ID\n * @returns {Object}\n */\n getSource: function(id) {\n return this.style.getSource(id);\n },\n\n /**\n * Add a layer to the map style. The layer will be inserted before the layer with\n * ID `before`, or appended if `before` is omitted.\n * @param {Layer} layer\n * @param {string=} before ID of an existing layer to insert before\n * @fires layer.add\n * @returns {Map} `this`\n */\n addLayer: function(layer, before) {\n this.style.addLayer(layer, before);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Remove the layer with the given `id` from the map. Any layers which refer to the\n * specified layer via a `ref` property are also removed.\n *\n * @param {string} id\n * @fires layer.remove\n * @returns {Map} this\n */\n removeLayer: function(id) {\n this.style.removeLayer(id);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Set the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {Array} filter filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n * @returns {Map} `this`\n */\n setFilter: function(layer, filter) {\n this.style.setFilter(layer, filter);\n return this;\n },\n\n /**\n * Get the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @returns {Array} filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n */\n getFilter: function(layer) {\n return this.style.getFilter(layer);\n },\n\n /**\n * Set the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {*} value value for the paint propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @param {string=} klass optional class specifier for the property\n * @returns {Map} `this`\n */\n setPaintProperty: function(layer, name, value, klass) {\n this.style.setPaintProperty(layer, name, value, klass);\n this.style._cascade(this._classes);\n this.update(true);\n return this;\n },\n\n /**\n * Get the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the paint propery\n */\n getPaintProperty: function(layer, name, klass) {\n return this.style.getPaintProperty(layer, name, klass);\n },\n\n /**\n * Set the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {*} value value for the layout propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @returns {Map} `this`\n */\n setLayoutProperty: function(layer, name, value) {\n this.style.setLayoutProperty(layer, name, value);\n return this;\n },\n\n /**\n * Get the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the layout propery\n */\n getLayoutProperty: function(layer, name) {\n return this.style.getLayoutProperty(layer, name);\n },\n\n /**\n * Get the Map's container as an HTML element\n * @returns {HTMLElement} container\n */\n getContainer: function() {\n return this._container;\n },\n\n /**\n * Get the Map's canvas as an HTML canvas\n * @returns {HTMLElement} canvas\n */\n getCanvas: function() {\n return this._canvas.getElement();\n },\n\n _move: function(zoom, rotate, pitch) {\n\n this.update(zoom).fire('move');\n\n if (zoom) this.fire('zoom');\n if (rotate) this.fire('rotate');\n if (pitch) this.fire('pitch');\n\n return this;\n },\n\n // map setup code\n _setupContainer: function() {\n var id = this.options.container;\n var container = this._container = typeof id === 'string' ? document.getElementById(id) : id;\n if (container) container.classList.add('mapboxgl-map');\n this._canvas = new Canvas(this, container);\n },\n\n _setupControlPos: function() {\n var corners = this._controlCorners = {};\n var prefix = 'mapboxgl-ctrl-';\n var container = this.getContainer();\n\n function createCorner(pos) {\n var className = prefix + pos;\n corners[pos] = DOM.create('div', className, container);\n }\n\n if (container && typeof document === 'object') {\n createCorner('top-left');\n createCorner('top-right');\n createCorner('bottom-left');\n createCorner('bottom-right');\n }\n },\n\n _setupPainter: function() {\n var gl = this._canvas.getWebGLContext(this.options.failIfMajorPerformanceCaveat);\n\n if (!gl) {\n console.error('Failed to initialize WebGL');\n return;\n }\n\n this.painter = new GLPainter(gl, this.transform);\n },\n\n _contextLost: function(event) {\n event.preventDefault();\n if (this._frameId) {\n browser.cancelFrame(this._frameId);\n }\n },\n\n _contextRestored: function() {\n this._setupPainter();\n this.resize();\n this.update();\n },\n\n /**\n * Is this map fully loaded? If the style isn't loaded\n * or it has a change to the sources or style that isn't\n * propagated to its style, return false.\n *\n * @returns {boolean} whether the map is loaded\n */\n loaded: function() {\n if (this._styleDirty || this._sourcesDirty)\n return false;\n if (this.style && !this.style.loaded())\n return false;\n return true;\n },\n\n /**\n * Update this map's style and re-render the map.\n *\n * @param {Object} updateStyle new style\n * @returns {Map} this\n */\n update: function(updateStyle) {\n if (!this.style) return this;\n\n this._styleDirty = this._styleDirty || updateStyle;\n this._sourcesDirty = true;\n\n this._rerender();\n\n return this;\n },\n\n /**\n * Call when a (re-)render of the map is required, e.g. when the\n * user panned or zoomed,f or new data is available.\n * @returns {Map} this\n */\n render: function() {\n if (this.style && this._styleDirty) {\n this._styleDirty = false;\n this.style._recalculate(this.transform.zoom);\n }\n\n if (this.style && this._sourcesDirty && !this._sourcesDirtyTimeout) {\n this._sourcesDirty = false;\n this._sourcesDirtyTimeout = setTimeout(function() {\n this._sourcesDirtyTimeout = null;\n }.bind(this), 50);\n this.style._updateSources(this.transform);\n }\n\n this.painter.render(this.style, {\n debug: this.debug,\n vertices: this.vertices,\n rotating: this.rotating,\n zooming: this.zooming\n });\n\n this.fire('render');\n\n if (this.loaded() && !this._loaded) {\n this._loaded = true;\n this.fire('load');\n }\n\n this._frameId = null;\n\n if (!this.animationLoop.stopped()) {\n this._styleDirty = true;\n }\n\n if (this._sourcesDirty || this._repaint || !this.animationLoop.stopped()) {\n this._rerender();\n }\n\n return this;\n },\n\n /**\n * Destroys the map's underlying resources, including web workers.\n * @returns {Map} this\n */\n remove: function() {\n if (this._hash) this._hash.remove();\n browser.cancelFrame(this._frameId);\n clearTimeout(this._sourcesDirtyTimeout);\n this.setStyle(null);\n return this;\n },\n\n _rerender: function() {\n if (this.style && !this._frameId) {\n this._frameId = browser.frame(this.render);\n }\n },\n\n _forwardStyleEvent: function(e) {\n this.fire('style.' + e.type, util.extend({style: e.target}, e));\n },\n\n _forwardSourceEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardLayerEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardTileEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _onStyleLoad: function(e) {\n this.style._cascade(this._classes, {transition: false});\n this._forwardStyleEvent(e);\n },\n\n _onStyleChange: function(e) {\n this.update(true);\n this._forwardStyleEvent(e);\n },\n\n _onSourceAdd: function(e) {\n var source = e.source;\n if (source.onAdd)\n source.onAdd(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceRemove: function(e) {\n var source = e.source;\n if (source.onRemove)\n source.onRemove(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceUpdate: function(e) {\n this.update();\n this._forwardSourceEvent(e);\n }\n}","path":"js/ui/map.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/map.js#L683-L722"},"returns":[{"title":"returns","description":"this","type":{"type":"NameExpression","name":"Map"}}],"name":"render","memberof":"Map","scope":"instance","members":{"instance":[],"static":[]},"path":["Map","render"]},{"description":"Destroys the map's underlying resources, including web workers.","tags":[{"title":"returns","description":"this","type":{"type":"NameExpression","name":"Map"}},{"title":"name","name":"remove"},{"title":"memberof","description":"Map"},{"title":"instance"}],"context":{"loc":{"start":{"line":728,"column":4},"end":{"line":734,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/map.js","code":"{\n\n options: {\n center: [0, 0],\n zoom: 0,\n bearing: 0,\n pitch: 0,\n\n minZoom: 0,\n maxZoom: 20,\n\n interactive: true,\n hash: false,\n\n attributionControl: true,\n\n failIfMajorPerformanceCaveat: false\n },\n\n addControl: function(control) {\n control.addTo(this);\n return this;\n },\n\n /**\n * Sets a map position\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @param {number} zoom Map zoom level\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setView: function(center, zoom, bearing, pitch) {\n this.stop();\n\n var tr = this.transform,\n zoomChanged = tr.zoom !== +zoom,\n bearingChanged = tr.bearing !== +bearing,\n pitchChanged = tr.pitch !== +pitch;\n\n tr.center = LatLng.convert(center);\n tr.zoom = +zoom;\n tr.bearing = +bearing;\n tr.pitch = +pitch;\n\n return this\n .fire('movestart')\n ._move(zoomChanged, bearingChanged, pitchChanged)\n .fire('moveend');\n },\n\n /**\n * Sets a map location\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setCenter: function(center) {\n this.setView(center, this.getZoom(), this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map zoom\n *\n * @param {number} zoom Map zoom level\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setZoom: function(zoom) {\n this.setView(this.getCenter(), zoom, this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map rotation\n *\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setBearing: function(bearing) {\n this.setView(this.getCenter(), this.getZoom(), bearing, this.getPitch());\n },\n\n /**\n * Sets a map angle\n *\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setPitch: function(pitch) {\n this.setView(this.getCenter(), this.getZoom(), this.getBearing(), pitch);\n },\n\n /**\n * Get the current view geographical point\n * @returns {LatLng}\n */\n getCenter: function() { return this.transform.center; },\n\n /**\n * Get the current zoom\n * @returns {number}\n */\n getZoom: function() { return this.transform.zoom; },\n\n /**\n * Get the current bearing in degrees\n * @returns {number}\n */\n getBearing: function() { return this.transform.bearing; },\n\n /**\n * Get the current angle in degrees\n * @returns {number}\n */\n getPitch: function() { return this.transform.pitch; },\n\n /**\n * @typedef {Object} [styleOptions]\n * @param {Boolean} [styleOptions.transition=true]\n */\n\n /**\n * Adds a style class to a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n addClass: function(klass, options) {\n if (this._classes[klass]) return;\n this._classes[klass] = true;\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Removes a style class from a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n removeClass: function(klass, options) {\n if (!this._classes[klass]) return;\n delete this._classes[klass];\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Helper method to add more than one class\n *\n * @param {Array} klasses An array of class names\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n setClasses: function(klasses, options) {\n this._classes = {};\n for (var i = 0; i < klasses.length; i++) {\n this._classes[klasses[i]] = true;\n }\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Check whether a style class is active\n *\n * @param {string} klass Name of style class\n * @returns {boolean}\n */\n hasClass: function(klass) {\n return !!this._classes[klass];\n },\n\n /**\n * Return an array of the current active style classes\n *\n * @returns {boolean}\n */\n getClasses: function() {\n return Object.keys(this._classes);\n },\n\n /**\n * Detect the map's new width and height and resize it.\n *\n * @returns {Map} `this`\n */\n resize: function() {\n var width = 0, height = 0;\n\n if (this._container) {\n width = this._container.offsetWidth || 400;\n height = this._container.offsetHeight || 300;\n }\n\n this._canvas.resize(width, height);\n\n this.transform.width = width;\n this.transform.height = height;\n this.transform._constrain();\n\n this.painter.resize(width, height);\n\n return this\n .fire('movestart')\n ._move()\n .fire('resize')\n .fire('moveend');\n },\n\n /**\n * Get the map's geographical bounds\n *\n * @returns {LatLngBounds}\n */\n getBounds: function() {\n return new LatLngBounds(\n this.transform.pointLocation(new Point(0, 0)),\n this.transform.pointLocation(this.transform.size));\n },\n\n /**\n * Get pixel coordinates (relative to map container) given a geographical location\n *\n * @param {LatLng} latlng\n * @returns {Object} `x` and `y` coordinates\n */\n project: function(latlng) {\n return this.transform.locationPoint(LatLng.convert(latlng));\n },\n\n /**\n * Get geographical coordinates given pixel coordinates\n *\n * @param {Array} point [x, y] pixel coordinates\n * @returns {LatLng}\n */\n unproject: function(point) {\n return this.transform.pointLocation(Point.convert(point));\n },\n\n /**\n * Get all features at a point ([x, y])\n *\n * @param {Array} point [x, y] pixel coordinates\n * @param {Object} params\n * @param {number} [params.radius=0] Optional. Radius in pixels to search in\n * @param {string} params.layer Optional. Only return features from a given layer\n * @param {string} params.type Optional. Either `raster` or `vector`\n * @param {featuresAtCallback} callback function that returns the response\n *\n * @callback featuresAtCallback\n * @param {Object|null} err Error _If any_\n * @param {Array} features Displays a JSON array of features given the passed parameters of `featuresAt`\n *\n * @returns {Map} `this`\n */\n featuresAt: function(point, params, callback) {\n var coord = this.transform.pointCoordinate(Point.convert(point));\n this.style.featuresAt(coord, params, callback);\n return this;\n },\n\n /**\n * Replaces the map's style object\n *\n * @param {Object} style A style object formatted as JSON\n * @returns {Map} `this`\n */\n setStyle: function(style) {\n if (this.style) {\n this.style\n .off('load', this._onStyleLoad)\n .off('error', this._forwardStyleEvent)\n .off('change', this._onStyleChange)\n .off('source.add', this._onSourceAdd)\n .off('source.remove', this._onSourceRemove)\n .off('source.load', this._onSourceUpdate)\n .off('source.error', this._forwardSourceEvent)\n .off('source.change', this._onSourceUpdate)\n .off('layer.add', this._forwardLayerEvent)\n .off('layer.remove', this._forwardLayerEvent)\n .off('tile.add', this._forwardTileEvent)\n .off('tile.remove', this._forwardTileEvent)\n .off('tile.load', this.update)\n .off('tile.error', this._forwardTileEvent)\n ._remove();\n\n this.off('rotate', this.style._redoPlacement);\n this.off('pitch', this.style._redoPlacement);\n }\n\n if (!style) {\n this.style = null;\n return this;\n } else if (style instanceof Style) {\n this.style = style;\n } else {\n this.style = new Style(style, this.animationLoop);\n }\n\n this.style\n .on('load', this._onStyleLoad)\n .on('error', this._forwardStyleEvent)\n .on('change', this._onStyleChange)\n .on('source.add', this._onSourceAdd)\n .on('source.remove', this._onSourceRemove)\n .on('source.load', this._onSourceUpdate)\n .on('source.error', this._forwardSourceEvent)\n .on('source.change', this._onSourceUpdate)\n .on('layer.add', this._forwardLayerEvent)\n .on('layer.remove', this._forwardLayerEvent)\n .on('tile.add', this._forwardTileEvent)\n .on('tile.remove', this._forwardTileEvent)\n .on('tile.load', this.update)\n .on('tile.error', this._forwardTileEvent);\n\n this.on('rotate', this.style._redoPlacement);\n this.on('pitch', this.style._redoPlacement);\n\n return this;\n },\n\n /**\n * Add a source to the map style.\n *\n * @param {string} id ID of the source. Must not be used by any existing source.\n * @param {Object} source source specification, following the\n * [Mapbox GL Style Reference](https://www.mapbox.com/mapbox-gl-style-spec/#sources)\n * @fires source.add\n * @returns {Map} `this`\n */\n addSource: function(id, source) {\n this.style.addSource(id, source);\n return this;\n },\n\n /**\n * Remove an existing source from the map style.\n *\n * @param {string} id ID of the source to remove\n * @fires source.remove\n * @returns {Map} `this`\n */\n removeSource: function(id) {\n this.style.removeSource(id);\n return this;\n },\n\n /**\n * Return the style source object with the given `id`.\n *\n * @param {string} id source ID\n * @returns {Object}\n */\n getSource: function(id) {\n return this.style.getSource(id);\n },\n\n /**\n * Add a layer to the map style. The layer will be inserted before the layer with\n * ID `before`, or appended if `before` is omitted.\n * @param {Layer} layer\n * @param {string=} before ID of an existing layer to insert before\n * @fires layer.add\n * @returns {Map} `this`\n */\n addLayer: function(layer, before) {\n this.style.addLayer(layer, before);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Remove the layer with the given `id` from the map. Any layers which refer to the\n * specified layer via a `ref` property are also removed.\n *\n * @param {string} id\n * @fires layer.remove\n * @returns {Map} this\n */\n removeLayer: function(id) {\n this.style.removeLayer(id);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Set the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {Array} filter filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n * @returns {Map} `this`\n */\n setFilter: function(layer, filter) {\n this.style.setFilter(layer, filter);\n return this;\n },\n\n /**\n * Get the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @returns {Array} filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n */\n getFilter: function(layer) {\n return this.style.getFilter(layer);\n },\n\n /**\n * Set the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {*} value value for the paint propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @param {string=} klass optional class specifier for the property\n * @returns {Map} `this`\n */\n setPaintProperty: function(layer, name, value, klass) {\n this.style.setPaintProperty(layer, name, value, klass);\n this.style._cascade(this._classes);\n this.update(true);\n return this;\n },\n\n /**\n * Get the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the paint propery\n */\n getPaintProperty: function(layer, name, klass) {\n return this.style.getPaintProperty(layer, name, klass);\n },\n\n /**\n * Set the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {*} value value for the layout propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @returns {Map} `this`\n */\n setLayoutProperty: function(layer, name, value) {\n this.style.setLayoutProperty(layer, name, value);\n return this;\n },\n\n /**\n * Get the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the layout propery\n */\n getLayoutProperty: function(layer, name) {\n return this.style.getLayoutProperty(layer, name);\n },\n\n /**\n * Get the Map's container as an HTML element\n * @returns {HTMLElement} container\n */\n getContainer: function() {\n return this._container;\n },\n\n /**\n * Get the Map's canvas as an HTML canvas\n * @returns {HTMLElement} canvas\n */\n getCanvas: function() {\n return this._canvas.getElement();\n },\n\n _move: function(zoom, rotate, pitch) {\n\n this.update(zoom).fire('move');\n\n if (zoom) this.fire('zoom');\n if (rotate) this.fire('rotate');\n if (pitch) this.fire('pitch');\n\n return this;\n },\n\n // map setup code\n _setupContainer: function() {\n var id = this.options.container;\n var container = this._container = typeof id === 'string' ? document.getElementById(id) : id;\n if (container) container.classList.add('mapboxgl-map');\n this._canvas = new Canvas(this, container);\n },\n\n _setupControlPos: function() {\n var corners = this._controlCorners = {};\n var prefix = 'mapboxgl-ctrl-';\n var container = this.getContainer();\n\n function createCorner(pos) {\n var className = prefix + pos;\n corners[pos] = DOM.create('div', className, container);\n }\n\n if (container && typeof document === 'object') {\n createCorner('top-left');\n createCorner('top-right');\n createCorner('bottom-left');\n createCorner('bottom-right');\n }\n },\n\n _setupPainter: function() {\n var gl = this._canvas.getWebGLContext(this.options.failIfMajorPerformanceCaveat);\n\n if (!gl) {\n console.error('Failed to initialize WebGL');\n return;\n }\n\n this.painter = new GLPainter(gl, this.transform);\n },\n\n _contextLost: function(event) {\n event.preventDefault();\n if (this._frameId) {\n browser.cancelFrame(this._frameId);\n }\n },\n\n _contextRestored: function() {\n this._setupPainter();\n this.resize();\n this.update();\n },\n\n /**\n * Is this map fully loaded? If the style isn't loaded\n * or it has a change to the sources or style that isn't\n * propagated to its style, return false.\n *\n * @returns {boolean} whether the map is loaded\n */\n loaded: function() {\n if (this._styleDirty || this._sourcesDirty)\n return false;\n if (this.style && !this.style.loaded())\n return false;\n return true;\n },\n\n /**\n * Update this map's style and re-render the map.\n *\n * @param {Object} updateStyle new style\n * @returns {Map} this\n */\n update: function(updateStyle) {\n if (!this.style) return this;\n\n this._styleDirty = this._styleDirty || updateStyle;\n this._sourcesDirty = true;\n\n this._rerender();\n\n return this;\n },\n\n /**\n * Call when a (re-)render of the map is required, e.g. when the\n * user panned or zoomed,f or new data is available.\n * @returns {Map} this\n */\n render: function() {\n if (this.style && this._styleDirty) {\n this._styleDirty = false;\n this.style._recalculate(this.transform.zoom);\n }\n\n if (this.style && this._sourcesDirty && !this._sourcesDirtyTimeout) {\n this._sourcesDirty = false;\n this._sourcesDirtyTimeout = setTimeout(function() {\n this._sourcesDirtyTimeout = null;\n }.bind(this), 50);\n this.style._updateSources(this.transform);\n }\n\n this.painter.render(this.style, {\n debug: this.debug,\n vertices: this.vertices,\n rotating: this.rotating,\n zooming: this.zooming\n });\n\n this.fire('render');\n\n if (this.loaded() && !this._loaded) {\n this._loaded = true;\n this.fire('load');\n }\n\n this._frameId = null;\n\n if (!this.animationLoop.stopped()) {\n this._styleDirty = true;\n }\n\n if (this._sourcesDirty || this._repaint || !this.animationLoop.stopped()) {\n this._rerender();\n }\n\n return this;\n },\n\n /**\n * Destroys the map's underlying resources, including web workers.\n * @returns {Map} this\n */\n remove: function() {\n if (this._hash) this._hash.remove();\n browser.cancelFrame(this._frameId);\n clearTimeout(this._sourcesDirtyTimeout);\n this.setStyle(null);\n return this;\n },\n\n _rerender: function() {\n if (this.style && !this._frameId) {\n this._frameId = browser.frame(this.render);\n }\n },\n\n _forwardStyleEvent: function(e) {\n this.fire('style.' + e.type, util.extend({style: e.target}, e));\n },\n\n _forwardSourceEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardLayerEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardTileEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _onStyleLoad: function(e) {\n this.style._cascade(this._classes, {transition: false});\n this._forwardStyleEvent(e);\n },\n\n _onStyleChange: function(e) {\n this.update(true);\n this._forwardStyleEvent(e);\n },\n\n _onSourceAdd: function(e) {\n var source = e.source;\n if (source.onAdd)\n source.onAdd(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceRemove: function(e) {\n var source = e.source;\n if (source.onRemove)\n source.onRemove(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceUpdate: function(e) {\n this.update();\n this._forwardSourceEvent(e);\n }\n}","path":"js/ui/map.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/map.js#L728-L734"},"returns":[{"title":"returns","description":"this","type":{"type":"NameExpression","name":"Map"}}],"name":"remove","memberof":"Map","scope":"instance","members":{"instance":[],"static":[]},"path":["Map","remove"]},{"description":"Pan to a certain location with easing","tags":[{"title":"param","description":"a `LatLng` object","type":{"type":"NameExpression","name":"Object"},"name":"latlng"},{"title":"param","description":null,"type":null,"name":"animOptions"},{"title":"fires","description":"movestart"},{"title":"fires","description":"moveend"},{"title":"returns","description":null,"type":{"type":"NameExpression","name":"this"}},{"title":"name","name":"panTo"},{"title":"memberof","description":"Map"},{"title":"instance"}],"context":{"loc":{"start":{"line":73,"column":4},"end":{"line":101,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/easings.js","code":"{\n isEasing: function() {\n return !!this._abortFn;\n },\n\n /**\n * Stop current animation\n *\n * @returns {this}\n */\n stop: function() {\n if (this._abortFn) {\n this._abortFn.call(this);\n delete this._abortFn;\n\n this._finishFn.call(this);\n delete this._finishFn;\n }\n return this;\n },\n\n _ease: function(frame, finish, options) {\n this._finishFn = finish;\n this._abortFn = browser.timed(function (t) {\n frame.call(this, options.easing(t));\n if (t === 1) {\n delete this._abortFn;\n this._finishFn.call(this);\n delete this._finishFn;\n }\n }, options.animate === false ? 0 : options.duration, this);\n },\n\n /**\n * Pan by a certain number of pixels\n *\n * @param {Array} offset [x, y]\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n panBy: function(offset, options) {\n this.panTo(this.transform.center, util.extend({offset: Point.convert(offset).mult(-1)}, options));\n return this;\n },\n\n /**\n * Pan to a certain location with easing\n *\n * @param {Object} latlng a `LatLng` object\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n panTo: function(latlng, options) {\n this.stop();\n\n latlng = LatLng.convert(latlng);\n\n options = util.extend({\n duration: 500,\n easing: util.ease,\n offset: [0, 0]\n }, options);\n\n var tr = this.transform,\n offset = Point.convert(options.offset).rotate(-tr.angle),\n from = tr.point,\n to = tr.project(latlng).sub(offset);\n\n if (!options.noMoveStart) {\n this.fire('movestart');\n }\n\n this._ease(function(k) {\n tr.center = tr.unproject(from.add(to.sub(from).mult(k)));\n this._move();\n }, function() {\n this.fire('moveend');\n }, options);\n\n return this;\n },\n\n /**\n * Zooms to a certain zoom level with easing.\n *\n * @param {Number} zoom\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n zoomTo: function(zoom, options) {\n this.stop();\n\n options = util.extend({\n duration: 500\n }, options);\n\n options.easing = this._updateEasing(options.duration, zoom, options.easing);\n\n var tr = this.transform,\n around = tr.center,\n startZoom = tr.zoom;\n\n if (options.around) {\n around = LatLng.convert(options.around);\n } else if (options.offset) {\n around = tr.pointLocation(tr.centerPoint.add(Point.convert(options.offset)));\n }\n\n if (options.animate === false) options.duration = 0;\n\n if (!this.zooming) {\n this.zooming = true;\n this.fire('movestart');\n }\n\n this._ease(function(k) {\n tr.setZoomAround(interpolate(startZoom, zoom, k), around);\n this.animationLoop.set(300); // text fading\n this._move(true);\n }, function() {\n this.ease = null;\n if (options.duration >= 200) {\n this.zooming = false;\n this.fire('moveend');\n }\n }, options);\n\n if (options.duration < 200) {\n clearTimeout(this._onZoomEnd);\n this._onZoomEnd = setTimeout(function() {\n this.zooming = false;\n this._rerender();\n this.fire('moveend');\n }.bind(this), 200);\n }\n\n return this;\n },\n\n /**\n * Zoom in by 1 level\n *\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n zoomIn: function(options) {\n this.zoomTo(this.getZoom() + 1, options);\n },\n\n /**\n * Zoom out by 1 level\n *\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n zoomOut: function(options) {\n this.zoomTo(this.getZoom() - 1, options);\n },\n\n /**\n * Rotate bearing by a certain number of degrees with easing\n *\n * @param {Number} bearing\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n rotateTo: function(bearing, options) {\n this.stop();\n\n options = util.extend({\n duration: 500,\n easing: util.ease\n }, options);\n\n var tr = this.transform,\n start = this.getBearing(),\n around = tr.center;\n\n if (options.around) {\n around = LatLng.convert(options.around);\n } else if (options.offset) {\n around = tr.pointLocation(tr.centerPoint.add(Point.convert(options.offset)));\n }\n\n bearing = this._normalizeBearing(bearing, start);\n\n this.rotating = true;\n this.fire('movestart');\n\n this._ease(function(k) {\n tr.setBearingAround(interpolate(start, bearing, k), around);\n this._move(false, true);\n }, function() {\n this.rotating = false;\n this.fire('moveend');\n }, options);\n\n return this;\n },\n\n /**\n * Sets map bearing to 0 (north) with easing\n *\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n resetNorth: function(options) {\n return this.rotateTo(0, util.extend({duration: 1000}, options));\n },\n\n /**\n * Zoom to contain certain geographical bounds\n *\n * @param {Array} bounds [[minLat, minLng], [maxLat, maxLng]]\n * @param {Object} options\n * @param {Number} [options.speed=1.2] How fast animation occurs\n * @param {Number} [options.curve=1.42] How much zooming out occurs during animation\n * @param {Function} options.easing\n * @param {Number} options.padding how much padding there is around the given bounds on each side in pixels\n * @param {Number} options.maxZoom\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n fitBounds: function(bounds, options) {\n\n options = util.extend({\n padding: 0,\n offset: [0, 0],\n maxZoom: Infinity\n }, options);\n\n bounds = LatLngBounds.convert(bounds);\n\n var offset = Point.convert(options.offset),\n tr = this.transform,\n nw = tr.project(bounds.getNorthWest()),\n se = tr.project(bounds.getSouthEast()),\n size = se.sub(nw),\n center = tr.unproject(nw.add(se).div(2)),\n\n scaleX = (tr.width - options.padding * 2 - Math.abs(offset.x) * 2) / size.x,\n scaleY = (tr.height - options.padding * 2 - Math.abs(offset.y) * 2) / size.y,\n\n zoom = Math.min(tr.scaleZoom(tr.scale * Math.min(scaleX, scaleY)), options.maxZoom);\n\n return options.linear ?\n this.easeTo(center, zoom, 0, options) :\n this.flyTo(center, zoom, 0, options);\n },\n\n /**\n * Easing animation to a specified location/zoom/bearing\n *\n * @param {Object} latlng a `LatLng` object\n * @param {Number} zoom\n * @param {Number} bearing\n * @param {Number} pitch\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n easeTo: function(latlng, zoom, bearing, pitch, options) {\n this.stop();\n\n options = util.extend({\n offset: [0, 0],\n duration: 500,\n easing: util.ease\n }, options);\n\n var tr = this.transform,\n offset = Point.convert(options.offset).rotate(-tr.angle),\n startZoom = this.getZoom(),\n startBearing = this.getBearing(),\n startPitch = this.getPitch();\n\n latlng = LatLng.convert(latlng);\n zoom = zoom === undefined ? startZoom : zoom;\n bearing = bearing === undefined ? startBearing : this._normalizeBearing(bearing, startBearing);\n pitch = pitch === undefined ? startPitch : pitch;\n\n var scale = tr.zoomScale(zoom - startZoom),\n from = tr.point,\n to = latlng ? tr.project(latlng).sub(offset.div(scale)) : tr.point,\n around;\n\n if (zoom !== startZoom) {\n around = tr.pointLocation(tr.centerPoint.add(to.sub(from).div(1 - 1 / scale)));\n this.zooming = true;\n }\n if (startBearing !== bearing) this.rotating = true;\n\n this.fire('movestart');\n\n this._ease(function (k) {\n if (zoom !== startZoom) {\n tr.setZoomAround(interpolate(startZoom, zoom, k), around);\n } else {\n tr.center = tr.unproject(from.add(to.sub(from).mult(k)));\n }\n\n if (bearing !== startBearing) {\n tr.bearing = interpolate(startBearing, bearing, k);\n }\n\n if (pitch !== startPitch) {\n tr.pitch = interpolate(startPitch, pitch, k);\n }\n\n this.animationLoop.set(300); // text fading\n this._move(zoom !== startZoom, bearing !== startBearing);\n }, function() {\n this.zooming = false;\n this.rotating = false;\n this.fire('moveend');\n }, options);\n\n return this;\n },\n\n /**\n * Flying animation to a specified location/zoom/bearing with automatic curve\n *\n * @param {Object} latlng a `LatLng` object\n * @param {Number} zoom\n * @param {Number} bearing\n * @param {Object} options\n * @param {Number} [options.speed=1.2] How fast animation occurs\n * @param {Number} [options.curve=1.42] How much zooming out occurs during animation\n * @param {Function} options.easing\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n flyTo: function(latlng, zoom, bearing, options) {\n this.stop();\n\n options = util.extend({\n offset: [0, 0],\n speed: 1.2,\n curve: 1.42,\n easing: util.ease\n }, options);\n\n latlng = LatLng.convert(latlng);\n\n var offset = Point.convert(options.offset),\n tr = this.transform,\n startZoom = this.getZoom(),\n startBearing = this.getBearing();\n\n zoom = zoom === undefined ? startZoom : zoom;\n bearing = bearing === undefined ? startBearing : this._normalizeBearing(bearing, startBearing);\n\n var scale = tr.zoomScale(zoom - startZoom),\n from = tr.point,\n to = tr.project(latlng).sub(offset.div(scale));\n\n if (options.animate === false) {\n return this.setView(latlng, zoom, bearing, this.getPitch());\n }\n\n var startWorldSize = tr.worldSize,\n rho = options.curve,\n V = options.speed,\n\n w0 = Math.max(tr.width, tr.height),\n w1 = w0 / scale,\n u1 = to.sub(from).mag(),\n rho2 = rho * rho;\n\n function r(i) {\n var b = (w1 * w1 - w0 * w0 + (i ? -1 : 1) * rho2 * rho2 * u1 * u1) / (2 * (i ? w1 : w0) * rho2 * u1);\n return Math.log(Math.sqrt(b * b + 1) - b);\n }\n\n function sinh(n) { return (Math.exp(n) - Math.exp(-n)) / 2; }\n function cosh(n) { return (Math.exp(n) + Math.exp(-n)) / 2; }\n function tanh(n) { return sinh(n) / cosh(n); }\n\n var r0 = r(0),\n w = function (s) { return (cosh(r0) / cosh(r0 + rho * s)); },\n u = function (s) { return w0 * ((cosh(r0) * tanh(r0 + rho * s) - sinh(r0)) / rho2) / u1; },\n S = (r(1) - r0) / rho;\n\n if (Math.abs(u1) < 0.000001) {\n if (Math.abs(w0 - w1) < 0.000001) return this;\n\n var k = w1 < w0 ? -1 : 1;\n S = Math.abs(Math.log(w1 / w0)) / rho;\n\n u = function() { return 0; };\n w = function(s) { return Math.exp(k * rho * s); };\n }\n\n options.duration = 1000 * S / V;\n\n this.zooming = true;\n if (startBearing !== bearing) this.rotating = true;\n\n this.fire('movestart');\n\n this._ease(function (k) {\n var s = k * S,\n us = u(s);\n\n tr.zoom = startZoom + tr.scaleZoom(1 / w(s));\n tr.center = tr.unproject(from.add(to.sub(from).mult(us)), startWorldSize);\n\n if (bearing !== startBearing) {\n tr.bearing = interpolate(startBearing, bearing, k);\n }\n\n this.animationLoop.set(300); // text fading\n\n this._move(true, bearing !== startBearing);\n }, function() {\n this.zooming = false;\n this.rotating = false;\n this.fire('moveend');\n }, options);\n\n return this;\n },\n\n // convert bearing so that it's numerically close to the current one so that it interpolates properly\n _normalizeBearing: function(bearing, currentBearing) {\n bearing = util.wrap(bearing, -180, 180);\n var diff = Math.abs(bearing - currentBearing);\n if (Math.abs(bearing - 360 - currentBearing) < diff) bearing -= 360;\n if (Math.abs(bearing + 360 - currentBearing) < diff) bearing += 360;\n return bearing;\n },\n\n _updateEasing: function(duration, zoom, bezier) {\n var easing;\n\n if (this.ease) {\n var ease = this.ease,\n t = (Date.now() - ease.start) / ease.duration,\n speed = ease.easing(t + 0.01) - ease.easing(t),\n\n // Quick hack to make new bezier that is continuous with last\n x = 0.27 / Math.sqrt(speed * speed + 0.0001) * 0.01,\n y = Math.sqrt(0.27 * 0.27 - x * x);\n\n easing = util.bezier(x, y, 0.25, 1);\n } else {\n easing = bezier ? util.bezier.apply(util, bezier) : util.ease;\n }\n\n // store information on current easing\n this.ease = {\n start: (new Date()).getTime(),\n to: Math.pow(2, zoom),\n duration: duration,\n easing: easing\n };\n\n return easing;\n }\n}","path":"js/ui/easings.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/easings.js#L73-L101"},"params":[{"title":"param","description":"a `LatLng` object","type":{"type":"NameExpression","name":"Object"},"name":"latlng"},{"title":"param","description":null,"type":null,"name":"animOptions"}],"returns":[{"title":"returns","description":null,"type":{"type":"NameExpression","name":"this"}}],"name":"panTo","memberof":"Map","scope":"instance","members":{"instance":[],"static":[]},"path":["Map","panTo"]},{"description":"Sets map bearing to 0 (north) with easing","tags":[{"title":"param","description":null,"type":null,"name":"animOptions"},{"title":"fires","description":"movestart"},{"title":"fires","description":"moveend"},{"title":"returns","description":null,"type":{"type":"NameExpression","name":"this"}},{"title":"name","name":"resetNorth"},{"title":"memberof","description":"Map"},{"title":"instance"}],"context":{"loc":{"start":{"line":237,"column":4},"end":{"line":239,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/easings.js","code":"{\n isEasing: function() {\n return !!this._abortFn;\n },\n\n /**\n * Stop current animation\n *\n * @returns {this}\n */\n stop: function() {\n if (this._abortFn) {\n this._abortFn.call(this);\n delete this._abortFn;\n\n this._finishFn.call(this);\n delete this._finishFn;\n }\n return this;\n },\n\n _ease: function(frame, finish, options) {\n this._finishFn = finish;\n this._abortFn = browser.timed(function (t) {\n frame.call(this, options.easing(t));\n if (t === 1) {\n delete this._abortFn;\n this._finishFn.call(this);\n delete this._finishFn;\n }\n }, options.animate === false ? 0 : options.duration, this);\n },\n\n /**\n * Pan by a certain number of pixels\n *\n * @param {Array} offset [x, y]\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n panBy: function(offset, options) {\n this.panTo(this.transform.center, util.extend({offset: Point.convert(offset).mult(-1)}, options));\n return this;\n },\n\n /**\n * Pan to a certain location with easing\n *\n * @param {Object} latlng a `LatLng` object\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n panTo: function(latlng, options) {\n this.stop();\n\n latlng = LatLng.convert(latlng);\n\n options = util.extend({\n duration: 500,\n easing: util.ease,\n offset: [0, 0]\n }, options);\n\n var tr = this.transform,\n offset = Point.convert(options.offset).rotate(-tr.angle),\n from = tr.point,\n to = tr.project(latlng).sub(offset);\n\n if (!options.noMoveStart) {\n this.fire('movestart');\n }\n\n this._ease(function(k) {\n tr.center = tr.unproject(from.add(to.sub(from).mult(k)));\n this._move();\n }, function() {\n this.fire('moveend');\n }, options);\n\n return this;\n },\n\n /**\n * Zooms to a certain zoom level with easing.\n *\n * @param {Number} zoom\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n zoomTo: function(zoom, options) {\n this.stop();\n\n options = util.extend({\n duration: 500\n }, options);\n\n options.easing = this._updateEasing(options.duration, zoom, options.easing);\n\n var tr = this.transform,\n around = tr.center,\n startZoom = tr.zoom;\n\n if (options.around) {\n around = LatLng.convert(options.around);\n } else if (options.offset) {\n around = tr.pointLocation(tr.centerPoint.add(Point.convert(options.offset)));\n }\n\n if (options.animate === false) options.duration = 0;\n\n if (!this.zooming) {\n this.zooming = true;\n this.fire('movestart');\n }\n\n this._ease(function(k) {\n tr.setZoomAround(interpolate(startZoom, zoom, k), around);\n this.animationLoop.set(300); // text fading\n this._move(true);\n }, function() {\n this.ease = null;\n if (options.duration >= 200) {\n this.zooming = false;\n this.fire('moveend');\n }\n }, options);\n\n if (options.duration < 200) {\n clearTimeout(this._onZoomEnd);\n this._onZoomEnd = setTimeout(function() {\n this.zooming = false;\n this._rerender();\n this.fire('moveend');\n }.bind(this), 200);\n }\n\n return this;\n },\n\n /**\n * Zoom in by 1 level\n *\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n zoomIn: function(options) {\n this.zoomTo(this.getZoom() + 1, options);\n },\n\n /**\n * Zoom out by 1 level\n *\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n zoomOut: function(options) {\n this.zoomTo(this.getZoom() - 1, options);\n },\n\n /**\n * Rotate bearing by a certain number of degrees with easing\n *\n * @param {Number} bearing\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n rotateTo: function(bearing, options) {\n this.stop();\n\n options = util.extend({\n duration: 500,\n easing: util.ease\n }, options);\n\n var tr = this.transform,\n start = this.getBearing(),\n around = tr.center;\n\n if (options.around) {\n around = LatLng.convert(options.around);\n } else if (options.offset) {\n around = tr.pointLocation(tr.centerPoint.add(Point.convert(options.offset)));\n }\n\n bearing = this._normalizeBearing(bearing, start);\n\n this.rotating = true;\n this.fire('movestart');\n\n this._ease(function(k) {\n tr.setBearingAround(interpolate(start, bearing, k), around);\n this._move(false, true);\n }, function() {\n this.rotating = false;\n this.fire('moveend');\n }, options);\n\n return this;\n },\n\n /**\n * Sets map bearing to 0 (north) with easing\n *\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n resetNorth: function(options) {\n return this.rotateTo(0, util.extend({duration: 1000}, options));\n },\n\n /**\n * Zoom to contain certain geographical bounds\n *\n * @param {Array} bounds [[minLat, minLng], [maxLat, maxLng]]\n * @param {Object} options\n * @param {Number} [options.speed=1.2] How fast animation occurs\n * @param {Number} [options.curve=1.42] How much zooming out occurs during animation\n * @param {Function} options.easing\n * @param {Number} options.padding how much padding there is around the given bounds on each side in pixels\n * @param {Number} options.maxZoom\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n fitBounds: function(bounds, options) {\n\n options = util.extend({\n padding: 0,\n offset: [0, 0],\n maxZoom: Infinity\n }, options);\n\n bounds = LatLngBounds.convert(bounds);\n\n var offset = Point.convert(options.offset),\n tr = this.transform,\n nw = tr.project(bounds.getNorthWest()),\n se = tr.project(bounds.getSouthEast()),\n size = se.sub(nw),\n center = tr.unproject(nw.add(se).div(2)),\n\n scaleX = (tr.width - options.padding * 2 - Math.abs(offset.x) * 2) / size.x,\n scaleY = (tr.height - options.padding * 2 - Math.abs(offset.y) * 2) / size.y,\n\n zoom = Math.min(tr.scaleZoom(tr.scale * Math.min(scaleX, scaleY)), options.maxZoom);\n\n return options.linear ?\n this.easeTo(center, zoom, 0, options) :\n this.flyTo(center, zoom, 0, options);\n },\n\n /**\n * Easing animation to a specified location/zoom/bearing\n *\n * @param {Object} latlng a `LatLng` object\n * @param {Number} zoom\n * @param {Number} bearing\n * @param {Number} pitch\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n easeTo: function(latlng, zoom, bearing, pitch, options) {\n this.stop();\n\n options = util.extend({\n offset: [0, 0],\n duration: 500,\n easing: util.ease\n }, options);\n\n var tr = this.transform,\n offset = Point.convert(options.offset).rotate(-tr.angle),\n startZoom = this.getZoom(),\n startBearing = this.getBearing(),\n startPitch = this.getPitch();\n\n latlng = LatLng.convert(latlng);\n zoom = zoom === undefined ? startZoom : zoom;\n bearing = bearing === undefined ? startBearing : this._normalizeBearing(bearing, startBearing);\n pitch = pitch === undefined ? startPitch : pitch;\n\n var scale = tr.zoomScale(zoom - startZoom),\n from = tr.point,\n to = latlng ? tr.project(latlng).sub(offset.div(scale)) : tr.point,\n around;\n\n if (zoom !== startZoom) {\n around = tr.pointLocation(tr.centerPoint.add(to.sub(from).div(1 - 1 / scale)));\n this.zooming = true;\n }\n if (startBearing !== bearing) this.rotating = true;\n\n this.fire('movestart');\n\n this._ease(function (k) {\n if (zoom !== startZoom) {\n tr.setZoomAround(interpolate(startZoom, zoom, k), around);\n } else {\n tr.center = tr.unproject(from.add(to.sub(from).mult(k)));\n }\n\n if (bearing !== startBearing) {\n tr.bearing = interpolate(startBearing, bearing, k);\n }\n\n if (pitch !== startPitch) {\n tr.pitch = interpolate(startPitch, pitch, k);\n }\n\n this.animationLoop.set(300); // text fading\n this._move(zoom !== startZoom, bearing !== startBearing);\n }, function() {\n this.zooming = false;\n this.rotating = false;\n this.fire('moveend');\n }, options);\n\n return this;\n },\n\n /**\n * Flying animation to a specified location/zoom/bearing with automatic curve\n *\n * @param {Object} latlng a `LatLng` object\n * @param {Number} zoom\n * @param {Number} bearing\n * @param {Object} options\n * @param {Number} [options.speed=1.2] How fast animation occurs\n * @param {Number} [options.curve=1.42] How much zooming out occurs during animation\n * @param {Function} options.easing\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n flyTo: function(latlng, zoom, bearing, options) {\n this.stop();\n\n options = util.extend({\n offset: [0, 0],\n speed: 1.2,\n curve: 1.42,\n easing: util.ease\n }, options);\n\n latlng = LatLng.convert(latlng);\n\n var offset = Point.convert(options.offset),\n tr = this.transform,\n startZoom = this.getZoom(),\n startBearing = this.getBearing();\n\n zoom = zoom === undefined ? startZoom : zoom;\n bearing = bearing === undefined ? startBearing : this._normalizeBearing(bearing, startBearing);\n\n var scale = tr.zoomScale(zoom - startZoom),\n from = tr.point,\n to = tr.project(latlng).sub(offset.div(scale));\n\n if (options.animate === false) {\n return this.setView(latlng, zoom, bearing, this.getPitch());\n }\n\n var startWorldSize = tr.worldSize,\n rho = options.curve,\n V = options.speed,\n\n w0 = Math.max(tr.width, tr.height),\n w1 = w0 / scale,\n u1 = to.sub(from).mag(),\n rho2 = rho * rho;\n\n function r(i) {\n var b = (w1 * w1 - w0 * w0 + (i ? -1 : 1) * rho2 * rho2 * u1 * u1) / (2 * (i ? w1 : w0) * rho2 * u1);\n return Math.log(Math.sqrt(b * b + 1) - b);\n }\n\n function sinh(n) { return (Math.exp(n) - Math.exp(-n)) / 2; }\n function cosh(n) { return (Math.exp(n) + Math.exp(-n)) / 2; }\n function tanh(n) { return sinh(n) / cosh(n); }\n\n var r0 = r(0),\n w = function (s) { return (cosh(r0) / cosh(r0 + rho * s)); },\n u = function (s) { return w0 * ((cosh(r0) * tanh(r0 + rho * s) - sinh(r0)) / rho2) / u1; },\n S = (r(1) - r0) / rho;\n\n if (Math.abs(u1) < 0.000001) {\n if (Math.abs(w0 - w1) < 0.000001) return this;\n\n var k = w1 < w0 ? -1 : 1;\n S = Math.abs(Math.log(w1 / w0)) / rho;\n\n u = function() { return 0; };\n w = function(s) { return Math.exp(k * rho * s); };\n }\n\n options.duration = 1000 * S / V;\n\n this.zooming = true;\n if (startBearing !== bearing) this.rotating = true;\n\n this.fire('movestart');\n\n this._ease(function (k) {\n var s = k * S,\n us = u(s);\n\n tr.zoom = startZoom + tr.scaleZoom(1 / w(s));\n tr.center = tr.unproject(from.add(to.sub(from).mult(us)), startWorldSize);\n\n if (bearing !== startBearing) {\n tr.bearing = interpolate(startBearing, bearing, k);\n }\n\n this.animationLoop.set(300); // text fading\n\n this._move(true, bearing !== startBearing);\n }, function() {\n this.zooming = false;\n this.rotating = false;\n this.fire('moveend');\n }, options);\n\n return this;\n },\n\n // convert bearing so that it's numerically close to the current one so that it interpolates properly\n _normalizeBearing: function(bearing, currentBearing) {\n bearing = util.wrap(bearing, -180, 180);\n var diff = Math.abs(bearing - currentBearing);\n if (Math.abs(bearing - 360 - currentBearing) < diff) bearing -= 360;\n if (Math.abs(bearing + 360 - currentBearing) < diff) bearing += 360;\n return bearing;\n },\n\n _updateEasing: function(duration, zoom, bezier) {\n var easing;\n\n if (this.ease) {\n var ease = this.ease,\n t = (Date.now() - ease.start) / ease.duration,\n speed = ease.easing(t + 0.01) - ease.easing(t),\n\n // Quick hack to make new bezier that is continuous with last\n x = 0.27 / Math.sqrt(speed * speed + 0.0001) * 0.01,\n y = Math.sqrt(0.27 * 0.27 - x * x);\n\n easing = util.bezier(x, y, 0.25, 1);\n } else {\n easing = bezier ? util.bezier.apply(util, bezier) : util.ease;\n }\n\n // store information on current easing\n this.ease = {\n start: (new Date()).getTime(),\n to: Math.pow(2, zoom),\n duration: duration,\n easing: easing\n };\n\n return easing;\n }\n}","path":"js/ui/easings.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/easings.js#L237-L239"},"params":[{"title":"param","description":null,"type":null,"name":"animOptions"}],"returns":[{"title":"returns","description":null,"type":{"type":"NameExpression","name":"this"}}],"name":"resetNorth","memberof":"Map","scope":"instance","members":{"instance":[],"static":[]},"path":["Map","resetNorth"]},{"description":"Detect the map's new width and height and resize it.","tags":[{"title":"returns","description":"`this`","type":{"type":"NameExpression","name":"Map"}},{"title":"name","name":"resize"},{"title":"memberof","description":"Map"},{"title":"instance"}],"context":{"loc":{"start":{"line":294,"column":4},"end":{"line":315,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/map.js","code":"{\n\n options: {\n center: [0, 0],\n zoom: 0,\n bearing: 0,\n pitch: 0,\n\n minZoom: 0,\n maxZoom: 20,\n\n interactive: true,\n hash: false,\n\n attributionControl: true,\n\n failIfMajorPerformanceCaveat: false\n },\n\n addControl: function(control) {\n control.addTo(this);\n return this;\n },\n\n /**\n * Sets a map position\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @param {number} zoom Map zoom level\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setView: function(center, zoom, bearing, pitch) {\n this.stop();\n\n var tr = this.transform,\n zoomChanged = tr.zoom !== +zoom,\n bearingChanged = tr.bearing !== +bearing,\n pitchChanged = tr.pitch !== +pitch;\n\n tr.center = LatLng.convert(center);\n tr.zoom = +zoom;\n tr.bearing = +bearing;\n tr.pitch = +pitch;\n\n return this\n .fire('movestart')\n ._move(zoomChanged, bearingChanged, pitchChanged)\n .fire('moveend');\n },\n\n /**\n * Sets a map location\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setCenter: function(center) {\n this.setView(center, this.getZoom(), this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map zoom\n *\n * @param {number} zoom Map zoom level\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setZoom: function(zoom) {\n this.setView(this.getCenter(), zoom, this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map rotation\n *\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setBearing: function(bearing) {\n this.setView(this.getCenter(), this.getZoom(), bearing, this.getPitch());\n },\n\n /**\n * Sets a map angle\n *\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setPitch: function(pitch) {\n this.setView(this.getCenter(), this.getZoom(), this.getBearing(), pitch);\n },\n\n /**\n * Get the current view geographical point\n * @returns {LatLng}\n */\n getCenter: function() { return this.transform.center; },\n\n /**\n * Get the current zoom\n * @returns {number}\n */\n getZoom: function() { return this.transform.zoom; },\n\n /**\n * Get the current bearing in degrees\n * @returns {number}\n */\n getBearing: function() { return this.transform.bearing; },\n\n /**\n * Get the current angle in degrees\n * @returns {number}\n */\n getPitch: function() { return this.transform.pitch; },\n\n /**\n * @typedef {Object} [styleOptions]\n * @param {Boolean} [styleOptions.transition=true]\n */\n\n /**\n * Adds a style class to a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n addClass: function(klass, options) {\n if (this._classes[klass]) return;\n this._classes[klass] = true;\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Removes a style class from a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n removeClass: function(klass, options) {\n if (!this._classes[klass]) return;\n delete this._classes[klass];\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Helper method to add more than one class\n *\n * @param {Array} klasses An array of class names\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n setClasses: function(klasses, options) {\n this._classes = {};\n for (var i = 0; i < klasses.length; i++) {\n this._classes[klasses[i]] = true;\n }\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Check whether a style class is active\n *\n * @param {string} klass Name of style class\n * @returns {boolean}\n */\n hasClass: function(klass) {\n return !!this._classes[klass];\n },\n\n /**\n * Return an array of the current active style classes\n *\n * @returns {boolean}\n */\n getClasses: function() {\n return Object.keys(this._classes);\n },\n\n /**\n * Detect the map's new width and height and resize it.\n *\n * @returns {Map} `this`\n */\n resize: function() {\n var width = 0, height = 0;\n\n if (this._container) {\n width = this._container.offsetWidth || 400;\n height = this._container.offsetHeight || 300;\n }\n\n this._canvas.resize(width, height);\n\n this.transform.width = width;\n this.transform.height = height;\n this.transform._constrain();\n\n this.painter.resize(width, height);\n\n return this\n .fire('movestart')\n ._move()\n .fire('resize')\n .fire('moveend');\n },\n\n /**\n * Get the map's geographical bounds\n *\n * @returns {LatLngBounds}\n */\n getBounds: function() {\n return new LatLngBounds(\n this.transform.pointLocation(new Point(0, 0)),\n this.transform.pointLocation(this.transform.size));\n },\n\n /**\n * Get pixel coordinates (relative to map container) given a geographical location\n *\n * @param {LatLng} latlng\n * @returns {Object} `x` and `y` coordinates\n */\n project: function(latlng) {\n return this.transform.locationPoint(LatLng.convert(latlng));\n },\n\n /**\n * Get geographical coordinates given pixel coordinates\n *\n * @param {Array} point [x, y] pixel coordinates\n * @returns {LatLng}\n */\n unproject: function(point) {\n return this.transform.pointLocation(Point.convert(point));\n },\n\n /**\n * Get all features at a point ([x, y])\n *\n * @param {Array} point [x, y] pixel coordinates\n * @param {Object} params\n * @param {number} [params.radius=0] Optional. Radius in pixels to search in\n * @param {string} params.layer Optional. Only return features from a given layer\n * @param {string} params.type Optional. Either `raster` or `vector`\n * @param {featuresAtCallback} callback function that returns the response\n *\n * @callback featuresAtCallback\n * @param {Object|null} err Error _If any_\n * @param {Array} features Displays a JSON array of features given the passed parameters of `featuresAt`\n *\n * @returns {Map} `this`\n */\n featuresAt: function(point, params, callback) {\n var coord = this.transform.pointCoordinate(Point.convert(point));\n this.style.featuresAt(coord, params, callback);\n return this;\n },\n\n /**\n * Replaces the map's style object\n *\n * @param {Object} style A style object formatted as JSON\n * @returns {Map} `this`\n */\n setStyle: function(style) {\n if (this.style) {\n this.style\n .off('load', this._onStyleLoad)\n .off('error', this._forwardStyleEvent)\n .off('change', this._onStyleChange)\n .off('source.add', this._onSourceAdd)\n .off('source.remove', this._onSourceRemove)\n .off('source.load', this._onSourceUpdate)\n .off('source.error', this._forwardSourceEvent)\n .off('source.change', this._onSourceUpdate)\n .off('layer.add', this._forwardLayerEvent)\n .off('layer.remove', this._forwardLayerEvent)\n .off('tile.add', this._forwardTileEvent)\n .off('tile.remove', this._forwardTileEvent)\n .off('tile.load', this.update)\n .off('tile.error', this._forwardTileEvent)\n ._remove();\n\n this.off('rotate', this.style._redoPlacement);\n this.off('pitch', this.style._redoPlacement);\n }\n\n if (!style) {\n this.style = null;\n return this;\n } else if (style instanceof Style) {\n this.style = style;\n } else {\n this.style = new Style(style, this.animationLoop);\n }\n\n this.style\n .on('load', this._onStyleLoad)\n .on('error', this._forwardStyleEvent)\n .on('change', this._onStyleChange)\n .on('source.add', this._onSourceAdd)\n .on('source.remove', this._onSourceRemove)\n .on('source.load', this._onSourceUpdate)\n .on('source.error', this._forwardSourceEvent)\n .on('source.change', this._onSourceUpdate)\n .on('layer.add', this._forwardLayerEvent)\n .on('layer.remove', this._forwardLayerEvent)\n .on('tile.add', this._forwardTileEvent)\n .on('tile.remove', this._forwardTileEvent)\n .on('tile.load', this.update)\n .on('tile.error', this._forwardTileEvent);\n\n this.on('rotate', this.style._redoPlacement);\n this.on('pitch', this.style._redoPlacement);\n\n return this;\n },\n\n /**\n * Add a source to the map style.\n *\n * @param {string} id ID of the source. Must not be used by any existing source.\n * @param {Object} source source specification, following the\n * [Mapbox GL Style Reference](https://www.mapbox.com/mapbox-gl-style-spec/#sources)\n * @fires source.add\n * @returns {Map} `this`\n */\n addSource: function(id, source) {\n this.style.addSource(id, source);\n return this;\n },\n\n /**\n * Remove an existing source from the map style.\n *\n * @param {string} id ID of the source to remove\n * @fires source.remove\n * @returns {Map} `this`\n */\n removeSource: function(id) {\n this.style.removeSource(id);\n return this;\n },\n\n /**\n * Return the style source object with the given `id`.\n *\n * @param {string} id source ID\n * @returns {Object}\n */\n getSource: function(id) {\n return this.style.getSource(id);\n },\n\n /**\n * Add a layer to the map style. The layer will be inserted before the layer with\n * ID `before`, or appended if `before` is omitted.\n * @param {Layer} layer\n * @param {string=} before ID of an existing layer to insert before\n * @fires layer.add\n * @returns {Map} `this`\n */\n addLayer: function(layer, before) {\n this.style.addLayer(layer, before);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Remove the layer with the given `id` from the map. Any layers which refer to the\n * specified layer via a `ref` property are also removed.\n *\n * @param {string} id\n * @fires layer.remove\n * @returns {Map} this\n */\n removeLayer: function(id) {\n this.style.removeLayer(id);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Set the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {Array} filter filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n * @returns {Map} `this`\n */\n setFilter: function(layer, filter) {\n this.style.setFilter(layer, filter);\n return this;\n },\n\n /**\n * Get the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @returns {Array} filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n */\n getFilter: function(layer) {\n return this.style.getFilter(layer);\n },\n\n /**\n * Set the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {*} value value for the paint propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @param {string=} klass optional class specifier for the property\n * @returns {Map} `this`\n */\n setPaintProperty: function(layer, name, value, klass) {\n this.style.setPaintProperty(layer, name, value, klass);\n this.style._cascade(this._classes);\n this.update(true);\n return this;\n },\n\n /**\n * Get the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the paint propery\n */\n getPaintProperty: function(layer, name, klass) {\n return this.style.getPaintProperty(layer, name, klass);\n },\n\n /**\n * Set the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {*} value value for the layout propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @returns {Map} `this`\n */\n setLayoutProperty: function(layer, name, value) {\n this.style.setLayoutProperty(layer, name, value);\n return this;\n },\n\n /**\n * Get the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the layout propery\n */\n getLayoutProperty: function(layer, name) {\n return this.style.getLayoutProperty(layer, name);\n },\n\n /**\n * Get the Map's container as an HTML element\n * @returns {HTMLElement} container\n */\n getContainer: function() {\n return this._container;\n },\n\n /**\n * Get the Map's canvas as an HTML canvas\n * @returns {HTMLElement} canvas\n */\n getCanvas: function() {\n return this._canvas.getElement();\n },\n\n _move: function(zoom, rotate, pitch) {\n\n this.update(zoom).fire('move');\n\n if (zoom) this.fire('zoom');\n if (rotate) this.fire('rotate');\n if (pitch) this.fire('pitch');\n\n return this;\n },\n\n // map setup code\n _setupContainer: function() {\n var id = this.options.container;\n var container = this._container = typeof id === 'string' ? document.getElementById(id) : id;\n if (container) container.classList.add('mapboxgl-map');\n this._canvas = new Canvas(this, container);\n },\n\n _setupControlPos: function() {\n var corners = this._controlCorners = {};\n var prefix = 'mapboxgl-ctrl-';\n var container = this.getContainer();\n\n function createCorner(pos) {\n var className = prefix + pos;\n corners[pos] = DOM.create('div', className, container);\n }\n\n if (container && typeof document === 'object') {\n createCorner('top-left');\n createCorner('top-right');\n createCorner('bottom-left');\n createCorner('bottom-right');\n }\n },\n\n _setupPainter: function() {\n var gl = this._canvas.getWebGLContext(this.options.failIfMajorPerformanceCaveat);\n\n if (!gl) {\n console.error('Failed to initialize WebGL');\n return;\n }\n\n this.painter = new GLPainter(gl, this.transform);\n },\n\n _contextLost: function(event) {\n event.preventDefault();\n if (this._frameId) {\n browser.cancelFrame(this._frameId);\n }\n },\n\n _contextRestored: function() {\n this._setupPainter();\n this.resize();\n this.update();\n },\n\n /**\n * Is this map fully loaded? If the style isn't loaded\n * or it has a change to the sources or style that isn't\n * propagated to its style, return false.\n *\n * @returns {boolean} whether the map is loaded\n */\n loaded: function() {\n if (this._styleDirty || this._sourcesDirty)\n return false;\n if (this.style && !this.style.loaded())\n return false;\n return true;\n },\n\n /**\n * Update this map's style and re-render the map.\n *\n * @param {Object} updateStyle new style\n * @returns {Map} this\n */\n update: function(updateStyle) {\n if (!this.style) return this;\n\n this._styleDirty = this._styleDirty || updateStyle;\n this._sourcesDirty = true;\n\n this._rerender();\n\n return this;\n },\n\n /**\n * Call when a (re-)render of the map is required, e.g. when the\n * user panned or zoomed,f or new data is available.\n * @returns {Map} this\n */\n render: function() {\n if (this.style && this._styleDirty) {\n this._styleDirty = false;\n this.style._recalculate(this.transform.zoom);\n }\n\n if (this.style && this._sourcesDirty && !this._sourcesDirtyTimeout) {\n this._sourcesDirty = false;\n this._sourcesDirtyTimeout = setTimeout(function() {\n this._sourcesDirtyTimeout = null;\n }.bind(this), 50);\n this.style._updateSources(this.transform);\n }\n\n this.painter.render(this.style, {\n debug: this.debug,\n vertices: this.vertices,\n rotating: this.rotating,\n zooming: this.zooming\n });\n\n this.fire('render');\n\n if (this.loaded() && !this._loaded) {\n this._loaded = true;\n this.fire('load');\n }\n\n this._frameId = null;\n\n if (!this.animationLoop.stopped()) {\n this._styleDirty = true;\n }\n\n if (this._sourcesDirty || this._repaint || !this.animationLoop.stopped()) {\n this._rerender();\n }\n\n return this;\n },\n\n /**\n * Destroys the map's underlying resources, including web workers.\n * @returns {Map} this\n */\n remove: function() {\n if (this._hash) this._hash.remove();\n browser.cancelFrame(this._frameId);\n clearTimeout(this._sourcesDirtyTimeout);\n this.setStyle(null);\n return this;\n },\n\n _rerender: function() {\n if (this.style && !this._frameId) {\n this._frameId = browser.frame(this.render);\n }\n },\n\n _forwardStyleEvent: function(e) {\n this.fire('style.' + e.type, util.extend({style: e.target}, e));\n },\n\n _forwardSourceEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardLayerEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardTileEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _onStyleLoad: function(e) {\n this.style._cascade(this._classes, {transition: false});\n this._forwardStyleEvent(e);\n },\n\n _onStyleChange: function(e) {\n this.update(true);\n this._forwardStyleEvent(e);\n },\n\n _onSourceAdd: function(e) {\n var source = e.source;\n if (source.onAdd)\n source.onAdd(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceRemove: function(e) {\n var source = e.source;\n if (source.onRemove)\n source.onRemove(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceUpdate: function(e) {\n this.update();\n this._forwardSourceEvent(e);\n }\n}","path":"js/ui/map.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/map.js#L294-L315"},"returns":[{"title":"returns","description":"`this`","type":{"type":"NameExpression","name":"Map"}}],"name":"resize","memberof":"Map","scope":"instance","members":{"instance":[],"static":[]},"path":["Map","resize"]},{"description":"Zoom to contain certain geographical bounds","tags":[{"title":"param","description":"[[minLat, minLng], [maxLat, maxLng]]","type":{"type":"NameExpression","name":"Array"},"name":"bounds"},{"title":"param","description":null,"type":{"type":"NameExpression","name":"Object"},"name":"options"},{"title":"name","name":"fitBounds"},{"title":"memberof","description":"Map"},{"title":"instance"}],"context":{"loc":{"start":{"line":255,"column":4},"end":{"line":280,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/easings.js","code":"{\n isEasing: function() {\n return !!this._abortFn;\n },\n\n /**\n * Stop current animation\n *\n * @returns {this}\n */\n stop: function() {\n if (this._abortFn) {\n this._abortFn.call(this);\n delete this._abortFn;\n\n this._finishFn.call(this);\n delete this._finishFn;\n }\n return this;\n },\n\n _ease: function(frame, finish, options) {\n this._finishFn = finish;\n this._abortFn = browser.timed(function (t) {\n frame.call(this, options.easing(t));\n if (t === 1) {\n delete this._abortFn;\n this._finishFn.call(this);\n delete this._finishFn;\n }\n }, options.animate === false ? 0 : options.duration, this);\n },\n\n /**\n * Pan by a certain number of pixels\n *\n * @param {Array} offset [x, y]\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n panBy: function(offset, options) {\n this.panTo(this.transform.center, util.extend({offset: Point.convert(offset).mult(-1)}, options));\n return this;\n },\n\n /**\n * Pan to a certain location with easing\n *\n * @param {Object} latlng a `LatLng` object\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n panTo: function(latlng, options) {\n this.stop();\n\n latlng = LatLng.convert(latlng);\n\n options = util.extend({\n duration: 500,\n easing: util.ease,\n offset: [0, 0]\n }, options);\n\n var tr = this.transform,\n offset = Point.convert(options.offset).rotate(-tr.angle),\n from = tr.point,\n to = tr.project(latlng).sub(offset);\n\n if (!options.noMoveStart) {\n this.fire('movestart');\n }\n\n this._ease(function(k) {\n tr.center = tr.unproject(from.add(to.sub(from).mult(k)));\n this._move();\n }, function() {\n this.fire('moveend');\n }, options);\n\n return this;\n },\n\n /**\n * Zooms to a certain zoom level with easing.\n *\n * @param {Number} zoom\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n zoomTo: function(zoom, options) {\n this.stop();\n\n options = util.extend({\n duration: 500\n }, options);\n\n options.easing = this._updateEasing(options.duration, zoom, options.easing);\n\n var tr = this.transform,\n around = tr.center,\n startZoom = tr.zoom;\n\n if (options.around) {\n around = LatLng.convert(options.around);\n } else if (options.offset) {\n around = tr.pointLocation(tr.centerPoint.add(Point.convert(options.offset)));\n }\n\n if (options.animate === false) options.duration = 0;\n\n if (!this.zooming) {\n this.zooming = true;\n this.fire('movestart');\n }\n\n this._ease(function(k) {\n tr.setZoomAround(interpolate(startZoom, zoom, k), around);\n this.animationLoop.set(300); // text fading\n this._move(true);\n }, function() {\n this.ease = null;\n if (options.duration >= 200) {\n this.zooming = false;\n this.fire('moveend');\n }\n }, options);\n\n if (options.duration < 200) {\n clearTimeout(this._onZoomEnd);\n this._onZoomEnd = setTimeout(function() {\n this.zooming = false;\n this._rerender();\n this.fire('moveend');\n }.bind(this), 200);\n }\n\n return this;\n },\n\n /**\n * Zoom in by 1 level\n *\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n zoomIn: function(options) {\n this.zoomTo(this.getZoom() + 1, options);\n },\n\n /**\n * Zoom out by 1 level\n *\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n zoomOut: function(options) {\n this.zoomTo(this.getZoom() - 1, options);\n },\n\n /**\n * Rotate bearing by a certain number of degrees with easing\n *\n * @param {Number} bearing\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n rotateTo: function(bearing, options) {\n this.stop();\n\n options = util.extend({\n duration: 500,\n easing: util.ease\n }, options);\n\n var tr = this.transform,\n start = this.getBearing(),\n around = tr.center;\n\n if (options.around) {\n around = LatLng.convert(options.around);\n } else if (options.offset) {\n around = tr.pointLocation(tr.centerPoint.add(Point.convert(options.offset)));\n }\n\n bearing = this._normalizeBearing(bearing, start);\n\n this.rotating = true;\n this.fire('movestart');\n\n this._ease(function(k) {\n tr.setBearingAround(interpolate(start, bearing, k), around);\n this._move(false, true);\n }, function() {\n this.rotating = false;\n this.fire('moveend');\n }, options);\n\n return this;\n },\n\n /**\n * Sets map bearing to 0 (north) with easing\n *\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n resetNorth: function(options) {\n return this.rotateTo(0, util.extend({duration: 1000}, options));\n },\n\n /**\n * Zoom to contain certain geographical bounds\n *\n * @param {Array} bounds [[minLat, minLng], [maxLat, maxLng]]\n * @param {Object} options\n * @param {Number} [options.speed=1.2] How fast animation occurs\n * @param {Number} [options.curve=1.42] How much zooming out occurs during animation\n * @param {Function} options.easing\n * @param {Number} options.padding how much padding there is around the given bounds on each side in pixels\n * @param {Number} options.maxZoom\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n fitBounds: function(bounds, options) {\n\n options = util.extend({\n padding: 0,\n offset: [0, 0],\n maxZoom: Infinity\n }, options);\n\n bounds = LatLngBounds.convert(bounds);\n\n var offset = Point.convert(options.offset),\n tr = this.transform,\n nw = tr.project(bounds.getNorthWest()),\n se = tr.project(bounds.getSouthEast()),\n size = se.sub(nw),\n center = tr.unproject(nw.add(se).div(2)),\n\n scaleX = (tr.width - options.padding * 2 - Math.abs(offset.x) * 2) / size.x,\n scaleY = (tr.height - options.padding * 2 - Math.abs(offset.y) * 2) / size.y,\n\n zoom = Math.min(tr.scaleZoom(tr.scale * Math.min(scaleX, scaleY)), options.maxZoom);\n\n return options.linear ?\n this.easeTo(center, zoom, 0, options) :\n this.flyTo(center, zoom, 0, options);\n },\n\n /**\n * Easing animation to a specified location/zoom/bearing\n *\n * @param {Object} latlng a `LatLng` object\n * @param {Number} zoom\n * @param {Number} bearing\n * @param {Number} pitch\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n easeTo: function(latlng, zoom, bearing, pitch, options) {\n this.stop();\n\n options = util.extend({\n offset: [0, 0],\n duration: 500,\n easing: util.ease\n }, options);\n\n var tr = this.transform,\n offset = Point.convert(options.offset).rotate(-tr.angle),\n startZoom = this.getZoom(),\n startBearing = this.getBearing(),\n startPitch = this.getPitch();\n\n latlng = LatLng.convert(latlng);\n zoom = zoom === undefined ? startZoom : zoom;\n bearing = bearing === undefined ? startBearing : this._normalizeBearing(bearing, startBearing);\n pitch = pitch === undefined ? startPitch : pitch;\n\n var scale = tr.zoomScale(zoom - startZoom),\n from = tr.point,\n to = latlng ? tr.project(latlng).sub(offset.div(scale)) : tr.point,\n around;\n\n if (zoom !== startZoom) {\n around = tr.pointLocation(tr.centerPoint.add(to.sub(from).div(1 - 1 / scale)));\n this.zooming = true;\n }\n if (startBearing !== bearing) this.rotating = true;\n\n this.fire('movestart');\n\n this._ease(function (k) {\n if (zoom !== startZoom) {\n tr.setZoomAround(interpolate(startZoom, zoom, k), around);\n } else {\n tr.center = tr.unproject(from.add(to.sub(from).mult(k)));\n }\n\n if (bearing !== startBearing) {\n tr.bearing = interpolate(startBearing, bearing, k);\n }\n\n if (pitch !== startPitch) {\n tr.pitch = interpolate(startPitch, pitch, k);\n }\n\n this.animationLoop.set(300); // text fading\n this._move(zoom !== startZoom, bearing !== startBearing);\n }, function() {\n this.zooming = false;\n this.rotating = false;\n this.fire('moveend');\n }, options);\n\n return this;\n },\n\n /**\n * Flying animation to a specified location/zoom/bearing with automatic curve\n *\n * @param {Object} latlng a `LatLng` object\n * @param {Number} zoom\n * @param {Number} bearing\n * @param {Object} options\n * @param {Number} [options.speed=1.2] How fast animation occurs\n * @param {Number} [options.curve=1.42] How much zooming out occurs during animation\n * @param {Function} options.easing\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n flyTo: function(latlng, zoom, bearing, options) {\n this.stop();\n\n options = util.extend({\n offset: [0, 0],\n speed: 1.2,\n curve: 1.42,\n easing: util.ease\n }, options);\n\n latlng = LatLng.convert(latlng);\n\n var offset = Point.convert(options.offset),\n tr = this.transform,\n startZoom = this.getZoom(),\n startBearing = this.getBearing();\n\n zoom = zoom === undefined ? startZoom : zoom;\n bearing = bearing === undefined ? startBearing : this._normalizeBearing(bearing, startBearing);\n\n var scale = tr.zoomScale(zoom - startZoom),\n from = tr.point,\n to = tr.project(latlng).sub(offset.div(scale));\n\n if (options.animate === false) {\n return this.setView(latlng, zoom, bearing, this.getPitch());\n }\n\n var startWorldSize = tr.worldSize,\n rho = options.curve,\n V = options.speed,\n\n w0 = Math.max(tr.width, tr.height),\n w1 = w0 / scale,\n u1 = to.sub(from).mag(),\n rho2 = rho * rho;\n\n function r(i) {\n var b = (w1 * w1 - w0 * w0 + (i ? -1 : 1) * rho2 * rho2 * u1 * u1) / (2 * (i ? w1 : w0) * rho2 * u1);\n return Math.log(Math.sqrt(b * b + 1) - b);\n }\n\n function sinh(n) { return (Math.exp(n) - Math.exp(-n)) / 2; }\n function cosh(n) { return (Math.exp(n) + Math.exp(-n)) / 2; }\n function tanh(n) { return sinh(n) / cosh(n); }\n\n var r0 = r(0),\n w = function (s) { return (cosh(r0) / cosh(r0 + rho * s)); },\n u = function (s) { return w0 * ((cosh(r0) * tanh(r0 + rho * s) - sinh(r0)) / rho2) / u1; },\n S = (r(1) - r0) / rho;\n\n if (Math.abs(u1) < 0.000001) {\n if (Math.abs(w0 - w1) < 0.000001) return this;\n\n var k = w1 < w0 ? -1 : 1;\n S = Math.abs(Math.log(w1 / w0)) / rho;\n\n u = function() { return 0; };\n w = function(s) { return Math.exp(k * rho * s); };\n }\n\n options.duration = 1000 * S / V;\n\n this.zooming = true;\n if (startBearing !== bearing) this.rotating = true;\n\n this.fire('movestart');\n\n this._ease(function (k) {\n var s = k * S,\n us = u(s);\n\n tr.zoom = startZoom + tr.scaleZoom(1 / w(s));\n tr.center = tr.unproject(from.add(to.sub(from).mult(us)), startWorldSize);\n\n if (bearing !== startBearing) {\n tr.bearing = interpolate(startBearing, bearing, k);\n }\n\n this.animationLoop.set(300); // text fading\n\n this._move(true, bearing !== startBearing);\n }, function() {\n this.zooming = false;\n this.rotating = false;\n this.fire('moveend');\n }, options);\n\n return this;\n },\n\n // convert bearing so that it's numerically close to the current one so that it interpolates properly\n _normalizeBearing: function(bearing, currentBearing) {\n bearing = util.wrap(bearing, -180, 180);\n var diff = Math.abs(bearing - currentBearing);\n if (Math.abs(bearing - 360 - currentBearing) < diff) bearing -= 360;\n if (Math.abs(bearing + 360 - currentBearing) < diff) bearing += 360;\n return bearing;\n },\n\n _updateEasing: function(duration, zoom, bezier) {\n var easing;\n\n if (this.ease) {\n var ease = this.ease,\n t = (Date.now() - ease.start) / ease.duration,\n speed = ease.easing(t + 0.01) - ease.easing(t),\n\n // Quick hack to make new bezier that is continuous with last\n x = 0.27 / Math.sqrt(speed * speed + 0.0001) * 0.01,\n y = Math.sqrt(0.27 * 0.27 - x * x);\n\n easing = util.bezier(x, y, 0.25, 1);\n } else {\n easing = bezier ? util.bezier.apply(util, bezier) : util.ease;\n }\n\n // store information on current easing\n this.ease = {\n start: (new Date()).getTime(),\n to: Math.pow(2, zoom),\n duration: duration,\n easing: easing\n };\n\n return easing;\n }\n}","path":"js/ui/easings.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/easings.js#L255-L280"},"params":[{"title":"param","description":"[[minLat, minLng], [maxLat, maxLng]]","type":{"type":"NameExpression","name":"Array"},"name":"bounds"},{"title":"param","description":null,"type":{"type":"NameExpression","name":"Object"},"name":"options"}],"name":"fitBounds","memberof":"Map","scope":"instance","members":{"instance":[],"static":[]},"path":["Map","fitBounds"]},{"description":"Easing animation to a specified location/zoom/bearing","tags":[{"title":"param","description":"a `LatLng` object","type":{"type":"NameExpression","name":"Object"},"name":"latlng"},{"title":"param","description":null,"type":{"type":"NameExpression","name":"Number"},"name":"zoom"},{"title":"param","description":null,"type":{"type":"NameExpression","name":"Number"},"name":"bearing"},{"title":"param","description":null,"type":{"type":"NameExpression","name":"Number"},"name":"pitch"},{"title":"param","description":null,"type":null,"name":"animOptions"},{"title":"fires","description":"movestart"},{"title":"fires","description":"moveend"},{"title":"returns","description":null,"type":{"type":"NameExpression","name":"this"}},{"title":"name","name":"easeTo"},{"title":"memberof","description":"Map"},{"title":"instance"}],"context":{"loc":{"start":{"line":294,"column":4},"end":{"line":351,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/easings.js","code":"{\n isEasing: function() {\n return !!this._abortFn;\n },\n\n /**\n * Stop current animation\n *\n * @returns {this}\n */\n stop: function() {\n if (this._abortFn) {\n this._abortFn.call(this);\n delete this._abortFn;\n\n this._finishFn.call(this);\n delete this._finishFn;\n }\n return this;\n },\n\n _ease: function(frame, finish, options) {\n this._finishFn = finish;\n this._abortFn = browser.timed(function (t) {\n frame.call(this, options.easing(t));\n if (t === 1) {\n delete this._abortFn;\n this._finishFn.call(this);\n delete this._finishFn;\n }\n }, options.animate === false ? 0 : options.duration, this);\n },\n\n /**\n * Pan by a certain number of pixels\n *\n * @param {Array} offset [x, y]\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n panBy: function(offset, options) {\n this.panTo(this.transform.center, util.extend({offset: Point.convert(offset).mult(-1)}, options));\n return this;\n },\n\n /**\n * Pan to a certain location with easing\n *\n * @param {Object} latlng a `LatLng` object\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n panTo: function(latlng, options) {\n this.stop();\n\n latlng = LatLng.convert(latlng);\n\n options = util.extend({\n duration: 500,\n easing: util.ease,\n offset: [0, 0]\n }, options);\n\n var tr = this.transform,\n offset = Point.convert(options.offset).rotate(-tr.angle),\n from = tr.point,\n to = tr.project(latlng).sub(offset);\n\n if (!options.noMoveStart) {\n this.fire('movestart');\n }\n\n this._ease(function(k) {\n tr.center = tr.unproject(from.add(to.sub(from).mult(k)));\n this._move();\n }, function() {\n this.fire('moveend');\n }, options);\n\n return this;\n },\n\n /**\n * Zooms to a certain zoom level with easing.\n *\n * @param {Number} zoom\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n zoomTo: function(zoom, options) {\n this.stop();\n\n options = util.extend({\n duration: 500\n }, options);\n\n options.easing = this._updateEasing(options.duration, zoom, options.easing);\n\n var tr = this.transform,\n around = tr.center,\n startZoom = tr.zoom;\n\n if (options.around) {\n around = LatLng.convert(options.around);\n } else if (options.offset) {\n around = tr.pointLocation(tr.centerPoint.add(Point.convert(options.offset)));\n }\n\n if (options.animate === false) options.duration = 0;\n\n if (!this.zooming) {\n this.zooming = true;\n this.fire('movestart');\n }\n\n this._ease(function(k) {\n tr.setZoomAround(interpolate(startZoom, zoom, k), around);\n this.animationLoop.set(300); // text fading\n this._move(true);\n }, function() {\n this.ease = null;\n if (options.duration >= 200) {\n this.zooming = false;\n this.fire('moveend');\n }\n }, options);\n\n if (options.duration < 200) {\n clearTimeout(this._onZoomEnd);\n this._onZoomEnd = setTimeout(function() {\n this.zooming = false;\n this._rerender();\n this.fire('moveend');\n }.bind(this), 200);\n }\n\n return this;\n },\n\n /**\n * Zoom in by 1 level\n *\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n zoomIn: function(options) {\n this.zoomTo(this.getZoom() + 1, options);\n },\n\n /**\n * Zoom out by 1 level\n *\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n zoomOut: function(options) {\n this.zoomTo(this.getZoom() - 1, options);\n },\n\n /**\n * Rotate bearing by a certain number of degrees with easing\n *\n * @param {Number} bearing\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n rotateTo: function(bearing, options) {\n this.stop();\n\n options = util.extend({\n duration: 500,\n easing: util.ease\n }, options);\n\n var tr = this.transform,\n start = this.getBearing(),\n around = tr.center;\n\n if (options.around) {\n around = LatLng.convert(options.around);\n } else if (options.offset) {\n around = tr.pointLocation(tr.centerPoint.add(Point.convert(options.offset)));\n }\n\n bearing = this._normalizeBearing(bearing, start);\n\n this.rotating = true;\n this.fire('movestart');\n\n this._ease(function(k) {\n tr.setBearingAround(interpolate(start, bearing, k), around);\n this._move(false, true);\n }, function() {\n this.rotating = false;\n this.fire('moveend');\n }, options);\n\n return this;\n },\n\n /**\n * Sets map bearing to 0 (north) with easing\n *\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n resetNorth: function(options) {\n return this.rotateTo(0, util.extend({duration: 1000}, options));\n },\n\n /**\n * Zoom to contain certain geographical bounds\n *\n * @param {Array} bounds [[minLat, minLng], [maxLat, maxLng]]\n * @param {Object} options\n * @param {Number} [options.speed=1.2] How fast animation occurs\n * @param {Number} [options.curve=1.42] How much zooming out occurs during animation\n * @param {Function} options.easing\n * @param {Number} options.padding how much padding there is around the given bounds on each side in pixels\n * @param {Number} options.maxZoom\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n fitBounds: function(bounds, options) {\n\n options = util.extend({\n padding: 0,\n offset: [0, 0],\n maxZoom: Infinity\n }, options);\n\n bounds = LatLngBounds.convert(bounds);\n\n var offset = Point.convert(options.offset),\n tr = this.transform,\n nw = tr.project(bounds.getNorthWest()),\n se = tr.project(bounds.getSouthEast()),\n size = se.sub(nw),\n center = tr.unproject(nw.add(se).div(2)),\n\n scaleX = (tr.width - options.padding * 2 - Math.abs(offset.x) * 2) / size.x,\n scaleY = (tr.height - options.padding * 2 - Math.abs(offset.y) * 2) / size.y,\n\n zoom = Math.min(tr.scaleZoom(tr.scale * Math.min(scaleX, scaleY)), options.maxZoom);\n\n return options.linear ?\n this.easeTo(center, zoom, 0, options) :\n this.flyTo(center, zoom, 0, options);\n },\n\n /**\n * Easing animation to a specified location/zoom/bearing\n *\n * @param {Object} latlng a `LatLng` object\n * @param {Number} zoom\n * @param {Number} bearing\n * @param {Number} pitch\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n easeTo: function(latlng, zoom, bearing, pitch, options) {\n this.stop();\n\n options = util.extend({\n offset: [0, 0],\n duration: 500,\n easing: util.ease\n }, options);\n\n var tr = this.transform,\n offset = Point.convert(options.offset).rotate(-tr.angle),\n startZoom = this.getZoom(),\n startBearing = this.getBearing(),\n startPitch = this.getPitch();\n\n latlng = LatLng.convert(latlng);\n zoom = zoom === undefined ? startZoom : zoom;\n bearing = bearing === undefined ? startBearing : this._normalizeBearing(bearing, startBearing);\n pitch = pitch === undefined ? startPitch : pitch;\n\n var scale = tr.zoomScale(zoom - startZoom),\n from = tr.point,\n to = latlng ? tr.project(latlng).sub(offset.div(scale)) : tr.point,\n around;\n\n if (zoom !== startZoom) {\n around = tr.pointLocation(tr.centerPoint.add(to.sub(from).div(1 - 1 / scale)));\n this.zooming = true;\n }\n if (startBearing !== bearing) this.rotating = true;\n\n this.fire('movestart');\n\n this._ease(function (k) {\n if (zoom !== startZoom) {\n tr.setZoomAround(interpolate(startZoom, zoom, k), around);\n } else {\n tr.center = tr.unproject(from.add(to.sub(from).mult(k)));\n }\n\n if (bearing !== startBearing) {\n tr.bearing = interpolate(startBearing, bearing, k);\n }\n\n if (pitch !== startPitch) {\n tr.pitch = interpolate(startPitch, pitch, k);\n }\n\n this.animationLoop.set(300); // text fading\n this._move(zoom !== startZoom, bearing !== startBearing);\n }, function() {\n this.zooming = false;\n this.rotating = false;\n this.fire('moveend');\n }, options);\n\n return this;\n },\n\n /**\n * Flying animation to a specified location/zoom/bearing with automatic curve\n *\n * @param {Object} latlng a `LatLng` object\n * @param {Number} zoom\n * @param {Number} bearing\n * @param {Object} options\n * @param {Number} [options.speed=1.2] How fast animation occurs\n * @param {Number} [options.curve=1.42] How much zooming out occurs during animation\n * @param {Function} options.easing\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n flyTo: function(latlng, zoom, bearing, options) {\n this.stop();\n\n options = util.extend({\n offset: [0, 0],\n speed: 1.2,\n curve: 1.42,\n easing: util.ease\n }, options);\n\n latlng = LatLng.convert(latlng);\n\n var offset = Point.convert(options.offset),\n tr = this.transform,\n startZoom = this.getZoom(),\n startBearing = this.getBearing();\n\n zoom = zoom === undefined ? startZoom : zoom;\n bearing = bearing === undefined ? startBearing : this._normalizeBearing(bearing, startBearing);\n\n var scale = tr.zoomScale(zoom - startZoom),\n from = tr.point,\n to = tr.project(latlng).sub(offset.div(scale));\n\n if (options.animate === false) {\n return this.setView(latlng, zoom, bearing, this.getPitch());\n }\n\n var startWorldSize = tr.worldSize,\n rho = options.curve,\n V = options.speed,\n\n w0 = Math.max(tr.width, tr.height),\n w1 = w0 / scale,\n u1 = to.sub(from).mag(),\n rho2 = rho * rho;\n\n function r(i) {\n var b = (w1 * w1 - w0 * w0 + (i ? -1 : 1) * rho2 * rho2 * u1 * u1) / (2 * (i ? w1 : w0) * rho2 * u1);\n return Math.log(Math.sqrt(b * b + 1) - b);\n }\n\n function sinh(n) { return (Math.exp(n) - Math.exp(-n)) / 2; }\n function cosh(n) { return (Math.exp(n) + Math.exp(-n)) / 2; }\n function tanh(n) { return sinh(n) / cosh(n); }\n\n var r0 = r(0),\n w = function (s) { return (cosh(r0) / cosh(r0 + rho * s)); },\n u = function (s) { return w0 * ((cosh(r0) * tanh(r0 + rho * s) - sinh(r0)) / rho2) / u1; },\n S = (r(1) - r0) / rho;\n\n if (Math.abs(u1) < 0.000001) {\n if (Math.abs(w0 - w1) < 0.000001) return this;\n\n var k = w1 < w0 ? -1 : 1;\n S = Math.abs(Math.log(w1 / w0)) / rho;\n\n u = function() { return 0; };\n w = function(s) { return Math.exp(k * rho * s); };\n }\n\n options.duration = 1000 * S / V;\n\n this.zooming = true;\n if (startBearing !== bearing) this.rotating = true;\n\n this.fire('movestart');\n\n this._ease(function (k) {\n var s = k * S,\n us = u(s);\n\n tr.zoom = startZoom + tr.scaleZoom(1 / w(s));\n tr.center = tr.unproject(from.add(to.sub(from).mult(us)), startWorldSize);\n\n if (bearing !== startBearing) {\n tr.bearing = interpolate(startBearing, bearing, k);\n }\n\n this.animationLoop.set(300); // text fading\n\n this._move(true, bearing !== startBearing);\n }, function() {\n this.zooming = false;\n this.rotating = false;\n this.fire('moveend');\n }, options);\n\n return this;\n },\n\n // convert bearing so that it's numerically close to the current one so that it interpolates properly\n _normalizeBearing: function(bearing, currentBearing) {\n bearing = util.wrap(bearing, -180, 180);\n var diff = Math.abs(bearing - currentBearing);\n if (Math.abs(bearing - 360 - currentBearing) < diff) bearing -= 360;\n if (Math.abs(bearing + 360 - currentBearing) < diff) bearing += 360;\n return bearing;\n },\n\n _updateEasing: function(duration, zoom, bezier) {\n var easing;\n\n if (this.ease) {\n var ease = this.ease,\n t = (Date.now() - ease.start) / ease.duration,\n speed = ease.easing(t + 0.01) - ease.easing(t),\n\n // Quick hack to make new bezier that is continuous with last\n x = 0.27 / Math.sqrt(speed * speed + 0.0001) * 0.01,\n y = Math.sqrt(0.27 * 0.27 - x * x);\n\n easing = util.bezier(x, y, 0.25, 1);\n } else {\n easing = bezier ? util.bezier.apply(util, bezier) : util.ease;\n }\n\n // store information on current easing\n this.ease = {\n start: (new Date()).getTime(),\n to: Math.pow(2, zoom),\n duration: duration,\n easing: easing\n };\n\n return easing;\n }\n}","path":"js/ui/easings.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/easings.js#L294-L351"},"params":[{"title":"param","description":"a `LatLng` object","type":{"type":"NameExpression","name":"Object"},"name":"latlng"},{"title":"param","description":null,"type":{"type":"NameExpression","name":"Number"},"name":"zoom"},{"title":"param","description":null,"type":{"type":"NameExpression","name":"Number"},"name":"bearing"},{"title":"param","description":null,"type":{"type":"NameExpression","name":"Number"},"name":"pitch"},{"title":"param","description":null,"type":null,"name":"animOptions"}],"returns":[{"title":"returns","description":null,"type":{"type":"NameExpression","name":"this"}}],"name":"easeTo","memberof":"Map","scope":"instance","members":{"instance":[],"static":[]},"path":["Map","easeTo"]},{"description":"Flying animation to a specified location/zoom/bearing with automatic curve","tags":[{"title":"param","description":"a `LatLng` object","type":{"type":"NameExpression","name":"Object"},"name":"latlng"},{"title":"param","description":null,"type":{"type":"NameExpression","name":"Number"},"name":"zoom"},{"title":"param","description":null,"type":{"type":"NameExpression","name":"Number"},"name":"bearing"},{"title":"param","description":null,"type":{"type":"NameExpression","name":"Object"},"name":"options"},{"title":"name","name":"flyTo"},{"title":"memberof","description":"Map"},{"title":"instance"}],"context":{"loc":{"start":{"line":367,"column":4},"end":{"line":456,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/easings.js","code":"{\n isEasing: function() {\n return !!this._abortFn;\n },\n\n /**\n * Stop current animation\n *\n * @returns {this}\n */\n stop: function() {\n if (this._abortFn) {\n this._abortFn.call(this);\n delete this._abortFn;\n\n this._finishFn.call(this);\n delete this._finishFn;\n }\n return this;\n },\n\n _ease: function(frame, finish, options) {\n this._finishFn = finish;\n this._abortFn = browser.timed(function (t) {\n frame.call(this, options.easing(t));\n if (t === 1) {\n delete this._abortFn;\n this._finishFn.call(this);\n delete this._finishFn;\n }\n }, options.animate === false ? 0 : options.duration, this);\n },\n\n /**\n * Pan by a certain number of pixels\n *\n * @param {Array} offset [x, y]\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n panBy: function(offset, options) {\n this.panTo(this.transform.center, util.extend({offset: Point.convert(offset).mult(-1)}, options));\n return this;\n },\n\n /**\n * Pan to a certain location with easing\n *\n * @param {Object} latlng a `LatLng` object\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n panTo: function(latlng, options) {\n this.stop();\n\n latlng = LatLng.convert(latlng);\n\n options = util.extend({\n duration: 500,\n easing: util.ease,\n offset: [0, 0]\n }, options);\n\n var tr = this.transform,\n offset = Point.convert(options.offset).rotate(-tr.angle),\n from = tr.point,\n to = tr.project(latlng).sub(offset);\n\n if (!options.noMoveStart) {\n this.fire('movestart');\n }\n\n this._ease(function(k) {\n tr.center = tr.unproject(from.add(to.sub(from).mult(k)));\n this._move();\n }, function() {\n this.fire('moveend');\n }, options);\n\n return this;\n },\n\n /**\n * Zooms to a certain zoom level with easing.\n *\n * @param {Number} zoom\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n zoomTo: function(zoom, options) {\n this.stop();\n\n options = util.extend({\n duration: 500\n }, options);\n\n options.easing = this._updateEasing(options.duration, zoom, options.easing);\n\n var tr = this.transform,\n around = tr.center,\n startZoom = tr.zoom;\n\n if (options.around) {\n around = LatLng.convert(options.around);\n } else if (options.offset) {\n around = tr.pointLocation(tr.centerPoint.add(Point.convert(options.offset)));\n }\n\n if (options.animate === false) options.duration = 0;\n\n if (!this.zooming) {\n this.zooming = true;\n this.fire('movestart');\n }\n\n this._ease(function(k) {\n tr.setZoomAround(interpolate(startZoom, zoom, k), around);\n this.animationLoop.set(300); // text fading\n this._move(true);\n }, function() {\n this.ease = null;\n if (options.duration >= 200) {\n this.zooming = false;\n this.fire('moveend');\n }\n }, options);\n\n if (options.duration < 200) {\n clearTimeout(this._onZoomEnd);\n this._onZoomEnd = setTimeout(function() {\n this.zooming = false;\n this._rerender();\n this.fire('moveend');\n }.bind(this), 200);\n }\n\n return this;\n },\n\n /**\n * Zoom in by 1 level\n *\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n zoomIn: function(options) {\n this.zoomTo(this.getZoom() + 1, options);\n },\n\n /**\n * Zoom out by 1 level\n *\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n zoomOut: function(options) {\n this.zoomTo(this.getZoom() - 1, options);\n },\n\n /**\n * Rotate bearing by a certain number of degrees with easing\n *\n * @param {Number} bearing\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n rotateTo: function(bearing, options) {\n this.stop();\n\n options = util.extend({\n duration: 500,\n easing: util.ease\n }, options);\n\n var tr = this.transform,\n start = this.getBearing(),\n around = tr.center;\n\n if (options.around) {\n around = LatLng.convert(options.around);\n } else if (options.offset) {\n around = tr.pointLocation(tr.centerPoint.add(Point.convert(options.offset)));\n }\n\n bearing = this._normalizeBearing(bearing, start);\n\n this.rotating = true;\n this.fire('movestart');\n\n this._ease(function(k) {\n tr.setBearingAround(interpolate(start, bearing, k), around);\n this._move(false, true);\n }, function() {\n this.rotating = false;\n this.fire('moveend');\n }, options);\n\n return this;\n },\n\n /**\n * Sets map bearing to 0 (north) with easing\n *\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n resetNorth: function(options) {\n return this.rotateTo(0, util.extend({duration: 1000}, options));\n },\n\n /**\n * Zoom to contain certain geographical bounds\n *\n * @param {Array} bounds [[minLat, minLng], [maxLat, maxLng]]\n * @param {Object} options\n * @param {Number} [options.speed=1.2] How fast animation occurs\n * @param {Number} [options.curve=1.42] How much zooming out occurs during animation\n * @param {Function} options.easing\n * @param {Number} options.padding how much padding there is around the given bounds on each side in pixels\n * @param {Number} options.maxZoom\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n fitBounds: function(bounds, options) {\n\n options = util.extend({\n padding: 0,\n offset: [0, 0],\n maxZoom: Infinity\n }, options);\n\n bounds = LatLngBounds.convert(bounds);\n\n var offset = Point.convert(options.offset),\n tr = this.transform,\n nw = tr.project(bounds.getNorthWest()),\n se = tr.project(bounds.getSouthEast()),\n size = se.sub(nw),\n center = tr.unproject(nw.add(se).div(2)),\n\n scaleX = (tr.width - options.padding * 2 - Math.abs(offset.x) * 2) / size.x,\n scaleY = (tr.height - options.padding * 2 - Math.abs(offset.y) * 2) / size.y,\n\n zoom = Math.min(tr.scaleZoom(tr.scale * Math.min(scaleX, scaleY)), options.maxZoom);\n\n return options.linear ?\n this.easeTo(center, zoom, 0, options) :\n this.flyTo(center, zoom, 0, options);\n },\n\n /**\n * Easing animation to a specified location/zoom/bearing\n *\n * @param {Object} latlng a `LatLng` object\n * @param {Number} zoom\n * @param {Number} bearing\n * @param {Number} pitch\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n easeTo: function(latlng, zoom, bearing, pitch, options) {\n this.stop();\n\n options = util.extend({\n offset: [0, 0],\n duration: 500,\n easing: util.ease\n }, options);\n\n var tr = this.transform,\n offset = Point.convert(options.offset).rotate(-tr.angle),\n startZoom = this.getZoom(),\n startBearing = this.getBearing(),\n startPitch = this.getPitch();\n\n latlng = LatLng.convert(latlng);\n zoom = zoom === undefined ? startZoom : zoom;\n bearing = bearing === undefined ? startBearing : this._normalizeBearing(bearing, startBearing);\n pitch = pitch === undefined ? startPitch : pitch;\n\n var scale = tr.zoomScale(zoom - startZoom),\n from = tr.point,\n to = latlng ? tr.project(latlng).sub(offset.div(scale)) : tr.point,\n around;\n\n if (zoom !== startZoom) {\n around = tr.pointLocation(tr.centerPoint.add(to.sub(from).div(1 - 1 / scale)));\n this.zooming = true;\n }\n if (startBearing !== bearing) this.rotating = true;\n\n this.fire('movestart');\n\n this._ease(function (k) {\n if (zoom !== startZoom) {\n tr.setZoomAround(interpolate(startZoom, zoom, k), around);\n } else {\n tr.center = tr.unproject(from.add(to.sub(from).mult(k)));\n }\n\n if (bearing !== startBearing) {\n tr.bearing = interpolate(startBearing, bearing, k);\n }\n\n if (pitch !== startPitch) {\n tr.pitch = interpolate(startPitch, pitch, k);\n }\n\n this.animationLoop.set(300); // text fading\n this._move(zoom !== startZoom, bearing !== startBearing);\n }, function() {\n this.zooming = false;\n this.rotating = false;\n this.fire('moveend');\n }, options);\n\n return this;\n },\n\n /**\n * Flying animation to a specified location/zoom/bearing with automatic curve\n *\n * @param {Object} latlng a `LatLng` object\n * @param {Number} zoom\n * @param {Number} bearing\n * @param {Object} options\n * @param {Number} [options.speed=1.2] How fast animation occurs\n * @param {Number} [options.curve=1.42] How much zooming out occurs during animation\n * @param {Function} options.easing\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n flyTo: function(latlng, zoom, bearing, options) {\n this.stop();\n\n options = util.extend({\n offset: [0, 0],\n speed: 1.2,\n curve: 1.42,\n easing: util.ease\n }, options);\n\n latlng = LatLng.convert(latlng);\n\n var offset = Point.convert(options.offset),\n tr = this.transform,\n startZoom = this.getZoom(),\n startBearing = this.getBearing();\n\n zoom = zoom === undefined ? startZoom : zoom;\n bearing = bearing === undefined ? startBearing : this._normalizeBearing(bearing, startBearing);\n\n var scale = tr.zoomScale(zoom - startZoom),\n from = tr.point,\n to = tr.project(latlng).sub(offset.div(scale));\n\n if (options.animate === false) {\n return this.setView(latlng, zoom, bearing, this.getPitch());\n }\n\n var startWorldSize = tr.worldSize,\n rho = options.curve,\n V = options.speed,\n\n w0 = Math.max(tr.width, tr.height),\n w1 = w0 / scale,\n u1 = to.sub(from).mag(),\n rho2 = rho * rho;\n\n function r(i) {\n var b = (w1 * w1 - w0 * w0 + (i ? -1 : 1) * rho2 * rho2 * u1 * u1) / (2 * (i ? w1 : w0) * rho2 * u1);\n return Math.log(Math.sqrt(b * b + 1) - b);\n }\n\n function sinh(n) { return (Math.exp(n) - Math.exp(-n)) / 2; }\n function cosh(n) { return (Math.exp(n) + Math.exp(-n)) / 2; }\n function tanh(n) { return sinh(n) / cosh(n); }\n\n var r0 = r(0),\n w = function (s) { return (cosh(r0) / cosh(r0 + rho * s)); },\n u = function (s) { return w0 * ((cosh(r0) * tanh(r0 + rho * s) - sinh(r0)) / rho2) / u1; },\n S = (r(1) - r0) / rho;\n\n if (Math.abs(u1) < 0.000001) {\n if (Math.abs(w0 - w1) < 0.000001) return this;\n\n var k = w1 < w0 ? -1 : 1;\n S = Math.abs(Math.log(w1 / w0)) / rho;\n\n u = function() { return 0; };\n w = function(s) { return Math.exp(k * rho * s); };\n }\n\n options.duration = 1000 * S / V;\n\n this.zooming = true;\n if (startBearing !== bearing) this.rotating = true;\n\n this.fire('movestart');\n\n this._ease(function (k) {\n var s = k * S,\n us = u(s);\n\n tr.zoom = startZoom + tr.scaleZoom(1 / w(s));\n tr.center = tr.unproject(from.add(to.sub(from).mult(us)), startWorldSize);\n\n if (bearing !== startBearing) {\n tr.bearing = interpolate(startBearing, bearing, k);\n }\n\n this.animationLoop.set(300); // text fading\n\n this._move(true, bearing !== startBearing);\n }, function() {\n this.zooming = false;\n this.rotating = false;\n this.fire('moveend');\n }, options);\n\n return this;\n },\n\n // convert bearing so that it's numerically close to the current one so that it interpolates properly\n _normalizeBearing: function(bearing, currentBearing) {\n bearing = util.wrap(bearing, -180, 180);\n var diff = Math.abs(bearing - currentBearing);\n if (Math.abs(bearing - 360 - currentBearing) < diff) bearing -= 360;\n if (Math.abs(bearing + 360 - currentBearing) < diff) bearing += 360;\n return bearing;\n },\n\n _updateEasing: function(duration, zoom, bezier) {\n var easing;\n\n if (this.ease) {\n var ease = this.ease,\n t = (Date.now() - ease.start) / ease.duration,\n speed = ease.easing(t + 0.01) - ease.easing(t),\n\n // Quick hack to make new bezier that is continuous with last\n x = 0.27 / Math.sqrt(speed * speed + 0.0001) * 0.01,\n y = Math.sqrt(0.27 * 0.27 - x * x);\n\n easing = util.bezier(x, y, 0.25, 1);\n } else {\n easing = bezier ? util.bezier.apply(util, bezier) : util.ease;\n }\n\n // store information on current easing\n this.ease = {\n start: (new Date()).getTime(),\n to: Math.pow(2, zoom),\n duration: duration,\n easing: easing\n };\n\n return easing;\n }\n}","path":"js/ui/easings.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/easings.js#L367-L456"},"params":[{"title":"param","description":"a `LatLng` object","type":{"type":"NameExpression","name":"Object"},"name":"latlng"},{"title":"param","description":null,"type":{"type":"NameExpression","name":"Number"},"name":"zoom"},{"title":"param","description":null,"type":{"type":"NameExpression","name":"Number"},"name":"bearing"},{"title":"param","description":null,"type":{"type":"NameExpression","name":"Object"},"name":"options"}],"name":"flyTo","memberof":"Map","scope":"instance","members":{"instance":[],"static":[]},"path":["Map","flyTo"]},{"description":"Get the current view geographical point","tags":[{"title":"returns","description":null,"type":{"type":"NameExpression","name":"LatLng"}},{"title":"name","name":"getCenter"},{"title":"memberof","description":"Map"},{"title":"instance"}],"context":{"loc":{"start":{"line":201,"column":4},"end":{"line":201,"column":59}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/map.js","code":"{\n\n options: {\n center: [0, 0],\n zoom: 0,\n bearing: 0,\n pitch: 0,\n\n minZoom: 0,\n maxZoom: 20,\n\n interactive: true,\n hash: false,\n\n attributionControl: true,\n\n failIfMajorPerformanceCaveat: false\n },\n\n addControl: function(control) {\n control.addTo(this);\n return this;\n },\n\n /**\n * Sets a map position\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @param {number} zoom Map zoom level\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setView: function(center, zoom, bearing, pitch) {\n this.stop();\n\n var tr = this.transform,\n zoomChanged = tr.zoom !== +zoom,\n bearingChanged = tr.bearing !== +bearing,\n pitchChanged = tr.pitch !== +pitch;\n\n tr.center = LatLng.convert(center);\n tr.zoom = +zoom;\n tr.bearing = +bearing;\n tr.pitch = +pitch;\n\n return this\n .fire('movestart')\n ._move(zoomChanged, bearingChanged, pitchChanged)\n .fire('moveend');\n },\n\n /**\n * Sets a map location\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setCenter: function(center) {\n this.setView(center, this.getZoom(), this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map zoom\n *\n * @param {number} zoom Map zoom level\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setZoom: function(zoom) {\n this.setView(this.getCenter(), zoom, this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map rotation\n *\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setBearing: function(bearing) {\n this.setView(this.getCenter(), this.getZoom(), bearing, this.getPitch());\n },\n\n /**\n * Sets a map angle\n *\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setPitch: function(pitch) {\n this.setView(this.getCenter(), this.getZoom(), this.getBearing(), pitch);\n },\n\n /**\n * Get the current view geographical point\n * @returns {LatLng}\n */\n getCenter: function() { return this.transform.center; },\n\n /**\n * Get the current zoom\n * @returns {number}\n */\n getZoom: function() { return this.transform.zoom; },\n\n /**\n * Get the current bearing in degrees\n * @returns {number}\n */\n getBearing: function() { return this.transform.bearing; },\n\n /**\n * Get the current angle in degrees\n * @returns {number}\n */\n getPitch: function() { return this.transform.pitch; },\n\n /**\n * @typedef {Object} [styleOptions]\n * @param {Boolean} [styleOptions.transition=true]\n */\n\n /**\n * Adds a style class to a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n addClass: function(klass, options) {\n if (this._classes[klass]) return;\n this._classes[klass] = true;\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Removes a style class from a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n removeClass: function(klass, options) {\n if (!this._classes[klass]) return;\n delete this._classes[klass];\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Helper method to add more than one class\n *\n * @param {Array} klasses An array of class names\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n setClasses: function(klasses, options) {\n this._classes = {};\n for (var i = 0; i < klasses.length; i++) {\n this._classes[klasses[i]] = true;\n }\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Check whether a style class is active\n *\n * @param {string} klass Name of style class\n * @returns {boolean}\n */\n hasClass: function(klass) {\n return !!this._classes[klass];\n },\n\n /**\n * Return an array of the current active style classes\n *\n * @returns {boolean}\n */\n getClasses: function() {\n return Object.keys(this._classes);\n },\n\n /**\n * Detect the map's new width and height and resize it.\n *\n * @returns {Map} `this`\n */\n resize: function() {\n var width = 0, height = 0;\n\n if (this._container) {\n width = this._container.offsetWidth || 400;\n height = this._container.offsetHeight || 300;\n }\n\n this._canvas.resize(width, height);\n\n this.transform.width = width;\n this.transform.height = height;\n this.transform._constrain();\n\n this.painter.resize(width, height);\n\n return this\n .fire('movestart')\n ._move()\n .fire('resize')\n .fire('moveend');\n },\n\n /**\n * Get the map's geographical bounds\n *\n * @returns {LatLngBounds}\n */\n getBounds: function() {\n return new LatLngBounds(\n this.transform.pointLocation(new Point(0, 0)),\n this.transform.pointLocation(this.transform.size));\n },\n\n /**\n * Get pixel coordinates (relative to map container) given a geographical location\n *\n * @param {LatLng} latlng\n * @returns {Object} `x` and `y` coordinates\n */\n project: function(latlng) {\n return this.transform.locationPoint(LatLng.convert(latlng));\n },\n\n /**\n * Get geographical coordinates given pixel coordinates\n *\n * @param {Array} point [x, y] pixel coordinates\n * @returns {LatLng}\n */\n unproject: function(point) {\n return this.transform.pointLocation(Point.convert(point));\n },\n\n /**\n * Get all features at a point ([x, y])\n *\n * @param {Array} point [x, y] pixel coordinates\n * @param {Object} params\n * @param {number} [params.radius=0] Optional. Radius in pixels to search in\n * @param {string} params.layer Optional. Only return features from a given layer\n * @param {string} params.type Optional. Either `raster` or `vector`\n * @param {featuresAtCallback} callback function that returns the response\n *\n * @callback featuresAtCallback\n * @param {Object|null} err Error _If any_\n * @param {Array} features Displays a JSON array of features given the passed parameters of `featuresAt`\n *\n * @returns {Map} `this`\n */\n featuresAt: function(point, params, callback) {\n var coord = this.transform.pointCoordinate(Point.convert(point));\n this.style.featuresAt(coord, params, callback);\n return this;\n },\n\n /**\n * Replaces the map's style object\n *\n * @param {Object} style A style object formatted as JSON\n * @returns {Map} `this`\n */\n setStyle: function(style) {\n if (this.style) {\n this.style\n .off('load', this._onStyleLoad)\n .off('error', this._forwardStyleEvent)\n .off('change', this._onStyleChange)\n .off('source.add', this._onSourceAdd)\n .off('source.remove', this._onSourceRemove)\n .off('source.load', this._onSourceUpdate)\n .off('source.error', this._forwardSourceEvent)\n .off('source.change', this._onSourceUpdate)\n .off('layer.add', this._forwardLayerEvent)\n .off('layer.remove', this._forwardLayerEvent)\n .off('tile.add', this._forwardTileEvent)\n .off('tile.remove', this._forwardTileEvent)\n .off('tile.load', this.update)\n .off('tile.error', this._forwardTileEvent)\n ._remove();\n\n this.off('rotate', this.style._redoPlacement);\n this.off('pitch', this.style._redoPlacement);\n }\n\n if (!style) {\n this.style = null;\n return this;\n } else if (style instanceof Style) {\n this.style = style;\n } else {\n this.style = new Style(style, this.animationLoop);\n }\n\n this.style\n .on('load', this._onStyleLoad)\n .on('error', this._forwardStyleEvent)\n .on('change', this._onStyleChange)\n .on('source.add', this._onSourceAdd)\n .on('source.remove', this._onSourceRemove)\n .on('source.load', this._onSourceUpdate)\n .on('source.error', this._forwardSourceEvent)\n .on('source.change', this._onSourceUpdate)\n .on('layer.add', this._forwardLayerEvent)\n .on('layer.remove', this._forwardLayerEvent)\n .on('tile.add', this._forwardTileEvent)\n .on('tile.remove', this._forwardTileEvent)\n .on('tile.load', this.update)\n .on('tile.error', this._forwardTileEvent);\n\n this.on('rotate', this.style._redoPlacement);\n this.on('pitch', this.style._redoPlacement);\n\n return this;\n },\n\n /**\n * Add a source to the map style.\n *\n * @param {string} id ID of the source. Must not be used by any existing source.\n * @param {Object} source source specification, following the\n * [Mapbox GL Style Reference](https://www.mapbox.com/mapbox-gl-style-spec/#sources)\n * @fires source.add\n * @returns {Map} `this`\n */\n addSource: function(id, source) {\n this.style.addSource(id, source);\n return this;\n },\n\n /**\n * Remove an existing source from the map style.\n *\n * @param {string} id ID of the source to remove\n * @fires source.remove\n * @returns {Map} `this`\n */\n removeSource: function(id) {\n this.style.removeSource(id);\n return this;\n },\n\n /**\n * Return the style source object with the given `id`.\n *\n * @param {string} id source ID\n * @returns {Object}\n */\n getSource: function(id) {\n return this.style.getSource(id);\n },\n\n /**\n * Add a layer to the map style. The layer will be inserted before the layer with\n * ID `before`, or appended if `before` is omitted.\n * @param {Layer} layer\n * @param {string=} before ID of an existing layer to insert before\n * @fires layer.add\n * @returns {Map} `this`\n */\n addLayer: function(layer, before) {\n this.style.addLayer(layer, before);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Remove the layer with the given `id` from the map. Any layers which refer to the\n * specified layer via a `ref` property are also removed.\n *\n * @param {string} id\n * @fires layer.remove\n * @returns {Map} this\n */\n removeLayer: function(id) {\n this.style.removeLayer(id);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Set the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {Array} filter filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n * @returns {Map} `this`\n */\n setFilter: function(layer, filter) {\n this.style.setFilter(layer, filter);\n return this;\n },\n\n /**\n * Get the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @returns {Array} filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n */\n getFilter: function(layer) {\n return this.style.getFilter(layer);\n },\n\n /**\n * Set the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {*} value value for the paint propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @param {string=} klass optional class specifier for the property\n * @returns {Map} `this`\n */\n setPaintProperty: function(layer, name, value, klass) {\n this.style.setPaintProperty(layer, name, value, klass);\n this.style._cascade(this._classes);\n this.update(true);\n return this;\n },\n\n /**\n * Get the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the paint propery\n */\n getPaintProperty: function(layer, name, klass) {\n return this.style.getPaintProperty(layer, name, klass);\n },\n\n /**\n * Set the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {*} value value for the layout propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @returns {Map} `this`\n */\n setLayoutProperty: function(layer, name, value) {\n this.style.setLayoutProperty(layer, name, value);\n return this;\n },\n\n /**\n * Get the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the layout propery\n */\n getLayoutProperty: function(layer, name) {\n return this.style.getLayoutProperty(layer, name);\n },\n\n /**\n * Get the Map's container as an HTML element\n * @returns {HTMLElement} container\n */\n getContainer: function() {\n return this._container;\n },\n\n /**\n * Get the Map's canvas as an HTML canvas\n * @returns {HTMLElement} canvas\n */\n getCanvas: function() {\n return this._canvas.getElement();\n },\n\n _move: function(zoom, rotate, pitch) {\n\n this.update(zoom).fire('move');\n\n if (zoom) this.fire('zoom');\n if (rotate) this.fire('rotate');\n if (pitch) this.fire('pitch');\n\n return this;\n },\n\n // map setup code\n _setupContainer: function() {\n var id = this.options.container;\n var container = this._container = typeof id === 'string' ? document.getElementById(id) : id;\n if (container) container.classList.add('mapboxgl-map');\n this._canvas = new Canvas(this, container);\n },\n\n _setupControlPos: function() {\n var corners = this._controlCorners = {};\n var prefix = 'mapboxgl-ctrl-';\n var container = this.getContainer();\n\n function createCorner(pos) {\n var className = prefix + pos;\n corners[pos] = DOM.create('div', className, container);\n }\n\n if (container && typeof document === 'object') {\n createCorner('top-left');\n createCorner('top-right');\n createCorner('bottom-left');\n createCorner('bottom-right');\n }\n },\n\n _setupPainter: function() {\n var gl = this._canvas.getWebGLContext(this.options.failIfMajorPerformanceCaveat);\n\n if (!gl) {\n console.error('Failed to initialize WebGL');\n return;\n }\n\n this.painter = new GLPainter(gl, this.transform);\n },\n\n _contextLost: function(event) {\n event.preventDefault();\n if (this._frameId) {\n browser.cancelFrame(this._frameId);\n }\n },\n\n _contextRestored: function() {\n this._setupPainter();\n this.resize();\n this.update();\n },\n\n /**\n * Is this map fully loaded? If the style isn't loaded\n * or it has a change to the sources or style that isn't\n * propagated to its style, return false.\n *\n * @returns {boolean} whether the map is loaded\n */\n loaded: function() {\n if (this._styleDirty || this._sourcesDirty)\n return false;\n if (this.style && !this.style.loaded())\n return false;\n return true;\n },\n\n /**\n * Update this map's style and re-render the map.\n *\n * @param {Object} updateStyle new style\n * @returns {Map} this\n */\n update: function(updateStyle) {\n if (!this.style) return this;\n\n this._styleDirty = this._styleDirty || updateStyle;\n this._sourcesDirty = true;\n\n this._rerender();\n\n return this;\n },\n\n /**\n * Call when a (re-)render of the map is required, e.g. when the\n * user panned or zoomed,f or new data is available.\n * @returns {Map} this\n */\n render: function() {\n if (this.style && this._styleDirty) {\n this._styleDirty = false;\n this.style._recalculate(this.transform.zoom);\n }\n\n if (this.style && this._sourcesDirty && !this._sourcesDirtyTimeout) {\n this._sourcesDirty = false;\n this._sourcesDirtyTimeout = setTimeout(function() {\n this._sourcesDirtyTimeout = null;\n }.bind(this), 50);\n this.style._updateSources(this.transform);\n }\n\n this.painter.render(this.style, {\n debug: this.debug,\n vertices: this.vertices,\n rotating: this.rotating,\n zooming: this.zooming\n });\n\n this.fire('render');\n\n if (this.loaded() && !this._loaded) {\n this._loaded = true;\n this.fire('load');\n }\n\n this._frameId = null;\n\n if (!this.animationLoop.stopped()) {\n this._styleDirty = true;\n }\n\n if (this._sourcesDirty || this._repaint || !this.animationLoop.stopped()) {\n this._rerender();\n }\n\n return this;\n },\n\n /**\n * Destroys the map's underlying resources, including web workers.\n * @returns {Map} this\n */\n remove: function() {\n if (this._hash) this._hash.remove();\n browser.cancelFrame(this._frameId);\n clearTimeout(this._sourcesDirtyTimeout);\n this.setStyle(null);\n return this;\n },\n\n _rerender: function() {\n if (this.style && !this._frameId) {\n this._frameId = browser.frame(this.render);\n }\n },\n\n _forwardStyleEvent: function(e) {\n this.fire('style.' + e.type, util.extend({style: e.target}, e));\n },\n\n _forwardSourceEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardLayerEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardTileEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _onStyleLoad: function(e) {\n this.style._cascade(this._classes, {transition: false});\n this._forwardStyleEvent(e);\n },\n\n _onStyleChange: function(e) {\n this.update(true);\n this._forwardStyleEvent(e);\n },\n\n _onSourceAdd: function(e) {\n var source = e.source;\n if (source.onAdd)\n source.onAdd(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceRemove: function(e) {\n var source = e.source;\n if (source.onRemove)\n source.onRemove(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceUpdate: function(e) {\n this.update();\n this._forwardSourceEvent(e);\n }\n}","path":"js/ui/map.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/map.js#L201-L201"},"returns":[{"title":"returns","description":null,"type":{"type":"NameExpression","name":"LatLng"}}],"name":"getCenter","memberof":"Map","scope":"instance","members":{"instance":[],"static":[]},"path":["Map","getCenter"]},{"description":"Get the current bearing in degrees","tags":[{"title":"returns","description":null,"type":{"type":"NameExpression","name":"number"}},{"title":"name","name":"getBearing"},{"title":"memberof","description":"Map"},{"title":"instance"}],"context":{"loc":{"start":{"line":213,"column":4},"end":{"line":213,"column":61}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/map.js","code":"{\n\n options: {\n center: [0, 0],\n zoom: 0,\n bearing: 0,\n pitch: 0,\n\n minZoom: 0,\n maxZoom: 20,\n\n interactive: true,\n hash: false,\n\n attributionControl: true,\n\n failIfMajorPerformanceCaveat: false\n },\n\n addControl: function(control) {\n control.addTo(this);\n return this;\n },\n\n /**\n * Sets a map position\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @param {number} zoom Map zoom level\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setView: function(center, zoom, bearing, pitch) {\n this.stop();\n\n var tr = this.transform,\n zoomChanged = tr.zoom !== +zoom,\n bearingChanged = tr.bearing !== +bearing,\n pitchChanged = tr.pitch !== +pitch;\n\n tr.center = LatLng.convert(center);\n tr.zoom = +zoom;\n tr.bearing = +bearing;\n tr.pitch = +pitch;\n\n return this\n .fire('movestart')\n ._move(zoomChanged, bearingChanged, pitchChanged)\n .fire('moveend');\n },\n\n /**\n * Sets a map location\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setCenter: function(center) {\n this.setView(center, this.getZoom(), this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map zoom\n *\n * @param {number} zoom Map zoom level\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setZoom: function(zoom) {\n this.setView(this.getCenter(), zoom, this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map rotation\n *\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setBearing: function(bearing) {\n this.setView(this.getCenter(), this.getZoom(), bearing, this.getPitch());\n },\n\n /**\n * Sets a map angle\n *\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setPitch: function(pitch) {\n this.setView(this.getCenter(), this.getZoom(), this.getBearing(), pitch);\n },\n\n /**\n * Get the current view geographical point\n * @returns {LatLng}\n */\n getCenter: function() { return this.transform.center; },\n\n /**\n * Get the current zoom\n * @returns {number}\n */\n getZoom: function() { return this.transform.zoom; },\n\n /**\n * Get the current bearing in degrees\n * @returns {number}\n */\n getBearing: function() { return this.transform.bearing; },\n\n /**\n * Get the current angle in degrees\n * @returns {number}\n */\n getPitch: function() { return this.transform.pitch; },\n\n /**\n * @typedef {Object} [styleOptions]\n * @param {Boolean} [styleOptions.transition=true]\n */\n\n /**\n * Adds a style class to a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n addClass: function(klass, options) {\n if (this._classes[klass]) return;\n this._classes[klass] = true;\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Removes a style class from a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n removeClass: function(klass, options) {\n if (!this._classes[klass]) return;\n delete this._classes[klass];\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Helper method to add more than one class\n *\n * @param {Array} klasses An array of class names\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n setClasses: function(klasses, options) {\n this._classes = {};\n for (var i = 0; i < klasses.length; i++) {\n this._classes[klasses[i]] = true;\n }\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Check whether a style class is active\n *\n * @param {string} klass Name of style class\n * @returns {boolean}\n */\n hasClass: function(klass) {\n return !!this._classes[klass];\n },\n\n /**\n * Return an array of the current active style classes\n *\n * @returns {boolean}\n */\n getClasses: function() {\n return Object.keys(this._classes);\n },\n\n /**\n * Detect the map's new width and height and resize it.\n *\n * @returns {Map} `this`\n */\n resize: function() {\n var width = 0, height = 0;\n\n if (this._container) {\n width = this._container.offsetWidth || 400;\n height = this._container.offsetHeight || 300;\n }\n\n this._canvas.resize(width, height);\n\n this.transform.width = width;\n this.transform.height = height;\n this.transform._constrain();\n\n this.painter.resize(width, height);\n\n return this\n .fire('movestart')\n ._move()\n .fire('resize')\n .fire('moveend');\n },\n\n /**\n * Get the map's geographical bounds\n *\n * @returns {LatLngBounds}\n */\n getBounds: function() {\n return new LatLngBounds(\n this.transform.pointLocation(new Point(0, 0)),\n this.transform.pointLocation(this.transform.size));\n },\n\n /**\n * Get pixel coordinates (relative to map container) given a geographical location\n *\n * @param {LatLng} latlng\n * @returns {Object} `x` and `y` coordinates\n */\n project: function(latlng) {\n return this.transform.locationPoint(LatLng.convert(latlng));\n },\n\n /**\n * Get geographical coordinates given pixel coordinates\n *\n * @param {Array} point [x, y] pixel coordinates\n * @returns {LatLng}\n */\n unproject: function(point) {\n return this.transform.pointLocation(Point.convert(point));\n },\n\n /**\n * Get all features at a point ([x, y])\n *\n * @param {Array} point [x, y] pixel coordinates\n * @param {Object} params\n * @param {number} [params.radius=0] Optional. Radius in pixels to search in\n * @param {string} params.layer Optional. Only return features from a given layer\n * @param {string} params.type Optional. Either `raster` or `vector`\n * @param {featuresAtCallback} callback function that returns the response\n *\n * @callback featuresAtCallback\n * @param {Object|null} err Error _If any_\n * @param {Array} features Displays a JSON array of features given the passed parameters of `featuresAt`\n *\n * @returns {Map} `this`\n */\n featuresAt: function(point, params, callback) {\n var coord = this.transform.pointCoordinate(Point.convert(point));\n this.style.featuresAt(coord, params, callback);\n return this;\n },\n\n /**\n * Replaces the map's style object\n *\n * @param {Object} style A style object formatted as JSON\n * @returns {Map} `this`\n */\n setStyle: function(style) {\n if (this.style) {\n this.style\n .off('load', this._onStyleLoad)\n .off('error', this._forwardStyleEvent)\n .off('change', this._onStyleChange)\n .off('source.add', this._onSourceAdd)\n .off('source.remove', this._onSourceRemove)\n .off('source.load', this._onSourceUpdate)\n .off('source.error', this._forwardSourceEvent)\n .off('source.change', this._onSourceUpdate)\n .off('layer.add', this._forwardLayerEvent)\n .off('layer.remove', this._forwardLayerEvent)\n .off('tile.add', this._forwardTileEvent)\n .off('tile.remove', this._forwardTileEvent)\n .off('tile.load', this.update)\n .off('tile.error', this._forwardTileEvent)\n ._remove();\n\n this.off('rotate', this.style._redoPlacement);\n this.off('pitch', this.style._redoPlacement);\n }\n\n if (!style) {\n this.style = null;\n return this;\n } else if (style instanceof Style) {\n this.style = style;\n } else {\n this.style = new Style(style, this.animationLoop);\n }\n\n this.style\n .on('load', this._onStyleLoad)\n .on('error', this._forwardStyleEvent)\n .on('change', this._onStyleChange)\n .on('source.add', this._onSourceAdd)\n .on('source.remove', this._onSourceRemove)\n .on('source.load', this._onSourceUpdate)\n .on('source.error', this._forwardSourceEvent)\n .on('source.change', this._onSourceUpdate)\n .on('layer.add', this._forwardLayerEvent)\n .on('layer.remove', this._forwardLayerEvent)\n .on('tile.add', this._forwardTileEvent)\n .on('tile.remove', this._forwardTileEvent)\n .on('tile.load', this.update)\n .on('tile.error', this._forwardTileEvent);\n\n this.on('rotate', this.style._redoPlacement);\n this.on('pitch', this.style._redoPlacement);\n\n return this;\n },\n\n /**\n * Add a source to the map style.\n *\n * @param {string} id ID of the source. Must not be used by any existing source.\n * @param {Object} source source specification, following the\n * [Mapbox GL Style Reference](https://www.mapbox.com/mapbox-gl-style-spec/#sources)\n * @fires source.add\n * @returns {Map} `this`\n */\n addSource: function(id, source) {\n this.style.addSource(id, source);\n return this;\n },\n\n /**\n * Remove an existing source from the map style.\n *\n * @param {string} id ID of the source to remove\n * @fires source.remove\n * @returns {Map} `this`\n */\n removeSource: function(id) {\n this.style.removeSource(id);\n return this;\n },\n\n /**\n * Return the style source object with the given `id`.\n *\n * @param {string} id source ID\n * @returns {Object}\n */\n getSource: function(id) {\n return this.style.getSource(id);\n },\n\n /**\n * Add a layer to the map style. The layer will be inserted before the layer with\n * ID `before`, or appended if `before` is omitted.\n * @param {Layer} layer\n * @param {string=} before ID of an existing layer to insert before\n * @fires layer.add\n * @returns {Map} `this`\n */\n addLayer: function(layer, before) {\n this.style.addLayer(layer, before);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Remove the layer with the given `id` from the map. Any layers which refer to the\n * specified layer via a `ref` property are also removed.\n *\n * @param {string} id\n * @fires layer.remove\n * @returns {Map} this\n */\n removeLayer: function(id) {\n this.style.removeLayer(id);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Set the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {Array} filter filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n * @returns {Map} `this`\n */\n setFilter: function(layer, filter) {\n this.style.setFilter(layer, filter);\n return this;\n },\n\n /**\n * Get the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @returns {Array} filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n */\n getFilter: function(layer) {\n return this.style.getFilter(layer);\n },\n\n /**\n * Set the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {*} value value for the paint propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @param {string=} klass optional class specifier for the property\n * @returns {Map} `this`\n */\n setPaintProperty: function(layer, name, value, klass) {\n this.style.setPaintProperty(layer, name, value, klass);\n this.style._cascade(this._classes);\n this.update(true);\n return this;\n },\n\n /**\n * Get the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the paint propery\n */\n getPaintProperty: function(layer, name, klass) {\n return this.style.getPaintProperty(layer, name, klass);\n },\n\n /**\n * Set the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {*} value value for the layout propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @returns {Map} `this`\n */\n setLayoutProperty: function(layer, name, value) {\n this.style.setLayoutProperty(layer, name, value);\n return this;\n },\n\n /**\n * Get the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the layout propery\n */\n getLayoutProperty: function(layer, name) {\n return this.style.getLayoutProperty(layer, name);\n },\n\n /**\n * Get the Map's container as an HTML element\n * @returns {HTMLElement} container\n */\n getContainer: function() {\n return this._container;\n },\n\n /**\n * Get the Map's canvas as an HTML canvas\n * @returns {HTMLElement} canvas\n */\n getCanvas: function() {\n return this._canvas.getElement();\n },\n\n _move: function(zoom, rotate, pitch) {\n\n this.update(zoom).fire('move');\n\n if (zoom) this.fire('zoom');\n if (rotate) this.fire('rotate');\n if (pitch) this.fire('pitch');\n\n return this;\n },\n\n // map setup code\n _setupContainer: function() {\n var id = this.options.container;\n var container = this._container = typeof id === 'string' ? document.getElementById(id) : id;\n if (container) container.classList.add('mapboxgl-map');\n this._canvas = new Canvas(this, container);\n },\n\n _setupControlPos: function() {\n var corners = this._controlCorners = {};\n var prefix = 'mapboxgl-ctrl-';\n var container = this.getContainer();\n\n function createCorner(pos) {\n var className = prefix + pos;\n corners[pos] = DOM.create('div', className, container);\n }\n\n if (container && typeof document === 'object') {\n createCorner('top-left');\n createCorner('top-right');\n createCorner('bottom-left');\n createCorner('bottom-right');\n }\n },\n\n _setupPainter: function() {\n var gl = this._canvas.getWebGLContext(this.options.failIfMajorPerformanceCaveat);\n\n if (!gl) {\n console.error('Failed to initialize WebGL');\n return;\n }\n\n this.painter = new GLPainter(gl, this.transform);\n },\n\n _contextLost: function(event) {\n event.preventDefault();\n if (this._frameId) {\n browser.cancelFrame(this._frameId);\n }\n },\n\n _contextRestored: function() {\n this._setupPainter();\n this.resize();\n this.update();\n },\n\n /**\n * Is this map fully loaded? If the style isn't loaded\n * or it has a change to the sources or style that isn't\n * propagated to its style, return false.\n *\n * @returns {boolean} whether the map is loaded\n */\n loaded: function() {\n if (this._styleDirty || this._sourcesDirty)\n return false;\n if (this.style && !this.style.loaded())\n return false;\n return true;\n },\n\n /**\n * Update this map's style and re-render the map.\n *\n * @param {Object} updateStyle new style\n * @returns {Map} this\n */\n update: function(updateStyle) {\n if (!this.style) return this;\n\n this._styleDirty = this._styleDirty || updateStyle;\n this._sourcesDirty = true;\n\n this._rerender();\n\n return this;\n },\n\n /**\n * Call when a (re-)render of the map is required, e.g. when the\n * user panned or zoomed,f or new data is available.\n * @returns {Map} this\n */\n render: function() {\n if (this.style && this._styleDirty) {\n this._styleDirty = false;\n this.style._recalculate(this.transform.zoom);\n }\n\n if (this.style && this._sourcesDirty && !this._sourcesDirtyTimeout) {\n this._sourcesDirty = false;\n this._sourcesDirtyTimeout = setTimeout(function() {\n this._sourcesDirtyTimeout = null;\n }.bind(this), 50);\n this.style._updateSources(this.transform);\n }\n\n this.painter.render(this.style, {\n debug: this.debug,\n vertices: this.vertices,\n rotating: this.rotating,\n zooming: this.zooming\n });\n\n this.fire('render');\n\n if (this.loaded() && !this._loaded) {\n this._loaded = true;\n this.fire('load');\n }\n\n this._frameId = null;\n\n if (!this.animationLoop.stopped()) {\n this._styleDirty = true;\n }\n\n if (this._sourcesDirty || this._repaint || !this.animationLoop.stopped()) {\n this._rerender();\n }\n\n return this;\n },\n\n /**\n * Destroys the map's underlying resources, including web workers.\n * @returns {Map} this\n */\n remove: function() {\n if (this._hash) this._hash.remove();\n browser.cancelFrame(this._frameId);\n clearTimeout(this._sourcesDirtyTimeout);\n this.setStyle(null);\n return this;\n },\n\n _rerender: function() {\n if (this.style && !this._frameId) {\n this._frameId = browser.frame(this.render);\n }\n },\n\n _forwardStyleEvent: function(e) {\n this.fire('style.' + e.type, util.extend({style: e.target}, e));\n },\n\n _forwardSourceEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardLayerEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardTileEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _onStyleLoad: function(e) {\n this.style._cascade(this._classes, {transition: false});\n this._forwardStyleEvent(e);\n },\n\n _onStyleChange: function(e) {\n this.update(true);\n this._forwardStyleEvent(e);\n },\n\n _onSourceAdd: function(e) {\n var source = e.source;\n if (source.onAdd)\n source.onAdd(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceRemove: function(e) {\n var source = e.source;\n if (source.onRemove)\n source.onRemove(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceUpdate: function(e) {\n this.update();\n this._forwardSourceEvent(e);\n }\n}","path":"js/ui/map.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/map.js#L213-L213"},"returns":[{"title":"returns","description":null,"type":{"type":"NameExpression","name":"number"}}],"name":"getBearing","memberof":"Map","scope":"instance","members":{"instance":[],"static":[]},"path":["Map","getBearing"]},{"description":"Return an array of the current active style classes","tags":[{"title":"returns","description":null,"type":{"type":"NameExpression","name":"boolean"}},{"title":"name","name":"getClasses"},{"title":"memberof","description":"Map"},{"title":"instance"}],"context":{"loc":{"start":{"line":285,"column":4},"end":{"line":287,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/map.js","code":"{\n\n options: {\n center: [0, 0],\n zoom: 0,\n bearing: 0,\n pitch: 0,\n\n minZoom: 0,\n maxZoom: 20,\n\n interactive: true,\n hash: false,\n\n attributionControl: true,\n\n failIfMajorPerformanceCaveat: false\n },\n\n addControl: function(control) {\n control.addTo(this);\n return this;\n },\n\n /**\n * Sets a map position\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @param {number} zoom Map zoom level\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setView: function(center, zoom, bearing, pitch) {\n this.stop();\n\n var tr = this.transform,\n zoomChanged = tr.zoom !== +zoom,\n bearingChanged = tr.bearing !== +bearing,\n pitchChanged = tr.pitch !== +pitch;\n\n tr.center = LatLng.convert(center);\n tr.zoom = +zoom;\n tr.bearing = +bearing;\n tr.pitch = +pitch;\n\n return this\n .fire('movestart')\n ._move(zoomChanged, bearingChanged, pitchChanged)\n .fire('moveend');\n },\n\n /**\n * Sets a map location\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setCenter: function(center) {\n this.setView(center, this.getZoom(), this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map zoom\n *\n * @param {number} zoom Map zoom level\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setZoom: function(zoom) {\n this.setView(this.getCenter(), zoom, this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map rotation\n *\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setBearing: function(bearing) {\n this.setView(this.getCenter(), this.getZoom(), bearing, this.getPitch());\n },\n\n /**\n * Sets a map angle\n *\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setPitch: function(pitch) {\n this.setView(this.getCenter(), this.getZoom(), this.getBearing(), pitch);\n },\n\n /**\n * Get the current view geographical point\n * @returns {LatLng}\n */\n getCenter: function() { return this.transform.center; },\n\n /**\n * Get the current zoom\n * @returns {number}\n */\n getZoom: function() { return this.transform.zoom; },\n\n /**\n * Get the current bearing in degrees\n * @returns {number}\n */\n getBearing: function() { return this.transform.bearing; },\n\n /**\n * Get the current angle in degrees\n * @returns {number}\n */\n getPitch: function() { return this.transform.pitch; },\n\n /**\n * @typedef {Object} [styleOptions]\n * @param {Boolean} [styleOptions.transition=true]\n */\n\n /**\n * Adds a style class to a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n addClass: function(klass, options) {\n if (this._classes[klass]) return;\n this._classes[klass] = true;\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Removes a style class from a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n removeClass: function(klass, options) {\n if (!this._classes[klass]) return;\n delete this._classes[klass];\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Helper method to add more than one class\n *\n * @param {Array} klasses An array of class names\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n setClasses: function(klasses, options) {\n this._classes = {};\n for (var i = 0; i < klasses.length; i++) {\n this._classes[klasses[i]] = true;\n }\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Check whether a style class is active\n *\n * @param {string} klass Name of style class\n * @returns {boolean}\n */\n hasClass: function(klass) {\n return !!this._classes[klass];\n },\n\n /**\n * Return an array of the current active style classes\n *\n * @returns {boolean}\n */\n getClasses: function() {\n return Object.keys(this._classes);\n },\n\n /**\n * Detect the map's new width and height and resize it.\n *\n * @returns {Map} `this`\n */\n resize: function() {\n var width = 0, height = 0;\n\n if (this._container) {\n width = this._container.offsetWidth || 400;\n height = this._container.offsetHeight || 300;\n }\n\n this._canvas.resize(width, height);\n\n this.transform.width = width;\n this.transform.height = height;\n this.transform._constrain();\n\n this.painter.resize(width, height);\n\n return this\n .fire('movestart')\n ._move()\n .fire('resize')\n .fire('moveend');\n },\n\n /**\n * Get the map's geographical bounds\n *\n * @returns {LatLngBounds}\n */\n getBounds: function() {\n return new LatLngBounds(\n this.transform.pointLocation(new Point(0, 0)),\n this.transform.pointLocation(this.transform.size));\n },\n\n /**\n * Get pixel coordinates (relative to map container) given a geographical location\n *\n * @param {LatLng} latlng\n * @returns {Object} `x` and `y` coordinates\n */\n project: function(latlng) {\n return this.transform.locationPoint(LatLng.convert(latlng));\n },\n\n /**\n * Get geographical coordinates given pixel coordinates\n *\n * @param {Array} point [x, y] pixel coordinates\n * @returns {LatLng}\n */\n unproject: function(point) {\n return this.transform.pointLocation(Point.convert(point));\n },\n\n /**\n * Get all features at a point ([x, y])\n *\n * @param {Array} point [x, y] pixel coordinates\n * @param {Object} params\n * @param {number} [params.radius=0] Optional. Radius in pixels to search in\n * @param {string} params.layer Optional. Only return features from a given layer\n * @param {string} params.type Optional. Either `raster` or `vector`\n * @param {featuresAtCallback} callback function that returns the response\n *\n * @callback featuresAtCallback\n * @param {Object|null} err Error _If any_\n * @param {Array} features Displays a JSON array of features given the passed parameters of `featuresAt`\n *\n * @returns {Map} `this`\n */\n featuresAt: function(point, params, callback) {\n var coord = this.transform.pointCoordinate(Point.convert(point));\n this.style.featuresAt(coord, params, callback);\n return this;\n },\n\n /**\n * Replaces the map's style object\n *\n * @param {Object} style A style object formatted as JSON\n * @returns {Map} `this`\n */\n setStyle: function(style) {\n if (this.style) {\n this.style\n .off('load', this._onStyleLoad)\n .off('error', this._forwardStyleEvent)\n .off('change', this._onStyleChange)\n .off('source.add', this._onSourceAdd)\n .off('source.remove', this._onSourceRemove)\n .off('source.load', this._onSourceUpdate)\n .off('source.error', this._forwardSourceEvent)\n .off('source.change', this._onSourceUpdate)\n .off('layer.add', this._forwardLayerEvent)\n .off('layer.remove', this._forwardLayerEvent)\n .off('tile.add', this._forwardTileEvent)\n .off('tile.remove', this._forwardTileEvent)\n .off('tile.load', this.update)\n .off('tile.error', this._forwardTileEvent)\n ._remove();\n\n this.off('rotate', this.style._redoPlacement);\n this.off('pitch', this.style._redoPlacement);\n }\n\n if (!style) {\n this.style = null;\n return this;\n } else if (style instanceof Style) {\n this.style = style;\n } else {\n this.style = new Style(style, this.animationLoop);\n }\n\n this.style\n .on('load', this._onStyleLoad)\n .on('error', this._forwardStyleEvent)\n .on('change', this._onStyleChange)\n .on('source.add', this._onSourceAdd)\n .on('source.remove', this._onSourceRemove)\n .on('source.load', this._onSourceUpdate)\n .on('source.error', this._forwardSourceEvent)\n .on('source.change', this._onSourceUpdate)\n .on('layer.add', this._forwardLayerEvent)\n .on('layer.remove', this._forwardLayerEvent)\n .on('tile.add', this._forwardTileEvent)\n .on('tile.remove', this._forwardTileEvent)\n .on('tile.load', this.update)\n .on('tile.error', this._forwardTileEvent);\n\n this.on('rotate', this.style._redoPlacement);\n this.on('pitch', this.style._redoPlacement);\n\n return this;\n },\n\n /**\n * Add a source to the map style.\n *\n * @param {string} id ID of the source. Must not be used by any existing source.\n * @param {Object} source source specification, following the\n * [Mapbox GL Style Reference](https://www.mapbox.com/mapbox-gl-style-spec/#sources)\n * @fires source.add\n * @returns {Map} `this`\n */\n addSource: function(id, source) {\n this.style.addSource(id, source);\n return this;\n },\n\n /**\n * Remove an existing source from the map style.\n *\n * @param {string} id ID of the source to remove\n * @fires source.remove\n * @returns {Map} `this`\n */\n removeSource: function(id) {\n this.style.removeSource(id);\n return this;\n },\n\n /**\n * Return the style source object with the given `id`.\n *\n * @param {string} id source ID\n * @returns {Object}\n */\n getSource: function(id) {\n return this.style.getSource(id);\n },\n\n /**\n * Add a layer to the map style. The layer will be inserted before the layer with\n * ID `before`, or appended if `before` is omitted.\n * @param {Layer} layer\n * @param {string=} before ID of an existing layer to insert before\n * @fires layer.add\n * @returns {Map} `this`\n */\n addLayer: function(layer, before) {\n this.style.addLayer(layer, before);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Remove the layer with the given `id` from the map. Any layers which refer to the\n * specified layer via a `ref` property are also removed.\n *\n * @param {string} id\n * @fires layer.remove\n * @returns {Map} this\n */\n removeLayer: function(id) {\n this.style.removeLayer(id);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Set the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {Array} filter filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n * @returns {Map} `this`\n */\n setFilter: function(layer, filter) {\n this.style.setFilter(layer, filter);\n return this;\n },\n\n /**\n * Get the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @returns {Array} filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n */\n getFilter: function(layer) {\n return this.style.getFilter(layer);\n },\n\n /**\n * Set the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {*} value value for the paint propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @param {string=} klass optional class specifier for the property\n * @returns {Map} `this`\n */\n setPaintProperty: function(layer, name, value, klass) {\n this.style.setPaintProperty(layer, name, value, klass);\n this.style._cascade(this._classes);\n this.update(true);\n return this;\n },\n\n /**\n * Get the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the paint propery\n */\n getPaintProperty: function(layer, name, klass) {\n return this.style.getPaintProperty(layer, name, klass);\n },\n\n /**\n * Set the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {*} value value for the layout propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @returns {Map} `this`\n */\n setLayoutProperty: function(layer, name, value) {\n this.style.setLayoutProperty(layer, name, value);\n return this;\n },\n\n /**\n * Get the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the layout propery\n */\n getLayoutProperty: function(layer, name) {\n return this.style.getLayoutProperty(layer, name);\n },\n\n /**\n * Get the Map's container as an HTML element\n * @returns {HTMLElement} container\n */\n getContainer: function() {\n return this._container;\n },\n\n /**\n * Get the Map's canvas as an HTML canvas\n * @returns {HTMLElement} canvas\n */\n getCanvas: function() {\n return this._canvas.getElement();\n },\n\n _move: function(zoom, rotate, pitch) {\n\n this.update(zoom).fire('move');\n\n if (zoom) this.fire('zoom');\n if (rotate) this.fire('rotate');\n if (pitch) this.fire('pitch');\n\n return this;\n },\n\n // map setup code\n _setupContainer: function() {\n var id = this.options.container;\n var container = this._container = typeof id === 'string' ? document.getElementById(id) : id;\n if (container) container.classList.add('mapboxgl-map');\n this._canvas = new Canvas(this, container);\n },\n\n _setupControlPos: function() {\n var corners = this._controlCorners = {};\n var prefix = 'mapboxgl-ctrl-';\n var container = this.getContainer();\n\n function createCorner(pos) {\n var className = prefix + pos;\n corners[pos] = DOM.create('div', className, container);\n }\n\n if (container && typeof document === 'object') {\n createCorner('top-left');\n createCorner('top-right');\n createCorner('bottom-left');\n createCorner('bottom-right');\n }\n },\n\n _setupPainter: function() {\n var gl = this._canvas.getWebGLContext(this.options.failIfMajorPerformanceCaveat);\n\n if (!gl) {\n console.error('Failed to initialize WebGL');\n return;\n }\n\n this.painter = new GLPainter(gl, this.transform);\n },\n\n _contextLost: function(event) {\n event.preventDefault();\n if (this._frameId) {\n browser.cancelFrame(this._frameId);\n }\n },\n\n _contextRestored: function() {\n this._setupPainter();\n this.resize();\n this.update();\n },\n\n /**\n * Is this map fully loaded? If the style isn't loaded\n * or it has a change to the sources or style that isn't\n * propagated to its style, return false.\n *\n * @returns {boolean} whether the map is loaded\n */\n loaded: function() {\n if (this._styleDirty || this._sourcesDirty)\n return false;\n if (this.style && !this.style.loaded())\n return false;\n return true;\n },\n\n /**\n * Update this map's style and re-render the map.\n *\n * @param {Object} updateStyle new style\n * @returns {Map} this\n */\n update: function(updateStyle) {\n if (!this.style) return this;\n\n this._styleDirty = this._styleDirty || updateStyle;\n this._sourcesDirty = true;\n\n this._rerender();\n\n return this;\n },\n\n /**\n * Call when a (re-)render of the map is required, e.g. when the\n * user panned or zoomed,f or new data is available.\n * @returns {Map} this\n */\n render: function() {\n if (this.style && this._styleDirty) {\n this._styleDirty = false;\n this.style._recalculate(this.transform.zoom);\n }\n\n if (this.style && this._sourcesDirty && !this._sourcesDirtyTimeout) {\n this._sourcesDirty = false;\n this._sourcesDirtyTimeout = setTimeout(function() {\n this._sourcesDirtyTimeout = null;\n }.bind(this), 50);\n this.style._updateSources(this.transform);\n }\n\n this.painter.render(this.style, {\n debug: this.debug,\n vertices: this.vertices,\n rotating: this.rotating,\n zooming: this.zooming\n });\n\n this.fire('render');\n\n if (this.loaded() && !this._loaded) {\n this._loaded = true;\n this.fire('load');\n }\n\n this._frameId = null;\n\n if (!this.animationLoop.stopped()) {\n this._styleDirty = true;\n }\n\n if (this._sourcesDirty || this._repaint || !this.animationLoop.stopped()) {\n this._rerender();\n }\n\n return this;\n },\n\n /**\n * Destroys the map's underlying resources, including web workers.\n * @returns {Map} this\n */\n remove: function() {\n if (this._hash) this._hash.remove();\n browser.cancelFrame(this._frameId);\n clearTimeout(this._sourcesDirtyTimeout);\n this.setStyle(null);\n return this;\n },\n\n _rerender: function() {\n if (this.style && !this._frameId) {\n this._frameId = browser.frame(this.render);\n }\n },\n\n _forwardStyleEvent: function(e) {\n this.fire('style.' + e.type, util.extend({style: e.target}, e));\n },\n\n _forwardSourceEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardLayerEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardTileEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _onStyleLoad: function(e) {\n this.style._cascade(this._classes, {transition: false});\n this._forwardStyleEvent(e);\n },\n\n _onStyleChange: function(e) {\n this.update(true);\n this._forwardStyleEvent(e);\n },\n\n _onSourceAdd: function(e) {\n var source = e.source;\n if (source.onAdd)\n source.onAdd(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceRemove: function(e) {\n var source = e.source;\n if (source.onRemove)\n source.onRemove(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceUpdate: function(e) {\n this.update();\n this._forwardSourceEvent(e);\n }\n}","path":"js/ui/map.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/map.js#L285-L287"},"returns":[{"title":"returns","description":null,"type":{"type":"NameExpression","name":"boolean"}}],"name":"getClasses","memberof":"Map","scope":"instance","members":{"instance":[],"static":[]},"path":["Map","getClasses"]},{"description":"Get the map's geographical bounds","tags":[{"title":"returns","description":null,"type":{"type":"NameExpression","name":"LatLngBounds"}},{"title":"name","name":"getBounds"},{"title":"memberof","description":"Map"},{"title":"instance"}],"context":{"loc":{"start":{"line":322,"column":4},"end":{"line":326,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/map.js","code":"{\n\n options: {\n center: [0, 0],\n zoom: 0,\n bearing: 0,\n pitch: 0,\n\n minZoom: 0,\n maxZoom: 20,\n\n interactive: true,\n hash: false,\n\n attributionControl: true,\n\n failIfMajorPerformanceCaveat: false\n },\n\n addControl: function(control) {\n control.addTo(this);\n return this;\n },\n\n /**\n * Sets a map position\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @param {number} zoom Map zoom level\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setView: function(center, zoom, bearing, pitch) {\n this.stop();\n\n var tr = this.transform,\n zoomChanged = tr.zoom !== +zoom,\n bearingChanged = tr.bearing !== +bearing,\n pitchChanged = tr.pitch !== +pitch;\n\n tr.center = LatLng.convert(center);\n tr.zoom = +zoom;\n tr.bearing = +bearing;\n tr.pitch = +pitch;\n\n return this\n .fire('movestart')\n ._move(zoomChanged, bearingChanged, pitchChanged)\n .fire('moveend');\n },\n\n /**\n * Sets a map location\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setCenter: function(center) {\n this.setView(center, this.getZoom(), this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map zoom\n *\n * @param {number} zoom Map zoom level\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setZoom: function(zoom) {\n this.setView(this.getCenter(), zoom, this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map rotation\n *\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setBearing: function(bearing) {\n this.setView(this.getCenter(), this.getZoom(), bearing, this.getPitch());\n },\n\n /**\n * Sets a map angle\n *\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setPitch: function(pitch) {\n this.setView(this.getCenter(), this.getZoom(), this.getBearing(), pitch);\n },\n\n /**\n * Get the current view geographical point\n * @returns {LatLng}\n */\n getCenter: function() { return this.transform.center; },\n\n /**\n * Get the current zoom\n * @returns {number}\n */\n getZoom: function() { return this.transform.zoom; },\n\n /**\n * Get the current bearing in degrees\n * @returns {number}\n */\n getBearing: function() { return this.transform.bearing; },\n\n /**\n * Get the current angle in degrees\n * @returns {number}\n */\n getPitch: function() { return this.transform.pitch; },\n\n /**\n * @typedef {Object} [styleOptions]\n * @param {Boolean} [styleOptions.transition=true]\n */\n\n /**\n * Adds a style class to a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n addClass: function(klass, options) {\n if (this._classes[klass]) return;\n this._classes[klass] = true;\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Removes a style class from a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n removeClass: function(klass, options) {\n if (!this._classes[klass]) return;\n delete this._classes[klass];\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Helper method to add more than one class\n *\n * @param {Array} klasses An array of class names\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n setClasses: function(klasses, options) {\n this._classes = {};\n for (var i = 0; i < klasses.length; i++) {\n this._classes[klasses[i]] = true;\n }\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Check whether a style class is active\n *\n * @param {string} klass Name of style class\n * @returns {boolean}\n */\n hasClass: function(klass) {\n return !!this._classes[klass];\n },\n\n /**\n * Return an array of the current active style classes\n *\n * @returns {boolean}\n */\n getClasses: function() {\n return Object.keys(this._classes);\n },\n\n /**\n * Detect the map's new width and height and resize it.\n *\n * @returns {Map} `this`\n */\n resize: function() {\n var width = 0, height = 0;\n\n if (this._container) {\n width = this._container.offsetWidth || 400;\n height = this._container.offsetHeight || 300;\n }\n\n this._canvas.resize(width, height);\n\n this.transform.width = width;\n this.transform.height = height;\n this.transform._constrain();\n\n this.painter.resize(width, height);\n\n return this\n .fire('movestart')\n ._move()\n .fire('resize')\n .fire('moveend');\n },\n\n /**\n * Get the map's geographical bounds\n *\n * @returns {LatLngBounds}\n */\n getBounds: function() {\n return new LatLngBounds(\n this.transform.pointLocation(new Point(0, 0)),\n this.transform.pointLocation(this.transform.size));\n },\n\n /**\n * Get pixel coordinates (relative to map container) given a geographical location\n *\n * @param {LatLng} latlng\n * @returns {Object} `x` and `y` coordinates\n */\n project: function(latlng) {\n return this.transform.locationPoint(LatLng.convert(latlng));\n },\n\n /**\n * Get geographical coordinates given pixel coordinates\n *\n * @param {Array} point [x, y] pixel coordinates\n * @returns {LatLng}\n */\n unproject: function(point) {\n return this.transform.pointLocation(Point.convert(point));\n },\n\n /**\n * Get all features at a point ([x, y])\n *\n * @param {Array} point [x, y] pixel coordinates\n * @param {Object} params\n * @param {number} [params.radius=0] Optional. Radius in pixels to search in\n * @param {string} params.layer Optional. Only return features from a given layer\n * @param {string} params.type Optional. Either `raster` or `vector`\n * @param {featuresAtCallback} callback function that returns the response\n *\n * @callback featuresAtCallback\n * @param {Object|null} err Error _If any_\n * @param {Array} features Displays a JSON array of features given the passed parameters of `featuresAt`\n *\n * @returns {Map} `this`\n */\n featuresAt: function(point, params, callback) {\n var coord = this.transform.pointCoordinate(Point.convert(point));\n this.style.featuresAt(coord, params, callback);\n return this;\n },\n\n /**\n * Replaces the map's style object\n *\n * @param {Object} style A style object formatted as JSON\n * @returns {Map} `this`\n */\n setStyle: function(style) {\n if (this.style) {\n this.style\n .off('load', this._onStyleLoad)\n .off('error', this._forwardStyleEvent)\n .off('change', this._onStyleChange)\n .off('source.add', this._onSourceAdd)\n .off('source.remove', this._onSourceRemove)\n .off('source.load', this._onSourceUpdate)\n .off('source.error', this._forwardSourceEvent)\n .off('source.change', this._onSourceUpdate)\n .off('layer.add', this._forwardLayerEvent)\n .off('layer.remove', this._forwardLayerEvent)\n .off('tile.add', this._forwardTileEvent)\n .off('tile.remove', this._forwardTileEvent)\n .off('tile.load', this.update)\n .off('tile.error', this._forwardTileEvent)\n ._remove();\n\n this.off('rotate', this.style._redoPlacement);\n this.off('pitch', this.style._redoPlacement);\n }\n\n if (!style) {\n this.style = null;\n return this;\n } else if (style instanceof Style) {\n this.style = style;\n } else {\n this.style = new Style(style, this.animationLoop);\n }\n\n this.style\n .on('load', this._onStyleLoad)\n .on('error', this._forwardStyleEvent)\n .on('change', this._onStyleChange)\n .on('source.add', this._onSourceAdd)\n .on('source.remove', this._onSourceRemove)\n .on('source.load', this._onSourceUpdate)\n .on('source.error', this._forwardSourceEvent)\n .on('source.change', this._onSourceUpdate)\n .on('layer.add', this._forwardLayerEvent)\n .on('layer.remove', this._forwardLayerEvent)\n .on('tile.add', this._forwardTileEvent)\n .on('tile.remove', this._forwardTileEvent)\n .on('tile.load', this.update)\n .on('tile.error', this._forwardTileEvent);\n\n this.on('rotate', this.style._redoPlacement);\n this.on('pitch', this.style._redoPlacement);\n\n return this;\n },\n\n /**\n * Add a source to the map style.\n *\n * @param {string} id ID of the source. Must not be used by any existing source.\n * @param {Object} source source specification, following the\n * [Mapbox GL Style Reference](https://www.mapbox.com/mapbox-gl-style-spec/#sources)\n * @fires source.add\n * @returns {Map} `this`\n */\n addSource: function(id, source) {\n this.style.addSource(id, source);\n return this;\n },\n\n /**\n * Remove an existing source from the map style.\n *\n * @param {string} id ID of the source to remove\n * @fires source.remove\n * @returns {Map} `this`\n */\n removeSource: function(id) {\n this.style.removeSource(id);\n return this;\n },\n\n /**\n * Return the style source object with the given `id`.\n *\n * @param {string} id source ID\n * @returns {Object}\n */\n getSource: function(id) {\n return this.style.getSource(id);\n },\n\n /**\n * Add a layer to the map style. The layer will be inserted before the layer with\n * ID `before`, or appended if `before` is omitted.\n * @param {Layer} layer\n * @param {string=} before ID of an existing layer to insert before\n * @fires layer.add\n * @returns {Map} `this`\n */\n addLayer: function(layer, before) {\n this.style.addLayer(layer, before);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Remove the layer with the given `id` from the map. Any layers which refer to the\n * specified layer via a `ref` property are also removed.\n *\n * @param {string} id\n * @fires layer.remove\n * @returns {Map} this\n */\n removeLayer: function(id) {\n this.style.removeLayer(id);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Set the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {Array} filter filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n * @returns {Map} `this`\n */\n setFilter: function(layer, filter) {\n this.style.setFilter(layer, filter);\n return this;\n },\n\n /**\n * Get the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @returns {Array} filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n */\n getFilter: function(layer) {\n return this.style.getFilter(layer);\n },\n\n /**\n * Set the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {*} value value for the paint propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @param {string=} klass optional class specifier for the property\n * @returns {Map} `this`\n */\n setPaintProperty: function(layer, name, value, klass) {\n this.style.setPaintProperty(layer, name, value, klass);\n this.style._cascade(this._classes);\n this.update(true);\n return this;\n },\n\n /**\n * Get the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the paint propery\n */\n getPaintProperty: function(layer, name, klass) {\n return this.style.getPaintProperty(layer, name, klass);\n },\n\n /**\n * Set the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {*} value value for the layout propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @returns {Map} `this`\n */\n setLayoutProperty: function(layer, name, value) {\n this.style.setLayoutProperty(layer, name, value);\n return this;\n },\n\n /**\n * Get the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the layout propery\n */\n getLayoutProperty: function(layer, name) {\n return this.style.getLayoutProperty(layer, name);\n },\n\n /**\n * Get the Map's container as an HTML element\n * @returns {HTMLElement} container\n */\n getContainer: function() {\n return this._container;\n },\n\n /**\n * Get the Map's canvas as an HTML canvas\n * @returns {HTMLElement} canvas\n */\n getCanvas: function() {\n return this._canvas.getElement();\n },\n\n _move: function(zoom, rotate, pitch) {\n\n this.update(zoom).fire('move');\n\n if (zoom) this.fire('zoom');\n if (rotate) this.fire('rotate');\n if (pitch) this.fire('pitch');\n\n return this;\n },\n\n // map setup code\n _setupContainer: function() {\n var id = this.options.container;\n var container = this._container = typeof id === 'string' ? document.getElementById(id) : id;\n if (container) container.classList.add('mapboxgl-map');\n this._canvas = new Canvas(this, container);\n },\n\n _setupControlPos: function() {\n var corners = this._controlCorners = {};\n var prefix = 'mapboxgl-ctrl-';\n var container = this.getContainer();\n\n function createCorner(pos) {\n var className = prefix + pos;\n corners[pos] = DOM.create('div', className, container);\n }\n\n if (container && typeof document === 'object') {\n createCorner('top-left');\n createCorner('top-right');\n createCorner('bottom-left');\n createCorner('bottom-right');\n }\n },\n\n _setupPainter: function() {\n var gl = this._canvas.getWebGLContext(this.options.failIfMajorPerformanceCaveat);\n\n if (!gl) {\n console.error('Failed to initialize WebGL');\n return;\n }\n\n this.painter = new GLPainter(gl, this.transform);\n },\n\n _contextLost: function(event) {\n event.preventDefault();\n if (this._frameId) {\n browser.cancelFrame(this._frameId);\n }\n },\n\n _contextRestored: function() {\n this._setupPainter();\n this.resize();\n this.update();\n },\n\n /**\n * Is this map fully loaded? If the style isn't loaded\n * or it has a change to the sources or style that isn't\n * propagated to its style, return false.\n *\n * @returns {boolean} whether the map is loaded\n */\n loaded: function() {\n if (this._styleDirty || this._sourcesDirty)\n return false;\n if (this.style && !this.style.loaded())\n return false;\n return true;\n },\n\n /**\n * Update this map's style and re-render the map.\n *\n * @param {Object} updateStyle new style\n * @returns {Map} this\n */\n update: function(updateStyle) {\n if (!this.style) return this;\n\n this._styleDirty = this._styleDirty || updateStyle;\n this._sourcesDirty = true;\n\n this._rerender();\n\n return this;\n },\n\n /**\n * Call when a (re-)render of the map is required, e.g. when the\n * user panned or zoomed,f or new data is available.\n * @returns {Map} this\n */\n render: function() {\n if (this.style && this._styleDirty) {\n this._styleDirty = false;\n this.style._recalculate(this.transform.zoom);\n }\n\n if (this.style && this._sourcesDirty && !this._sourcesDirtyTimeout) {\n this._sourcesDirty = false;\n this._sourcesDirtyTimeout = setTimeout(function() {\n this._sourcesDirtyTimeout = null;\n }.bind(this), 50);\n this.style._updateSources(this.transform);\n }\n\n this.painter.render(this.style, {\n debug: this.debug,\n vertices: this.vertices,\n rotating: this.rotating,\n zooming: this.zooming\n });\n\n this.fire('render');\n\n if (this.loaded() && !this._loaded) {\n this._loaded = true;\n this.fire('load');\n }\n\n this._frameId = null;\n\n if (!this.animationLoop.stopped()) {\n this._styleDirty = true;\n }\n\n if (this._sourcesDirty || this._repaint || !this.animationLoop.stopped()) {\n this._rerender();\n }\n\n return this;\n },\n\n /**\n * Destroys the map's underlying resources, including web workers.\n * @returns {Map} this\n */\n remove: function() {\n if (this._hash) this._hash.remove();\n browser.cancelFrame(this._frameId);\n clearTimeout(this._sourcesDirtyTimeout);\n this.setStyle(null);\n return this;\n },\n\n _rerender: function() {\n if (this.style && !this._frameId) {\n this._frameId = browser.frame(this.render);\n }\n },\n\n _forwardStyleEvent: function(e) {\n this.fire('style.' + e.type, util.extend({style: e.target}, e));\n },\n\n _forwardSourceEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardLayerEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardTileEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _onStyleLoad: function(e) {\n this.style._cascade(this._classes, {transition: false});\n this._forwardStyleEvent(e);\n },\n\n _onStyleChange: function(e) {\n this.update(true);\n this._forwardStyleEvent(e);\n },\n\n _onSourceAdd: function(e) {\n var source = e.source;\n if (source.onAdd)\n source.onAdd(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceRemove: function(e) {\n var source = e.source;\n if (source.onRemove)\n source.onRemove(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceUpdate: function(e) {\n this.update();\n this._forwardSourceEvent(e);\n }\n}","path":"js/ui/map.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/map.js#L322-L326"},"returns":[{"title":"returns","description":null,"type":{"type":"NameExpression","name":"LatLngBounds"}}],"name":"getBounds","memberof":"Map","scope":"instance","members":{"instance":[],"static":[]},"path":["Map","getBounds"]},{"description":"Get all features at a point ([x, y])","tags":[{"title":"param","description":"[x, y] pixel coordinates","type":{"type":"TypeApplication","expression":{"type":"NameExpression","name":"Array"},"applications":[{"type":"NameExpression","name":"number"}]},"name":"point"},{"title":"param","description":null,"type":{"type":"NameExpression","name":"Object"},"name":"params"},{"title":"name","name":"featuresAt"},{"title":"memberof","description":"Map"},{"title":"instance"}],"context":{"loc":{"start":{"line":364,"column":4},"end":{"line":368,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/map.js","code":"{\n\n options: {\n center: [0, 0],\n zoom: 0,\n bearing: 0,\n pitch: 0,\n\n minZoom: 0,\n maxZoom: 20,\n\n interactive: true,\n hash: false,\n\n attributionControl: true,\n\n failIfMajorPerformanceCaveat: false\n },\n\n addControl: function(control) {\n control.addTo(this);\n return this;\n },\n\n /**\n * Sets a map position\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @param {number} zoom Map zoom level\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setView: function(center, zoom, bearing, pitch) {\n this.stop();\n\n var tr = this.transform,\n zoomChanged = tr.zoom !== +zoom,\n bearingChanged = tr.bearing !== +bearing,\n pitchChanged = tr.pitch !== +pitch;\n\n tr.center = LatLng.convert(center);\n tr.zoom = +zoom;\n tr.bearing = +bearing;\n tr.pitch = +pitch;\n\n return this\n .fire('movestart')\n ._move(zoomChanged, bearingChanged, pitchChanged)\n .fire('moveend');\n },\n\n /**\n * Sets a map location\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setCenter: function(center) {\n this.setView(center, this.getZoom(), this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map zoom\n *\n * @param {number} zoom Map zoom level\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setZoom: function(zoom) {\n this.setView(this.getCenter(), zoom, this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map rotation\n *\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setBearing: function(bearing) {\n this.setView(this.getCenter(), this.getZoom(), bearing, this.getPitch());\n },\n\n /**\n * Sets a map angle\n *\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setPitch: function(pitch) {\n this.setView(this.getCenter(), this.getZoom(), this.getBearing(), pitch);\n },\n\n /**\n * Get the current view geographical point\n * @returns {LatLng}\n */\n getCenter: function() { return this.transform.center; },\n\n /**\n * Get the current zoom\n * @returns {number}\n */\n getZoom: function() { return this.transform.zoom; },\n\n /**\n * Get the current bearing in degrees\n * @returns {number}\n */\n getBearing: function() { return this.transform.bearing; },\n\n /**\n * Get the current angle in degrees\n * @returns {number}\n */\n getPitch: function() { return this.transform.pitch; },\n\n /**\n * @typedef {Object} [styleOptions]\n * @param {Boolean} [styleOptions.transition=true]\n */\n\n /**\n * Adds a style class to a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n addClass: function(klass, options) {\n if (this._classes[klass]) return;\n this._classes[klass] = true;\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Removes a style class from a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n removeClass: function(klass, options) {\n if (!this._classes[klass]) return;\n delete this._classes[klass];\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Helper method to add more than one class\n *\n * @param {Array} klasses An array of class names\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n setClasses: function(klasses, options) {\n this._classes = {};\n for (var i = 0; i < klasses.length; i++) {\n this._classes[klasses[i]] = true;\n }\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Check whether a style class is active\n *\n * @param {string} klass Name of style class\n * @returns {boolean}\n */\n hasClass: function(klass) {\n return !!this._classes[klass];\n },\n\n /**\n * Return an array of the current active style classes\n *\n * @returns {boolean}\n */\n getClasses: function() {\n return Object.keys(this._classes);\n },\n\n /**\n * Detect the map's new width and height and resize it.\n *\n * @returns {Map} `this`\n */\n resize: function() {\n var width = 0, height = 0;\n\n if (this._container) {\n width = this._container.offsetWidth || 400;\n height = this._container.offsetHeight || 300;\n }\n\n this._canvas.resize(width, height);\n\n this.transform.width = width;\n this.transform.height = height;\n this.transform._constrain();\n\n this.painter.resize(width, height);\n\n return this\n .fire('movestart')\n ._move()\n .fire('resize')\n .fire('moveend');\n },\n\n /**\n * Get the map's geographical bounds\n *\n * @returns {LatLngBounds}\n */\n getBounds: function() {\n return new LatLngBounds(\n this.transform.pointLocation(new Point(0, 0)),\n this.transform.pointLocation(this.transform.size));\n },\n\n /**\n * Get pixel coordinates (relative to map container) given a geographical location\n *\n * @param {LatLng} latlng\n * @returns {Object} `x` and `y` coordinates\n */\n project: function(latlng) {\n return this.transform.locationPoint(LatLng.convert(latlng));\n },\n\n /**\n * Get geographical coordinates given pixel coordinates\n *\n * @param {Array} point [x, y] pixel coordinates\n * @returns {LatLng}\n */\n unproject: function(point) {\n return this.transform.pointLocation(Point.convert(point));\n },\n\n /**\n * Get all features at a point ([x, y])\n *\n * @param {Array} point [x, y] pixel coordinates\n * @param {Object} params\n * @param {number} [params.radius=0] Optional. Radius in pixels to search in\n * @param {string} params.layer Optional. Only return features from a given layer\n * @param {string} params.type Optional. Either `raster` or `vector`\n * @param {featuresAtCallback} callback function that returns the response\n *\n * @callback featuresAtCallback\n * @param {Object|null} err Error _If any_\n * @param {Array} features Displays a JSON array of features given the passed parameters of `featuresAt`\n *\n * @returns {Map} `this`\n */\n featuresAt: function(point, params, callback) {\n var coord = this.transform.pointCoordinate(Point.convert(point));\n this.style.featuresAt(coord, params, callback);\n return this;\n },\n\n /**\n * Replaces the map's style object\n *\n * @param {Object} style A style object formatted as JSON\n * @returns {Map} `this`\n */\n setStyle: function(style) {\n if (this.style) {\n this.style\n .off('load', this._onStyleLoad)\n .off('error', this._forwardStyleEvent)\n .off('change', this._onStyleChange)\n .off('source.add', this._onSourceAdd)\n .off('source.remove', this._onSourceRemove)\n .off('source.load', this._onSourceUpdate)\n .off('source.error', this._forwardSourceEvent)\n .off('source.change', this._onSourceUpdate)\n .off('layer.add', this._forwardLayerEvent)\n .off('layer.remove', this._forwardLayerEvent)\n .off('tile.add', this._forwardTileEvent)\n .off('tile.remove', this._forwardTileEvent)\n .off('tile.load', this.update)\n .off('tile.error', this._forwardTileEvent)\n ._remove();\n\n this.off('rotate', this.style._redoPlacement);\n this.off('pitch', this.style._redoPlacement);\n }\n\n if (!style) {\n this.style = null;\n return this;\n } else if (style instanceof Style) {\n this.style = style;\n } else {\n this.style = new Style(style, this.animationLoop);\n }\n\n this.style\n .on('load', this._onStyleLoad)\n .on('error', this._forwardStyleEvent)\n .on('change', this._onStyleChange)\n .on('source.add', this._onSourceAdd)\n .on('source.remove', this._onSourceRemove)\n .on('source.load', this._onSourceUpdate)\n .on('source.error', this._forwardSourceEvent)\n .on('source.change', this._onSourceUpdate)\n .on('layer.add', this._forwardLayerEvent)\n .on('layer.remove', this._forwardLayerEvent)\n .on('tile.add', this._forwardTileEvent)\n .on('tile.remove', this._forwardTileEvent)\n .on('tile.load', this.update)\n .on('tile.error', this._forwardTileEvent);\n\n this.on('rotate', this.style._redoPlacement);\n this.on('pitch', this.style._redoPlacement);\n\n return this;\n },\n\n /**\n * Add a source to the map style.\n *\n * @param {string} id ID of the source. Must not be used by any existing source.\n * @param {Object} source source specification, following the\n * [Mapbox GL Style Reference](https://www.mapbox.com/mapbox-gl-style-spec/#sources)\n * @fires source.add\n * @returns {Map} `this`\n */\n addSource: function(id, source) {\n this.style.addSource(id, source);\n return this;\n },\n\n /**\n * Remove an existing source from the map style.\n *\n * @param {string} id ID of the source to remove\n * @fires source.remove\n * @returns {Map} `this`\n */\n removeSource: function(id) {\n this.style.removeSource(id);\n return this;\n },\n\n /**\n * Return the style source object with the given `id`.\n *\n * @param {string} id source ID\n * @returns {Object}\n */\n getSource: function(id) {\n return this.style.getSource(id);\n },\n\n /**\n * Add a layer to the map style. The layer will be inserted before the layer with\n * ID `before`, or appended if `before` is omitted.\n * @param {Layer} layer\n * @param {string=} before ID of an existing layer to insert before\n * @fires layer.add\n * @returns {Map} `this`\n */\n addLayer: function(layer, before) {\n this.style.addLayer(layer, before);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Remove the layer with the given `id` from the map. Any layers which refer to the\n * specified layer via a `ref` property are also removed.\n *\n * @param {string} id\n * @fires layer.remove\n * @returns {Map} this\n */\n removeLayer: function(id) {\n this.style.removeLayer(id);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Set the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {Array} filter filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n * @returns {Map} `this`\n */\n setFilter: function(layer, filter) {\n this.style.setFilter(layer, filter);\n return this;\n },\n\n /**\n * Get the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @returns {Array} filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n */\n getFilter: function(layer) {\n return this.style.getFilter(layer);\n },\n\n /**\n * Set the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {*} value value for the paint propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @param {string=} klass optional class specifier for the property\n * @returns {Map} `this`\n */\n setPaintProperty: function(layer, name, value, klass) {\n this.style.setPaintProperty(layer, name, value, klass);\n this.style._cascade(this._classes);\n this.update(true);\n return this;\n },\n\n /**\n * Get the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the paint propery\n */\n getPaintProperty: function(layer, name, klass) {\n return this.style.getPaintProperty(layer, name, klass);\n },\n\n /**\n * Set the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {*} value value for the layout propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @returns {Map} `this`\n */\n setLayoutProperty: function(layer, name, value) {\n this.style.setLayoutProperty(layer, name, value);\n return this;\n },\n\n /**\n * Get the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the layout propery\n */\n getLayoutProperty: function(layer, name) {\n return this.style.getLayoutProperty(layer, name);\n },\n\n /**\n * Get the Map's container as an HTML element\n * @returns {HTMLElement} container\n */\n getContainer: function() {\n return this._container;\n },\n\n /**\n * Get the Map's canvas as an HTML canvas\n * @returns {HTMLElement} canvas\n */\n getCanvas: function() {\n return this._canvas.getElement();\n },\n\n _move: function(zoom, rotate, pitch) {\n\n this.update(zoom).fire('move');\n\n if (zoom) this.fire('zoom');\n if (rotate) this.fire('rotate');\n if (pitch) this.fire('pitch');\n\n return this;\n },\n\n // map setup code\n _setupContainer: function() {\n var id = this.options.container;\n var container = this._container = typeof id === 'string' ? document.getElementById(id) : id;\n if (container) container.classList.add('mapboxgl-map');\n this._canvas = new Canvas(this, container);\n },\n\n _setupControlPos: function() {\n var corners = this._controlCorners = {};\n var prefix = 'mapboxgl-ctrl-';\n var container = this.getContainer();\n\n function createCorner(pos) {\n var className = prefix + pos;\n corners[pos] = DOM.create('div', className, container);\n }\n\n if (container && typeof document === 'object') {\n createCorner('top-left');\n createCorner('top-right');\n createCorner('bottom-left');\n createCorner('bottom-right');\n }\n },\n\n _setupPainter: function() {\n var gl = this._canvas.getWebGLContext(this.options.failIfMajorPerformanceCaveat);\n\n if (!gl) {\n console.error('Failed to initialize WebGL');\n return;\n }\n\n this.painter = new GLPainter(gl, this.transform);\n },\n\n _contextLost: function(event) {\n event.preventDefault();\n if (this._frameId) {\n browser.cancelFrame(this._frameId);\n }\n },\n\n _contextRestored: function() {\n this._setupPainter();\n this.resize();\n this.update();\n },\n\n /**\n * Is this map fully loaded? If the style isn't loaded\n * or it has a change to the sources or style that isn't\n * propagated to its style, return false.\n *\n * @returns {boolean} whether the map is loaded\n */\n loaded: function() {\n if (this._styleDirty || this._sourcesDirty)\n return false;\n if (this.style && !this.style.loaded())\n return false;\n return true;\n },\n\n /**\n * Update this map's style and re-render the map.\n *\n * @param {Object} updateStyle new style\n * @returns {Map} this\n */\n update: function(updateStyle) {\n if (!this.style) return this;\n\n this._styleDirty = this._styleDirty || updateStyle;\n this._sourcesDirty = true;\n\n this._rerender();\n\n return this;\n },\n\n /**\n * Call when a (re-)render of the map is required, e.g. when the\n * user panned or zoomed,f or new data is available.\n * @returns {Map} this\n */\n render: function() {\n if (this.style && this._styleDirty) {\n this._styleDirty = false;\n this.style._recalculate(this.transform.zoom);\n }\n\n if (this.style && this._sourcesDirty && !this._sourcesDirtyTimeout) {\n this._sourcesDirty = false;\n this._sourcesDirtyTimeout = setTimeout(function() {\n this._sourcesDirtyTimeout = null;\n }.bind(this), 50);\n this.style._updateSources(this.transform);\n }\n\n this.painter.render(this.style, {\n debug: this.debug,\n vertices: this.vertices,\n rotating: this.rotating,\n zooming: this.zooming\n });\n\n this.fire('render');\n\n if (this.loaded() && !this._loaded) {\n this._loaded = true;\n this.fire('load');\n }\n\n this._frameId = null;\n\n if (!this.animationLoop.stopped()) {\n this._styleDirty = true;\n }\n\n if (this._sourcesDirty || this._repaint || !this.animationLoop.stopped()) {\n this._rerender();\n }\n\n return this;\n },\n\n /**\n * Destroys the map's underlying resources, including web workers.\n * @returns {Map} this\n */\n remove: function() {\n if (this._hash) this._hash.remove();\n browser.cancelFrame(this._frameId);\n clearTimeout(this._sourcesDirtyTimeout);\n this.setStyle(null);\n return this;\n },\n\n _rerender: function() {\n if (this.style && !this._frameId) {\n this._frameId = browser.frame(this.render);\n }\n },\n\n _forwardStyleEvent: function(e) {\n this.fire('style.' + e.type, util.extend({style: e.target}, e));\n },\n\n _forwardSourceEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardLayerEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardTileEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _onStyleLoad: function(e) {\n this.style._cascade(this._classes, {transition: false});\n this._forwardStyleEvent(e);\n },\n\n _onStyleChange: function(e) {\n this.update(true);\n this._forwardStyleEvent(e);\n },\n\n _onSourceAdd: function(e) {\n var source = e.source;\n if (source.onAdd)\n source.onAdd(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceRemove: function(e) {\n var source = e.source;\n if (source.onRemove)\n source.onRemove(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceUpdate: function(e) {\n this.update();\n this._forwardSourceEvent(e);\n }\n}","path":"js/ui/map.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/map.js#L364-L368"},"params":[{"title":"param","description":"[x, y] pixel coordinates","type":{"type":"TypeApplication","expression":{"type":"NameExpression","name":"Array"},"applications":[{"type":"NameExpression","name":"number"}]},"name":"point"},{"title":"param","description":null,"type":{"type":"NameExpression","name":"Object"},"name":"params"}],"name":"featuresAt","memberof":"Map","scope":"instance","members":{"instance":[],"static":[]},"path":["Map","featuresAt"]},{"description":"Get the filter for a given style layer.","tags":[{"title":"param","description":"ID of a layer","type":{"type":"NameExpression","name":"string"},"name":"layer"},{"title":"returns","description":"filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)","type":{"type":"NameExpression","name":"Array"}},{"title":"name","name":"getFilter"},{"title":"memberof","description":"Map"},{"title":"instance"}],"context":{"loc":{"start":{"line":512,"column":4},"end":{"line":514,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/map.js","code":"{\n\n options: {\n center: [0, 0],\n zoom: 0,\n bearing: 0,\n pitch: 0,\n\n minZoom: 0,\n maxZoom: 20,\n\n interactive: true,\n hash: false,\n\n attributionControl: true,\n\n failIfMajorPerformanceCaveat: false\n },\n\n addControl: function(control) {\n control.addTo(this);\n return this;\n },\n\n /**\n * Sets a map position\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @param {number} zoom Map zoom level\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setView: function(center, zoom, bearing, pitch) {\n this.stop();\n\n var tr = this.transform,\n zoomChanged = tr.zoom !== +zoom,\n bearingChanged = tr.bearing !== +bearing,\n pitchChanged = tr.pitch !== +pitch;\n\n tr.center = LatLng.convert(center);\n tr.zoom = +zoom;\n tr.bearing = +bearing;\n tr.pitch = +pitch;\n\n return this\n .fire('movestart')\n ._move(zoomChanged, bearingChanged, pitchChanged)\n .fire('moveend');\n },\n\n /**\n * Sets a map location\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setCenter: function(center) {\n this.setView(center, this.getZoom(), this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map zoom\n *\n * @param {number} zoom Map zoom level\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setZoom: function(zoom) {\n this.setView(this.getCenter(), zoom, this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map rotation\n *\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setBearing: function(bearing) {\n this.setView(this.getCenter(), this.getZoom(), bearing, this.getPitch());\n },\n\n /**\n * Sets a map angle\n *\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setPitch: function(pitch) {\n this.setView(this.getCenter(), this.getZoom(), this.getBearing(), pitch);\n },\n\n /**\n * Get the current view geographical point\n * @returns {LatLng}\n */\n getCenter: function() { return this.transform.center; },\n\n /**\n * Get the current zoom\n * @returns {number}\n */\n getZoom: function() { return this.transform.zoom; },\n\n /**\n * Get the current bearing in degrees\n * @returns {number}\n */\n getBearing: function() { return this.transform.bearing; },\n\n /**\n * Get the current angle in degrees\n * @returns {number}\n */\n getPitch: function() { return this.transform.pitch; },\n\n /**\n * @typedef {Object} [styleOptions]\n * @param {Boolean} [styleOptions.transition=true]\n */\n\n /**\n * Adds a style class to a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n addClass: function(klass, options) {\n if (this._classes[klass]) return;\n this._classes[klass] = true;\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Removes a style class from a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n removeClass: function(klass, options) {\n if (!this._classes[klass]) return;\n delete this._classes[klass];\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Helper method to add more than one class\n *\n * @param {Array} klasses An array of class names\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n setClasses: function(klasses, options) {\n this._classes = {};\n for (var i = 0; i < klasses.length; i++) {\n this._classes[klasses[i]] = true;\n }\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Check whether a style class is active\n *\n * @param {string} klass Name of style class\n * @returns {boolean}\n */\n hasClass: function(klass) {\n return !!this._classes[klass];\n },\n\n /**\n * Return an array of the current active style classes\n *\n * @returns {boolean}\n */\n getClasses: function() {\n return Object.keys(this._classes);\n },\n\n /**\n * Detect the map's new width and height and resize it.\n *\n * @returns {Map} `this`\n */\n resize: function() {\n var width = 0, height = 0;\n\n if (this._container) {\n width = this._container.offsetWidth || 400;\n height = this._container.offsetHeight || 300;\n }\n\n this._canvas.resize(width, height);\n\n this.transform.width = width;\n this.transform.height = height;\n this.transform._constrain();\n\n this.painter.resize(width, height);\n\n return this\n .fire('movestart')\n ._move()\n .fire('resize')\n .fire('moveend');\n },\n\n /**\n * Get the map's geographical bounds\n *\n * @returns {LatLngBounds}\n */\n getBounds: function() {\n return new LatLngBounds(\n this.transform.pointLocation(new Point(0, 0)),\n this.transform.pointLocation(this.transform.size));\n },\n\n /**\n * Get pixel coordinates (relative to map container) given a geographical location\n *\n * @param {LatLng} latlng\n * @returns {Object} `x` and `y` coordinates\n */\n project: function(latlng) {\n return this.transform.locationPoint(LatLng.convert(latlng));\n },\n\n /**\n * Get geographical coordinates given pixel coordinates\n *\n * @param {Array} point [x, y] pixel coordinates\n * @returns {LatLng}\n */\n unproject: function(point) {\n return this.transform.pointLocation(Point.convert(point));\n },\n\n /**\n * Get all features at a point ([x, y])\n *\n * @param {Array} point [x, y] pixel coordinates\n * @param {Object} params\n * @param {number} [params.radius=0] Optional. Radius in pixels to search in\n * @param {string} params.layer Optional. Only return features from a given layer\n * @param {string} params.type Optional. Either `raster` or `vector`\n * @param {featuresAtCallback} callback function that returns the response\n *\n * @callback featuresAtCallback\n * @param {Object|null} err Error _If any_\n * @param {Array} features Displays a JSON array of features given the passed parameters of `featuresAt`\n *\n * @returns {Map} `this`\n */\n featuresAt: function(point, params, callback) {\n var coord = this.transform.pointCoordinate(Point.convert(point));\n this.style.featuresAt(coord, params, callback);\n return this;\n },\n\n /**\n * Replaces the map's style object\n *\n * @param {Object} style A style object formatted as JSON\n * @returns {Map} `this`\n */\n setStyle: function(style) {\n if (this.style) {\n this.style\n .off('load', this._onStyleLoad)\n .off('error', this._forwardStyleEvent)\n .off('change', this._onStyleChange)\n .off('source.add', this._onSourceAdd)\n .off('source.remove', this._onSourceRemove)\n .off('source.load', this._onSourceUpdate)\n .off('source.error', this._forwardSourceEvent)\n .off('source.change', this._onSourceUpdate)\n .off('layer.add', this._forwardLayerEvent)\n .off('layer.remove', this._forwardLayerEvent)\n .off('tile.add', this._forwardTileEvent)\n .off('tile.remove', this._forwardTileEvent)\n .off('tile.load', this.update)\n .off('tile.error', this._forwardTileEvent)\n ._remove();\n\n this.off('rotate', this.style._redoPlacement);\n this.off('pitch', this.style._redoPlacement);\n }\n\n if (!style) {\n this.style = null;\n return this;\n } else if (style instanceof Style) {\n this.style = style;\n } else {\n this.style = new Style(style, this.animationLoop);\n }\n\n this.style\n .on('load', this._onStyleLoad)\n .on('error', this._forwardStyleEvent)\n .on('change', this._onStyleChange)\n .on('source.add', this._onSourceAdd)\n .on('source.remove', this._onSourceRemove)\n .on('source.load', this._onSourceUpdate)\n .on('source.error', this._forwardSourceEvent)\n .on('source.change', this._onSourceUpdate)\n .on('layer.add', this._forwardLayerEvent)\n .on('layer.remove', this._forwardLayerEvent)\n .on('tile.add', this._forwardTileEvent)\n .on('tile.remove', this._forwardTileEvent)\n .on('tile.load', this.update)\n .on('tile.error', this._forwardTileEvent);\n\n this.on('rotate', this.style._redoPlacement);\n this.on('pitch', this.style._redoPlacement);\n\n return this;\n },\n\n /**\n * Add a source to the map style.\n *\n * @param {string} id ID of the source. Must not be used by any existing source.\n * @param {Object} source source specification, following the\n * [Mapbox GL Style Reference](https://www.mapbox.com/mapbox-gl-style-spec/#sources)\n * @fires source.add\n * @returns {Map} `this`\n */\n addSource: function(id, source) {\n this.style.addSource(id, source);\n return this;\n },\n\n /**\n * Remove an existing source from the map style.\n *\n * @param {string} id ID of the source to remove\n * @fires source.remove\n * @returns {Map} `this`\n */\n removeSource: function(id) {\n this.style.removeSource(id);\n return this;\n },\n\n /**\n * Return the style source object with the given `id`.\n *\n * @param {string} id source ID\n * @returns {Object}\n */\n getSource: function(id) {\n return this.style.getSource(id);\n },\n\n /**\n * Add a layer to the map style. The layer will be inserted before the layer with\n * ID `before`, or appended if `before` is omitted.\n * @param {Layer} layer\n * @param {string=} before ID of an existing layer to insert before\n * @fires layer.add\n * @returns {Map} `this`\n */\n addLayer: function(layer, before) {\n this.style.addLayer(layer, before);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Remove the layer with the given `id` from the map. Any layers which refer to the\n * specified layer via a `ref` property are also removed.\n *\n * @param {string} id\n * @fires layer.remove\n * @returns {Map} this\n */\n removeLayer: function(id) {\n this.style.removeLayer(id);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Set the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {Array} filter filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n * @returns {Map} `this`\n */\n setFilter: function(layer, filter) {\n this.style.setFilter(layer, filter);\n return this;\n },\n\n /**\n * Get the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @returns {Array} filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n */\n getFilter: function(layer) {\n return this.style.getFilter(layer);\n },\n\n /**\n * Set the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {*} value value for the paint propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @param {string=} klass optional class specifier for the property\n * @returns {Map} `this`\n */\n setPaintProperty: function(layer, name, value, klass) {\n this.style.setPaintProperty(layer, name, value, klass);\n this.style._cascade(this._classes);\n this.update(true);\n return this;\n },\n\n /**\n * Get the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the paint propery\n */\n getPaintProperty: function(layer, name, klass) {\n return this.style.getPaintProperty(layer, name, klass);\n },\n\n /**\n * Set the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {*} value value for the layout propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @returns {Map} `this`\n */\n setLayoutProperty: function(layer, name, value) {\n this.style.setLayoutProperty(layer, name, value);\n return this;\n },\n\n /**\n * Get the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the layout propery\n */\n getLayoutProperty: function(layer, name) {\n return this.style.getLayoutProperty(layer, name);\n },\n\n /**\n * Get the Map's container as an HTML element\n * @returns {HTMLElement} container\n */\n getContainer: function() {\n return this._container;\n },\n\n /**\n * Get the Map's canvas as an HTML canvas\n * @returns {HTMLElement} canvas\n */\n getCanvas: function() {\n return this._canvas.getElement();\n },\n\n _move: function(zoom, rotate, pitch) {\n\n this.update(zoom).fire('move');\n\n if (zoom) this.fire('zoom');\n if (rotate) this.fire('rotate');\n if (pitch) this.fire('pitch');\n\n return this;\n },\n\n // map setup code\n _setupContainer: function() {\n var id = this.options.container;\n var container = this._container = typeof id === 'string' ? document.getElementById(id) : id;\n if (container) container.classList.add('mapboxgl-map');\n this._canvas = new Canvas(this, container);\n },\n\n _setupControlPos: function() {\n var corners = this._controlCorners = {};\n var prefix = 'mapboxgl-ctrl-';\n var container = this.getContainer();\n\n function createCorner(pos) {\n var className = prefix + pos;\n corners[pos] = DOM.create('div', className, container);\n }\n\n if (container && typeof document === 'object') {\n createCorner('top-left');\n createCorner('top-right');\n createCorner('bottom-left');\n createCorner('bottom-right');\n }\n },\n\n _setupPainter: function() {\n var gl = this._canvas.getWebGLContext(this.options.failIfMajorPerformanceCaveat);\n\n if (!gl) {\n console.error('Failed to initialize WebGL');\n return;\n }\n\n this.painter = new GLPainter(gl, this.transform);\n },\n\n _contextLost: function(event) {\n event.preventDefault();\n if (this._frameId) {\n browser.cancelFrame(this._frameId);\n }\n },\n\n _contextRestored: function() {\n this._setupPainter();\n this.resize();\n this.update();\n },\n\n /**\n * Is this map fully loaded? If the style isn't loaded\n * or it has a change to the sources or style that isn't\n * propagated to its style, return false.\n *\n * @returns {boolean} whether the map is loaded\n */\n loaded: function() {\n if (this._styleDirty || this._sourcesDirty)\n return false;\n if (this.style && !this.style.loaded())\n return false;\n return true;\n },\n\n /**\n * Update this map's style and re-render the map.\n *\n * @param {Object} updateStyle new style\n * @returns {Map} this\n */\n update: function(updateStyle) {\n if (!this.style) return this;\n\n this._styleDirty = this._styleDirty || updateStyle;\n this._sourcesDirty = true;\n\n this._rerender();\n\n return this;\n },\n\n /**\n * Call when a (re-)render of the map is required, e.g. when the\n * user panned or zoomed,f or new data is available.\n * @returns {Map} this\n */\n render: function() {\n if (this.style && this._styleDirty) {\n this._styleDirty = false;\n this.style._recalculate(this.transform.zoom);\n }\n\n if (this.style && this._sourcesDirty && !this._sourcesDirtyTimeout) {\n this._sourcesDirty = false;\n this._sourcesDirtyTimeout = setTimeout(function() {\n this._sourcesDirtyTimeout = null;\n }.bind(this), 50);\n this.style._updateSources(this.transform);\n }\n\n this.painter.render(this.style, {\n debug: this.debug,\n vertices: this.vertices,\n rotating: this.rotating,\n zooming: this.zooming\n });\n\n this.fire('render');\n\n if (this.loaded() && !this._loaded) {\n this._loaded = true;\n this.fire('load');\n }\n\n this._frameId = null;\n\n if (!this.animationLoop.stopped()) {\n this._styleDirty = true;\n }\n\n if (this._sourcesDirty || this._repaint || !this.animationLoop.stopped()) {\n this._rerender();\n }\n\n return this;\n },\n\n /**\n * Destroys the map's underlying resources, including web workers.\n * @returns {Map} this\n */\n remove: function() {\n if (this._hash) this._hash.remove();\n browser.cancelFrame(this._frameId);\n clearTimeout(this._sourcesDirtyTimeout);\n this.setStyle(null);\n return this;\n },\n\n _rerender: function() {\n if (this.style && !this._frameId) {\n this._frameId = browser.frame(this.render);\n }\n },\n\n _forwardStyleEvent: function(e) {\n this.fire('style.' + e.type, util.extend({style: e.target}, e));\n },\n\n _forwardSourceEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardLayerEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardTileEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _onStyleLoad: function(e) {\n this.style._cascade(this._classes, {transition: false});\n this._forwardStyleEvent(e);\n },\n\n _onStyleChange: function(e) {\n this.update(true);\n this._forwardStyleEvent(e);\n },\n\n _onSourceAdd: function(e) {\n var source = e.source;\n if (source.onAdd)\n source.onAdd(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceRemove: function(e) {\n var source = e.source;\n if (source.onRemove)\n source.onRemove(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceUpdate: function(e) {\n this.update();\n this._forwardSourceEvent(e);\n }\n}","path":"js/ui/map.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/map.js#L512-L514"},"params":[{"title":"param","description":"ID of a layer","type":{"type":"NameExpression","name":"string"},"name":"layer"}],"returns":[{"title":"returns","description":"filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)","type":{"type":"NameExpression","name":"Array"}}],"name":"getFilter","memberof":"Map","scope":"instance","members":{"instance":[],"static":[]},"path":["Map","getFilter"]},{"description":"Get the value of a layout property in a given style layer.","tags":[{"title":"param","description":"ID of a layer","type":{"type":"NameExpression","name":"string"},"name":"layer"},{"title":"param","description":"name of a layout property","type":{"type":"NameExpression","name":"string"},"name":"name"},{"title":"param","description":"optional class specifier for the property","type":{"type":"OptionalType","expression":{"type":"NameExpression","name":"string"}},"name":"klass"},{"title":"returns","description":"value for the layout propery","type":{"type":"AllLiteral"}},{"title":"name","name":"getLayoutProperty"},{"title":"memberof","description":"Map"},{"title":"instance"}],"context":{"loc":{"start":{"line":565,"column":4},"end":{"line":567,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/map.js","code":"{\n\n options: {\n center: [0, 0],\n zoom: 0,\n bearing: 0,\n pitch: 0,\n\n minZoom: 0,\n maxZoom: 20,\n\n interactive: true,\n hash: false,\n\n attributionControl: true,\n\n failIfMajorPerformanceCaveat: false\n },\n\n addControl: function(control) {\n control.addTo(this);\n return this;\n },\n\n /**\n * Sets a map position\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @param {number} zoom Map zoom level\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setView: function(center, zoom, bearing, pitch) {\n this.stop();\n\n var tr = this.transform,\n zoomChanged = tr.zoom !== +zoom,\n bearingChanged = tr.bearing !== +bearing,\n pitchChanged = tr.pitch !== +pitch;\n\n tr.center = LatLng.convert(center);\n tr.zoom = +zoom;\n tr.bearing = +bearing;\n tr.pitch = +pitch;\n\n return this\n .fire('movestart')\n ._move(zoomChanged, bearingChanged, pitchChanged)\n .fire('moveend');\n },\n\n /**\n * Sets a map location\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setCenter: function(center) {\n this.setView(center, this.getZoom(), this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map zoom\n *\n * @param {number} zoom Map zoom level\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setZoom: function(zoom) {\n this.setView(this.getCenter(), zoom, this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map rotation\n *\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setBearing: function(bearing) {\n this.setView(this.getCenter(), this.getZoom(), bearing, this.getPitch());\n },\n\n /**\n * Sets a map angle\n *\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setPitch: function(pitch) {\n this.setView(this.getCenter(), this.getZoom(), this.getBearing(), pitch);\n },\n\n /**\n * Get the current view geographical point\n * @returns {LatLng}\n */\n getCenter: function() { return this.transform.center; },\n\n /**\n * Get the current zoom\n * @returns {number}\n */\n getZoom: function() { return this.transform.zoom; },\n\n /**\n * Get the current bearing in degrees\n * @returns {number}\n */\n getBearing: function() { return this.transform.bearing; },\n\n /**\n * Get the current angle in degrees\n * @returns {number}\n */\n getPitch: function() { return this.transform.pitch; },\n\n /**\n * @typedef {Object} [styleOptions]\n * @param {Boolean} [styleOptions.transition=true]\n */\n\n /**\n * Adds a style class to a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n addClass: function(klass, options) {\n if (this._classes[klass]) return;\n this._classes[klass] = true;\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Removes a style class from a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n removeClass: function(klass, options) {\n if (!this._classes[klass]) return;\n delete this._classes[klass];\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Helper method to add more than one class\n *\n * @param {Array} klasses An array of class names\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n setClasses: function(klasses, options) {\n this._classes = {};\n for (var i = 0; i < klasses.length; i++) {\n this._classes[klasses[i]] = true;\n }\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Check whether a style class is active\n *\n * @param {string} klass Name of style class\n * @returns {boolean}\n */\n hasClass: function(klass) {\n return !!this._classes[klass];\n },\n\n /**\n * Return an array of the current active style classes\n *\n * @returns {boolean}\n */\n getClasses: function() {\n return Object.keys(this._classes);\n },\n\n /**\n * Detect the map's new width and height and resize it.\n *\n * @returns {Map} `this`\n */\n resize: function() {\n var width = 0, height = 0;\n\n if (this._container) {\n width = this._container.offsetWidth || 400;\n height = this._container.offsetHeight || 300;\n }\n\n this._canvas.resize(width, height);\n\n this.transform.width = width;\n this.transform.height = height;\n this.transform._constrain();\n\n this.painter.resize(width, height);\n\n return this\n .fire('movestart')\n ._move()\n .fire('resize')\n .fire('moveend');\n },\n\n /**\n * Get the map's geographical bounds\n *\n * @returns {LatLngBounds}\n */\n getBounds: function() {\n return new LatLngBounds(\n this.transform.pointLocation(new Point(0, 0)),\n this.transform.pointLocation(this.transform.size));\n },\n\n /**\n * Get pixel coordinates (relative to map container) given a geographical location\n *\n * @param {LatLng} latlng\n * @returns {Object} `x` and `y` coordinates\n */\n project: function(latlng) {\n return this.transform.locationPoint(LatLng.convert(latlng));\n },\n\n /**\n * Get geographical coordinates given pixel coordinates\n *\n * @param {Array} point [x, y] pixel coordinates\n * @returns {LatLng}\n */\n unproject: function(point) {\n return this.transform.pointLocation(Point.convert(point));\n },\n\n /**\n * Get all features at a point ([x, y])\n *\n * @param {Array} point [x, y] pixel coordinates\n * @param {Object} params\n * @param {number} [params.radius=0] Optional. Radius in pixels to search in\n * @param {string} params.layer Optional. Only return features from a given layer\n * @param {string} params.type Optional. Either `raster` or `vector`\n * @param {featuresAtCallback} callback function that returns the response\n *\n * @callback featuresAtCallback\n * @param {Object|null} err Error _If any_\n * @param {Array} features Displays a JSON array of features given the passed parameters of `featuresAt`\n *\n * @returns {Map} `this`\n */\n featuresAt: function(point, params, callback) {\n var coord = this.transform.pointCoordinate(Point.convert(point));\n this.style.featuresAt(coord, params, callback);\n return this;\n },\n\n /**\n * Replaces the map's style object\n *\n * @param {Object} style A style object formatted as JSON\n * @returns {Map} `this`\n */\n setStyle: function(style) {\n if (this.style) {\n this.style\n .off('load', this._onStyleLoad)\n .off('error', this._forwardStyleEvent)\n .off('change', this._onStyleChange)\n .off('source.add', this._onSourceAdd)\n .off('source.remove', this._onSourceRemove)\n .off('source.load', this._onSourceUpdate)\n .off('source.error', this._forwardSourceEvent)\n .off('source.change', this._onSourceUpdate)\n .off('layer.add', this._forwardLayerEvent)\n .off('layer.remove', this._forwardLayerEvent)\n .off('tile.add', this._forwardTileEvent)\n .off('tile.remove', this._forwardTileEvent)\n .off('tile.load', this.update)\n .off('tile.error', this._forwardTileEvent)\n ._remove();\n\n this.off('rotate', this.style._redoPlacement);\n this.off('pitch', this.style._redoPlacement);\n }\n\n if (!style) {\n this.style = null;\n return this;\n } else if (style instanceof Style) {\n this.style = style;\n } else {\n this.style = new Style(style, this.animationLoop);\n }\n\n this.style\n .on('load', this._onStyleLoad)\n .on('error', this._forwardStyleEvent)\n .on('change', this._onStyleChange)\n .on('source.add', this._onSourceAdd)\n .on('source.remove', this._onSourceRemove)\n .on('source.load', this._onSourceUpdate)\n .on('source.error', this._forwardSourceEvent)\n .on('source.change', this._onSourceUpdate)\n .on('layer.add', this._forwardLayerEvent)\n .on('layer.remove', this._forwardLayerEvent)\n .on('tile.add', this._forwardTileEvent)\n .on('tile.remove', this._forwardTileEvent)\n .on('tile.load', this.update)\n .on('tile.error', this._forwardTileEvent);\n\n this.on('rotate', this.style._redoPlacement);\n this.on('pitch', this.style._redoPlacement);\n\n return this;\n },\n\n /**\n * Add a source to the map style.\n *\n * @param {string} id ID of the source. Must not be used by any existing source.\n * @param {Object} source source specification, following the\n * [Mapbox GL Style Reference](https://www.mapbox.com/mapbox-gl-style-spec/#sources)\n * @fires source.add\n * @returns {Map} `this`\n */\n addSource: function(id, source) {\n this.style.addSource(id, source);\n return this;\n },\n\n /**\n * Remove an existing source from the map style.\n *\n * @param {string} id ID of the source to remove\n * @fires source.remove\n * @returns {Map} `this`\n */\n removeSource: function(id) {\n this.style.removeSource(id);\n return this;\n },\n\n /**\n * Return the style source object with the given `id`.\n *\n * @param {string} id source ID\n * @returns {Object}\n */\n getSource: function(id) {\n return this.style.getSource(id);\n },\n\n /**\n * Add a layer to the map style. The layer will be inserted before the layer with\n * ID `before`, or appended if `before` is omitted.\n * @param {Layer} layer\n * @param {string=} before ID of an existing layer to insert before\n * @fires layer.add\n * @returns {Map} `this`\n */\n addLayer: function(layer, before) {\n this.style.addLayer(layer, before);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Remove the layer with the given `id` from the map. Any layers which refer to the\n * specified layer via a `ref` property are also removed.\n *\n * @param {string} id\n * @fires layer.remove\n * @returns {Map} this\n */\n removeLayer: function(id) {\n this.style.removeLayer(id);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Set the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {Array} filter filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n * @returns {Map} `this`\n */\n setFilter: function(layer, filter) {\n this.style.setFilter(layer, filter);\n return this;\n },\n\n /**\n * Get the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @returns {Array} filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n */\n getFilter: function(layer) {\n return this.style.getFilter(layer);\n },\n\n /**\n * Set the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {*} value value for the paint propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @param {string=} klass optional class specifier for the property\n * @returns {Map} `this`\n */\n setPaintProperty: function(layer, name, value, klass) {\n this.style.setPaintProperty(layer, name, value, klass);\n this.style._cascade(this._classes);\n this.update(true);\n return this;\n },\n\n /**\n * Get the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the paint propery\n */\n getPaintProperty: function(layer, name, klass) {\n return this.style.getPaintProperty(layer, name, klass);\n },\n\n /**\n * Set the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {*} value value for the layout propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @returns {Map} `this`\n */\n setLayoutProperty: function(layer, name, value) {\n this.style.setLayoutProperty(layer, name, value);\n return this;\n },\n\n /**\n * Get the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the layout propery\n */\n getLayoutProperty: function(layer, name) {\n return this.style.getLayoutProperty(layer, name);\n },\n\n /**\n * Get the Map's container as an HTML element\n * @returns {HTMLElement} container\n */\n getContainer: function() {\n return this._container;\n },\n\n /**\n * Get the Map's canvas as an HTML canvas\n * @returns {HTMLElement} canvas\n */\n getCanvas: function() {\n return this._canvas.getElement();\n },\n\n _move: function(zoom, rotate, pitch) {\n\n this.update(zoom).fire('move');\n\n if (zoom) this.fire('zoom');\n if (rotate) this.fire('rotate');\n if (pitch) this.fire('pitch');\n\n return this;\n },\n\n // map setup code\n _setupContainer: function() {\n var id = this.options.container;\n var container = this._container = typeof id === 'string' ? document.getElementById(id) : id;\n if (container) container.classList.add('mapboxgl-map');\n this._canvas = new Canvas(this, container);\n },\n\n _setupControlPos: function() {\n var corners = this._controlCorners = {};\n var prefix = 'mapboxgl-ctrl-';\n var container = this.getContainer();\n\n function createCorner(pos) {\n var className = prefix + pos;\n corners[pos] = DOM.create('div', className, container);\n }\n\n if (container && typeof document === 'object') {\n createCorner('top-left');\n createCorner('top-right');\n createCorner('bottom-left');\n createCorner('bottom-right');\n }\n },\n\n _setupPainter: function() {\n var gl = this._canvas.getWebGLContext(this.options.failIfMajorPerformanceCaveat);\n\n if (!gl) {\n console.error('Failed to initialize WebGL');\n return;\n }\n\n this.painter = new GLPainter(gl, this.transform);\n },\n\n _contextLost: function(event) {\n event.preventDefault();\n if (this._frameId) {\n browser.cancelFrame(this._frameId);\n }\n },\n\n _contextRestored: function() {\n this._setupPainter();\n this.resize();\n this.update();\n },\n\n /**\n * Is this map fully loaded? If the style isn't loaded\n * or it has a change to the sources or style that isn't\n * propagated to its style, return false.\n *\n * @returns {boolean} whether the map is loaded\n */\n loaded: function() {\n if (this._styleDirty || this._sourcesDirty)\n return false;\n if (this.style && !this.style.loaded())\n return false;\n return true;\n },\n\n /**\n * Update this map's style and re-render the map.\n *\n * @param {Object} updateStyle new style\n * @returns {Map} this\n */\n update: function(updateStyle) {\n if (!this.style) return this;\n\n this._styleDirty = this._styleDirty || updateStyle;\n this._sourcesDirty = true;\n\n this._rerender();\n\n return this;\n },\n\n /**\n * Call when a (re-)render of the map is required, e.g. when the\n * user panned or zoomed,f or new data is available.\n * @returns {Map} this\n */\n render: function() {\n if (this.style && this._styleDirty) {\n this._styleDirty = false;\n this.style._recalculate(this.transform.zoom);\n }\n\n if (this.style && this._sourcesDirty && !this._sourcesDirtyTimeout) {\n this._sourcesDirty = false;\n this._sourcesDirtyTimeout = setTimeout(function() {\n this._sourcesDirtyTimeout = null;\n }.bind(this), 50);\n this.style._updateSources(this.transform);\n }\n\n this.painter.render(this.style, {\n debug: this.debug,\n vertices: this.vertices,\n rotating: this.rotating,\n zooming: this.zooming\n });\n\n this.fire('render');\n\n if (this.loaded() && !this._loaded) {\n this._loaded = true;\n this.fire('load');\n }\n\n this._frameId = null;\n\n if (!this.animationLoop.stopped()) {\n this._styleDirty = true;\n }\n\n if (this._sourcesDirty || this._repaint || !this.animationLoop.stopped()) {\n this._rerender();\n }\n\n return this;\n },\n\n /**\n * Destroys the map's underlying resources, including web workers.\n * @returns {Map} this\n */\n remove: function() {\n if (this._hash) this._hash.remove();\n browser.cancelFrame(this._frameId);\n clearTimeout(this._sourcesDirtyTimeout);\n this.setStyle(null);\n return this;\n },\n\n _rerender: function() {\n if (this.style && !this._frameId) {\n this._frameId = browser.frame(this.render);\n }\n },\n\n _forwardStyleEvent: function(e) {\n this.fire('style.' + e.type, util.extend({style: e.target}, e));\n },\n\n _forwardSourceEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardLayerEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardTileEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _onStyleLoad: function(e) {\n this.style._cascade(this._classes, {transition: false});\n this._forwardStyleEvent(e);\n },\n\n _onStyleChange: function(e) {\n this.update(true);\n this._forwardStyleEvent(e);\n },\n\n _onSourceAdd: function(e) {\n var source = e.source;\n if (source.onAdd)\n source.onAdd(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceRemove: function(e) {\n var source = e.source;\n if (source.onRemove)\n source.onRemove(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceUpdate: function(e) {\n this.update();\n this._forwardSourceEvent(e);\n }\n}","path":"js/ui/map.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/map.js#L565-L567"},"params":[{"title":"param","description":"ID of a layer","type":{"type":"NameExpression","name":"string"},"name":"layer"},{"title":"param","description":"name of a layout property","type":{"type":"NameExpression","name":"string"},"name":"name"},{"title":"param","description":"optional class specifier for the property","type":{"type":"OptionalType","expression":{"type":"NameExpression","name":"string"}},"name":"klass"}],"returns":[{"title":"returns","description":"value for the layout propery","type":{"type":"AllLiteral"}}],"name":"getLayoutProperty","memberof":"Map","scope":"instance","members":{"instance":[],"static":[]},"path":["Map","getLayoutProperty"]},{"description":"Get the Map's container as an HTML element","tags":[{"title":"returns","description":"container","type":{"type":"NameExpression","name":"HTMLElement"}},{"title":"name","name":"getContainer"},{"title":"memberof","description":"Map"},{"title":"instance"}],"context":{"loc":{"start":{"line":573,"column":4},"end":{"line":575,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/map.js","code":"{\n\n options: {\n center: [0, 0],\n zoom: 0,\n bearing: 0,\n pitch: 0,\n\n minZoom: 0,\n maxZoom: 20,\n\n interactive: true,\n hash: false,\n\n attributionControl: true,\n\n failIfMajorPerformanceCaveat: false\n },\n\n addControl: function(control) {\n control.addTo(this);\n return this;\n },\n\n /**\n * Sets a map position\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @param {number} zoom Map zoom level\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setView: function(center, zoom, bearing, pitch) {\n this.stop();\n\n var tr = this.transform,\n zoomChanged = tr.zoom !== +zoom,\n bearingChanged = tr.bearing !== +bearing,\n pitchChanged = tr.pitch !== +pitch;\n\n tr.center = LatLng.convert(center);\n tr.zoom = +zoom;\n tr.bearing = +bearing;\n tr.pitch = +pitch;\n\n return this\n .fire('movestart')\n ._move(zoomChanged, bearingChanged, pitchChanged)\n .fire('moveend');\n },\n\n /**\n * Sets a map location\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setCenter: function(center) {\n this.setView(center, this.getZoom(), this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map zoom\n *\n * @param {number} zoom Map zoom level\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setZoom: function(zoom) {\n this.setView(this.getCenter(), zoom, this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map rotation\n *\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setBearing: function(bearing) {\n this.setView(this.getCenter(), this.getZoom(), bearing, this.getPitch());\n },\n\n /**\n * Sets a map angle\n *\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setPitch: function(pitch) {\n this.setView(this.getCenter(), this.getZoom(), this.getBearing(), pitch);\n },\n\n /**\n * Get the current view geographical point\n * @returns {LatLng}\n */\n getCenter: function() { return this.transform.center; },\n\n /**\n * Get the current zoom\n * @returns {number}\n */\n getZoom: function() { return this.transform.zoom; },\n\n /**\n * Get the current bearing in degrees\n * @returns {number}\n */\n getBearing: function() { return this.transform.bearing; },\n\n /**\n * Get the current angle in degrees\n * @returns {number}\n */\n getPitch: function() { return this.transform.pitch; },\n\n /**\n * @typedef {Object} [styleOptions]\n * @param {Boolean} [styleOptions.transition=true]\n */\n\n /**\n * Adds a style class to a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n addClass: function(klass, options) {\n if (this._classes[klass]) return;\n this._classes[klass] = true;\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Removes a style class from a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n removeClass: function(klass, options) {\n if (!this._classes[klass]) return;\n delete this._classes[klass];\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Helper method to add more than one class\n *\n * @param {Array} klasses An array of class names\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n setClasses: function(klasses, options) {\n this._classes = {};\n for (var i = 0; i < klasses.length; i++) {\n this._classes[klasses[i]] = true;\n }\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Check whether a style class is active\n *\n * @param {string} klass Name of style class\n * @returns {boolean}\n */\n hasClass: function(klass) {\n return !!this._classes[klass];\n },\n\n /**\n * Return an array of the current active style classes\n *\n * @returns {boolean}\n */\n getClasses: function() {\n return Object.keys(this._classes);\n },\n\n /**\n * Detect the map's new width and height and resize it.\n *\n * @returns {Map} `this`\n */\n resize: function() {\n var width = 0, height = 0;\n\n if (this._container) {\n width = this._container.offsetWidth || 400;\n height = this._container.offsetHeight || 300;\n }\n\n this._canvas.resize(width, height);\n\n this.transform.width = width;\n this.transform.height = height;\n this.transform._constrain();\n\n this.painter.resize(width, height);\n\n return this\n .fire('movestart')\n ._move()\n .fire('resize')\n .fire('moveend');\n },\n\n /**\n * Get the map's geographical bounds\n *\n * @returns {LatLngBounds}\n */\n getBounds: function() {\n return new LatLngBounds(\n this.transform.pointLocation(new Point(0, 0)),\n this.transform.pointLocation(this.transform.size));\n },\n\n /**\n * Get pixel coordinates (relative to map container) given a geographical location\n *\n * @param {LatLng} latlng\n * @returns {Object} `x` and `y` coordinates\n */\n project: function(latlng) {\n return this.transform.locationPoint(LatLng.convert(latlng));\n },\n\n /**\n * Get geographical coordinates given pixel coordinates\n *\n * @param {Array} point [x, y] pixel coordinates\n * @returns {LatLng}\n */\n unproject: function(point) {\n return this.transform.pointLocation(Point.convert(point));\n },\n\n /**\n * Get all features at a point ([x, y])\n *\n * @param {Array} point [x, y] pixel coordinates\n * @param {Object} params\n * @param {number} [params.radius=0] Optional. Radius in pixels to search in\n * @param {string} params.layer Optional. Only return features from a given layer\n * @param {string} params.type Optional. Either `raster` or `vector`\n * @param {featuresAtCallback} callback function that returns the response\n *\n * @callback featuresAtCallback\n * @param {Object|null} err Error _If any_\n * @param {Array} features Displays a JSON array of features given the passed parameters of `featuresAt`\n *\n * @returns {Map} `this`\n */\n featuresAt: function(point, params, callback) {\n var coord = this.transform.pointCoordinate(Point.convert(point));\n this.style.featuresAt(coord, params, callback);\n return this;\n },\n\n /**\n * Replaces the map's style object\n *\n * @param {Object} style A style object formatted as JSON\n * @returns {Map} `this`\n */\n setStyle: function(style) {\n if (this.style) {\n this.style\n .off('load', this._onStyleLoad)\n .off('error', this._forwardStyleEvent)\n .off('change', this._onStyleChange)\n .off('source.add', this._onSourceAdd)\n .off('source.remove', this._onSourceRemove)\n .off('source.load', this._onSourceUpdate)\n .off('source.error', this._forwardSourceEvent)\n .off('source.change', this._onSourceUpdate)\n .off('layer.add', this._forwardLayerEvent)\n .off('layer.remove', this._forwardLayerEvent)\n .off('tile.add', this._forwardTileEvent)\n .off('tile.remove', this._forwardTileEvent)\n .off('tile.load', this.update)\n .off('tile.error', this._forwardTileEvent)\n ._remove();\n\n this.off('rotate', this.style._redoPlacement);\n this.off('pitch', this.style._redoPlacement);\n }\n\n if (!style) {\n this.style = null;\n return this;\n } else if (style instanceof Style) {\n this.style = style;\n } else {\n this.style = new Style(style, this.animationLoop);\n }\n\n this.style\n .on('load', this._onStyleLoad)\n .on('error', this._forwardStyleEvent)\n .on('change', this._onStyleChange)\n .on('source.add', this._onSourceAdd)\n .on('source.remove', this._onSourceRemove)\n .on('source.load', this._onSourceUpdate)\n .on('source.error', this._forwardSourceEvent)\n .on('source.change', this._onSourceUpdate)\n .on('layer.add', this._forwardLayerEvent)\n .on('layer.remove', this._forwardLayerEvent)\n .on('tile.add', this._forwardTileEvent)\n .on('tile.remove', this._forwardTileEvent)\n .on('tile.load', this.update)\n .on('tile.error', this._forwardTileEvent);\n\n this.on('rotate', this.style._redoPlacement);\n this.on('pitch', this.style._redoPlacement);\n\n return this;\n },\n\n /**\n * Add a source to the map style.\n *\n * @param {string} id ID of the source. Must not be used by any existing source.\n * @param {Object} source source specification, following the\n * [Mapbox GL Style Reference](https://www.mapbox.com/mapbox-gl-style-spec/#sources)\n * @fires source.add\n * @returns {Map} `this`\n */\n addSource: function(id, source) {\n this.style.addSource(id, source);\n return this;\n },\n\n /**\n * Remove an existing source from the map style.\n *\n * @param {string} id ID of the source to remove\n * @fires source.remove\n * @returns {Map} `this`\n */\n removeSource: function(id) {\n this.style.removeSource(id);\n return this;\n },\n\n /**\n * Return the style source object with the given `id`.\n *\n * @param {string} id source ID\n * @returns {Object}\n */\n getSource: function(id) {\n return this.style.getSource(id);\n },\n\n /**\n * Add a layer to the map style. The layer will be inserted before the layer with\n * ID `before`, or appended if `before` is omitted.\n * @param {Layer} layer\n * @param {string=} before ID of an existing layer to insert before\n * @fires layer.add\n * @returns {Map} `this`\n */\n addLayer: function(layer, before) {\n this.style.addLayer(layer, before);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Remove the layer with the given `id` from the map. Any layers which refer to the\n * specified layer via a `ref` property are also removed.\n *\n * @param {string} id\n * @fires layer.remove\n * @returns {Map} this\n */\n removeLayer: function(id) {\n this.style.removeLayer(id);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Set the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {Array} filter filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n * @returns {Map} `this`\n */\n setFilter: function(layer, filter) {\n this.style.setFilter(layer, filter);\n return this;\n },\n\n /**\n * Get the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @returns {Array} filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n */\n getFilter: function(layer) {\n return this.style.getFilter(layer);\n },\n\n /**\n * Set the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {*} value value for the paint propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @param {string=} klass optional class specifier for the property\n * @returns {Map} `this`\n */\n setPaintProperty: function(layer, name, value, klass) {\n this.style.setPaintProperty(layer, name, value, klass);\n this.style._cascade(this._classes);\n this.update(true);\n return this;\n },\n\n /**\n * Get the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the paint propery\n */\n getPaintProperty: function(layer, name, klass) {\n return this.style.getPaintProperty(layer, name, klass);\n },\n\n /**\n * Set the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {*} value value for the layout propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @returns {Map} `this`\n */\n setLayoutProperty: function(layer, name, value) {\n this.style.setLayoutProperty(layer, name, value);\n return this;\n },\n\n /**\n * Get the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the layout propery\n */\n getLayoutProperty: function(layer, name) {\n return this.style.getLayoutProperty(layer, name);\n },\n\n /**\n * Get the Map's container as an HTML element\n * @returns {HTMLElement} container\n */\n getContainer: function() {\n return this._container;\n },\n\n /**\n * Get the Map's canvas as an HTML canvas\n * @returns {HTMLElement} canvas\n */\n getCanvas: function() {\n return this._canvas.getElement();\n },\n\n _move: function(zoom, rotate, pitch) {\n\n this.update(zoom).fire('move');\n\n if (zoom) this.fire('zoom');\n if (rotate) this.fire('rotate');\n if (pitch) this.fire('pitch');\n\n return this;\n },\n\n // map setup code\n _setupContainer: function() {\n var id = this.options.container;\n var container = this._container = typeof id === 'string' ? document.getElementById(id) : id;\n if (container) container.classList.add('mapboxgl-map');\n this._canvas = new Canvas(this, container);\n },\n\n _setupControlPos: function() {\n var corners = this._controlCorners = {};\n var prefix = 'mapboxgl-ctrl-';\n var container = this.getContainer();\n\n function createCorner(pos) {\n var className = prefix + pos;\n corners[pos] = DOM.create('div', className, container);\n }\n\n if (container && typeof document === 'object') {\n createCorner('top-left');\n createCorner('top-right');\n createCorner('bottom-left');\n createCorner('bottom-right');\n }\n },\n\n _setupPainter: function() {\n var gl = this._canvas.getWebGLContext(this.options.failIfMajorPerformanceCaveat);\n\n if (!gl) {\n console.error('Failed to initialize WebGL');\n return;\n }\n\n this.painter = new GLPainter(gl, this.transform);\n },\n\n _contextLost: function(event) {\n event.preventDefault();\n if (this._frameId) {\n browser.cancelFrame(this._frameId);\n }\n },\n\n _contextRestored: function() {\n this._setupPainter();\n this.resize();\n this.update();\n },\n\n /**\n * Is this map fully loaded? If the style isn't loaded\n * or it has a change to the sources or style that isn't\n * propagated to its style, return false.\n *\n * @returns {boolean} whether the map is loaded\n */\n loaded: function() {\n if (this._styleDirty || this._sourcesDirty)\n return false;\n if (this.style && !this.style.loaded())\n return false;\n return true;\n },\n\n /**\n * Update this map's style and re-render the map.\n *\n * @param {Object} updateStyle new style\n * @returns {Map} this\n */\n update: function(updateStyle) {\n if (!this.style) return this;\n\n this._styleDirty = this._styleDirty || updateStyle;\n this._sourcesDirty = true;\n\n this._rerender();\n\n return this;\n },\n\n /**\n * Call when a (re-)render of the map is required, e.g. when the\n * user panned or zoomed,f or new data is available.\n * @returns {Map} this\n */\n render: function() {\n if (this.style && this._styleDirty) {\n this._styleDirty = false;\n this.style._recalculate(this.transform.zoom);\n }\n\n if (this.style && this._sourcesDirty && !this._sourcesDirtyTimeout) {\n this._sourcesDirty = false;\n this._sourcesDirtyTimeout = setTimeout(function() {\n this._sourcesDirtyTimeout = null;\n }.bind(this), 50);\n this.style._updateSources(this.transform);\n }\n\n this.painter.render(this.style, {\n debug: this.debug,\n vertices: this.vertices,\n rotating: this.rotating,\n zooming: this.zooming\n });\n\n this.fire('render');\n\n if (this.loaded() && !this._loaded) {\n this._loaded = true;\n this.fire('load');\n }\n\n this._frameId = null;\n\n if (!this.animationLoop.stopped()) {\n this._styleDirty = true;\n }\n\n if (this._sourcesDirty || this._repaint || !this.animationLoop.stopped()) {\n this._rerender();\n }\n\n return this;\n },\n\n /**\n * Destroys the map's underlying resources, including web workers.\n * @returns {Map} this\n */\n remove: function() {\n if (this._hash) this._hash.remove();\n browser.cancelFrame(this._frameId);\n clearTimeout(this._sourcesDirtyTimeout);\n this.setStyle(null);\n return this;\n },\n\n _rerender: function() {\n if (this.style && !this._frameId) {\n this._frameId = browser.frame(this.render);\n }\n },\n\n _forwardStyleEvent: function(e) {\n this.fire('style.' + e.type, util.extend({style: e.target}, e));\n },\n\n _forwardSourceEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardLayerEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardTileEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _onStyleLoad: function(e) {\n this.style._cascade(this._classes, {transition: false});\n this._forwardStyleEvent(e);\n },\n\n _onStyleChange: function(e) {\n this.update(true);\n this._forwardStyleEvent(e);\n },\n\n _onSourceAdd: function(e) {\n var source = e.source;\n if (source.onAdd)\n source.onAdd(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceRemove: function(e) {\n var source = e.source;\n if (source.onRemove)\n source.onRemove(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceUpdate: function(e) {\n this.update();\n this._forwardSourceEvent(e);\n }\n}","path":"js/ui/map.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/map.js#L573-L575"},"returns":[{"title":"returns","description":"container","type":{"type":"NameExpression","name":"HTMLElement"}}],"name":"getContainer","memberof":"Map","scope":"instance","members":{"instance":[],"static":[]},"path":["Map","getContainer"]},{"description":"Get the Map's canvas as an HTML canvas","tags":[{"title":"returns","description":"canvas","type":{"type":"NameExpression","name":"HTMLElement"}},{"title":"name","name":"getCanvas"},{"title":"memberof","description":"Map"},{"title":"instance"}],"context":{"loc":{"start":{"line":581,"column":4},"end":{"line":583,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/map.js","code":"{\n\n options: {\n center: [0, 0],\n zoom: 0,\n bearing: 0,\n pitch: 0,\n\n minZoom: 0,\n maxZoom: 20,\n\n interactive: true,\n hash: false,\n\n attributionControl: true,\n\n failIfMajorPerformanceCaveat: false\n },\n\n addControl: function(control) {\n control.addTo(this);\n return this;\n },\n\n /**\n * Sets a map position\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @param {number} zoom Map zoom level\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setView: function(center, zoom, bearing, pitch) {\n this.stop();\n\n var tr = this.transform,\n zoomChanged = tr.zoom !== +zoom,\n bearingChanged = tr.bearing !== +bearing,\n pitchChanged = tr.pitch !== +pitch;\n\n tr.center = LatLng.convert(center);\n tr.zoom = +zoom;\n tr.bearing = +bearing;\n tr.pitch = +pitch;\n\n return this\n .fire('movestart')\n ._move(zoomChanged, bearingChanged, pitchChanged)\n .fire('moveend');\n },\n\n /**\n * Sets a map location\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setCenter: function(center) {\n this.setView(center, this.getZoom(), this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map zoom\n *\n * @param {number} zoom Map zoom level\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setZoom: function(zoom) {\n this.setView(this.getCenter(), zoom, this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map rotation\n *\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setBearing: function(bearing) {\n this.setView(this.getCenter(), this.getZoom(), bearing, this.getPitch());\n },\n\n /**\n * Sets a map angle\n *\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setPitch: function(pitch) {\n this.setView(this.getCenter(), this.getZoom(), this.getBearing(), pitch);\n },\n\n /**\n * Get the current view geographical point\n * @returns {LatLng}\n */\n getCenter: function() { return this.transform.center; },\n\n /**\n * Get the current zoom\n * @returns {number}\n */\n getZoom: function() { return this.transform.zoom; },\n\n /**\n * Get the current bearing in degrees\n * @returns {number}\n */\n getBearing: function() { return this.transform.bearing; },\n\n /**\n * Get the current angle in degrees\n * @returns {number}\n */\n getPitch: function() { return this.transform.pitch; },\n\n /**\n * @typedef {Object} [styleOptions]\n * @param {Boolean} [styleOptions.transition=true]\n */\n\n /**\n * Adds a style class to a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n addClass: function(klass, options) {\n if (this._classes[klass]) return;\n this._classes[klass] = true;\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Removes a style class from a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n removeClass: function(klass, options) {\n if (!this._classes[klass]) return;\n delete this._classes[klass];\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Helper method to add more than one class\n *\n * @param {Array} klasses An array of class names\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n setClasses: function(klasses, options) {\n this._classes = {};\n for (var i = 0; i < klasses.length; i++) {\n this._classes[klasses[i]] = true;\n }\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Check whether a style class is active\n *\n * @param {string} klass Name of style class\n * @returns {boolean}\n */\n hasClass: function(klass) {\n return !!this._classes[klass];\n },\n\n /**\n * Return an array of the current active style classes\n *\n * @returns {boolean}\n */\n getClasses: function() {\n return Object.keys(this._classes);\n },\n\n /**\n * Detect the map's new width and height and resize it.\n *\n * @returns {Map} `this`\n */\n resize: function() {\n var width = 0, height = 0;\n\n if (this._container) {\n width = this._container.offsetWidth || 400;\n height = this._container.offsetHeight || 300;\n }\n\n this._canvas.resize(width, height);\n\n this.transform.width = width;\n this.transform.height = height;\n this.transform._constrain();\n\n this.painter.resize(width, height);\n\n return this\n .fire('movestart')\n ._move()\n .fire('resize')\n .fire('moveend');\n },\n\n /**\n * Get the map's geographical bounds\n *\n * @returns {LatLngBounds}\n */\n getBounds: function() {\n return new LatLngBounds(\n this.transform.pointLocation(new Point(0, 0)),\n this.transform.pointLocation(this.transform.size));\n },\n\n /**\n * Get pixel coordinates (relative to map container) given a geographical location\n *\n * @param {LatLng} latlng\n * @returns {Object} `x` and `y` coordinates\n */\n project: function(latlng) {\n return this.transform.locationPoint(LatLng.convert(latlng));\n },\n\n /**\n * Get geographical coordinates given pixel coordinates\n *\n * @param {Array} point [x, y] pixel coordinates\n * @returns {LatLng}\n */\n unproject: function(point) {\n return this.transform.pointLocation(Point.convert(point));\n },\n\n /**\n * Get all features at a point ([x, y])\n *\n * @param {Array} point [x, y] pixel coordinates\n * @param {Object} params\n * @param {number} [params.radius=0] Optional. Radius in pixels to search in\n * @param {string} params.layer Optional. Only return features from a given layer\n * @param {string} params.type Optional. Either `raster` or `vector`\n * @param {featuresAtCallback} callback function that returns the response\n *\n * @callback featuresAtCallback\n * @param {Object|null} err Error _If any_\n * @param {Array} features Displays a JSON array of features given the passed parameters of `featuresAt`\n *\n * @returns {Map} `this`\n */\n featuresAt: function(point, params, callback) {\n var coord = this.transform.pointCoordinate(Point.convert(point));\n this.style.featuresAt(coord, params, callback);\n return this;\n },\n\n /**\n * Replaces the map's style object\n *\n * @param {Object} style A style object formatted as JSON\n * @returns {Map} `this`\n */\n setStyle: function(style) {\n if (this.style) {\n this.style\n .off('load', this._onStyleLoad)\n .off('error', this._forwardStyleEvent)\n .off('change', this._onStyleChange)\n .off('source.add', this._onSourceAdd)\n .off('source.remove', this._onSourceRemove)\n .off('source.load', this._onSourceUpdate)\n .off('source.error', this._forwardSourceEvent)\n .off('source.change', this._onSourceUpdate)\n .off('layer.add', this._forwardLayerEvent)\n .off('layer.remove', this._forwardLayerEvent)\n .off('tile.add', this._forwardTileEvent)\n .off('tile.remove', this._forwardTileEvent)\n .off('tile.load', this.update)\n .off('tile.error', this._forwardTileEvent)\n ._remove();\n\n this.off('rotate', this.style._redoPlacement);\n this.off('pitch', this.style._redoPlacement);\n }\n\n if (!style) {\n this.style = null;\n return this;\n } else if (style instanceof Style) {\n this.style = style;\n } else {\n this.style = new Style(style, this.animationLoop);\n }\n\n this.style\n .on('load', this._onStyleLoad)\n .on('error', this._forwardStyleEvent)\n .on('change', this._onStyleChange)\n .on('source.add', this._onSourceAdd)\n .on('source.remove', this._onSourceRemove)\n .on('source.load', this._onSourceUpdate)\n .on('source.error', this._forwardSourceEvent)\n .on('source.change', this._onSourceUpdate)\n .on('layer.add', this._forwardLayerEvent)\n .on('layer.remove', this._forwardLayerEvent)\n .on('tile.add', this._forwardTileEvent)\n .on('tile.remove', this._forwardTileEvent)\n .on('tile.load', this.update)\n .on('tile.error', this._forwardTileEvent);\n\n this.on('rotate', this.style._redoPlacement);\n this.on('pitch', this.style._redoPlacement);\n\n return this;\n },\n\n /**\n * Add a source to the map style.\n *\n * @param {string} id ID of the source. Must not be used by any existing source.\n * @param {Object} source source specification, following the\n * [Mapbox GL Style Reference](https://www.mapbox.com/mapbox-gl-style-spec/#sources)\n * @fires source.add\n * @returns {Map} `this`\n */\n addSource: function(id, source) {\n this.style.addSource(id, source);\n return this;\n },\n\n /**\n * Remove an existing source from the map style.\n *\n * @param {string} id ID of the source to remove\n * @fires source.remove\n * @returns {Map} `this`\n */\n removeSource: function(id) {\n this.style.removeSource(id);\n return this;\n },\n\n /**\n * Return the style source object with the given `id`.\n *\n * @param {string} id source ID\n * @returns {Object}\n */\n getSource: function(id) {\n return this.style.getSource(id);\n },\n\n /**\n * Add a layer to the map style. The layer will be inserted before the layer with\n * ID `before`, or appended if `before` is omitted.\n * @param {Layer} layer\n * @param {string=} before ID of an existing layer to insert before\n * @fires layer.add\n * @returns {Map} `this`\n */\n addLayer: function(layer, before) {\n this.style.addLayer(layer, before);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Remove the layer with the given `id` from the map. Any layers which refer to the\n * specified layer via a `ref` property are also removed.\n *\n * @param {string} id\n * @fires layer.remove\n * @returns {Map} this\n */\n removeLayer: function(id) {\n this.style.removeLayer(id);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Set the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {Array} filter filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n * @returns {Map} `this`\n */\n setFilter: function(layer, filter) {\n this.style.setFilter(layer, filter);\n return this;\n },\n\n /**\n * Get the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @returns {Array} filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n */\n getFilter: function(layer) {\n return this.style.getFilter(layer);\n },\n\n /**\n * Set the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {*} value value for the paint propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @param {string=} klass optional class specifier for the property\n * @returns {Map} `this`\n */\n setPaintProperty: function(layer, name, value, klass) {\n this.style.setPaintProperty(layer, name, value, klass);\n this.style._cascade(this._classes);\n this.update(true);\n return this;\n },\n\n /**\n * Get the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the paint propery\n */\n getPaintProperty: function(layer, name, klass) {\n return this.style.getPaintProperty(layer, name, klass);\n },\n\n /**\n * Set the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {*} value value for the layout propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @returns {Map} `this`\n */\n setLayoutProperty: function(layer, name, value) {\n this.style.setLayoutProperty(layer, name, value);\n return this;\n },\n\n /**\n * Get the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the layout propery\n */\n getLayoutProperty: function(layer, name) {\n return this.style.getLayoutProperty(layer, name);\n },\n\n /**\n * Get the Map's container as an HTML element\n * @returns {HTMLElement} container\n */\n getContainer: function() {\n return this._container;\n },\n\n /**\n * Get the Map's canvas as an HTML canvas\n * @returns {HTMLElement} canvas\n */\n getCanvas: function() {\n return this._canvas.getElement();\n },\n\n _move: function(zoom, rotate, pitch) {\n\n this.update(zoom).fire('move');\n\n if (zoom) this.fire('zoom');\n if (rotate) this.fire('rotate');\n if (pitch) this.fire('pitch');\n\n return this;\n },\n\n // map setup code\n _setupContainer: function() {\n var id = this.options.container;\n var container = this._container = typeof id === 'string' ? document.getElementById(id) : id;\n if (container) container.classList.add('mapboxgl-map');\n this._canvas = new Canvas(this, container);\n },\n\n _setupControlPos: function() {\n var corners = this._controlCorners = {};\n var prefix = 'mapboxgl-ctrl-';\n var container = this.getContainer();\n\n function createCorner(pos) {\n var className = prefix + pos;\n corners[pos] = DOM.create('div', className, container);\n }\n\n if (container && typeof document === 'object') {\n createCorner('top-left');\n createCorner('top-right');\n createCorner('bottom-left');\n createCorner('bottom-right');\n }\n },\n\n _setupPainter: function() {\n var gl = this._canvas.getWebGLContext(this.options.failIfMajorPerformanceCaveat);\n\n if (!gl) {\n console.error('Failed to initialize WebGL');\n return;\n }\n\n this.painter = new GLPainter(gl, this.transform);\n },\n\n _contextLost: function(event) {\n event.preventDefault();\n if (this._frameId) {\n browser.cancelFrame(this._frameId);\n }\n },\n\n _contextRestored: function() {\n this._setupPainter();\n this.resize();\n this.update();\n },\n\n /**\n * Is this map fully loaded? If the style isn't loaded\n * or it has a change to the sources or style that isn't\n * propagated to its style, return false.\n *\n * @returns {boolean} whether the map is loaded\n */\n loaded: function() {\n if (this._styleDirty || this._sourcesDirty)\n return false;\n if (this.style && !this.style.loaded())\n return false;\n return true;\n },\n\n /**\n * Update this map's style and re-render the map.\n *\n * @param {Object} updateStyle new style\n * @returns {Map} this\n */\n update: function(updateStyle) {\n if (!this.style) return this;\n\n this._styleDirty = this._styleDirty || updateStyle;\n this._sourcesDirty = true;\n\n this._rerender();\n\n return this;\n },\n\n /**\n * Call when a (re-)render of the map is required, e.g. when the\n * user panned or zoomed,f or new data is available.\n * @returns {Map} this\n */\n render: function() {\n if (this.style && this._styleDirty) {\n this._styleDirty = false;\n this.style._recalculate(this.transform.zoom);\n }\n\n if (this.style && this._sourcesDirty && !this._sourcesDirtyTimeout) {\n this._sourcesDirty = false;\n this._sourcesDirtyTimeout = setTimeout(function() {\n this._sourcesDirtyTimeout = null;\n }.bind(this), 50);\n this.style._updateSources(this.transform);\n }\n\n this.painter.render(this.style, {\n debug: this.debug,\n vertices: this.vertices,\n rotating: this.rotating,\n zooming: this.zooming\n });\n\n this.fire('render');\n\n if (this.loaded() && !this._loaded) {\n this._loaded = true;\n this.fire('load');\n }\n\n this._frameId = null;\n\n if (!this.animationLoop.stopped()) {\n this._styleDirty = true;\n }\n\n if (this._sourcesDirty || this._repaint || !this.animationLoop.stopped()) {\n this._rerender();\n }\n\n return this;\n },\n\n /**\n * Destroys the map's underlying resources, including web workers.\n * @returns {Map} this\n */\n remove: function() {\n if (this._hash) this._hash.remove();\n browser.cancelFrame(this._frameId);\n clearTimeout(this._sourcesDirtyTimeout);\n this.setStyle(null);\n return this;\n },\n\n _rerender: function() {\n if (this.style && !this._frameId) {\n this._frameId = browser.frame(this.render);\n }\n },\n\n _forwardStyleEvent: function(e) {\n this.fire('style.' + e.type, util.extend({style: e.target}, e));\n },\n\n _forwardSourceEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardLayerEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardTileEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _onStyleLoad: function(e) {\n this.style._cascade(this._classes, {transition: false});\n this._forwardStyleEvent(e);\n },\n\n _onStyleChange: function(e) {\n this.update(true);\n this._forwardStyleEvent(e);\n },\n\n _onSourceAdd: function(e) {\n var source = e.source;\n if (source.onAdd)\n source.onAdd(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceRemove: function(e) {\n var source = e.source;\n if (source.onRemove)\n source.onRemove(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceUpdate: function(e) {\n this.update();\n this._forwardSourceEvent(e);\n }\n}","path":"js/ui/map.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/map.js#L581-L583"},"returns":[{"title":"returns","description":"canvas","type":{"type":"NameExpression","name":"HTMLElement"}}],"name":"getCanvas","memberof":"Map","scope":"instance","members":{"instance":[],"static":[]},"path":["Map","getCanvas"]},{"description":"Sets a map angle","tags":[{"title":"param","description":"The angle at which the camera is looking at the ground","type":{"type":"NameExpression","name":"number"},"name":"pitch"},{"title":"fires","description":"movestart"},{"title":"fires","description":"moveend"},{"title":"returns","description":"`this`","type":{"type":"NameExpression","name":"Map"}},{"title":"name","name":"setPitch"},{"title":"memberof","description":"Map"},{"title":"instance"}],"context":{"loc":{"start":{"line":193,"column":4},"end":{"line":195,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/map.js","code":"{\n\n options: {\n center: [0, 0],\n zoom: 0,\n bearing: 0,\n pitch: 0,\n\n minZoom: 0,\n maxZoom: 20,\n\n interactive: true,\n hash: false,\n\n attributionControl: true,\n\n failIfMajorPerformanceCaveat: false\n },\n\n addControl: function(control) {\n control.addTo(this);\n return this;\n },\n\n /**\n * Sets a map position\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @param {number} zoom Map zoom level\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setView: function(center, zoom, bearing, pitch) {\n this.stop();\n\n var tr = this.transform,\n zoomChanged = tr.zoom !== +zoom,\n bearingChanged = tr.bearing !== +bearing,\n pitchChanged = tr.pitch !== +pitch;\n\n tr.center = LatLng.convert(center);\n tr.zoom = +zoom;\n tr.bearing = +bearing;\n tr.pitch = +pitch;\n\n return this\n .fire('movestart')\n ._move(zoomChanged, bearingChanged, pitchChanged)\n .fire('moveend');\n },\n\n /**\n * Sets a map location\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setCenter: function(center) {\n this.setView(center, this.getZoom(), this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map zoom\n *\n * @param {number} zoom Map zoom level\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setZoom: function(zoom) {\n this.setView(this.getCenter(), zoom, this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map rotation\n *\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setBearing: function(bearing) {\n this.setView(this.getCenter(), this.getZoom(), bearing, this.getPitch());\n },\n\n /**\n * Sets a map angle\n *\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setPitch: function(pitch) {\n this.setView(this.getCenter(), this.getZoom(), this.getBearing(), pitch);\n },\n\n /**\n * Get the current view geographical point\n * @returns {LatLng}\n */\n getCenter: function() { return this.transform.center; },\n\n /**\n * Get the current zoom\n * @returns {number}\n */\n getZoom: function() { return this.transform.zoom; },\n\n /**\n * Get the current bearing in degrees\n * @returns {number}\n */\n getBearing: function() { return this.transform.bearing; },\n\n /**\n * Get the current angle in degrees\n * @returns {number}\n */\n getPitch: function() { return this.transform.pitch; },\n\n /**\n * @typedef {Object} [styleOptions]\n * @param {Boolean} [styleOptions.transition=true]\n */\n\n /**\n * Adds a style class to a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n addClass: function(klass, options) {\n if (this._classes[klass]) return;\n this._classes[klass] = true;\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Removes a style class from a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n removeClass: function(klass, options) {\n if (!this._classes[klass]) return;\n delete this._classes[klass];\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Helper method to add more than one class\n *\n * @param {Array} klasses An array of class names\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n setClasses: function(klasses, options) {\n this._classes = {};\n for (var i = 0; i < klasses.length; i++) {\n this._classes[klasses[i]] = true;\n }\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Check whether a style class is active\n *\n * @param {string} klass Name of style class\n * @returns {boolean}\n */\n hasClass: function(klass) {\n return !!this._classes[klass];\n },\n\n /**\n * Return an array of the current active style classes\n *\n * @returns {boolean}\n */\n getClasses: function() {\n return Object.keys(this._classes);\n },\n\n /**\n * Detect the map's new width and height and resize it.\n *\n * @returns {Map} `this`\n */\n resize: function() {\n var width = 0, height = 0;\n\n if (this._container) {\n width = this._container.offsetWidth || 400;\n height = this._container.offsetHeight || 300;\n }\n\n this._canvas.resize(width, height);\n\n this.transform.width = width;\n this.transform.height = height;\n this.transform._constrain();\n\n this.painter.resize(width, height);\n\n return this\n .fire('movestart')\n ._move()\n .fire('resize')\n .fire('moveend');\n },\n\n /**\n * Get the map's geographical bounds\n *\n * @returns {LatLngBounds}\n */\n getBounds: function() {\n return new LatLngBounds(\n this.transform.pointLocation(new Point(0, 0)),\n this.transform.pointLocation(this.transform.size));\n },\n\n /**\n * Get pixel coordinates (relative to map container) given a geographical location\n *\n * @param {LatLng} latlng\n * @returns {Object} `x` and `y` coordinates\n */\n project: function(latlng) {\n return this.transform.locationPoint(LatLng.convert(latlng));\n },\n\n /**\n * Get geographical coordinates given pixel coordinates\n *\n * @param {Array} point [x, y] pixel coordinates\n * @returns {LatLng}\n */\n unproject: function(point) {\n return this.transform.pointLocation(Point.convert(point));\n },\n\n /**\n * Get all features at a point ([x, y])\n *\n * @param {Array} point [x, y] pixel coordinates\n * @param {Object} params\n * @param {number} [params.radius=0] Optional. Radius in pixels to search in\n * @param {string} params.layer Optional. Only return features from a given layer\n * @param {string} params.type Optional. Either `raster` or `vector`\n * @param {featuresAtCallback} callback function that returns the response\n *\n * @callback featuresAtCallback\n * @param {Object|null} err Error _If any_\n * @param {Array} features Displays a JSON array of features given the passed parameters of `featuresAt`\n *\n * @returns {Map} `this`\n */\n featuresAt: function(point, params, callback) {\n var coord = this.transform.pointCoordinate(Point.convert(point));\n this.style.featuresAt(coord, params, callback);\n return this;\n },\n\n /**\n * Replaces the map's style object\n *\n * @param {Object} style A style object formatted as JSON\n * @returns {Map} `this`\n */\n setStyle: function(style) {\n if (this.style) {\n this.style\n .off('load', this._onStyleLoad)\n .off('error', this._forwardStyleEvent)\n .off('change', this._onStyleChange)\n .off('source.add', this._onSourceAdd)\n .off('source.remove', this._onSourceRemove)\n .off('source.load', this._onSourceUpdate)\n .off('source.error', this._forwardSourceEvent)\n .off('source.change', this._onSourceUpdate)\n .off('layer.add', this._forwardLayerEvent)\n .off('layer.remove', this._forwardLayerEvent)\n .off('tile.add', this._forwardTileEvent)\n .off('tile.remove', this._forwardTileEvent)\n .off('tile.load', this.update)\n .off('tile.error', this._forwardTileEvent)\n ._remove();\n\n this.off('rotate', this.style._redoPlacement);\n this.off('pitch', this.style._redoPlacement);\n }\n\n if (!style) {\n this.style = null;\n return this;\n } else if (style instanceof Style) {\n this.style = style;\n } else {\n this.style = new Style(style, this.animationLoop);\n }\n\n this.style\n .on('load', this._onStyleLoad)\n .on('error', this._forwardStyleEvent)\n .on('change', this._onStyleChange)\n .on('source.add', this._onSourceAdd)\n .on('source.remove', this._onSourceRemove)\n .on('source.load', this._onSourceUpdate)\n .on('source.error', this._forwardSourceEvent)\n .on('source.change', this._onSourceUpdate)\n .on('layer.add', this._forwardLayerEvent)\n .on('layer.remove', this._forwardLayerEvent)\n .on('tile.add', this._forwardTileEvent)\n .on('tile.remove', this._forwardTileEvent)\n .on('tile.load', this.update)\n .on('tile.error', this._forwardTileEvent);\n\n this.on('rotate', this.style._redoPlacement);\n this.on('pitch', this.style._redoPlacement);\n\n return this;\n },\n\n /**\n * Add a source to the map style.\n *\n * @param {string} id ID of the source. Must not be used by any existing source.\n * @param {Object} source source specification, following the\n * [Mapbox GL Style Reference](https://www.mapbox.com/mapbox-gl-style-spec/#sources)\n * @fires source.add\n * @returns {Map} `this`\n */\n addSource: function(id, source) {\n this.style.addSource(id, source);\n return this;\n },\n\n /**\n * Remove an existing source from the map style.\n *\n * @param {string} id ID of the source to remove\n * @fires source.remove\n * @returns {Map} `this`\n */\n removeSource: function(id) {\n this.style.removeSource(id);\n return this;\n },\n\n /**\n * Return the style source object with the given `id`.\n *\n * @param {string} id source ID\n * @returns {Object}\n */\n getSource: function(id) {\n return this.style.getSource(id);\n },\n\n /**\n * Add a layer to the map style. The layer will be inserted before the layer with\n * ID `before`, or appended if `before` is omitted.\n * @param {Layer} layer\n * @param {string=} before ID of an existing layer to insert before\n * @fires layer.add\n * @returns {Map} `this`\n */\n addLayer: function(layer, before) {\n this.style.addLayer(layer, before);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Remove the layer with the given `id` from the map. Any layers which refer to the\n * specified layer via a `ref` property are also removed.\n *\n * @param {string} id\n * @fires layer.remove\n * @returns {Map} this\n */\n removeLayer: function(id) {\n this.style.removeLayer(id);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Set the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {Array} filter filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n * @returns {Map} `this`\n */\n setFilter: function(layer, filter) {\n this.style.setFilter(layer, filter);\n return this;\n },\n\n /**\n * Get the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @returns {Array} filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n */\n getFilter: function(layer) {\n return this.style.getFilter(layer);\n },\n\n /**\n * Set the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {*} value value for the paint propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @param {string=} klass optional class specifier for the property\n * @returns {Map} `this`\n */\n setPaintProperty: function(layer, name, value, klass) {\n this.style.setPaintProperty(layer, name, value, klass);\n this.style._cascade(this._classes);\n this.update(true);\n return this;\n },\n\n /**\n * Get the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the paint propery\n */\n getPaintProperty: function(layer, name, klass) {\n return this.style.getPaintProperty(layer, name, klass);\n },\n\n /**\n * Set the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {*} value value for the layout propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @returns {Map} `this`\n */\n setLayoutProperty: function(layer, name, value) {\n this.style.setLayoutProperty(layer, name, value);\n return this;\n },\n\n /**\n * Get the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the layout propery\n */\n getLayoutProperty: function(layer, name) {\n return this.style.getLayoutProperty(layer, name);\n },\n\n /**\n * Get the Map's container as an HTML element\n * @returns {HTMLElement} container\n */\n getContainer: function() {\n return this._container;\n },\n\n /**\n * Get the Map's canvas as an HTML canvas\n * @returns {HTMLElement} canvas\n */\n getCanvas: function() {\n return this._canvas.getElement();\n },\n\n _move: function(zoom, rotate, pitch) {\n\n this.update(zoom).fire('move');\n\n if (zoom) this.fire('zoom');\n if (rotate) this.fire('rotate');\n if (pitch) this.fire('pitch');\n\n return this;\n },\n\n // map setup code\n _setupContainer: function() {\n var id = this.options.container;\n var container = this._container = typeof id === 'string' ? document.getElementById(id) : id;\n if (container) container.classList.add('mapboxgl-map');\n this._canvas = new Canvas(this, container);\n },\n\n _setupControlPos: function() {\n var corners = this._controlCorners = {};\n var prefix = 'mapboxgl-ctrl-';\n var container = this.getContainer();\n\n function createCorner(pos) {\n var className = prefix + pos;\n corners[pos] = DOM.create('div', className, container);\n }\n\n if (container && typeof document === 'object') {\n createCorner('top-left');\n createCorner('top-right');\n createCorner('bottom-left');\n createCorner('bottom-right');\n }\n },\n\n _setupPainter: function() {\n var gl = this._canvas.getWebGLContext(this.options.failIfMajorPerformanceCaveat);\n\n if (!gl) {\n console.error('Failed to initialize WebGL');\n return;\n }\n\n this.painter = new GLPainter(gl, this.transform);\n },\n\n _contextLost: function(event) {\n event.preventDefault();\n if (this._frameId) {\n browser.cancelFrame(this._frameId);\n }\n },\n\n _contextRestored: function() {\n this._setupPainter();\n this.resize();\n this.update();\n },\n\n /**\n * Is this map fully loaded? If the style isn't loaded\n * or it has a change to the sources or style that isn't\n * propagated to its style, return false.\n *\n * @returns {boolean} whether the map is loaded\n */\n loaded: function() {\n if (this._styleDirty || this._sourcesDirty)\n return false;\n if (this.style && !this.style.loaded())\n return false;\n return true;\n },\n\n /**\n * Update this map's style and re-render the map.\n *\n * @param {Object} updateStyle new style\n * @returns {Map} this\n */\n update: function(updateStyle) {\n if (!this.style) return this;\n\n this._styleDirty = this._styleDirty || updateStyle;\n this._sourcesDirty = true;\n\n this._rerender();\n\n return this;\n },\n\n /**\n * Call when a (re-)render of the map is required, e.g. when the\n * user panned or zoomed,f or new data is available.\n * @returns {Map} this\n */\n render: function() {\n if (this.style && this._styleDirty) {\n this._styleDirty = false;\n this.style._recalculate(this.transform.zoom);\n }\n\n if (this.style && this._sourcesDirty && !this._sourcesDirtyTimeout) {\n this._sourcesDirty = false;\n this._sourcesDirtyTimeout = setTimeout(function() {\n this._sourcesDirtyTimeout = null;\n }.bind(this), 50);\n this.style._updateSources(this.transform);\n }\n\n this.painter.render(this.style, {\n debug: this.debug,\n vertices: this.vertices,\n rotating: this.rotating,\n zooming: this.zooming\n });\n\n this.fire('render');\n\n if (this.loaded() && !this._loaded) {\n this._loaded = true;\n this.fire('load');\n }\n\n this._frameId = null;\n\n if (!this.animationLoop.stopped()) {\n this._styleDirty = true;\n }\n\n if (this._sourcesDirty || this._repaint || !this.animationLoop.stopped()) {\n this._rerender();\n }\n\n return this;\n },\n\n /**\n * Destroys the map's underlying resources, including web workers.\n * @returns {Map} this\n */\n remove: function() {\n if (this._hash) this._hash.remove();\n browser.cancelFrame(this._frameId);\n clearTimeout(this._sourcesDirtyTimeout);\n this.setStyle(null);\n return this;\n },\n\n _rerender: function() {\n if (this.style && !this._frameId) {\n this._frameId = browser.frame(this.render);\n }\n },\n\n _forwardStyleEvent: function(e) {\n this.fire('style.' + e.type, util.extend({style: e.target}, e));\n },\n\n _forwardSourceEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardLayerEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardTileEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _onStyleLoad: function(e) {\n this.style._cascade(this._classes, {transition: false});\n this._forwardStyleEvent(e);\n },\n\n _onStyleChange: function(e) {\n this.update(true);\n this._forwardStyleEvent(e);\n },\n\n _onSourceAdd: function(e) {\n var source = e.source;\n if (source.onAdd)\n source.onAdd(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceRemove: function(e) {\n var source = e.source;\n if (source.onRemove)\n source.onRemove(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceUpdate: function(e) {\n this.update();\n this._forwardSourceEvent(e);\n }\n}","path":"js/ui/map.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/map.js#L193-L195"},"params":[{"title":"param","description":"The angle at which the camera is looking at the ground","type":{"type":"NameExpression","name":"number"},"name":"pitch"}],"returns":[{"title":"returns","description":"`this`","type":{"type":"NameExpression","name":"Map"}}],"name":"setPitch","memberof":"Map","scope":"instance","members":{"instance":[],"static":[]},"path":["Map","setPitch"]},{"description":"","tags":[{"title":"typedef","description":"[styleOptions]","type":{"type":"NameExpression","name":"Object"}},{"title":"name","name":"addClass"},{"title":"kind","kind":"typedef"},{"title":"memberof","description":"Map"},{"title":"instance"}],"context":{"loc":{"start":{"line":234,"column":4},"end":{"line":238,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/map.js","code":"{\n\n options: {\n center: [0, 0],\n zoom: 0,\n bearing: 0,\n pitch: 0,\n\n minZoom: 0,\n maxZoom: 20,\n\n interactive: true,\n hash: false,\n\n attributionControl: true,\n\n failIfMajorPerformanceCaveat: false\n },\n\n addControl: function(control) {\n control.addTo(this);\n return this;\n },\n\n /**\n * Sets a map position\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @param {number} zoom Map zoom level\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setView: function(center, zoom, bearing, pitch) {\n this.stop();\n\n var tr = this.transform,\n zoomChanged = tr.zoom !== +zoom,\n bearingChanged = tr.bearing !== +bearing,\n pitchChanged = tr.pitch !== +pitch;\n\n tr.center = LatLng.convert(center);\n tr.zoom = +zoom;\n tr.bearing = +bearing;\n tr.pitch = +pitch;\n\n return this\n .fire('movestart')\n ._move(zoomChanged, bearingChanged, pitchChanged)\n .fire('moveend');\n },\n\n /**\n * Sets a map location\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setCenter: function(center) {\n this.setView(center, this.getZoom(), this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map zoom\n *\n * @param {number} zoom Map zoom level\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setZoom: function(zoom) {\n this.setView(this.getCenter(), zoom, this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map rotation\n *\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setBearing: function(bearing) {\n this.setView(this.getCenter(), this.getZoom(), bearing, this.getPitch());\n },\n\n /**\n * Sets a map angle\n *\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setPitch: function(pitch) {\n this.setView(this.getCenter(), this.getZoom(), this.getBearing(), pitch);\n },\n\n /**\n * Get the current view geographical point\n * @returns {LatLng}\n */\n getCenter: function() { return this.transform.center; },\n\n /**\n * Get the current zoom\n * @returns {number}\n */\n getZoom: function() { return this.transform.zoom; },\n\n /**\n * Get the current bearing in degrees\n * @returns {number}\n */\n getBearing: function() { return this.transform.bearing; },\n\n /**\n * Get the current angle in degrees\n * @returns {number}\n */\n getPitch: function() { return this.transform.pitch; },\n\n /**\n * @typedef {Object} [styleOptions]\n * @param {Boolean} [styleOptions.transition=true]\n */\n\n /**\n * Adds a style class to a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n addClass: function(klass, options) {\n if (this._classes[klass]) return;\n this._classes[klass] = true;\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Removes a style class from a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n removeClass: function(klass, options) {\n if (!this._classes[klass]) return;\n delete this._classes[klass];\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Helper method to add more than one class\n *\n * @param {Array} klasses An array of class names\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n setClasses: function(klasses, options) {\n this._classes = {};\n for (var i = 0; i < klasses.length; i++) {\n this._classes[klasses[i]] = true;\n }\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Check whether a style class is active\n *\n * @param {string} klass Name of style class\n * @returns {boolean}\n */\n hasClass: function(klass) {\n return !!this._classes[klass];\n },\n\n /**\n * Return an array of the current active style classes\n *\n * @returns {boolean}\n */\n getClasses: function() {\n return Object.keys(this._classes);\n },\n\n /**\n * Detect the map's new width and height and resize it.\n *\n * @returns {Map} `this`\n */\n resize: function() {\n var width = 0, height = 0;\n\n if (this._container) {\n width = this._container.offsetWidth || 400;\n height = this._container.offsetHeight || 300;\n }\n\n this._canvas.resize(width, height);\n\n this.transform.width = width;\n this.transform.height = height;\n this.transform._constrain();\n\n this.painter.resize(width, height);\n\n return this\n .fire('movestart')\n ._move()\n .fire('resize')\n .fire('moveend');\n },\n\n /**\n * Get the map's geographical bounds\n *\n * @returns {LatLngBounds}\n */\n getBounds: function() {\n return new LatLngBounds(\n this.transform.pointLocation(new Point(0, 0)),\n this.transform.pointLocation(this.transform.size));\n },\n\n /**\n * Get pixel coordinates (relative to map container) given a geographical location\n *\n * @param {LatLng} latlng\n * @returns {Object} `x` and `y` coordinates\n */\n project: function(latlng) {\n return this.transform.locationPoint(LatLng.convert(latlng));\n },\n\n /**\n * Get geographical coordinates given pixel coordinates\n *\n * @param {Array} point [x, y] pixel coordinates\n * @returns {LatLng}\n */\n unproject: function(point) {\n return this.transform.pointLocation(Point.convert(point));\n },\n\n /**\n * Get all features at a point ([x, y])\n *\n * @param {Array} point [x, y] pixel coordinates\n * @param {Object} params\n * @param {number} [params.radius=0] Optional. Radius in pixels to search in\n * @param {string} params.layer Optional. Only return features from a given layer\n * @param {string} params.type Optional. Either `raster` or `vector`\n * @param {featuresAtCallback} callback function that returns the response\n *\n * @callback featuresAtCallback\n * @param {Object|null} err Error _If any_\n * @param {Array} features Displays a JSON array of features given the passed parameters of `featuresAt`\n *\n * @returns {Map} `this`\n */\n featuresAt: function(point, params, callback) {\n var coord = this.transform.pointCoordinate(Point.convert(point));\n this.style.featuresAt(coord, params, callback);\n return this;\n },\n\n /**\n * Replaces the map's style object\n *\n * @param {Object} style A style object formatted as JSON\n * @returns {Map} `this`\n */\n setStyle: function(style) {\n if (this.style) {\n this.style\n .off('load', this._onStyleLoad)\n .off('error', this._forwardStyleEvent)\n .off('change', this._onStyleChange)\n .off('source.add', this._onSourceAdd)\n .off('source.remove', this._onSourceRemove)\n .off('source.load', this._onSourceUpdate)\n .off('source.error', this._forwardSourceEvent)\n .off('source.change', this._onSourceUpdate)\n .off('layer.add', this._forwardLayerEvent)\n .off('layer.remove', this._forwardLayerEvent)\n .off('tile.add', this._forwardTileEvent)\n .off('tile.remove', this._forwardTileEvent)\n .off('tile.load', this.update)\n .off('tile.error', this._forwardTileEvent)\n ._remove();\n\n this.off('rotate', this.style._redoPlacement);\n this.off('pitch', this.style._redoPlacement);\n }\n\n if (!style) {\n this.style = null;\n return this;\n } else if (style instanceof Style) {\n this.style = style;\n } else {\n this.style = new Style(style, this.animationLoop);\n }\n\n this.style\n .on('load', this._onStyleLoad)\n .on('error', this._forwardStyleEvent)\n .on('change', this._onStyleChange)\n .on('source.add', this._onSourceAdd)\n .on('source.remove', this._onSourceRemove)\n .on('source.load', this._onSourceUpdate)\n .on('source.error', this._forwardSourceEvent)\n .on('source.change', this._onSourceUpdate)\n .on('layer.add', this._forwardLayerEvent)\n .on('layer.remove', this._forwardLayerEvent)\n .on('tile.add', this._forwardTileEvent)\n .on('tile.remove', this._forwardTileEvent)\n .on('tile.load', this.update)\n .on('tile.error', this._forwardTileEvent);\n\n this.on('rotate', this.style._redoPlacement);\n this.on('pitch', this.style._redoPlacement);\n\n return this;\n },\n\n /**\n * Add a source to the map style.\n *\n * @param {string} id ID of the source. Must not be used by any existing source.\n * @param {Object} source source specification, following the\n * [Mapbox GL Style Reference](https://www.mapbox.com/mapbox-gl-style-spec/#sources)\n * @fires source.add\n * @returns {Map} `this`\n */\n addSource: function(id, source) {\n this.style.addSource(id, source);\n return this;\n },\n\n /**\n * Remove an existing source from the map style.\n *\n * @param {string} id ID of the source to remove\n * @fires source.remove\n * @returns {Map} `this`\n */\n removeSource: function(id) {\n this.style.removeSource(id);\n return this;\n },\n\n /**\n * Return the style source object with the given `id`.\n *\n * @param {string} id source ID\n * @returns {Object}\n */\n getSource: function(id) {\n return this.style.getSource(id);\n },\n\n /**\n * Add a layer to the map style. The layer will be inserted before the layer with\n * ID `before`, or appended if `before` is omitted.\n * @param {Layer} layer\n * @param {string=} before ID of an existing layer to insert before\n * @fires layer.add\n * @returns {Map} `this`\n */\n addLayer: function(layer, before) {\n this.style.addLayer(layer, before);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Remove the layer with the given `id` from the map. Any layers which refer to the\n * specified layer via a `ref` property are also removed.\n *\n * @param {string} id\n * @fires layer.remove\n * @returns {Map} this\n */\n removeLayer: function(id) {\n this.style.removeLayer(id);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Set the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {Array} filter filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n * @returns {Map} `this`\n */\n setFilter: function(layer, filter) {\n this.style.setFilter(layer, filter);\n return this;\n },\n\n /**\n * Get the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @returns {Array} filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n */\n getFilter: function(layer) {\n return this.style.getFilter(layer);\n },\n\n /**\n * Set the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {*} value value for the paint propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @param {string=} klass optional class specifier for the property\n * @returns {Map} `this`\n */\n setPaintProperty: function(layer, name, value, klass) {\n this.style.setPaintProperty(layer, name, value, klass);\n this.style._cascade(this._classes);\n this.update(true);\n return this;\n },\n\n /**\n * Get the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the paint propery\n */\n getPaintProperty: function(layer, name, klass) {\n return this.style.getPaintProperty(layer, name, klass);\n },\n\n /**\n * Set the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {*} value value for the layout propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @returns {Map} `this`\n */\n setLayoutProperty: function(layer, name, value) {\n this.style.setLayoutProperty(layer, name, value);\n return this;\n },\n\n /**\n * Get the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the layout propery\n */\n getLayoutProperty: function(layer, name) {\n return this.style.getLayoutProperty(layer, name);\n },\n\n /**\n * Get the Map's container as an HTML element\n * @returns {HTMLElement} container\n */\n getContainer: function() {\n return this._container;\n },\n\n /**\n * Get the Map's canvas as an HTML canvas\n * @returns {HTMLElement} canvas\n */\n getCanvas: function() {\n return this._canvas.getElement();\n },\n\n _move: function(zoom, rotate, pitch) {\n\n this.update(zoom).fire('move');\n\n if (zoom) this.fire('zoom');\n if (rotate) this.fire('rotate');\n if (pitch) this.fire('pitch');\n\n return this;\n },\n\n // map setup code\n _setupContainer: function() {\n var id = this.options.container;\n var container = this._container = typeof id === 'string' ? document.getElementById(id) : id;\n if (container) container.classList.add('mapboxgl-map');\n this._canvas = new Canvas(this, container);\n },\n\n _setupControlPos: function() {\n var corners = this._controlCorners = {};\n var prefix = 'mapboxgl-ctrl-';\n var container = this.getContainer();\n\n function createCorner(pos) {\n var className = prefix + pos;\n corners[pos] = DOM.create('div', className, container);\n }\n\n if (container && typeof document === 'object') {\n createCorner('top-left');\n createCorner('top-right');\n createCorner('bottom-left');\n createCorner('bottom-right');\n }\n },\n\n _setupPainter: function() {\n var gl = this._canvas.getWebGLContext(this.options.failIfMajorPerformanceCaveat);\n\n if (!gl) {\n console.error('Failed to initialize WebGL');\n return;\n }\n\n this.painter = new GLPainter(gl, this.transform);\n },\n\n _contextLost: function(event) {\n event.preventDefault();\n if (this._frameId) {\n browser.cancelFrame(this._frameId);\n }\n },\n\n _contextRestored: function() {\n this._setupPainter();\n this.resize();\n this.update();\n },\n\n /**\n * Is this map fully loaded? If the style isn't loaded\n * or it has a change to the sources or style that isn't\n * propagated to its style, return false.\n *\n * @returns {boolean} whether the map is loaded\n */\n loaded: function() {\n if (this._styleDirty || this._sourcesDirty)\n return false;\n if (this.style && !this.style.loaded())\n return false;\n return true;\n },\n\n /**\n * Update this map's style and re-render the map.\n *\n * @param {Object} updateStyle new style\n * @returns {Map} this\n */\n update: function(updateStyle) {\n if (!this.style) return this;\n\n this._styleDirty = this._styleDirty || updateStyle;\n this._sourcesDirty = true;\n\n this._rerender();\n\n return this;\n },\n\n /**\n * Call when a (re-)render of the map is required, e.g. when the\n * user panned or zoomed,f or new data is available.\n * @returns {Map} this\n */\n render: function() {\n if (this.style && this._styleDirty) {\n this._styleDirty = false;\n this.style._recalculate(this.transform.zoom);\n }\n\n if (this.style && this._sourcesDirty && !this._sourcesDirtyTimeout) {\n this._sourcesDirty = false;\n this._sourcesDirtyTimeout = setTimeout(function() {\n this._sourcesDirtyTimeout = null;\n }.bind(this), 50);\n this.style._updateSources(this.transform);\n }\n\n this.painter.render(this.style, {\n debug: this.debug,\n vertices: this.vertices,\n rotating: this.rotating,\n zooming: this.zooming\n });\n\n this.fire('render');\n\n if (this.loaded() && !this._loaded) {\n this._loaded = true;\n this.fire('load');\n }\n\n this._frameId = null;\n\n if (!this.animationLoop.stopped()) {\n this._styleDirty = true;\n }\n\n if (this._sourcesDirty || this._repaint || !this.animationLoop.stopped()) {\n this._rerender();\n }\n\n return this;\n },\n\n /**\n * Destroys the map's underlying resources, including web workers.\n * @returns {Map} this\n */\n remove: function() {\n if (this._hash) this._hash.remove();\n browser.cancelFrame(this._frameId);\n clearTimeout(this._sourcesDirtyTimeout);\n this.setStyle(null);\n return this;\n },\n\n _rerender: function() {\n if (this.style && !this._frameId) {\n this._frameId = browser.frame(this.render);\n }\n },\n\n _forwardStyleEvent: function(e) {\n this.fire('style.' + e.type, util.extend({style: e.target}, e));\n },\n\n _forwardSourceEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardLayerEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardTileEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _onStyleLoad: function(e) {\n this.style._cascade(this._classes, {transition: false});\n this._forwardStyleEvent(e);\n },\n\n _onStyleChange: function(e) {\n this.update(true);\n this._forwardStyleEvent(e);\n },\n\n _onSourceAdd: function(e) {\n var source = e.source;\n if (source.onAdd)\n source.onAdd(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceRemove: function(e) {\n var source = e.source;\n if (source.onRemove)\n source.onRemove(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceUpdate: function(e) {\n this.update();\n this._forwardSourceEvent(e);\n }\n}","path":"js/ui/map.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/map.js#L234-L238"},"name":"addClass","kind":"typedef","memberof":"Map","scope":"instance","members":{"instance":[],"static":[]},"path":["Map","addClass"]},{"description":"Adds a style class to a map","tags":[{"title":"param","description":"name of style class","type":{"type":"NameExpression","name":"string"},"name":"klass"},{"title":"param","description":null,"type":{"type":"NameExpression","name":"styleOptions"},"name":"options"},{"title":"fires","description":"change"},{"title":"returns","description":"`this`","type":{"type":"NameExpression","name":"Map"}},{"title":"name","name":"addClass"},{"title":"memberof","description":"Map"},{"title":"instance"}],"context":{"loc":{"start":{"line":234,"column":4},"end":{"line":238,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/map.js","code":"{\n\n options: {\n center: [0, 0],\n zoom: 0,\n bearing: 0,\n pitch: 0,\n\n minZoom: 0,\n maxZoom: 20,\n\n interactive: true,\n hash: false,\n\n attributionControl: true,\n\n failIfMajorPerformanceCaveat: false\n },\n\n addControl: function(control) {\n control.addTo(this);\n return this;\n },\n\n /**\n * Sets a map position\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @param {number} zoom Map zoom level\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setView: function(center, zoom, bearing, pitch) {\n this.stop();\n\n var tr = this.transform,\n zoomChanged = tr.zoom !== +zoom,\n bearingChanged = tr.bearing !== +bearing,\n pitchChanged = tr.pitch !== +pitch;\n\n tr.center = LatLng.convert(center);\n tr.zoom = +zoom;\n tr.bearing = +bearing;\n tr.pitch = +pitch;\n\n return this\n .fire('movestart')\n ._move(zoomChanged, bearingChanged, pitchChanged)\n .fire('moveend');\n },\n\n /**\n * Sets a map location\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setCenter: function(center) {\n this.setView(center, this.getZoom(), this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map zoom\n *\n * @param {number} zoom Map zoom level\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setZoom: function(zoom) {\n this.setView(this.getCenter(), zoom, this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map rotation\n *\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setBearing: function(bearing) {\n this.setView(this.getCenter(), this.getZoom(), bearing, this.getPitch());\n },\n\n /**\n * Sets a map angle\n *\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setPitch: function(pitch) {\n this.setView(this.getCenter(), this.getZoom(), this.getBearing(), pitch);\n },\n\n /**\n * Get the current view geographical point\n * @returns {LatLng}\n */\n getCenter: function() { return this.transform.center; },\n\n /**\n * Get the current zoom\n * @returns {number}\n */\n getZoom: function() { return this.transform.zoom; },\n\n /**\n * Get the current bearing in degrees\n * @returns {number}\n */\n getBearing: function() { return this.transform.bearing; },\n\n /**\n * Get the current angle in degrees\n * @returns {number}\n */\n getPitch: function() { return this.transform.pitch; },\n\n /**\n * @typedef {Object} [styleOptions]\n * @param {Boolean} [styleOptions.transition=true]\n */\n\n /**\n * Adds a style class to a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n addClass: function(klass, options) {\n if (this._classes[klass]) return;\n this._classes[klass] = true;\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Removes a style class from a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n removeClass: function(klass, options) {\n if (!this._classes[klass]) return;\n delete this._classes[klass];\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Helper method to add more than one class\n *\n * @param {Array} klasses An array of class names\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n setClasses: function(klasses, options) {\n this._classes = {};\n for (var i = 0; i < klasses.length; i++) {\n this._classes[klasses[i]] = true;\n }\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Check whether a style class is active\n *\n * @param {string} klass Name of style class\n * @returns {boolean}\n */\n hasClass: function(klass) {\n return !!this._classes[klass];\n },\n\n /**\n * Return an array of the current active style classes\n *\n * @returns {boolean}\n */\n getClasses: function() {\n return Object.keys(this._classes);\n },\n\n /**\n * Detect the map's new width and height and resize it.\n *\n * @returns {Map} `this`\n */\n resize: function() {\n var width = 0, height = 0;\n\n if (this._container) {\n width = this._container.offsetWidth || 400;\n height = this._container.offsetHeight || 300;\n }\n\n this._canvas.resize(width, height);\n\n this.transform.width = width;\n this.transform.height = height;\n this.transform._constrain();\n\n this.painter.resize(width, height);\n\n return this\n .fire('movestart')\n ._move()\n .fire('resize')\n .fire('moveend');\n },\n\n /**\n * Get the map's geographical bounds\n *\n * @returns {LatLngBounds}\n */\n getBounds: function() {\n return new LatLngBounds(\n this.transform.pointLocation(new Point(0, 0)),\n this.transform.pointLocation(this.transform.size));\n },\n\n /**\n * Get pixel coordinates (relative to map container) given a geographical location\n *\n * @param {LatLng} latlng\n * @returns {Object} `x` and `y` coordinates\n */\n project: function(latlng) {\n return this.transform.locationPoint(LatLng.convert(latlng));\n },\n\n /**\n * Get geographical coordinates given pixel coordinates\n *\n * @param {Array} point [x, y] pixel coordinates\n * @returns {LatLng}\n */\n unproject: function(point) {\n return this.transform.pointLocation(Point.convert(point));\n },\n\n /**\n * Get all features at a point ([x, y])\n *\n * @param {Array} point [x, y] pixel coordinates\n * @param {Object} params\n * @param {number} [params.radius=0] Optional. Radius in pixels to search in\n * @param {string} params.layer Optional. Only return features from a given layer\n * @param {string} params.type Optional. Either `raster` or `vector`\n * @param {featuresAtCallback} callback function that returns the response\n *\n * @callback featuresAtCallback\n * @param {Object|null} err Error _If any_\n * @param {Array} features Displays a JSON array of features given the passed parameters of `featuresAt`\n *\n * @returns {Map} `this`\n */\n featuresAt: function(point, params, callback) {\n var coord = this.transform.pointCoordinate(Point.convert(point));\n this.style.featuresAt(coord, params, callback);\n return this;\n },\n\n /**\n * Replaces the map's style object\n *\n * @param {Object} style A style object formatted as JSON\n * @returns {Map} `this`\n */\n setStyle: function(style) {\n if (this.style) {\n this.style\n .off('load', this._onStyleLoad)\n .off('error', this._forwardStyleEvent)\n .off('change', this._onStyleChange)\n .off('source.add', this._onSourceAdd)\n .off('source.remove', this._onSourceRemove)\n .off('source.load', this._onSourceUpdate)\n .off('source.error', this._forwardSourceEvent)\n .off('source.change', this._onSourceUpdate)\n .off('layer.add', this._forwardLayerEvent)\n .off('layer.remove', this._forwardLayerEvent)\n .off('tile.add', this._forwardTileEvent)\n .off('tile.remove', this._forwardTileEvent)\n .off('tile.load', this.update)\n .off('tile.error', this._forwardTileEvent)\n ._remove();\n\n this.off('rotate', this.style._redoPlacement);\n this.off('pitch', this.style._redoPlacement);\n }\n\n if (!style) {\n this.style = null;\n return this;\n } else if (style instanceof Style) {\n this.style = style;\n } else {\n this.style = new Style(style, this.animationLoop);\n }\n\n this.style\n .on('load', this._onStyleLoad)\n .on('error', this._forwardStyleEvent)\n .on('change', this._onStyleChange)\n .on('source.add', this._onSourceAdd)\n .on('source.remove', this._onSourceRemove)\n .on('source.load', this._onSourceUpdate)\n .on('source.error', this._forwardSourceEvent)\n .on('source.change', this._onSourceUpdate)\n .on('layer.add', this._forwardLayerEvent)\n .on('layer.remove', this._forwardLayerEvent)\n .on('tile.add', this._forwardTileEvent)\n .on('tile.remove', this._forwardTileEvent)\n .on('tile.load', this.update)\n .on('tile.error', this._forwardTileEvent);\n\n this.on('rotate', this.style._redoPlacement);\n this.on('pitch', this.style._redoPlacement);\n\n return this;\n },\n\n /**\n * Add a source to the map style.\n *\n * @param {string} id ID of the source. Must not be used by any existing source.\n * @param {Object} source source specification, following the\n * [Mapbox GL Style Reference](https://www.mapbox.com/mapbox-gl-style-spec/#sources)\n * @fires source.add\n * @returns {Map} `this`\n */\n addSource: function(id, source) {\n this.style.addSource(id, source);\n return this;\n },\n\n /**\n * Remove an existing source from the map style.\n *\n * @param {string} id ID of the source to remove\n * @fires source.remove\n * @returns {Map} `this`\n */\n removeSource: function(id) {\n this.style.removeSource(id);\n return this;\n },\n\n /**\n * Return the style source object with the given `id`.\n *\n * @param {string} id source ID\n * @returns {Object}\n */\n getSource: function(id) {\n return this.style.getSource(id);\n },\n\n /**\n * Add a layer to the map style. The layer will be inserted before the layer with\n * ID `before`, or appended if `before` is omitted.\n * @param {Layer} layer\n * @param {string=} before ID of an existing layer to insert before\n * @fires layer.add\n * @returns {Map} `this`\n */\n addLayer: function(layer, before) {\n this.style.addLayer(layer, before);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Remove the layer with the given `id` from the map. Any layers which refer to the\n * specified layer via a `ref` property are also removed.\n *\n * @param {string} id\n * @fires layer.remove\n * @returns {Map} this\n */\n removeLayer: function(id) {\n this.style.removeLayer(id);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Set the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {Array} filter filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n * @returns {Map} `this`\n */\n setFilter: function(layer, filter) {\n this.style.setFilter(layer, filter);\n return this;\n },\n\n /**\n * Get the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @returns {Array} filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n */\n getFilter: function(layer) {\n return this.style.getFilter(layer);\n },\n\n /**\n * Set the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {*} value value for the paint propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @param {string=} klass optional class specifier for the property\n * @returns {Map} `this`\n */\n setPaintProperty: function(layer, name, value, klass) {\n this.style.setPaintProperty(layer, name, value, klass);\n this.style._cascade(this._classes);\n this.update(true);\n return this;\n },\n\n /**\n * Get the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the paint propery\n */\n getPaintProperty: function(layer, name, klass) {\n return this.style.getPaintProperty(layer, name, klass);\n },\n\n /**\n * Set the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {*} value value for the layout propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @returns {Map} `this`\n */\n setLayoutProperty: function(layer, name, value) {\n this.style.setLayoutProperty(layer, name, value);\n return this;\n },\n\n /**\n * Get the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the layout propery\n */\n getLayoutProperty: function(layer, name) {\n return this.style.getLayoutProperty(layer, name);\n },\n\n /**\n * Get the Map's container as an HTML element\n * @returns {HTMLElement} container\n */\n getContainer: function() {\n return this._container;\n },\n\n /**\n * Get the Map's canvas as an HTML canvas\n * @returns {HTMLElement} canvas\n */\n getCanvas: function() {\n return this._canvas.getElement();\n },\n\n _move: function(zoom, rotate, pitch) {\n\n this.update(zoom).fire('move');\n\n if (zoom) this.fire('zoom');\n if (rotate) this.fire('rotate');\n if (pitch) this.fire('pitch');\n\n return this;\n },\n\n // map setup code\n _setupContainer: function() {\n var id = this.options.container;\n var container = this._container = typeof id === 'string' ? document.getElementById(id) : id;\n if (container) container.classList.add('mapboxgl-map');\n this._canvas = new Canvas(this, container);\n },\n\n _setupControlPos: function() {\n var corners = this._controlCorners = {};\n var prefix = 'mapboxgl-ctrl-';\n var container = this.getContainer();\n\n function createCorner(pos) {\n var className = prefix + pos;\n corners[pos] = DOM.create('div', className, container);\n }\n\n if (container && typeof document === 'object') {\n createCorner('top-left');\n createCorner('top-right');\n createCorner('bottom-left');\n createCorner('bottom-right');\n }\n },\n\n _setupPainter: function() {\n var gl = this._canvas.getWebGLContext(this.options.failIfMajorPerformanceCaveat);\n\n if (!gl) {\n console.error('Failed to initialize WebGL');\n return;\n }\n\n this.painter = new GLPainter(gl, this.transform);\n },\n\n _contextLost: function(event) {\n event.preventDefault();\n if (this._frameId) {\n browser.cancelFrame(this._frameId);\n }\n },\n\n _contextRestored: function() {\n this._setupPainter();\n this.resize();\n this.update();\n },\n\n /**\n * Is this map fully loaded? If the style isn't loaded\n * or it has a change to the sources or style that isn't\n * propagated to its style, return false.\n *\n * @returns {boolean} whether the map is loaded\n */\n loaded: function() {\n if (this._styleDirty || this._sourcesDirty)\n return false;\n if (this.style && !this.style.loaded())\n return false;\n return true;\n },\n\n /**\n * Update this map's style and re-render the map.\n *\n * @param {Object} updateStyle new style\n * @returns {Map} this\n */\n update: function(updateStyle) {\n if (!this.style) return this;\n\n this._styleDirty = this._styleDirty || updateStyle;\n this._sourcesDirty = true;\n\n this._rerender();\n\n return this;\n },\n\n /**\n * Call when a (re-)render of the map is required, e.g. when the\n * user panned or zoomed,f or new data is available.\n * @returns {Map} this\n */\n render: function() {\n if (this.style && this._styleDirty) {\n this._styleDirty = false;\n this.style._recalculate(this.transform.zoom);\n }\n\n if (this.style && this._sourcesDirty && !this._sourcesDirtyTimeout) {\n this._sourcesDirty = false;\n this._sourcesDirtyTimeout = setTimeout(function() {\n this._sourcesDirtyTimeout = null;\n }.bind(this), 50);\n this.style._updateSources(this.transform);\n }\n\n this.painter.render(this.style, {\n debug: this.debug,\n vertices: this.vertices,\n rotating: this.rotating,\n zooming: this.zooming\n });\n\n this.fire('render');\n\n if (this.loaded() && !this._loaded) {\n this._loaded = true;\n this.fire('load');\n }\n\n this._frameId = null;\n\n if (!this.animationLoop.stopped()) {\n this._styleDirty = true;\n }\n\n if (this._sourcesDirty || this._repaint || !this.animationLoop.stopped()) {\n this._rerender();\n }\n\n return this;\n },\n\n /**\n * Destroys the map's underlying resources, including web workers.\n * @returns {Map} this\n */\n remove: function() {\n if (this._hash) this._hash.remove();\n browser.cancelFrame(this._frameId);\n clearTimeout(this._sourcesDirtyTimeout);\n this.setStyle(null);\n return this;\n },\n\n _rerender: function() {\n if (this.style && !this._frameId) {\n this._frameId = browser.frame(this.render);\n }\n },\n\n _forwardStyleEvent: function(e) {\n this.fire('style.' + e.type, util.extend({style: e.target}, e));\n },\n\n _forwardSourceEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardLayerEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardTileEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _onStyleLoad: function(e) {\n this.style._cascade(this._classes, {transition: false});\n this._forwardStyleEvent(e);\n },\n\n _onStyleChange: function(e) {\n this.update(true);\n this._forwardStyleEvent(e);\n },\n\n _onSourceAdd: function(e) {\n var source = e.source;\n if (source.onAdd)\n source.onAdd(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceRemove: function(e) {\n var source = e.source;\n if (source.onRemove)\n source.onRemove(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceUpdate: function(e) {\n this.update();\n this._forwardSourceEvent(e);\n }\n}","path":"js/ui/map.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/map.js#L234-L238"},"params":[{"title":"param","description":"name of style class","type":{"type":"NameExpression","name":"string"},"name":"klass"},{"title":"param","description":null,"type":{"type":"NameExpression","name":"styleOptions"},"name":"options"}],"returns":[{"title":"returns","description":"`this`","type":{"type":"NameExpression","name":"Map"}}],"name":"addClass","memberof":"Map","scope":"instance","members":{"instance":[],"static":[]},"path":["Map","addClass"]},{"description":"Add a source to the map style.","tags":[{"title":"param","description":"ID of the source. Must not be used by any existing source.","type":{"type":"NameExpression","name":"string"},"name":"id"},{"title":"param","description":"source specification, following the\n[Mapbox GL Style Reference](https://www.mapbox.com/mapbox-gl-style-spec/#sources)","type":{"type":"NameExpression","name":"Object"},"name":"source"},{"title":"fires","description":"source.add"},{"title":"returns","description":"`this`","type":{"type":"NameExpression","name":"Map"}},{"title":"name","name":"addSource"},{"title":"memberof","description":"Map"},{"title":"instance"}],"context":{"loc":{"start":{"line":439,"column":4},"end":{"line":442,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/map.js","code":"{\n\n options: {\n center: [0, 0],\n zoom: 0,\n bearing: 0,\n pitch: 0,\n\n minZoom: 0,\n maxZoom: 20,\n\n interactive: true,\n hash: false,\n\n attributionControl: true,\n\n failIfMajorPerformanceCaveat: false\n },\n\n addControl: function(control) {\n control.addTo(this);\n return this;\n },\n\n /**\n * Sets a map position\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @param {number} zoom Map zoom level\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setView: function(center, zoom, bearing, pitch) {\n this.stop();\n\n var tr = this.transform,\n zoomChanged = tr.zoom !== +zoom,\n bearingChanged = tr.bearing !== +bearing,\n pitchChanged = tr.pitch !== +pitch;\n\n tr.center = LatLng.convert(center);\n tr.zoom = +zoom;\n tr.bearing = +bearing;\n tr.pitch = +pitch;\n\n return this\n .fire('movestart')\n ._move(zoomChanged, bearingChanged, pitchChanged)\n .fire('moveend');\n },\n\n /**\n * Sets a map location\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setCenter: function(center) {\n this.setView(center, this.getZoom(), this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map zoom\n *\n * @param {number} zoom Map zoom level\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setZoom: function(zoom) {\n this.setView(this.getCenter(), zoom, this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map rotation\n *\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setBearing: function(bearing) {\n this.setView(this.getCenter(), this.getZoom(), bearing, this.getPitch());\n },\n\n /**\n * Sets a map angle\n *\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setPitch: function(pitch) {\n this.setView(this.getCenter(), this.getZoom(), this.getBearing(), pitch);\n },\n\n /**\n * Get the current view geographical point\n * @returns {LatLng}\n */\n getCenter: function() { return this.transform.center; },\n\n /**\n * Get the current zoom\n * @returns {number}\n */\n getZoom: function() { return this.transform.zoom; },\n\n /**\n * Get the current bearing in degrees\n * @returns {number}\n */\n getBearing: function() { return this.transform.bearing; },\n\n /**\n * Get the current angle in degrees\n * @returns {number}\n */\n getPitch: function() { return this.transform.pitch; },\n\n /**\n * @typedef {Object} [styleOptions]\n * @param {Boolean} [styleOptions.transition=true]\n */\n\n /**\n * Adds a style class to a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n addClass: function(klass, options) {\n if (this._classes[klass]) return;\n this._classes[klass] = true;\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Removes a style class from a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n removeClass: function(klass, options) {\n if (!this._classes[klass]) return;\n delete this._classes[klass];\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Helper method to add more than one class\n *\n * @param {Array} klasses An array of class names\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n setClasses: function(klasses, options) {\n this._classes = {};\n for (var i = 0; i < klasses.length; i++) {\n this._classes[klasses[i]] = true;\n }\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Check whether a style class is active\n *\n * @param {string} klass Name of style class\n * @returns {boolean}\n */\n hasClass: function(klass) {\n return !!this._classes[klass];\n },\n\n /**\n * Return an array of the current active style classes\n *\n * @returns {boolean}\n */\n getClasses: function() {\n return Object.keys(this._classes);\n },\n\n /**\n * Detect the map's new width and height and resize it.\n *\n * @returns {Map} `this`\n */\n resize: function() {\n var width = 0, height = 0;\n\n if (this._container) {\n width = this._container.offsetWidth || 400;\n height = this._container.offsetHeight || 300;\n }\n\n this._canvas.resize(width, height);\n\n this.transform.width = width;\n this.transform.height = height;\n this.transform._constrain();\n\n this.painter.resize(width, height);\n\n return this\n .fire('movestart')\n ._move()\n .fire('resize')\n .fire('moveend');\n },\n\n /**\n * Get the map's geographical bounds\n *\n * @returns {LatLngBounds}\n */\n getBounds: function() {\n return new LatLngBounds(\n this.transform.pointLocation(new Point(0, 0)),\n this.transform.pointLocation(this.transform.size));\n },\n\n /**\n * Get pixel coordinates (relative to map container) given a geographical location\n *\n * @param {LatLng} latlng\n * @returns {Object} `x` and `y` coordinates\n */\n project: function(latlng) {\n return this.transform.locationPoint(LatLng.convert(latlng));\n },\n\n /**\n * Get geographical coordinates given pixel coordinates\n *\n * @param {Array} point [x, y] pixel coordinates\n * @returns {LatLng}\n */\n unproject: function(point) {\n return this.transform.pointLocation(Point.convert(point));\n },\n\n /**\n * Get all features at a point ([x, y])\n *\n * @param {Array} point [x, y] pixel coordinates\n * @param {Object} params\n * @param {number} [params.radius=0] Optional. Radius in pixels to search in\n * @param {string} params.layer Optional. Only return features from a given layer\n * @param {string} params.type Optional. Either `raster` or `vector`\n * @param {featuresAtCallback} callback function that returns the response\n *\n * @callback featuresAtCallback\n * @param {Object|null} err Error _If any_\n * @param {Array} features Displays a JSON array of features given the passed parameters of `featuresAt`\n *\n * @returns {Map} `this`\n */\n featuresAt: function(point, params, callback) {\n var coord = this.transform.pointCoordinate(Point.convert(point));\n this.style.featuresAt(coord, params, callback);\n return this;\n },\n\n /**\n * Replaces the map's style object\n *\n * @param {Object} style A style object formatted as JSON\n * @returns {Map} `this`\n */\n setStyle: function(style) {\n if (this.style) {\n this.style\n .off('load', this._onStyleLoad)\n .off('error', this._forwardStyleEvent)\n .off('change', this._onStyleChange)\n .off('source.add', this._onSourceAdd)\n .off('source.remove', this._onSourceRemove)\n .off('source.load', this._onSourceUpdate)\n .off('source.error', this._forwardSourceEvent)\n .off('source.change', this._onSourceUpdate)\n .off('layer.add', this._forwardLayerEvent)\n .off('layer.remove', this._forwardLayerEvent)\n .off('tile.add', this._forwardTileEvent)\n .off('tile.remove', this._forwardTileEvent)\n .off('tile.load', this.update)\n .off('tile.error', this._forwardTileEvent)\n ._remove();\n\n this.off('rotate', this.style._redoPlacement);\n this.off('pitch', this.style._redoPlacement);\n }\n\n if (!style) {\n this.style = null;\n return this;\n } else if (style instanceof Style) {\n this.style = style;\n } else {\n this.style = new Style(style, this.animationLoop);\n }\n\n this.style\n .on('load', this._onStyleLoad)\n .on('error', this._forwardStyleEvent)\n .on('change', this._onStyleChange)\n .on('source.add', this._onSourceAdd)\n .on('source.remove', this._onSourceRemove)\n .on('source.load', this._onSourceUpdate)\n .on('source.error', this._forwardSourceEvent)\n .on('source.change', this._onSourceUpdate)\n .on('layer.add', this._forwardLayerEvent)\n .on('layer.remove', this._forwardLayerEvent)\n .on('tile.add', this._forwardTileEvent)\n .on('tile.remove', this._forwardTileEvent)\n .on('tile.load', this.update)\n .on('tile.error', this._forwardTileEvent);\n\n this.on('rotate', this.style._redoPlacement);\n this.on('pitch', this.style._redoPlacement);\n\n return this;\n },\n\n /**\n * Add a source to the map style.\n *\n * @param {string} id ID of the source. Must not be used by any existing source.\n * @param {Object} source source specification, following the\n * [Mapbox GL Style Reference](https://www.mapbox.com/mapbox-gl-style-spec/#sources)\n * @fires source.add\n * @returns {Map} `this`\n */\n addSource: function(id, source) {\n this.style.addSource(id, source);\n return this;\n },\n\n /**\n * Remove an existing source from the map style.\n *\n * @param {string} id ID of the source to remove\n * @fires source.remove\n * @returns {Map} `this`\n */\n removeSource: function(id) {\n this.style.removeSource(id);\n return this;\n },\n\n /**\n * Return the style source object with the given `id`.\n *\n * @param {string} id source ID\n * @returns {Object}\n */\n getSource: function(id) {\n return this.style.getSource(id);\n },\n\n /**\n * Add a layer to the map style. The layer will be inserted before the layer with\n * ID `before`, or appended if `before` is omitted.\n * @param {Layer} layer\n * @param {string=} before ID of an existing layer to insert before\n * @fires layer.add\n * @returns {Map} `this`\n */\n addLayer: function(layer, before) {\n this.style.addLayer(layer, before);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Remove the layer with the given `id` from the map. Any layers which refer to the\n * specified layer via a `ref` property are also removed.\n *\n * @param {string} id\n * @fires layer.remove\n * @returns {Map} this\n */\n removeLayer: function(id) {\n this.style.removeLayer(id);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Set the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {Array} filter filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n * @returns {Map} `this`\n */\n setFilter: function(layer, filter) {\n this.style.setFilter(layer, filter);\n return this;\n },\n\n /**\n * Get the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @returns {Array} filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n */\n getFilter: function(layer) {\n return this.style.getFilter(layer);\n },\n\n /**\n * Set the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {*} value value for the paint propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @param {string=} klass optional class specifier for the property\n * @returns {Map} `this`\n */\n setPaintProperty: function(layer, name, value, klass) {\n this.style.setPaintProperty(layer, name, value, klass);\n this.style._cascade(this._classes);\n this.update(true);\n return this;\n },\n\n /**\n * Get the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the paint propery\n */\n getPaintProperty: function(layer, name, klass) {\n return this.style.getPaintProperty(layer, name, klass);\n },\n\n /**\n * Set the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {*} value value for the layout propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @returns {Map} `this`\n */\n setLayoutProperty: function(layer, name, value) {\n this.style.setLayoutProperty(layer, name, value);\n return this;\n },\n\n /**\n * Get the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the layout propery\n */\n getLayoutProperty: function(layer, name) {\n return this.style.getLayoutProperty(layer, name);\n },\n\n /**\n * Get the Map's container as an HTML element\n * @returns {HTMLElement} container\n */\n getContainer: function() {\n return this._container;\n },\n\n /**\n * Get the Map's canvas as an HTML canvas\n * @returns {HTMLElement} canvas\n */\n getCanvas: function() {\n return this._canvas.getElement();\n },\n\n _move: function(zoom, rotate, pitch) {\n\n this.update(zoom).fire('move');\n\n if (zoom) this.fire('zoom');\n if (rotate) this.fire('rotate');\n if (pitch) this.fire('pitch');\n\n return this;\n },\n\n // map setup code\n _setupContainer: function() {\n var id = this.options.container;\n var container = this._container = typeof id === 'string' ? document.getElementById(id) : id;\n if (container) container.classList.add('mapboxgl-map');\n this._canvas = new Canvas(this, container);\n },\n\n _setupControlPos: function() {\n var corners = this._controlCorners = {};\n var prefix = 'mapboxgl-ctrl-';\n var container = this.getContainer();\n\n function createCorner(pos) {\n var className = prefix + pos;\n corners[pos] = DOM.create('div', className, container);\n }\n\n if (container && typeof document === 'object') {\n createCorner('top-left');\n createCorner('top-right');\n createCorner('bottom-left');\n createCorner('bottom-right');\n }\n },\n\n _setupPainter: function() {\n var gl = this._canvas.getWebGLContext(this.options.failIfMajorPerformanceCaveat);\n\n if (!gl) {\n console.error('Failed to initialize WebGL');\n return;\n }\n\n this.painter = new GLPainter(gl, this.transform);\n },\n\n _contextLost: function(event) {\n event.preventDefault();\n if (this._frameId) {\n browser.cancelFrame(this._frameId);\n }\n },\n\n _contextRestored: function() {\n this._setupPainter();\n this.resize();\n this.update();\n },\n\n /**\n * Is this map fully loaded? If the style isn't loaded\n * or it has a change to the sources or style that isn't\n * propagated to its style, return false.\n *\n * @returns {boolean} whether the map is loaded\n */\n loaded: function() {\n if (this._styleDirty || this._sourcesDirty)\n return false;\n if (this.style && !this.style.loaded())\n return false;\n return true;\n },\n\n /**\n * Update this map's style and re-render the map.\n *\n * @param {Object} updateStyle new style\n * @returns {Map} this\n */\n update: function(updateStyle) {\n if (!this.style) return this;\n\n this._styleDirty = this._styleDirty || updateStyle;\n this._sourcesDirty = true;\n\n this._rerender();\n\n return this;\n },\n\n /**\n * Call when a (re-)render of the map is required, e.g. when the\n * user panned or zoomed,f or new data is available.\n * @returns {Map} this\n */\n render: function() {\n if (this.style && this._styleDirty) {\n this._styleDirty = false;\n this.style._recalculate(this.transform.zoom);\n }\n\n if (this.style && this._sourcesDirty && !this._sourcesDirtyTimeout) {\n this._sourcesDirty = false;\n this._sourcesDirtyTimeout = setTimeout(function() {\n this._sourcesDirtyTimeout = null;\n }.bind(this), 50);\n this.style._updateSources(this.transform);\n }\n\n this.painter.render(this.style, {\n debug: this.debug,\n vertices: this.vertices,\n rotating: this.rotating,\n zooming: this.zooming\n });\n\n this.fire('render');\n\n if (this.loaded() && !this._loaded) {\n this._loaded = true;\n this.fire('load');\n }\n\n this._frameId = null;\n\n if (!this.animationLoop.stopped()) {\n this._styleDirty = true;\n }\n\n if (this._sourcesDirty || this._repaint || !this.animationLoop.stopped()) {\n this._rerender();\n }\n\n return this;\n },\n\n /**\n * Destroys the map's underlying resources, including web workers.\n * @returns {Map} this\n */\n remove: function() {\n if (this._hash) this._hash.remove();\n browser.cancelFrame(this._frameId);\n clearTimeout(this._sourcesDirtyTimeout);\n this.setStyle(null);\n return this;\n },\n\n _rerender: function() {\n if (this.style && !this._frameId) {\n this._frameId = browser.frame(this.render);\n }\n },\n\n _forwardStyleEvent: function(e) {\n this.fire('style.' + e.type, util.extend({style: e.target}, e));\n },\n\n _forwardSourceEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardLayerEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardTileEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _onStyleLoad: function(e) {\n this.style._cascade(this._classes, {transition: false});\n this._forwardStyleEvent(e);\n },\n\n _onStyleChange: function(e) {\n this.update(true);\n this._forwardStyleEvent(e);\n },\n\n _onSourceAdd: function(e) {\n var source = e.source;\n if (source.onAdd)\n source.onAdd(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceRemove: function(e) {\n var source = e.source;\n if (source.onRemove)\n source.onRemove(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceUpdate: function(e) {\n this.update();\n this._forwardSourceEvent(e);\n }\n}","path":"js/ui/map.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/map.js#L439-L442"},"params":[{"title":"param","description":"ID of the source. Must not be used by any existing source.","type":{"type":"NameExpression","name":"string"},"name":"id"},{"title":"param","description":"source specification, following the\n[Mapbox GL Style Reference](https://www.mapbox.com/mapbox-gl-style-spec/#sources)","type":{"type":"NameExpression","name":"Object"},"name":"source"}],"returns":[{"title":"returns","description":"`this`","type":{"type":"NameExpression","name":"Map"}}],"name":"addSource","memberof":"Map","scope":"instance","members":{"instance":[],"static":[]},"path":["Map","addSource"]},{"description":"Add a layer to the map style. The layer will be inserted before the layer with\nID `before`, or appended if `before` is omitted.","tags":[{"title":"param","description":null,"type":{"type":"NameExpression","name":"Layer"},"name":"layer"},{"title":"param","description":"ID of an existing layer to insert before","type":{"type":"OptionalType","expression":{"type":"NameExpression","name":"string"}},"name":"before"},{"title":"fires","description":"layer.add"},{"title":"returns","description":"`this`","type":{"type":"NameExpression","name":"Map"}},{"title":"name","name":"addLayer"},{"title":"memberof","description":"Map"},{"title":"instance"}],"context":{"loc":{"start":{"line":474,"column":4},"end":{"line":478,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/map.js","code":"{\n\n options: {\n center: [0, 0],\n zoom: 0,\n bearing: 0,\n pitch: 0,\n\n minZoom: 0,\n maxZoom: 20,\n\n interactive: true,\n hash: false,\n\n attributionControl: true,\n\n failIfMajorPerformanceCaveat: false\n },\n\n addControl: function(control) {\n control.addTo(this);\n return this;\n },\n\n /**\n * Sets a map position\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @param {number} zoom Map zoom level\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setView: function(center, zoom, bearing, pitch) {\n this.stop();\n\n var tr = this.transform,\n zoomChanged = tr.zoom !== +zoom,\n bearingChanged = tr.bearing !== +bearing,\n pitchChanged = tr.pitch !== +pitch;\n\n tr.center = LatLng.convert(center);\n tr.zoom = +zoom;\n tr.bearing = +bearing;\n tr.pitch = +pitch;\n\n return this\n .fire('movestart')\n ._move(zoomChanged, bearingChanged, pitchChanged)\n .fire('moveend');\n },\n\n /**\n * Sets a map location\n *\n * @param {Array} center Latitude and longitude (passed as `[lat, lng]`)\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setCenter: function(center) {\n this.setView(center, this.getZoom(), this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map zoom\n *\n * @param {number} zoom Map zoom level\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setZoom: function(zoom) {\n this.setView(this.getCenter(), zoom, this.getBearing(), this.getPitch());\n },\n\n /**\n * Sets a map rotation\n *\n * @param {number} bearing Map rotation bearing in degrees counter-clockwise from north\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setBearing: function(bearing) {\n this.setView(this.getCenter(), this.getZoom(), bearing, this.getPitch());\n },\n\n /**\n * Sets a map angle\n *\n * @param {number} pitch The angle at which the camera is looking at the ground\n * @fires movestart\n * @fires moveend\n * @returns {Map} `this`\n */\n setPitch: function(pitch) {\n this.setView(this.getCenter(), this.getZoom(), this.getBearing(), pitch);\n },\n\n /**\n * Get the current view geographical point\n * @returns {LatLng}\n */\n getCenter: function() { return this.transform.center; },\n\n /**\n * Get the current zoom\n * @returns {number}\n */\n getZoom: function() { return this.transform.zoom; },\n\n /**\n * Get the current bearing in degrees\n * @returns {number}\n */\n getBearing: function() { return this.transform.bearing; },\n\n /**\n * Get the current angle in degrees\n * @returns {number}\n */\n getPitch: function() { return this.transform.pitch; },\n\n /**\n * @typedef {Object} [styleOptions]\n * @param {Boolean} [styleOptions.transition=true]\n */\n\n /**\n * Adds a style class to a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n addClass: function(klass, options) {\n if (this._classes[klass]) return;\n this._classes[klass] = true;\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Removes a style class from a map\n *\n * @param {string} klass name of style class\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n removeClass: function(klass, options) {\n if (!this._classes[klass]) return;\n delete this._classes[klass];\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Helper method to add more than one class\n *\n * @param {Array} klasses An array of class names\n * @param {styleOptions} options\n * @fires change\n * @returns {Map} `this`\n */\n setClasses: function(klasses, options) {\n this._classes = {};\n for (var i = 0; i < klasses.length; i++) {\n this._classes[klasses[i]] = true;\n }\n if (this.style) this.style._cascade(this._classes, options);\n },\n\n /**\n * Check whether a style class is active\n *\n * @param {string} klass Name of style class\n * @returns {boolean}\n */\n hasClass: function(klass) {\n return !!this._classes[klass];\n },\n\n /**\n * Return an array of the current active style classes\n *\n * @returns {boolean}\n */\n getClasses: function() {\n return Object.keys(this._classes);\n },\n\n /**\n * Detect the map's new width and height and resize it.\n *\n * @returns {Map} `this`\n */\n resize: function() {\n var width = 0, height = 0;\n\n if (this._container) {\n width = this._container.offsetWidth || 400;\n height = this._container.offsetHeight || 300;\n }\n\n this._canvas.resize(width, height);\n\n this.transform.width = width;\n this.transform.height = height;\n this.transform._constrain();\n\n this.painter.resize(width, height);\n\n return this\n .fire('movestart')\n ._move()\n .fire('resize')\n .fire('moveend');\n },\n\n /**\n * Get the map's geographical bounds\n *\n * @returns {LatLngBounds}\n */\n getBounds: function() {\n return new LatLngBounds(\n this.transform.pointLocation(new Point(0, 0)),\n this.transform.pointLocation(this.transform.size));\n },\n\n /**\n * Get pixel coordinates (relative to map container) given a geographical location\n *\n * @param {LatLng} latlng\n * @returns {Object} `x` and `y` coordinates\n */\n project: function(latlng) {\n return this.transform.locationPoint(LatLng.convert(latlng));\n },\n\n /**\n * Get geographical coordinates given pixel coordinates\n *\n * @param {Array} point [x, y] pixel coordinates\n * @returns {LatLng}\n */\n unproject: function(point) {\n return this.transform.pointLocation(Point.convert(point));\n },\n\n /**\n * Get all features at a point ([x, y])\n *\n * @param {Array} point [x, y] pixel coordinates\n * @param {Object} params\n * @param {number} [params.radius=0] Optional. Radius in pixels to search in\n * @param {string} params.layer Optional. Only return features from a given layer\n * @param {string} params.type Optional. Either `raster` or `vector`\n * @param {featuresAtCallback} callback function that returns the response\n *\n * @callback featuresAtCallback\n * @param {Object|null} err Error _If any_\n * @param {Array} features Displays a JSON array of features given the passed parameters of `featuresAt`\n *\n * @returns {Map} `this`\n */\n featuresAt: function(point, params, callback) {\n var coord = this.transform.pointCoordinate(Point.convert(point));\n this.style.featuresAt(coord, params, callback);\n return this;\n },\n\n /**\n * Replaces the map's style object\n *\n * @param {Object} style A style object formatted as JSON\n * @returns {Map} `this`\n */\n setStyle: function(style) {\n if (this.style) {\n this.style\n .off('load', this._onStyleLoad)\n .off('error', this._forwardStyleEvent)\n .off('change', this._onStyleChange)\n .off('source.add', this._onSourceAdd)\n .off('source.remove', this._onSourceRemove)\n .off('source.load', this._onSourceUpdate)\n .off('source.error', this._forwardSourceEvent)\n .off('source.change', this._onSourceUpdate)\n .off('layer.add', this._forwardLayerEvent)\n .off('layer.remove', this._forwardLayerEvent)\n .off('tile.add', this._forwardTileEvent)\n .off('tile.remove', this._forwardTileEvent)\n .off('tile.load', this.update)\n .off('tile.error', this._forwardTileEvent)\n ._remove();\n\n this.off('rotate', this.style._redoPlacement);\n this.off('pitch', this.style._redoPlacement);\n }\n\n if (!style) {\n this.style = null;\n return this;\n } else if (style instanceof Style) {\n this.style = style;\n } else {\n this.style = new Style(style, this.animationLoop);\n }\n\n this.style\n .on('load', this._onStyleLoad)\n .on('error', this._forwardStyleEvent)\n .on('change', this._onStyleChange)\n .on('source.add', this._onSourceAdd)\n .on('source.remove', this._onSourceRemove)\n .on('source.load', this._onSourceUpdate)\n .on('source.error', this._forwardSourceEvent)\n .on('source.change', this._onSourceUpdate)\n .on('layer.add', this._forwardLayerEvent)\n .on('layer.remove', this._forwardLayerEvent)\n .on('tile.add', this._forwardTileEvent)\n .on('tile.remove', this._forwardTileEvent)\n .on('tile.load', this.update)\n .on('tile.error', this._forwardTileEvent);\n\n this.on('rotate', this.style._redoPlacement);\n this.on('pitch', this.style._redoPlacement);\n\n return this;\n },\n\n /**\n * Add a source to the map style.\n *\n * @param {string} id ID of the source. Must not be used by any existing source.\n * @param {Object} source source specification, following the\n * [Mapbox GL Style Reference](https://www.mapbox.com/mapbox-gl-style-spec/#sources)\n * @fires source.add\n * @returns {Map} `this`\n */\n addSource: function(id, source) {\n this.style.addSource(id, source);\n return this;\n },\n\n /**\n * Remove an existing source from the map style.\n *\n * @param {string} id ID of the source to remove\n * @fires source.remove\n * @returns {Map} `this`\n */\n removeSource: function(id) {\n this.style.removeSource(id);\n return this;\n },\n\n /**\n * Return the style source object with the given `id`.\n *\n * @param {string} id source ID\n * @returns {Object}\n */\n getSource: function(id) {\n return this.style.getSource(id);\n },\n\n /**\n * Add a layer to the map style. The layer will be inserted before the layer with\n * ID `before`, or appended if `before` is omitted.\n * @param {Layer} layer\n * @param {string=} before ID of an existing layer to insert before\n * @fires layer.add\n * @returns {Map} `this`\n */\n addLayer: function(layer, before) {\n this.style.addLayer(layer, before);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Remove the layer with the given `id` from the map. Any layers which refer to the\n * specified layer via a `ref` property are also removed.\n *\n * @param {string} id\n * @fires layer.remove\n * @returns {Map} this\n */\n removeLayer: function(id) {\n this.style.removeLayer(id);\n this.style._cascade(this._classes);\n return this;\n },\n\n /**\n * Set the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {Array} filter filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n * @returns {Map} `this`\n */\n setFilter: function(layer, filter) {\n this.style.setFilter(layer, filter);\n return this;\n },\n\n /**\n * Get the filter for a given style layer.\n *\n * @param {string} layer ID of a layer\n * @returns {Array} filter specification, as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#filter)\n */\n getFilter: function(layer) {\n return this.style.getFilter(layer);\n },\n\n /**\n * Set the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {*} value value for the paint propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @param {string=} klass optional class specifier for the property\n * @returns {Map} `this`\n */\n setPaintProperty: function(layer, name, value, klass) {\n this.style.setPaintProperty(layer, name, value, klass);\n this.style._cascade(this._classes);\n this.update(true);\n return this;\n },\n\n /**\n * Get the value of a paint property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a paint property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the paint propery\n */\n getPaintProperty: function(layer, name, klass) {\n return this.style.getPaintProperty(layer, name, klass);\n },\n\n /**\n * Set the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {*} value value for the layout propery; must have the type appropriate for the property as defined in the [Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/)\n * @returns {Map} `this`\n */\n setLayoutProperty: function(layer, name, value) {\n this.style.setLayoutProperty(layer, name, value);\n return this;\n },\n\n /**\n * Get the value of a layout property in a given style layer.\n *\n * @param {string} layer ID of a layer\n * @param {string} name name of a layout property\n * @param {string=} klass optional class specifier for the property\n * @returns {*} value for the layout propery\n */\n getLayoutProperty: function(layer, name) {\n return this.style.getLayoutProperty(layer, name);\n },\n\n /**\n * Get the Map's container as an HTML element\n * @returns {HTMLElement} container\n */\n getContainer: function() {\n return this._container;\n },\n\n /**\n * Get the Map's canvas as an HTML canvas\n * @returns {HTMLElement} canvas\n */\n getCanvas: function() {\n return this._canvas.getElement();\n },\n\n _move: function(zoom, rotate, pitch) {\n\n this.update(zoom).fire('move');\n\n if (zoom) this.fire('zoom');\n if (rotate) this.fire('rotate');\n if (pitch) this.fire('pitch');\n\n return this;\n },\n\n // map setup code\n _setupContainer: function() {\n var id = this.options.container;\n var container = this._container = typeof id === 'string' ? document.getElementById(id) : id;\n if (container) container.classList.add('mapboxgl-map');\n this._canvas = new Canvas(this, container);\n },\n\n _setupControlPos: function() {\n var corners = this._controlCorners = {};\n var prefix = 'mapboxgl-ctrl-';\n var container = this.getContainer();\n\n function createCorner(pos) {\n var className = prefix + pos;\n corners[pos] = DOM.create('div', className, container);\n }\n\n if (container && typeof document === 'object') {\n createCorner('top-left');\n createCorner('top-right');\n createCorner('bottom-left');\n createCorner('bottom-right');\n }\n },\n\n _setupPainter: function() {\n var gl = this._canvas.getWebGLContext(this.options.failIfMajorPerformanceCaveat);\n\n if (!gl) {\n console.error('Failed to initialize WebGL');\n return;\n }\n\n this.painter = new GLPainter(gl, this.transform);\n },\n\n _contextLost: function(event) {\n event.preventDefault();\n if (this._frameId) {\n browser.cancelFrame(this._frameId);\n }\n },\n\n _contextRestored: function() {\n this._setupPainter();\n this.resize();\n this.update();\n },\n\n /**\n * Is this map fully loaded? If the style isn't loaded\n * or it has a change to the sources or style that isn't\n * propagated to its style, return false.\n *\n * @returns {boolean} whether the map is loaded\n */\n loaded: function() {\n if (this._styleDirty || this._sourcesDirty)\n return false;\n if (this.style && !this.style.loaded())\n return false;\n return true;\n },\n\n /**\n * Update this map's style and re-render the map.\n *\n * @param {Object} updateStyle new style\n * @returns {Map} this\n */\n update: function(updateStyle) {\n if (!this.style) return this;\n\n this._styleDirty = this._styleDirty || updateStyle;\n this._sourcesDirty = true;\n\n this._rerender();\n\n return this;\n },\n\n /**\n * Call when a (re-)render of the map is required, e.g. when the\n * user panned or zoomed,f or new data is available.\n * @returns {Map} this\n */\n render: function() {\n if (this.style && this._styleDirty) {\n this._styleDirty = false;\n this.style._recalculate(this.transform.zoom);\n }\n\n if (this.style && this._sourcesDirty && !this._sourcesDirtyTimeout) {\n this._sourcesDirty = false;\n this._sourcesDirtyTimeout = setTimeout(function() {\n this._sourcesDirtyTimeout = null;\n }.bind(this), 50);\n this.style._updateSources(this.transform);\n }\n\n this.painter.render(this.style, {\n debug: this.debug,\n vertices: this.vertices,\n rotating: this.rotating,\n zooming: this.zooming\n });\n\n this.fire('render');\n\n if (this.loaded() && !this._loaded) {\n this._loaded = true;\n this.fire('load');\n }\n\n this._frameId = null;\n\n if (!this.animationLoop.stopped()) {\n this._styleDirty = true;\n }\n\n if (this._sourcesDirty || this._repaint || !this.animationLoop.stopped()) {\n this._rerender();\n }\n\n return this;\n },\n\n /**\n * Destroys the map's underlying resources, including web workers.\n * @returns {Map} this\n */\n remove: function() {\n if (this._hash) this._hash.remove();\n browser.cancelFrame(this._frameId);\n clearTimeout(this._sourcesDirtyTimeout);\n this.setStyle(null);\n return this;\n },\n\n _rerender: function() {\n if (this.style && !this._frameId) {\n this._frameId = browser.frame(this.render);\n }\n },\n\n _forwardStyleEvent: function(e) {\n this.fire('style.' + e.type, util.extend({style: e.target}, e));\n },\n\n _forwardSourceEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardLayerEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _forwardTileEvent: function(e) {\n this.fire(e.type, util.extend({style: e.target}, e));\n },\n\n _onStyleLoad: function(e) {\n this.style._cascade(this._classes, {transition: false});\n this._forwardStyleEvent(e);\n },\n\n _onStyleChange: function(e) {\n this.update(true);\n this._forwardStyleEvent(e);\n },\n\n _onSourceAdd: function(e) {\n var source = e.source;\n if (source.onAdd)\n source.onAdd(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceRemove: function(e) {\n var source = e.source;\n if (source.onRemove)\n source.onRemove(this);\n this._forwardSourceEvent(e);\n },\n\n _onSourceUpdate: function(e) {\n this.update();\n this._forwardSourceEvent(e);\n }\n}","path":"js/ui/map.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/map.js#L474-L478"},"params":[{"title":"param","description":null,"type":{"type":"NameExpression","name":"Layer"},"name":"layer"},{"title":"param","description":"ID of an existing layer to insert before","type":{"type":"OptionalType","expression":{"type":"NameExpression","name":"string"}},"name":"before"}],"returns":[{"title":"returns","description":"`this`","type":{"type":"NameExpression","name":"Map"}}],"name":"addLayer","memberof":"Map","scope":"instance","members":{"instance":[],"static":[]},"path":["Map","addLayer"]}],"static":[]},"path":["Map"]},{"description":"Create a GeoJSON data source instance given an options object","tags":[{"title":"class","description":null,"type":null,"name":"GeoJSONSource"},{"title":"name","name":"GeoJSONSource"},{"title":"kind","kind":"class"}],"context":{"loc":{"start":{"line":35,"column":0},"end":{"line":53,"column":1}},"file":"/Users/tmcw/src/mapbox-gl-js/js/source/geojson_source.js","code":"'use strict';\n\nvar util = require('../util/util');\nvar Evented = require('../util/evented');\nvar TilePyramid = require('./tile_pyramid');\nvar Source = require('./source');\n\nmodule.exports = GeoJSONSource;\n\n/**\n * Create a GeoJSON data source instance given an options object\n * @class GeoJSONSource\n * @param {Object} [options]\n * @param {Object|String} options.data A GeoJSON data object or URL to it. The latter is preferable in case of large GeoJSON files.\n * @param {Number} [options.maxzoom=14] Maximum zoom to preserve detail at.\n * @example\n * var sourceObj = new mapboxgl.GeoJSONSource({\n * data: {\n * \"type\": \"FeatureCollection\",\n * \"features\": [{\n * \"type\": \"Feature\",\n * \"geometry\": {\n * \"type\": \"Point\",\n * \"coordinates\": [\n * -76.53063297271729,\n * 39.18174077994108\n * ]\n * }\n * }]\n * }\n * });\n * map.addSource('some id', sourceObj); // add\n * map.removeSource('some id'); // remove\n */\nfunction GeoJSONSource(options) {\n options = options || {};\n\n this._data = options.data;\n\n if (options.maxzoom !== undefined) this.maxzoom = options.maxzoom;\n\n this._pyramid = new TilePyramid({\n tileSize: 512,\n minzoom: this.minzoom,\n maxzoom: this.maxzoom,\n cacheSize: 20,\n load: this._loadTile.bind(this),\n abort: this._abortTile.bind(this),\n unload: this._unloadTile.bind(this),\n add: this._addTile.bind(this),\n remove: this._removeTile.bind(this)\n });\n}\n\nGeoJSONSource.prototype = util.inherit(Evented, /** @lends GeoJSONSource.prototype */{\n minzoom: 0,\n maxzoom: 14,\n _dirty: true,\n\n /**\n * Update source geojson data and rerender map\n *\n * @param {Object|String} data A GeoJSON data object or URL to it. The latter is preferable in case of large GeoJSON files.\n */\n setData: function(data) {\n this._data = data;\n this._dirty = true;\n\n this.fire('change');\n\n if (this.map)\n this.update(this.map.transform);\n\n return this;\n },\n\n onAdd: function(map) {\n this.map = map;\n },\n\n loaded: function() {\n return this._loaded && this._pyramid.loaded();\n },\n\n update: function(transform) {\n if (this._dirty) {\n this._updateData();\n }\n\n if (this._loaded) {\n this._pyramid.update(this.used, transform);\n }\n },\n\n reload: function() {\n this._pyramid.reload();\n },\n\n render: Source._renderTiles,\n featuresAt: Source._vectorFeaturesAt,\n\n _updateData: function() {\n this._dirty = false;\n\n this.workerID = this.dispatcher.send('parse geojson', {\n data: this._data,\n tileSize: 512,\n source: this.id,\n maxZoom: this.maxzoom\n }, function(err) {\n\n if (err) {\n this.fire('error', {error: err});\n return;\n }\n this._loaded = true;\n this._pyramid.reload();\n\n this.fire('change');\n }.bind(this));\n },\n\n _loadTile: function(tile) {\n var overscaling = tile.zoom > this.maxzoom ? Math.pow(2, tile.zoom - this.maxzoom) : 1;\n var params = {\n uid: tile.uid,\n id: tile.id,\n zoom: tile.zoom,\n maxZoom: this.maxzoom,\n tileSize: 512,\n source: this.id,\n overscaling: overscaling,\n angle: this.map.transform.angle,\n pitch: this.map.transform.pitch,\n collisionDebug: this.map.collisionDebug\n };\n\n tile.workerID = this.dispatcher.send('load geojson tile', params, function(err, data) {\n\n tile.unloadVectorData(this.map.painter);\n\n if (tile.aborted)\n return;\n\n if (err) {\n this.fire('tile.error', {tile: tile});\n return;\n }\n\n tile.loadVectorData(data);\n this.fire('tile.load', {tile: tile});\n\n }.bind(this), this.workerID);\n },\n\n _abortTile: function(tile) {\n tile.aborted = true;\n },\n\n _addTile: function(tile) {\n this.fire('tile.add', {tile: tile});\n },\n\n _removeTile: function(tile) {\n this.fire('tile.remove', {tile: tile});\n },\n\n _unloadTile: function(tile) {\n tile.unloadVectorData(this.map.painter);\n this.glyphAtlas.removeGlyphs(tile.uid);\n this.dispatcher.send('remove tile', { uid: tile.uid, source: this.id }, null, tile.workerID);\n }\n});","path":"js/source/geojson_source.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/source/geojson_source.js#L35-L53"},"name":"GeoJSONSource","kind":"class","members":{"instance":[{"description":"Update source geojson data and rerender map","tags":[{"title":"param","description":"A GeoJSON data object or URL to it. The latter is preferable in case of large GeoJSON files.","type":{"type":"UnionType","elements":[{"type":"NameExpression","name":"Object"},{"type":"NameExpression","name":"String"}]},"name":"data"},{"title":"name","name":"setData"},{"title":"memberof","description":"GeoJSONSource"},{"title":"instance"}],"context":{"loc":{"start":{"line":65,"column":4},"end":{"line":75,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/source/geojson_source.js","code":"{\n minzoom: 0,\n maxzoom: 14,\n _dirty: true,\n\n /**\n * Update source geojson data and rerender map\n *\n * @param {Object|String} data A GeoJSON data object or URL to it. The latter is preferable in case of large GeoJSON files.\n */\n setData: function(data) {\n this._data = data;\n this._dirty = true;\n\n this.fire('change');\n\n if (this.map)\n this.update(this.map.transform);\n\n return this;\n },\n\n onAdd: function(map) {\n this.map = map;\n },\n\n loaded: function() {\n return this._loaded && this._pyramid.loaded();\n },\n\n update: function(transform) {\n if (this._dirty) {\n this._updateData();\n }\n\n if (this._loaded) {\n this._pyramid.update(this.used, transform);\n }\n },\n\n reload: function() {\n this._pyramid.reload();\n },\n\n render: Source._renderTiles,\n featuresAt: Source._vectorFeaturesAt,\n\n _updateData: function() {\n this._dirty = false;\n\n this.workerID = this.dispatcher.send('parse geojson', {\n data: this._data,\n tileSize: 512,\n source: this.id,\n maxZoom: this.maxzoom\n }, function(err) {\n\n if (err) {\n this.fire('error', {error: err});\n return;\n }\n this._loaded = true;\n this._pyramid.reload();\n\n this.fire('change');\n }.bind(this));\n },\n\n _loadTile: function(tile) {\n var overscaling = tile.zoom > this.maxzoom ? Math.pow(2, tile.zoom - this.maxzoom) : 1;\n var params = {\n uid: tile.uid,\n id: tile.id,\n zoom: tile.zoom,\n maxZoom: this.maxzoom,\n tileSize: 512,\n source: this.id,\n overscaling: overscaling,\n angle: this.map.transform.angle,\n pitch: this.map.transform.pitch,\n collisionDebug: this.map.collisionDebug\n };\n\n tile.workerID = this.dispatcher.send('load geojson tile', params, function(err, data) {\n\n tile.unloadVectorData(this.map.painter);\n\n if (tile.aborted)\n return;\n\n if (err) {\n this.fire('tile.error', {tile: tile});\n return;\n }\n\n tile.loadVectorData(data);\n this.fire('tile.load', {tile: tile});\n\n }.bind(this), this.workerID);\n },\n\n _abortTile: function(tile) {\n tile.aborted = true;\n },\n\n _addTile: function(tile) {\n this.fire('tile.add', {tile: tile});\n },\n\n _removeTile: function(tile) {\n this.fire('tile.remove', {tile: tile});\n },\n\n _unloadTile: function(tile) {\n tile.unloadVectorData(this.map.painter);\n this.glyphAtlas.removeGlyphs(tile.uid);\n this.dispatcher.send('remove tile', { uid: tile.uid, source: this.id }, null, tile.workerID);\n }\n}","path":"js/source/geojson_source.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/source/geojson_source.js#L65-L75"},"params":[{"title":"param","description":"A GeoJSON data object or URL to it. The latter is preferable in case of large GeoJSON files.","type":{"type":"UnionType","elements":[{"type":"NameExpression","name":"Object"},{"type":"NameExpression","name":"String"}]},"name":"data"}],"name":"setData","memberof":"GeoJSONSource","scope":"instance","members":{"instance":[],"static":[]},"path":["GeoJSONSource","setData"]}],"static":[]},"path":["GeoJSONSource"]},{"description":"Creates a navigation control with zoom buttons and a compass","tags":[{"title":"class","description":null,"type":null,"name":"Navigation"},{"title":"name","name":"Navigation"},{"title":"kind","kind":"class"}],"context":{"loc":{"start":{"line":17,"column":0},"end":{"line":19,"column":1}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/control/navigation.js","code":"'use strict';\n\nvar Control = require('./control');\nvar DOM = require('../../util/dom');\nvar util = require('../../util/util');\n\nmodule.exports = Navigation;\n\n/**\n * Creates a navigation control with zoom buttons and a compass\n * @class Navigation\n * @param {Object} [options]\n * @param {String} [options.position=top-right] A string indicating the control's position on the map. Options are `top-right`, `top-left`, `bottom-right`, `bottom-left`\n * @example\n * map.addControl(new mapboxgl.Navigation({position: 'top-left'})); // position is optional\n */\nfunction Navigation(options) {\n util.setOptions(this, options);\n}\n\nNavigation.prototype = util.inherit(Control, {\n options: {\n position: 'top-right'\n },\n\n onAdd: function(map) {\n var className = 'mapboxgl-ctrl';\n\n var container = this._container = DOM.create('div', className + '-group', map.getContainer());\n\n this._zoomInButton = this._createButton(className + '-icon ' + className + '-zoom-in', map.zoomIn.bind(map));\n this._zoomOutButton = this._createButton(className + '-icon ' + className + '-zoom-out', map.zoomOut.bind(map));\n this._compass = this._createButton(className + '-compass', map.resetNorth.bind(map));\n\n var compassCanvas = this._compassCanvas = DOM.create('canvas', className + '-compass-canvas', this._compass);\n compassCanvas.style.cssText = 'width:26px; height:26px;';\n compassCanvas.width = 26 * 2;\n compassCanvas.height = 26 * 2;\n\n this._compass.addEventListener('mousedown', this._onCompassDown.bind(this));\n this._onCompassMove = this._onCompassMove.bind(this);\n this._onCompassUp = this._onCompassUp.bind(this);\n\n this._compassCtx = compassCanvas.getContext('2d');\n\n map.on('rotate', this._drawNorth.bind(this));\n this._drawNorth();\n\n return container;\n },\n\n _onCompassDown: function(e) {\n DOM.disableDrag();\n\n document.addEventListener('mousemove', this._onCompassMove);\n document.addEventListener('mouseup', this._onCompassUp);\n this._prevX = e.screenX;\n\n e.stopPropagation();\n },\n\n _onCompassMove: function(e) {\n var x = e.screenX,\n d = x < 2 ? -5 : // left edge of the screen, continue rotating\n x > window.screen.width - 2 ? 5 : // right edge\n (x - this._prevX) / 4;\n\n this._map.setBearing(this._map.getBearing() - d);\n this._prevX = e.screenX;\n this._moved = true;\n\n e.preventDefault();\n },\n\n _onCompassUp: function() {\n document.removeEventListener('mousemove', this._onCompassMove);\n document.removeEventListener('mouseup', this._onCompassUp);\n DOM.enableDrag();\n\n if (this._moved) {\n this._moved = false;\n DOM.suppressClick();\n }\n },\n\n _createButton: function(className, fn) {\n var a = DOM.create('button', className, this._container);\n a.addEventListener('click', function() { fn(); });\n return a;\n },\n\n _drawNorth: function() {\n var rad = 20,\n width = 8,\n center = 26,\n angle = this._map.transform.angle + (Math.PI / 2),\n ctx = this._compassCtx;\n\n this._compassCanvas.width = this._compassCanvas.width;\n\n ctx.translate(center, center);\n ctx.rotate(angle);\n\n ctx.beginPath();\n ctx.fillStyle = '#000';\n ctx.lineTo(0, -width);\n ctx.lineTo(-rad, 0);\n ctx.lineTo(0, width);\n ctx.fill();\n\n ctx.beginPath();\n ctx.fillStyle = '#bbb';\n ctx.moveTo(0, 0);\n ctx.lineTo(0, width);\n ctx.lineTo(rad, 0);\n ctx.lineTo(0, -width);\n ctx.fill();\n\n ctx.beginPath();\n ctx.strokeStyle = '#fff';\n ctx.lineWidth = 4;\n ctx.moveTo(0, -width);\n ctx.lineTo(0, width);\n ctx.stroke();\n }\n});","path":"js/ui/control/navigation.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/control/navigation.js#L17-L19"},"name":"Navigation","kind":"class","members":{"instance":[],"static":[]},"path":["Navigation"]},{"description":"A base class for map-related interface elements.","tags":[{"title":"class","description":null,"type":null,"name":"Control"},{"title":"name","name":"Control"},{"title":"kind","kind":"class"}],"context":{"loc":{"start":{"line":10,"column":0},"end":{"line":10,"column":21}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/control/control.js","code":"'use strict';\n\nmodule.exports = Control;\n\n/**\n * A base class for map-related interface elements.\n *\n * @class Control\n */\nfunction Control() {}\n\nControl.prototype = {\n /**\n * Add this control to the map, returning the control itself\n * for chaining. This will insert the control's DOM element into\n * the map's DOM element if the control has a `position` specified.\n *\n * @param {Map} map\n * @returns {Control} this\n */\n addTo: function(map) {\n this._map = map;\n var container = this._container = this.onAdd(map);\n if (this.options && this.options.position) {\n var pos = this.options.position;\n var corner = map._controlCorners[pos];\n container.className += ' mapboxgl-ctrl';\n if (pos.indexOf('bottom') !== -1) {\n corner.insertBefore(container, corner.firstChild);\n } else {\n corner.appendChild(container);\n }\n }\n\n return this;\n },\n\n /**\n * Remove this control from the map it has been added to.\n *\n * @returns {Control} this\n */\n remove: function() {\n this._container.parentNode.removeChild(this._container);\n if (this.onRemove) this.onRemove(this._map);\n this._map = null;\n return this;\n }\n};","path":"js/ui/control/control.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/control/control.js#L10-L10"},"name":"Control","kind":"class","members":{"instance":[{"description":"Remove this control from the map it has been added to.","tags":[{"title":"returns","description":"this","type":{"type":"NameExpression","name":"Control"}},{"title":"name","name":"remove"},{"title":"memberof","description":"Control"},{"title":"instance"}],"context":{"loc":{"start":{"line":43,"column":4},"end":{"line":48,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/control/control.js","code":"{\n /**\n * Add this control to the map, returning the control itself\n * for chaining. This will insert the control's DOM element into\n * the map's DOM element if the control has a `position` specified.\n *\n * @param {Map} map\n * @returns {Control} this\n */\n addTo: function(map) {\n this._map = map;\n var container = this._container = this.onAdd(map);\n if (this.options && this.options.position) {\n var pos = this.options.position;\n var corner = map._controlCorners[pos];\n container.className += ' mapboxgl-ctrl';\n if (pos.indexOf('bottom') !== -1) {\n corner.insertBefore(container, corner.firstChild);\n } else {\n corner.appendChild(container);\n }\n }\n\n return this;\n },\n\n /**\n * Remove this control from the map it has been added to.\n *\n * @returns {Control} this\n */\n remove: function() {\n this._container.parentNode.removeChild(this._container);\n if (this.onRemove) this.onRemove(this._map);\n this._map = null;\n return this;\n }\n}","path":"js/ui/control/control.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/control/control.js#L43-L48"},"returns":[{"title":"returns","description":"this","type":{"type":"NameExpression","name":"Control"}}],"name":"remove","memberof":"Control","scope":"instance","members":{"instance":[],"static":[]},"path":["Control","remove"]},{"description":"Add this control to the map, returning the control itself\nfor chaining. This will insert the control's DOM element into\nthe map's DOM element if the control has a `position` specified.","tags":[{"title":"param","description":null,"type":{"type":"NameExpression","name":"Map"},"name":"map"},{"title":"returns","description":"this","type":{"type":"NameExpression","name":"Control"}},{"title":"name","name":"addTo"},{"title":"memberof","description":"Control"},{"title":"instance"}],"context":{"loc":{"start":{"line":21,"column":4},"end":{"line":36,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/control/control.js","code":"{\n /**\n * Add this control to the map, returning the control itself\n * for chaining. This will insert the control's DOM element into\n * the map's DOM element if the control has a `position` specified.\n *\n * @param {Map} map\n * @returns {Control} this\n */\n addTo: function(map) {\n this._map = map;\n var container = this._container = this.onAdd(map);\n if (this.options && this.options.position) {\n var pos = this.options.position;\n var corner = map._controlCorners[pos];\n container.className += ' mapboxgl-ctrl';\n if (pos.indexOf('bottom') !== -1) {\n corner.insertBefore(container, corner.firstChild);\n } else {\n corner.appendChild(container);\n }\n }\n\n return this;\n },\n\n /**\n * Remove this control from the map it has been added to.\n *\n * @returns {Control} this\n */\n remove: function() {\n this._container.parentNode.removeChild(this._container);\n if (this.onRemove) this.onRemove(this._map);\n this._map = null;\n return this;\n }\n}","path":"js/ui/control/control.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/control/control.js#L21-L36"},"params":[{"title":"param","description":null,"type":{"type":"NameExpression","name":"Map"},"name":"map"}],"returns":[{"title":"returns","description":"this","type":{"type":"NameExpression","name":"Control"}}],"name":"addTo","memberof":"Control","scope":"instance","members":{"instance":[],"static":[]},"path":["Control","addTo"]}],"static":[]},"path":["Control"]},{"description":"Creates an attribution control","tags":[{"title":"class","description":null,"type":null,"name":"Attribution"},{"title":"augments","description":null,"type":null,"name":"Control"},{"title":"example","description":"map.addControl(new mapboxgl.Attribution());"},{"title":"name","name":"Attribution"},{"title":"kind","kind":"class"}],"context":{"loc":{"start":{"line":16,"column":0},"end":{"line":16,"column":25}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/control/attribution.js","code":"'use strict';\n\nvar Control = require('./control');\nvar DOM = require('../../util/dom');\nvar util = require('../../util/util');\n\nmodule.exports = Attribution;\n\n/**\n * Creates an attribution control\n * @class Attribution\n * @augments Control\n * @example\n * map.addControl(new mapboxgl.Attribution());\n */\nfunction Attribution() {}\n\nAttribution.prototype = util.inherit(Control, {\n options: {\n position: 'bottom-right'\n },\n\n onAdd: function(map) {\n var className = 'mapboxgl-ctrl-attrib',\n container = this._container = DOM.create('div', className, map.getContainer());\n\n this._update();\n map.on('source.load', this._update.bind(this));\n map.on('source.change', this._update.bind(this));\n map.on('source.remove', this._update.bind(this));\n map.on('moveend', this._updateEditLink.bind(this));\n\n return container;\n },\n\n _update: function() {\n var attributions = [];\n\n if (this._map.style) {\n for (var id in this._map.style.sources) {\n var source = this._map.style.sources[id];\n if (source.attribution && attributions.indexOf(source.attribution) < 0) {\n attributions.push(source.attribution);\n }\n }\n }\n\n this._container.innerHTML = attributions.join(' | ');\n this._editLink = this._container.getElementsByClassName('mapbox-improve-map')[0];\n this._updateEditLink();\n },\n\n _updateEditLink: function() {\n if (this._editLink) {\n var center = this._map.getCenter();\n this._editLink.href = 'https://www.mapbox.com/map-feedback/#/' +\n center.lng + '/' + center.lat + '/' + Math.round(this._map.getZoom() + 1);\n }\n }\n});","path":"js/ui/control/attribution.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/control/attribution.js#L16-L16"},"augments":[{"title":"augments","description":null,"type":null,"name":"Control"}],"examples":["map.addControl(new mapboxgl.Attribution());"],"name":"Attribution","kind":"class","members":{"instance":[],"static":[]},"path":["Attribution"]},{"description":"Create a latitude, longitude object from a given latitude and longitude pair in degrees.","tags":[{"title":"class","description":null,"type":null,"name":"LatLng"},{"title":"classdesc","description":"A representation of a latitude and longitude point, in degrees."},{"title":"param","description":"latitude","type":{"type":"NameExpression","name":"number"},"name":"lat"},{"title":"param","description":"longitude","type":{"type":"NameExpression","name":"number"},"name":"lng"},{"title":"example","description":"var latlng = new mapboxgl.LatLng(37.76, -122.44);"},{"title":"name","name":"LatLng"},{"title":"kind","kind":"class"}],"context":{"loc":{"start":{"line":18,"column":0},"end":{"line":24,"column":1}},"file":"/Users/tmcw/src/mapbox-gl-js/js/geo/lat_lng.js","code":"'use strict';\n\nmodule.exports = LatLng;\n\nvar wrap = require('../util/util').wrap;\n\n/**\n * Create a latitude, longitude object from a given latitude and longitude pair in degrees.\n *\n * @class LatLng\n * @classdesc A representation of a latitude and longitude point, in degrees.\n * @param {number} lat latitude\n * @param {number} lng longitude\n * @example\n * var latlng = new mapboxgl.LatLng(37.76, -122.44);\n *\n */\nfunction LatLng(lat, lng) {\n if (isNaN(lat) || isNaN(lng)) {\n throw new Error('Invalid LatLng object: (' + lat + ', ' + lng + ')');\n }\n this.lat = +lat;\n this.lng = +lng;\n}\n\n/**\n * Return a new `LatLng` object whose longitude is wrapped to the range (-180, 180).\n *\n * @returns {LatLng} wrapped LatLng object\n */\nLatLng.prototype.wrap = function () {\n return new LatLng(this.lat, wrap(this.lng, -180, 180));\n};\n\n/**\n * Convert an array to a `LatLng` object, or return an existing `LatLng` object\n * unchanged.\n *\n * @param {Array|LatLng} input `input` to convert\n * @returns {LatLng} LatLng object or original input\n */\nLatLng.convert = function (input) {\n if (input instanceof LatLng) {\n return input;\n }\n if (Array.isArray(input)) {\n return new LatLng(input[0], input[1]);\n }\n return input;\n};","path":"js/geo/lat_lng.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/geo/lat_lng.js#L18-L24"},"classdesc":"A representation of a latitude and longitude point, in degrees.","params":[{"title":"param","description":"latitude","type":{"type":"NameExpression","name":"number"},"name":"lat"},{"title":"param","description":"longitude","type":{"type":"NameExpression","name":"number"},"name":"lng"}],"examples":["var latlng = new mapboxgl.LatLng(37.76, -122.44);"],"name":"LatLng","kind":"class","members":{"instance":[{"description":"Return a new `LatLng` object whose longitude is wrapped to the range (-180, 180).","tags":[{"title":"returns","description":"wrapped LatLng object","type":{"type":"NameExpression","name":"LatLng"}},{"title":"name","name":"wrap"},{"title":"memberof","description":"LatLng"},{"title":"instance"}],"context":{"loc":{"start":{"line":31,"column":0},"end":{"line":33,"column":2}},"file":"/Users/tmcw/src/mapbox-gl-js/js/geo/lat_lng.js","code":"'use strict';\n\nmodule.exports = LatLng;\n\nvar wrap = require('../util/util').wrap;\n\n/**\n * Create a latitude, longitude object from a given latitude and longitude pair in degrees.\n *\n * @class LatLng\n * @classdesc A representation of a latitude and longitude point, in degrees.\n * @param {number} lat latitude\n * @param {number} lng longitude\n * @example\n * var latlng = new mapboxgl.LatLng(37.76, -122.44);\n *\n */\nfunction LatLng(lat, lng) {\n if (isNaN(lat) || isNaN(lng)) {\n throw new Error('Invalid LatLng object: (' + lat + ', ' + lng + ')');\n }\n this.lat = +lat;\n this.lng = +lng;\n}\n\n/**\n * Return a new `LatLng` object whose longitude is wrapped to the range (-180, 180).\n *\n * @returns {LatLng} wrapped LatLng object\n */\nLatLng.prototype.wrap = function () {\n return new LatLng(this.lat, wrap(this.lng, -180, 180));\n};\n\n/**\n * Convert an array to a `LatLng` object, or return an existing `LatLng` object\n * unchanged.\n *\n * @param {Array|LatLng} input `input` to convert\n * @returns {LatLng} LatLng object or original input\n */\nLatLng.convert = function (input) {\n if (input instanceof LatLng) {\n return input;\n }\n if (Array.isArray(input)) {\n return new LatLng(input[0], input[1]);\n }\n return input;\n};","path":"js/geo/lat_lng.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/geo/lat_lng.js#L31-L33"},"returns":[{"title":"returns","description":"wrapped LatLng object","type":{"type":"NameExpression","name":"LatLng"}}],"name":"wrap","memberof":"LatLng","scope":"instance","members":{"instance":[],"static":[]},"path":["LatLng","wrap"]}],"static":[{"description":"Convert an array to a `LatLng` object, or return an existing `LatLng` object\nunchanged.","tags":[{"title":"param","description":"`input` to convert","type":{"type":"UnionType","elements":[{"type":"TypeApplication","expression":{"type":"NameExpression","name":"Array"},"applications":[{"type":"NameExpression","name":"number"}]},{"type":"NameExpression","name":"LatLng"}]},"name":"input"},{"title":"returns","description":"LatLng object or original input","type":{"type":"NameExpression","name":"LatLng"}},{"title":"name","name":"convert"},{"title":"memberof","description":"LatLng"},{"title":"static"}],"context":{"loc":{"start":{"line":42,"column":0},"end":{"line":50,"column":2}},"file":"/Users/tmcw/src/mapbox-gl-js/js/geo/lat_lng.js","code":"'use strict';\n\nmodule.exports = LatLng;\n\nvar wrap = require('../util/util').wrap;\n\n/**\n * Create a latitude, longitude object from a given latitude and longitude pair in degrees.\n *\n * @class LatLng\n * @classdesc A representation of a latitude and longitude point, in degrees.\n * @param {number} lat latitude\n * @param {number} lng longitude\n * @example\n * var latlng = new mapboxgl.LatLng(37.76, -122.44);\n *\n */\nfunction LatLng(lat, lng) {\n if (isNaN(lat) || isNaN(lng)) {\n throw new Error('Invalid LatLng object: (' + lat + ', ' + lng + ')');\n }\n this.lat = +lat;\n this.lng = +lng;\n}\n\n/**\n * Return a new `LatLng` object whose longitude is wrapped to the range (-180, 180).\n *\n * @returns {LatLng} wrapped LatLng object\n */\nLatLng.prototype.wrap = function () {\n return new LatLng(this.lat, wrap(this.lng, -180, 180));\n};\n\n/**\n * Convert an array to a `LatLng` object, or return an existing `LatLng` object\n * unchanged.\n *\n * @param {Array|LatLng} input `input` to convert\n * @returns {LatLng} LatLng object or original input\n */\nLatLng.convert = function (input) {\n if (input instanceof LatLng) {\n return input;\n }\n if (Array.isArray(input)) {\n return new LatLng(input[0], input[1]);\n }\n return input;\n};","path":"js/geo/lat_lng.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/geo/lat_lng.js#L42-L50"},"params":[{"title":"param","description":"`input` to convert","type":{"type":"UnionType","elements":[{"type":"TypeApplication","expression":{"type":"NameExpression","name":"Array"},"applications":[{"type":"NameExpression","name":"number"}]},{"type":"NameExpression","name":"LatLng"}]},"name":"input"}],"returns":[{"title":"returns","description":"LatLng object or original input","type":{"type":"NameExpression","name":"LatLng"}}],"name":"convert","memberof":"LatLng","scope":"static","members":{"instance":[],"static":[]},"path":["LatLng","convert"]}]},"path":["LatLng"]},{"description":"Methods mixed in to other classes for event capabilities.","tags":[{"title":"mixin","description":null,"name":"Evented"},{"title":"name","name":"Evented"},{"title":"kind","kind":"mixin"}],"context":{"loc":{"start":{"line":9,"column":0},"end":{"line":100,"column":2}},"file":"/Users/tmcw/src/mapbox-gl-js/js/util/evented.js","code":"'use strict';\n\nvar util = require('./util');\n\n/**\n * Methods mixed in to other classes for event capabilities.\n * @mixin Evented\n */\nvar Evented = {\n\n /**\n * Subscribe to a specified event with a listener function the latter gets the data object that was passed to `fire` and additionally `target` and `type` properties\n *\n * @param {String} type Event type\n * @param {Function} listener Function to be called when the event is fired\n */\n on: function(type, fn) {\n this._events = this._events || {};\n this._events[type] = this._events[type] || [];\n this._events[type].push(fn);\n\n return this;\n },\n\n /**\n * Remove a event listener\n *\n * @param {String} [type] Event type. If none is specified, remove all listeners\n * @param {Function} [listener] Function to be called when the event is fired. If none is specified all listeners are removed\n */\n off: function(type, fn) {\n if (!type) {\n // clear all listeners if no arguments specified\n delete this._events;\n return this;\n }\n\n if (!this.listens(type)) return this;\n\n if (fn) {\n var idx = this._events[type].indexOf(fn);\n if (idx >= 0) {\n this._events[type].splice(idx, 1);\n }\n if (!this._events[type].length) {\n delete this._events[type];\n }\n } else {\n delete this._events[type];\n }\n\n return this;\n },\n\n /**\n * Call a function once when an event has fired\n *\n * @param {String} type Event type.\n * @param {Function} listener Function to be called once when the event is fired\n */\n once: function(type, fn) {\n var wrapper = function(data) {\n this.off(type, wrapper);\n fn.call(this, data);\n }.bind(this);\n this.on(type, wrapper);\n return this;\n },\n\n /**\n * Fire event of a given string type with the given data object\n *\n * @param {String} type The event name\n * @param {Object} [data] Optional data passed down to the event object\n * @returns {Boolean} Returns true if the object listens to an event of a particular type\n */\n fire: function(type, data) {\n if (!this.listens(type)) return this;\n\n data = util.extend({}, data);\n util.extend(data, {type: type, target: this});\n\n // make sure adding/removing listeners inside other listeners won't cause infinite loop\n var listeners = this._events[type].slice();\n\n for (var i = 0; i < listeners.length; i++) {\n listeners[i].call(this, data);\n }\n\n return this;\n },\n\n /**\n * Check if an event is registered to a type\n * @returns {Boolean} Returns true if the object listens to an event of a particular type\n */\n listens: function(type) {\n return !!(this._events && this._events[type]);\n }\n};\n\nmodule.exports = Evented;","path":"js/util/evented.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/util/evented.js#L9-L100"},"name":"Evented","kind":"mixin","members":{"instance":[],"static":[{"description":"Check if an event is registered to a type","tags":[{"title":"returns","description":"Returns true if the object listens to an event of a particular type","type":{"type":"NameExpression","name":"Boolean"}},{"title":"name","name":"listens"},{"title":"memberof","description":"Evented"},{"title":"static"}],"context":{"loc":{"start":{"line":97,"column":4},"end":{"line":99,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/util/evented.js","code":"{\n\n /**\n * Subscribe to a specified event with a listener function the latter gets the data object that was passed to `fire` and additionally `target` and `type` properties\n *\n * @param {String} type Event type\n * @param {Function} listener Function to be called when the event is fired\n */\n on: function(type, fn) {\n this._events = this._events || {};\n this._events[type] = this._events[type] || [];\n this._events[type].push(fn);\n\n return this;\n },\n\n /**\n * Remove a event listener\n *\n * @param {String} [type] Event type. If none is specified, remove all listeners\n * @param {Function} [listener] Function to be called when the event is fired. If none is specified all listeners are removed\n */\n off: function(type, fn) {\n if (!type) {\n // clear all listeners if no arguments specified\n delete this._events;\n return this;\n }\n\n if (!this.listens(type)) return this;\n\n if (fn) {\n var idx = this._events[type].indexOf(fn);\n if (idx >= 0) {\n this._events[type].splice(idx, 1);\n }\n if (!this._events[type].length) {\n delete this._events[type];\n }\n } else {\n delete this._events[type];\n }\n\n return this;\n },\n\n /**\n * Call a function once when an event has fired\n *\n * @param {String} type Event type.\n * @param {Function} listener Function to be called once when the event is fired\n */\n once: function(type, fn) {\n var wrapper = function(data) {\n this.off(type, wrapper);\n fn.call(this, data);\n }.bind(this);\n this.on(type, wrapper);\n return this;\n },\n\n /**\n * Fire event of a given string type with the given data object\n *\n * @param {String} type The event name\n * @param {Object} [data] Optional data passed down to the event object\n * @returns {Boolean} Returns true if the object listens to an event of a particular type\n */\n fire: function(type, data) {\n if (!this.listens(type)) return this;\n\n data = util.extend({}, data);\n util.extend(data, {type: type, target: this});\n\n // make sure adding/removing listeners inside other listeners won't cause infinite loop\n var listeners = this._events[type].slice();\n\n for (var i = 0; i < listeners.length; i++) {\n listeners[i].call(this, data);\n }\n\n return this;\n },\n\n /**\n * Check if an event is registered to a type\n * @returns {Boolean} Returns true if the object listens to an event of a particular type\n */\n listens: function(type) {\n return !!(this._events && this._events[type]);\n }\n}","path":"js/util/evented.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/util/evented.js#L97-L99"},"returns":[{"title":"returns","description":"Returns true if the object listens to an event of a particular type","type":{"type":"NameExpression","name":"Boolean"}}],"name":"listens","memberof":"Evented","scope":"static","members":{"instance":[],"static":[]},"path":["Evented","listens"]},{"description":"Call a function once when an event has fired","tags":[{"title":"param","description":"Event type.","type":{"type":"NameExpression","name":"String"},"name":"type"},{"title":"param","description":"Function to be called once when the event is fired","type":{"type":"NameExpression","name":"Function"},"name":"listener"},{"title":"name","name":"once"},{"title":"memberof","description":"Evented"},{"title":"static"}],"context":{"loc":{"start":{"line":61,"column":4},"end":{"line":68,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/util/evented.js","code":"{\n\n /**\n * Subscribe to a specified event with a listener function the latter gets the data object that was passed to `fire` and additionally `target` and `type` properties\n *\n * @param {String} type Event type\n * @param {Function} listener Function to be called when the event is fired\n */\n on: function(type, fn) {\n this._events = this._events || {};\n this._events[type] = this._events[type] || [];\n this._events[type].push(fn);\n\n return this;\n },\n\n /**\n * Remove a event listener\n *\n * @param {String} [type] Event type. If none is specified, remove all listeners\n * @param {Function} [listener] Function to be called when the event is fired. If none is specified all listeners are removed\n */\n off: function(type, fn) {\n if (!type) {\n // clear all listeners if no arguments specified\n delete this._events;\n return this;\n }\n\n if (!this.listens(type)) return this;\n\n if (fn) {\n var idx = this._events[type].indexOf(fn);\n if (idx >= 0) {\n this._events[type].splice(idx, 1);\n }\n if (!this._events[type].length) {\n delete this._events[type];\n }\n } else {\n delete this._events[type];\n }\n\n return this;\n },\n\n /**\n * Call a function once when an event has fired\n *\n * @param {String} type Event type.\n * @param {Function} listener Function to be called once when the event is fired\n */\n once: function(type, fn) {\n var wrapper = function(data) {\n this.off(type, wrapper);\n fn.call(this, data);\n }.bind(this);\n this.on(type, wrapper);\n return this;\n },\n\n /**\n * Fire event of a given string type with the given data object\n *\n * @param {String} type The event name\n * @param {Object} [data] Optional data passed down to the event object\n * @returns {Boolean} Returns true if the object listens to an event of a particular type\n */\n fire: function(type, data) {\n if (!this.listens(type)) return this;\n\n data = util.extend({}, data);\n util.extend(data, {type: type, target: this});\n\n // make sure adding/removing listeners inside other listeners won't cause infinite loop\n var listeners = this._events[type].slice();\n\n for (var i = 0; i < listeners.length; i++) {\n listeners[i].call(this, data);\n }\n\n return this;\n },\n\n /**\n * Check if an event is registered to a type\n * @returns {Boolean} Returns true if the object listens to an event of a particular type\n */\n listens: function(type) {\n return !!(this._events && this._events[type]);\n }\n}","path":"js/util/evented.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/util/evented.js#L61-L68"},"params":[{"title":"param","description":"Event type.","type":{"type":"NameExpression","name":"String"},"name":"type"},{"title":"param","description":"Function to be called once when the event is fired","type":{"type":"NameExpression","name":"Function"},"name":"listener"}],"name":"once","memberof":"Evented","scope":"static","members":{"instance":[],"static":[]},"path":["Evented","once"]},{"description":"Remove a event listener","tags":[{"title":"name","name":"off"},{"title":"memberof","description":"Evented"},{"title":"static"}],"context":{"loc":{"start":{"line":31,"column":4},"end":{"line":53,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/util/evented.js","code":"{\n\n /**\n * Subscribe to a specified event with a listener function the latter gets the data object that was passed to `fire` and additionally `target` and `type` properties\n *\n * @param {String} type Event type\n * @param {Function} listener Function to be called when the event is fired\n */\n on: function(type, fn) {\n this._events = this._events || {};\n this._events[type] = this._events[type] || [];\n this._events[type].push(fn);\n\n return this;\n },\n\n /**\n * Remove a event listener\n *\n * @param {String} [type] Event type. If none is specified, remove all listeners\n * @param {Function} [listener] Function to be called when the event is fired. If none is specified all listeners are removed\n */\n off: function(type, fn) {\n if (!type) {\n // clear all listeners if no arguments specified\n delete this._events;\n return this;\n }\n\n if (!this.listens(type)) return this;\n\n if (fn) {\n var idx = this._events[type].indexOf(fn);\n if (idx >= 0) {\n this._events[type].splice(idx, 1);\n }\n if (!this._events[type].length) {\n delete this._events[type];\n }\n } else {\n delete this._events[type];\n }\n\n return this;\n },\n\n /**\n * Call a function once when an event has fired\n *\n * @param {String} type Event type.\n * @param {Function} listener Function to be called once when the event is fired\n */\n once: function(type, fn) {\n var wrapper = function(data) {\n this.off(type, wrapper);\n fn.call(this, data);\n }.bind(this);\n this.on(type, wrapper);\n return this;\n },\n\n /**\n * Fire event of a given string type with the given data object\n *\n * @param {String} type The event name\n * @param {Object} [data] Optional data passed down to the event object\n * @returns {Boolean} Returns true if the object listens to an event of a particular type\n */\n fire: function(type, data) {\n if (!this.listens(type)) return this;\n\n data = util.extend({}, data);\n util.extend(data, {type: type, target: this});\n\n // make sure adding/removing listeners inside other listeners won't cause infinite loop\n var listeners = this._events[type].slice();\n\n for (var i = 0; i < listeners.length; i++) {\n listeners[i].call(this, data);\n }\n\n return this;\n },\n\n /**\n * Check if an event is registered to a type\n * @returns {Boolean} Returns true if the object listens to an event of a particular type\n */\n listens: function(type) {\n return !!(this._events && this._events[type]);\n }\n}","path":"js/util/evented.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/util/evented.js#L31-L53"},"name":"off","memberof":"Evented","scope":"static","members":{"instance":[],"static":[]},"path":["Evented","off"]},{"description":"Subscribe to a specified event with a listener function the latter gets the data object that was passed to `fire` and additionally `target` and `type` properties","tags":[{"title":"param","description":"Event type","type":{"type":"NameExpression","name":"String"},"name":"type"},{"title":"param","description":"Function to be called when the event is fired","type":{"type":"NameExpression","name":"Function"},"name":"listener"},{"title":"name","name":"on"},{"title":"memberof","description":"Evented"},{"title":"static"}],"context":{"loc":{"start":{"line":17,"column":4},"end":{"line":23,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/util/evented.js","code":"{\n\n /**\n * Subscribe to a specified event with a listener function the latter gets the data object that was passed to `fire` and additionally `target` and `type` properties\n *\n * @param {String} type Event type\n * @param {Function} listener Function to be called when the event is fired\n */\n on: function(type, fn) {\n this._events = this._events || {};\n this._events[type] = this._events[type] || [];\n this._events[type].push(fn);\n\n return this;\n },\n\n /**\n * Remove a event listener\n *\n * @param {String} [type] Event type. If none is specified, remove all listeners\n * @param {Function} [listener] Function to be called when the event is fired. If none is specified all listeners are removed\n */\n off: function(type, fn) {\n if (!type) {\n // clear all listeners if no arguments specified\n delete this._events;\n return this;\n }\n\n if (!this.listens(type)) return this;\n\n if (fn) {\n var idx = this._events[type].indexOf(fn);\n if (idx >= 0) {\n this._events[type].splice(idx, 1);\n }\n if (!this._events[type].length) {\n delete this._events[type];\n }\n } else {\n delete this._events[type];\n }\n\n return this;\n },\n\n /**\n * Call a function once when an event has fired\n *\n * @param {String} type Event type.\n * @param {Function} listener Function to be called once when the event is fired\n */\n once: function(type, fn) {\n var wrapper = function(data) {\n this.off(type, wrapper);\n fn.call(this, data);\n }.bind(this);\n this.on(type, wrapper);\n return this;\n },\n\n /**\n * Fire event of a given string type with the given data object\n *\n * @param {String} type The event name\n * @param {Object} [data] Optional data passed down to the event object\n * @returns {Boolean} Returns true if the object listens to an event of a particular type\n */\n fire: function(type, data) {\n if (!this.listens(type)) return this;\n\n data = util.extend({}, data);\n util.extend(data, {type: type, target: this});\n\n // make sure adding/removing listeners inside other listeners won't cause infinite loop\n var listeners = this._events[type].slice();\n\n for (var i = 0; i < listeners.length; i++) {\n listeners[i].call(this, data);\n }\n\n return this;\n },\n\n /**\n * Check if an event is registered to a type\n * @returns {Boolean} Returns true if the object listens to an event of a particular type\n */\n listens: function(type) {\n return !!(this._events && this._events[type]);\n }\n}","path":"js/util/evented.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/util/evented.js#L17-L23"},"params":[{"title":"param","description":"Event type","type":{"type":"NameExpression","name":"String"},"name":"type"},{"title":"param","description":"Function to be called when the event is fired","type":{"type":"NameExpression","name":"Function"},"name":"listener"}],"name":"on","memberof":"Evented","scope":"static","members":{"instance":[],"static":[]},"path":["Evented","on"]},{"description":"Fire event of a given string type with the given data object","tags":[{"title":"param","description":"The event name","type":{"type":"NameExpression","name":"String"},"name":"type"},{"title":"name","name":"fire"},{"title":"memberof","description":"Evented"},{"title":"static"}],"context":{"loc":{"start":{"line":77,"column":4},"end":{"line":91,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/util/evented.js","code":"{\n\n /**\n * Subscribe to a specified event with a listener function the latter gets the data object that was passed to `fire` and additionally `target` and `type` properties\n *\n * @param {String} type Event type\n * @param {Function} listener Function to be called when the event is fired\n */\n on: function(type, fn) {\n this._events = this._events || {};\n this._events[type] = this._events[type] || [];\n this._events[type].push(fn);\n\n return this;\n },\n\n /**\n * Remove a event listener\n *\n * @param {String} [type] Event type. If none is specified, remove all listeners\n * @param {Function} [listener] Function to be called when the event is fired. If none is specified all listeners are removed\n */\n off: function(type, fn) {\n if (!type) {\n // clear all listeners if no arguments specified\n delete this._events;\n return this;\n }\n\n if (!this.listens(type)) return this;\n\n if (fn) {\n var idx = this._events[type].indexOf(fn);\n if (idx >= 0) {\n this._events[type].splice(idx, 1);\n }\n if (!this._events[type].length) {\n delete this._events[type];\n }\n } else {\n delete this._events[type];\n }\n\n return this;\n },\n\n /**\n * Call a function once when an event has fired\n *\n * @param {String} type Event type.\n * @param {Function} listener Function to be called once when the event is fired\n */\n once: function(type, fn) {\n var wrapper = function(data) {\n this.off(type, wrapper);\n fn.call(this, data);\n }.bind(this);\n this.on(type, wrapper);\n return this;\n },\n\n /**\n * Fire event of a given string type with the given data object\n *\n * @param {String} type The event name\n * @param {Object} [data] Optional data passed down to the event object\n * @returns {Boolean} Returns true if the object listens to an event of a particular type\n */\n fire: function(type, data) {\n if (!this.listens(type)) return this;\n\n data = util.extend({}, data);\n util.extend(data, {type: type, target: this});\n\n // make sure adding/removing listeners inside other listeners won't cause infinite loop\n var listeners = this._events[type].slice();\n\n for (var i = 0; i < listeners.length; i++) {\n listeners[i].call(this, data);\n }\n\n return this;\n },\n\n /**\n * Check if an event is registered to a type\n * @returns {Boolean} Returns true if the object listens to an event of a particular type\n */\n listens: function(type) {\n return !!(this._events && this._events[type]);\n }\n}","path":"js/util/evented.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/util/evented.js#L77-L91"},"params":[{"title":"param","description":"The event name","type":{"type":"NameExpression","name":"String"},"name":"type"}],"name":"fire","memberof":"Evented","scope":"static","members":{"instance":[],"static":[]},"path":["Evented","fire"]}]},"path":["Evented"]},{"description":"Creates a bounding box from the given pair of points. If parameteres are omitted, a `null` bounding box is created.","tags":[{"title":"class","description":null,"type":null,"name":"LatLngBounds"},{"title":"classdesc","description":"A representation of rectangular box on the earth, defined by its southwest and northeast points in latitude and longitude."},{"title":"param","description":"southwest","type":{"type":"NameExpression","name":"LatLng"},"name":"sw"},{"title":"param","description":"northeast","type":{"type":"NameExpression","name":"LatLng"},"name":"ne"},{"title":"example","description":"var sw = new mapboxgl.LatLng(0, 0);\nvar ne = new mapboxgl.LatLng(10, -10);\nvar bounds = new mapboxgl.LatLngBounds(sw, ne);"},{"title":"name","name":"LatLngBounds"},{"title":"kind","kind":"class"}],"context":{"loc":{"start":{"line":20,"column":0},"end":{"line":28,"column":1}},"file":"/Users/tmcw/src/mapbox-gl-js/js/geo/lat_lng_bounds.js","code":"'use strict';\n\nmodule.exports = LatLngBounds;\n\nvar LatLng = require('./lat_lng');\n\n/**\n * Creates a bounding box from the given pair of points. If parameteres are omitted, a `null` bounding box is created.\n *\n * @class LatLngBounds\n * @classdesc A representation of rectangular box on the earth, defined by its southwest and northeast points in latitude and longitude.\n * @param {LatLng} sw southwest\n * @param {LatLng} ne northeast\n * @example\n * var sw = new mapboxgl.LatLng(0, 0);\n * var ne = new mapboxgl.LatLng(10, -10);\n * var bounds = new mapboxgl.LatLngBounds(sw, ne);\n *\n */\nfunction LatLngBounds(sw, ne) {\n if (!sw) return;\n\n var latlngs = ne ? [sw, ne] : sw;\n\n for (var i = 0, len = latlngs.length; i < len; i++) {\n this.extend(latlngs[i]);\n }\n}\n\nLatLngBounds.prototype = {\n\n /**\n * Extend the bounds to include a given LatLng or LatLngBounds.\n *\n * @param {LatLng|LatLngBounds} obj object to extend to\n * @returns {LatLngBounds} `this`\n */\n extend: function(obj) {\n var sw = this._sw,\n ne = this._ne,\n sw2, ne2;\n\n if (obj instanceof LatLng) {\n sw2 = obj;\n ne2 = obj;\n\n } else if (obj instanceof LatLngBounds) {\n sw2 = obj._sw;\n ne2 = obj._ne;\n\n if (!sw2 || !ne2) return this;\n\n } else {\n return obj ? this.extend(LatLng.convert(obj) || LatLngBounds.convert(obj)) : this;\n }\n\n if (!sw && !ne) {\n this._sw = new LatLng(sw2.lat, sw2.lng);\n this._ne = new LatLng(ne2.lat, ne2.lng);\n\n } else {\n sw.lat = Math.min(sw2.lat, sw.lat);\n sw.lng = Math.min(sw2.lng, sw.lng);\n ne.lat = Math.max(ne2.lat, ne.lat);\n ne.lng = Math.max(ne2.lng, ne.lng);\n }\n\n return this;\n },\n\n /**\n * Get the point equidistant from this box's corners\n * @returns {LatLng} centerpoint\n */\n getCenter: function() {\n return new LatLng((this._sw.lat + this._ne.lat) / 2, (this._sw.lng + this._ne.lng) / 2);\n },\n\n /**\n * Get southwest corner\n * @returns {LatLng} southwest\n */\n getSouthWest: function() { return this._sw; },\n\n /**\n * Get northeast corner\n * @returns {LatLng} northeast\n */\n getNorthEast: function() { return this._ne; },\n\n /**\n * Get northwest corner\n * @returns {LatLng} northwest\n */\n getNorthWest: function() { return new LatLng(this.getNorth(), this.getWest()); },\n\n /**\n * Get southeast corner\n * @returns {LatLng} southeast\n */\n getSouthEast: function() { return new LatLng(this.getSouth(), this.getEast()); },\n\n /**\n * Get west edge longitude\n * @returns {number} west\n */\n getWest: function() { return this._sw.lng; },\n\n /**\n * Get south edge latitude\n * @returns {number} south\n */\n getSouth: function() { return this._sw.lat; },\n\n /**\n * Get east edge longitude\n * @returns {number} east\n */\n getEast: function() { return this._ne.lng; },\n\n /**\n * Get north edge latitude\n * @returns {number} north\n */\n getNorth: function() { return this._ne.lat; }\n};\n\n// constructs LatLngBounds from an array if necessary\nLatLngBounds.convert = function (a) {\n if (!a || a instanceof LatLngBounds) return a;\n return new LatLngBounds(a);\n};","path":"js/geo/lat_lng_bounds.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/geo/lat_lng_bounds.js#L20-L28"},"classdesc":"A representation of rectangular box on the earth, defined by its southwest and northeast points in latitude and longitude.","params":[{"title":"param","description":"southwest","type":{"type":"NameExpression","name":"LatLng"},"name":"sw"},{"title":"param","description":"northeast","type":{"type":"NameExpression","name":"LatLng"},"name":"ne"}],"examples":["var sw = new mapboxgl.LatLng(0, 0);\nvar ne = new mapboxgl.LatLng(10, -10);\nvar bounds = new mapboxgl.LatLngBounds(sw, ne);"],"name":"LatLngBounds","kind":"class","members":{"instance":[{"description":"Get southwest corner","tags":[{"title":"returns","description":"southwest","type":{"type":"NameExpression","name":"LatLng"}},{"title":"name","name":"getSouthWest"},{"title":"memberof","description":"LatLngBounds"},{"title":"instance"}],"context":{"loc":{"start":{"line":83,"column":4},"end":{"line":83,"column":49}},"file":"/Users/tmcw/src/mapbox-gl-js/js/geo/lat_lng_bounds.js","code":"{\n\n /**\n * Extend the bounds to include a given LatLng or LatLngBounds.\n *\n * @param {LatLng|LatLngBounds} obj object to extend to\n * @returns {LatLngBounds} `this`\n */\n extend: function(obj) {\n var sw = this._sw,\n ne = this._ne,\n sw2, ne2;\n\n if (obj instanceof LatLng) {\n sw2 = obj;\n ne2 = obj;\n\n } else if (obj instanceof LatLngBounds) {\n sw2 = obj._sw;\n ne2 = obj._ne;\n\n if (!sw2 || !ne2) return this;\n\n } else {\n return obj ? this.extend(LatLng.convert(obj) || LatLngBounds.convert(obj)) : this;\n }\n\n if (!sw && !ne) {\n this._sw = new LatLng(sw2.lat, sw2.lng);\n this._ne = new LatLng(ne2.lat, ne2.lng);\n\n } else {\n sw.lat = Math.min(sw2.lat, sw.lat);\n sw.lng = Math.min(sw2.lng, sw.lng);\n ne.lat = Math.max(ne2.lat, ne.lat);\n ne.lng = Math.max(ne2.lng, ne.lng);\n }\n\n return this;\n },\n\n /**\n * Get the point equidistant from this box's corners\n * @returns {LatLng} centerpoint\n */\n getCenter: function() {\n return new LatLng((this._sw.lat + this._ne.lat) / 2, (this._sw.lng + this._ne.lng) / 2);\n },\n\n /**\n * Get southwest corner\n * @returns {LatLng} southwest\n */\n getSouthWest: function() { return this._sw; },\n\n /**\n * Get northeast corner\n * @returns {LatLng} northeast\n */\n getNorthEast: function() { return this._ne; },\n\n /**\n * Get northwest corner\n * @returns {LatLng} northwest\n */\n getNorthWest: function() { return new LatLng(this.getNorth(), this.getWest()); },\n\n /**\n * Get southeast corner\n * @returns {LatLng} southeast\n */\n getSouthEast: function() { return new LatLng(this.getSouth(), this.getEast()); },\n\n /**\n * Get west edge longitude\n * @returns {number} west\n */\n getWest: function() { return this._sw.lng; },\n\n /**\n * Get south edge latitude\n * @returns {number} south\n */\n getSouth: function() { return this._sw.lat; },\n\n /**\n * Get east edge longitude\n * @returns {number} east\n */\n getEast: function() { return this._ne.lng; },\n\n /**\n * Get north edge latitude\n * @returns {number} north\n */\n getNorth: function() { return this._ne.lat; }\n}","path":"js/geo/lat_lng_bounds.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/geo/lat_lng_bounds.js#L83-L83"},"returns":[{"title":"returns","description":"southwest","type":{"type":"NameExpression","name":"LatLng"}}],"name":"getSouthWest","memberof":"LatLngBounds","scope":"instance","members":{"instance":[],"static":[]},"path":["LatLngBounds","getSouthWest"]},{"description":"Get south edge latitude","tags":[{"title":"returns","description":"south","type":{"type":"NameExpression","name":"number"}},{"title":"name","name":"getSouth"},{"title":"memberof","description":"LatLngBounds"},{"title":"instance"}],"context":{"loc":{"start":{"line":113,"column":4},"end":{"line":113,"column":49}},"file":"/Users/tmcw/src/mapbox-gl-js/js/geo/lat_lng_bounds.js","code":"{\n\n /**\n * Extend the bounds to include a given LatLng or LatLngBounds.\n *\n * @param {LatLng|LatLngBounds} obj object to extend to\n * @returns {LatLngBounds} `this`\n */\n extend: function(obj) {\n var sw = this._sw,\n ne = this._ne,\n sw2, ne2;\n\n if (obj instanceof LatLng) {\n sw2 = obj;\n ne2 = obj;\n\n } else if (obj instanceof LatLngBounds) {\n sw2 = obj._sw;\n ne2 = obj._ne;\n\n if (!sw2 || !ne2) return this;\n\n } else {\n return obj ? this.extend(LatLng.convert(obj) || LatLngBounds.convert(obj)) : this;\n }\n\n if (!sw && !ne) {\n this._sw = new LatLng(sw2.lat, sw2.lng);\n this._ne = new LatLng(ne2.lat, ne2.lng);\n\n } else {\n sw.lat = Math.min(sw2.lat, sw.lat);\n sw.lng = Math.min(sw2.lng, sw.lng);\n ne.lat = Math.max(ne2.lat, ne.lat);\n ne.lng = Math.max(ne2.lng, ne.lng);\n }\n\n return this;\n },\n\n /**\n * Get the point equidistant from this box's corners\n * @returns {LatLng} centerpoint\n */\n getCenter: function() {\n return new LatLng((this._sw.lat + this._ne.lat) / 2, (this._sw.lng + this._ne.lng) / 2);\n },\n\n /**\n * Get southwest corner\n * @returns {LatLng} southwest\n */\n getSouthWest: function() { return this._sw; },\n\n /**\n * Get northeast corner\n * @returns {LatLng} northeast\n */\n getNorthEast: function() { return this._ne; },\n\n /**\n * Get northwest corner\n * @returns {LatLng} northwest\n */\n getNorthWest: function() { return new LatLng(this.getNorth(), this.getWest()); },\n\n /**\n * Get southeast corner\n * @returns {LatLng} southeast\n */\n getSouthEast: function() { return new LatLng(this.getSouth(), this.getEast()); },\n\n /**\n * Get west edge longitude\n * @returns {number} west\n */\n getWest: function() { return this._sw.lng; },\n\n /**\n * Get south edge latitude\n * @returns {number} south\n */\n getSouth: function() { return this._sw.lat; },\n\n /**\n * Get east edge longitude\n * @returns {number} east\n */\n getEast: function() { return this._ne.lng; },\n\n /**\n * Get north edge latitude\n * @returns {number} north\n */\n getNorth: function() { return this._ne.lat; }\n}","path":"js/geo/lat_lng_bounds.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/geo/lat_lng_bounds.js#L113-L113"},"returns":[{"title":"returns","description":"south","type":{"type":"NameExpression","name":"number"}}],"name":"getSouth","memberof":"LatLngBounds","scope":"instance","members":{"instance":[],"static":[]},"path":["LatLngBounds","getSouth"]},{"description":"Get northeast corner","tags":[{"title":"returns","description":"northeast","type":{"type":"NameExpression","name":"LatLng"}},{"title":"name","name":"getNorthEast"},{"title":"memberof","description":"LatLngBounds"},{"title":"instance"}],"context":{"loc":{"start":{"line":89,"column":4},"end":{"line":89,"column":49}},"file":"/Users/tmcw/src/mapbox-gl-js/js/geo/lat_lng_bounds.js","code":"{\n\n /**\n * Extend the bounds to include a given LatLng or LatLngBounds.\n *\n * @param {LatLng|LatLngBounds} obj object to extend to\n * @returns {LatLngBounds} `this`\n */\n extend: function(obj) {\n var sw = this._sw,\n ne = this._ne,\n sw2, ne2;\n\n if (obj instanceof LatLng) {\n sw2 = obj;\n ne2 = obj;\n\n } else if (obj instanceof LatLngBounds) {\n sw2 = obj._sw;\n ne2 = obj._ne;\n\n if (!sw2 || !ne2) return this;\n\n } else {\n return obj ? this.extend(LatLng.convert(obj) || LatLngBounds.convert(obj)) : this;\n }\n\n if (!sw && !ne) {\n this._sw = new LatLng(sw2.lat, sw2.lng);\n this._ne = new LatLng(ne2.lat, ne2.lng);\n\n } else {\n sw.lat = Math.min(sw2.lat, sw.lat);\n sw.lng = Math.min(sw2.lng, sw.lng);\n ne.lat = Math.max(ne2.lat, ne.lat);\n ne.lng = Math.max(ne2.lng, ne.lng);\n }\n\n return this;\n },\n\n /**\n * Get the point equidistant from this box's corners\n * @returns {LatLng} centerpoint\n */\n getCenter: function() {\n return new LatLng((this._sw.lat + this._ne.lat) / 2, (this._sw.lng + this._ne.lng) / 2);\n },\n\n /**\n * Get southwest corner\n * @returns {LatLng} southwest\n */\n getSouthWest: function() { return this._sw; },\n\n /**\n * Get northeast corner\n * @returns {LatLng} northeast\n */\n getNorthEast: function() { return this._ne; },\n\n /**\n * Get northwest corner\n * @returns {LatLng} northwest\n */\n getNorthWest: function() { return new LatLng(this.getNorth(), this.getWest()); },\n\n /**\n * Get southeast corner\n * @returns {LatLng} southeast\n */\n getSouthEast: function() { return new LatLng(this.getSouth(), this.getEast()); },\n\n /**\n * Get west edge longitude\n * @returns {number} west\n */\n getWest: function() { return this._sw.lng; },\n\n /**\n * Get south edge latitude\n * @returns {number} south\n */\n getSouth: function() { return this._sw.lat; },\n\n /**\n * Get east edge longitude\n * @returns {number} east\n */\n getEast: function() { return this._ne.lng; },\n\n /**\n * Get north edge latitude\n * @returns {number} north\n */\n getNorth: function() { return this._ne.lat; }\n}","path":"js/geo/lat_lng_bounds.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/geo/lat_lng_bounds.js#L89-L89"},"returns":[{"title":"returns","description":"northeast","type":{"type":"NameExpression","name":"LatLng"}}],"name":"getNorthEast","memberof":"LatLngBounds","scope":"instance","members":{"instance":[],"static":[]},"path":["LatLngBounds","getNorthEast"]},{"description":"Get northwest corner","tags":[{"title":"returns","description":"northwest","type":{"type":"NameExpression","name":"LatLng"}},{"title":"name","name":"getNorthWest"},{"title":"memberof","description":"LatLngBounds"},{"title":"instance"}],"context":{"loc":{"start":{"line":95,"column":4},"end":{"line":95,"column":84}},"file":"/Users/tmcw/src/mapbox-gl-js/js/geo/lat_lng_bounds.js","code":"{\n\n /**\n * Extend the bounds to include a given LatLng or LatLngBounds.\n *\n * @param {LatLng|LatLngBounds} obj object to extend to\n * @returns {LatLngBounds} `this`\n */\n extend: function(obj) {\n var sw = this._sw,\n ne = this._ne,\n sw2, ne2;\n\n if (obj instanceof LatLng) {\n sw2 = obj;\n ne2 = obj;\n\n } else if (obj instanceof LatLngBounds) {\n sw2 = obj._sw;\n ne2 = obj._ne;\n\n if (!sw2 || !ne2) return this;\n\n } else {\n return obj ? this.extend(LatLng.convert(obj) || LatLngBounds.convert(obj)) : this;\n }\n\n if (!sw && !ne) {\n this._sw = new LatLng(sw2.lat, sw2.lng);\n this._ne = new LatLng(ne2.lat, ne2.lng);\n\n } else {\n sw.lat = Math.min(sw2.lat, sw.lat);\n sw.lng = Math.min(sw2.lng, sw.lng);\n ne.lat = Math.max(ne2.lat, ne.lat);\n ne.lng = Math.max(ne2.lng, ne.lng);\n }\n\n return this;\n },\n\n /**\n * Get the point equidistant from this box's corners\n * @returns {LatLng} centerpoint\n */\n getCenter: function() {\n return new LatLng((this._sw.lat + this._ne.lat) / 2, (this._sw.lng + this._ne.lng) / 2);\n },\n\n /**\n * Get southwest corner\n * @returns {LatLng} southwest\n */\n getSouthWest: function() { return this._sw; },\n\n /**\n * Get northeast corner\n * @returns {LatLng} northeast\n */\n getNorthEast: function() { return this._ne; },\n\n /**\n * Get northwest corner\n * @returns {LatLng} northwest\n */\n getNorthWest: function() { return new LatLng(this.getNorth(), this.getWest()); },\n\n /**\n * Get southeast corner\n * @returns {LatLng} southeast\n */\n getSouthEast: function() { return new LatLng(this.getSouth(), this.getEast()); },\n\n /**\n * Get west edge longitude\n * @returns {number} west\n */\n getWest: function() { return this._sw.lng; },\n\n /**\n * Get south edge latitude\n * @returns {number} south\n */\n getSouth: function() { return this._sw.lat; },\n\n /**\n * Get east edge longitude\n * @returns {number} east\n */\n getEast: function() { return this._ne.lng; },\n\n /**\n * Get north edge latitude\n * @returns {number} north\n */\n getNorth: function() { return this._ne.lat; }\n}","path":"js/geo/lat_lng_bounds.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/geo/lat_lng_bounds.js#L95-L95"},"returns":[{"title":"returns","description":"northwest","type":{"type":"NameExpression","name":"LatLng"}}],"name":"getNorthWest","memberof":"LatLngBounds","scope":"instance","members":{"instance":[],"static":[]},"path":["LatLngBounds","getNorthWest"]},{"description":"Get southeast corner","tags":[{"title":"returns","description":"southeast","type":{"type":"NameExpression","name":"LatLng"}},{"title":"name","name":"getSouthEast"},{"title":"memberof","description":"LatLngBounds"},{"title":"instance"}],"context":{"loc":{"start":{"line":101,"column":4},"end":{"line":101,"column":84}},"file":"/Users/tmcw/src/mapbox-gl-js/js/geo/lat_lng_bounds.js","code":"{\n\n /**\n * Extend the bounds to include a given LatLng or LatLngBounds.\n *\n * @param {LatLng|LatLngBounds} obj object to extend to\n * @returns {LatLngBounds} `this`\n */\n extend: function(obj) {\n var sw = this._sw,\n ne = this._ne,\n sw2, ne2;\n\n if (obj instanceof LatLng) {\n sw2 = obj;\n ne2 = obj;\n\n } else if (obj instanceof LatLngBounds) {\n sw2 = obj._sw;\n ne2 = obj._ne;\n\n if (!sw2 || !ne2) return this;\n\n } else {\n return obj ? this.extend(LatLng.convert(obj) || LatLngBounds.convert(obj)) : this;\n }\n\n if (!sw && !ne) {\n this._sw = new LatLng(sw2.lat, sw2.lng);\n this._ne = new LatLng(ne2.lat, ne2.lng);\n\n } else {\n sw.lat = Math.min(sw2.lat, sw.lat);\n sw.lng = Math.min(sw2.lng, sw.lng);\n ne.lat = Math.max(ne2.lat, ne.lat);\n ne.lng = Math.max(ne2.lng, ne.lng);\n }\n\n return this;\n },\n\n /**\n * Get the point equidistant from this box's corners\n * @returns {LatLng} centerpoint\n */\n getCenter: function() {\n return new LatLng((this._sw.lat + this._ne.lat) / 2, (this._sw.lng + this._ne.lng) / 2);\n },\n\n /**\n * Get southwest corner\n * @returns {LatLng} southwest\n */\n getSouthWest: function() { return this._sw; },\n\n /**\n * Get northeast corner\n * @returns {LatLng} northeast\n */\n getNorthEast: function() { return this._ne; },\n\n /**\n * Get northwest corner\n * @returns {LatLng} northwest\n */\n getNorthWest: function() { return new LatLng(this.getNorth(), this.getWest()); },\n\n /**\n * Get southeast corner\n * @returns {LatLng} southeast\n */\n getSouthEast: function() { return new LatLng(this.getSouth(), this.getEast()); },\n\n /**\n * Get west edge longitude\n * @returns {number} west\n */\n getWest: function() { return this._sw.lng; },\n\n /**\n * Get south edge latitude\n * @returns {number} south\n */\n getSouth: function() { return this._sw.lat; },\n\n /**\n * Get east edge longitude\n * @returns {number} east\n */\n getEast: function() { return this._ne.lng; },\n\n /**\n * Get north edge latitude\n * @returns {number} north\n */\n getNorth: function() { return this._ne.lat; }\n}","path":"js/geo/lat_lng_bounds.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/geo/lat_lng_bounds.js#L101-L101"},"returns":[{"title":"returns","description":"southeast","type":{"type":"NameExpression","name":"LatLng"}}],"name":"getSouthEast","memberof":"LatLngBounds","scope":"instance","members":{"instance":[],"static":[]},"path":["LatLngBounds","getSouthEast"]},{"description":"Get west edge longitude","tags":[{"title":"returns","description":"west","type":{"type":"NameExpression","name":"number"}},{"title":"name","name":"getWest"},{"title":"memberof","description":"LatLngBounds"},{"title":"instance"}],"context":{"loc":{"start":{"line":107,"column":4},"end":{"line":107,"column":49}},"file":"/Users/tmcw/src/mapbox-gl-js/js/geo/lat_lng_bounds.js","code":"{\n\n /**\n * Extend the bounds to include a given LatLng or LatLngBounds.\n *\n * @param {LatLng|LatLngBounds} obj object to extend to\n * @returns {LatLngBounds} `this`\n */\n extend: function(obj) {\n var sw = this._sw,\n ne = this._ne,\n sw2, ne2;\n\n if (obj instanceof LatLng) {\n sw2 = obj;\n ne2 = obj;\n\n } else if (obj instanceof LatLngBounds) {\n sw2 = obj._sw;\n ne2 = obj._ne;\n\n if (!sw2 || !ne2) return this;\n\n } else {\n return obj ? this.extend(LatLng.convert(obj) || LatLngBounds.convert(obj)) : this;\n }\n\n if (!sw && !ne) {\n this._sw = new LatLng(sw2.lat, sw2.lng);\n this._ne = new LatLng(ne2.lat, ne2.lng);\n\n } else {\n sw.lat = Math.min(sw2.lat, sw.lat);\n sw.lng = Math.min(sw2.lng, sw.lng);\n ne.lat = Math.max(ne2.lat, ne.lat);\n ne.lng = Math.max(ne2.lng, ne.lng);\n }\n\n return this;\n },\n\n /**\n * Get the point equidistant from this box's corners\n * @returns {LatLng} centerpoint\n */\n getCenter: function() {\n return new LatLng((this._sw.lat + this._ne.lat) / 2, (this._sw.lng + this._ne.lng) / 2);\n },\n\n /**\n * Get southwest corner\n * @returns {LatLng} southwest\n */\n getSouthWest: function() { return this._sw; },\n\n /**\n * Get northeast corner\n * @returns {LatLng} northeast\n */\n getNorthEast: function() { return this._ne; },\n\n /**\n * Get northwest corner\n * @returns {LatLng} northwest\n */\n getNorthWest: function() { return new LatLng(this.getNorth(), this.getWest()); },\n\n /**\n * Get southeast corner\n * @returns {LatLng} southeast\n */\n getSouthEast: function() { return new LatLng(this.getSouth(), this.getEast()); },\n\n /**\n * Get west edge longitude\n * @returns {number} west\n */\n getWest: function() { return this._sw.lng; },\n\n /**\n * Get south edge latitude\n * @returns {number} south\n */\n getSouth: function() { return this._sw.lat; },\n\n /**\n * Get east edge longitude\n * @returns {number} east\n */\n getEast: function() { return this._ne.lng; },\n\n /**\n * Get north edge latitude\n * @returns {number} north\n */\n getNorth: function() { return this._ne.lat; }\n}","path":"js/geo/lat_lng_bounds.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/geo/lat_lng_bounds.js#L107-L107"},"returns":[{"title":"returns","description":"west","type":{"type":"NameExpression","name":"number"}}],"name":"getWest","memberof":"LatLngBounds","scope":"instance","members":{"instance":[],"static":[]},"path":["LatLngBounds","getWest"]},{"description":"Extend the bounds to include a given LatLng or LatLngBounds.","tags":[{"title":"param","description":"object to extend to","type":{"type":"UnionType","elements":[{"type":"NameExpression","name":"LatLng"},{"type":"NameExpression","name":"LatLngBounds"}]},"name":"obj"},{"title":"returns","description":"`this`","type":{"type":"NameExpression","name":"LatLngBounds"}},{"title":"name","name":"extend"},{"title":"memberof","description":"LatLngBounds"},{"title":"instance"}],"context":{"loc":{"start":{"line":38,"column":4},"end":{"line":69,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/geo/lat_lng_bounds.js","code":"{\n\n /**\n * Extend the bounds to include a given LatLng or LatLngBounds.\n *\n * @param {LatLng|LatLngBounds} obj object to extend to\n * @returns {LatLngBounds} `this`\n */\n extend: function(obj) {\n var sw = this._sw,\n ne = this._ne,\n sw2, ne2;\n\n if (obj instanceof LatLng) {\n sw2 = obj;\n ne2 = obj;\n\n } else if (obj instanceof LatLngBounds) {\n sw2 = obj._sw;\n ne2 = obj._ne;\n\n if (!sw2 || !ne2) return this;\n\n } else {\n return obj ? this.extend(LatLng.convert(obj) || LatLngBounds.convert(obj)) : this;\n }\n\n if (!sw && !ne) {\n this._sw = new LatLng(sw2.lat, sw2.lng);\n this._ne = new LatLng(ne2.lat, ne2.lng);\n\n } else {\n sw.lat = Math.min(sw2.lat, sw.lat);\n sw.lng = Math.min(sw2.lng, sw.lng);\n ne.lat = Math.max(ne2.lat, ne.lat);\n ne.lng = Math.max(ne2.lng, ne.lng);\n }\n\n return this;\n },\n\n /**\n * Get the point equidistant from this box's corners\n * @returns {LatLng} centerpoint\n */\n getCenter: function() {\n return new LatLng((this._sw.lat + this._ne.lat) / 2, (this._sw.lng + this._ne.lng) / 2);\n },\n\n /**\n * Get southwest corner\n * @returns {LatLng} southwest\n */\n getSouthWest: function() { return this._sw; },\n\n /**\n * Get northeast corner\n * @returns {LatLng} northeast\n */\n getNorthEast: function() { return this._ne; },\n\n /**\n * Get northwest corner\n * @returns {LatLng} northwest\n */\n getNorthWest: function() { return new LatLng(this.getNorth(), this.getWest()); },\n\n /**\n * Get southeast corner\n * @returns {LatLng} southeast\n */\n getSouthEast: function() { return new LatLng(this.getSouth(), this.getEast()); },\n\n /**\n * Get west edge longitude\n * @returns {number} west\n */\n getWest: function() { return this._sw.lng; },\n\n /**\n * Get south edge latitude\n * @returns {number} south\n */\n getSouth: function() { return this._sw.lat; },\n\n /**\n * Get east edge longitude\n * @returns {number} east\n */\n getEast: function() { return this._ne.lng; },\n\n /**\n * Get north edge latitude\n * @returns {number} north\n */\n getNorth: function() { return this._ne.lat; }\n}","path":"js/geo/lat_lng_bounds.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/geo/lat_lng_bounds.js#L38-L69"},"params":[{"title":"param","description":"object to extend to","type":{"type":"UnionType","elements":[{"type":"NameExpression","name":"LatLng"},{"type":"NameExpression","name":"LatLngBounds"}]},"name":"obj"}],"returns":[{"title":"returns","description":"`this`","type":{"type":"NameExpression","name":"LatLngBounds"}}],"name":"extend","memberof":"LatLngBounds","scope":"instance","members":{"instance":[],"static":[]},"path":["LatLngBounds","extend"]},{"description":"Get the point equidistant from this box's corners","tags":[{"title":"returns","description":"centerpoint","type":{"type":"NameExpression","name":"LatLng"}},{"title":"name","name":"getCenter"},{"title":"memberof","description":"LatLngBounds"},{"title":"instance"}],"context":{"loc":{"start":{"line":75,"column":4},"end":{"line":77,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/geo/lat_lng_bounds.js","code":"{\n\n /**\n * Extend the bounds to include a given LatLng or LatLngBounds.\n *\n * @param {LatLng|LatLngBounds} obj object to extend to\n * @returns {LatLngBounds} `this`\n */\n extend: function(obj) {\n var sw = this._sw,\n ne = this._ne,\n sw2, ne2;\n\n if (obj instanceof LatLng) {\n sw2 = obj;\n ne2 = obj;\n\n } else if (obj instanceof LatLngBounds) {\n sw2 = obj._sw;\n ne2 = obj._ne;\n\n if (!sw2 || !ne2) return this;\n\n } else {\n return obj ? this.extend(LatLng.convert(obj) || LatLngBounds.convert(obj)) : this;\n }\n\n if (!sw && !ne) {\n this._sw = new LatLng(sw2.lat, sw2.lng);\n this._ne = new LatLng(ne2.lat, ne2.lng);\n\n } else {\n sw.lat = Math.min(sw2.lat, sw.lat);\n sw.lng = Math.min(sw2.lng, sw.lng);\n ne.lat = Math.max(ne2.lat, ne.lat);\n ne.lng = Math.max(ne2.lng, ne.lng);\n }\n\n return this;\n },\n\n /**\n * Get the point equidistant from this box's corners\n * @returns {LatLng} centerpoint\n */\n getCenter: function() {\n return new LatLng((this._sw.lat + this._ne.lat) / 2, (this._sw.lng + this._ne.lng) / 2);\n },\n\n /**\n * Get southwest corner\n * @returns {LatLng} southwest\n */\n getSouthWest: function() { return this._sw; },\n\n /**\n * Get northeast corner\n * @returns {LatLng} northeast\n */\n getNorthEast: function() { return this._ne; },\n\n /**\n * Get northwest corner\n * @returns {LatLng} northwest\n */\n getNorthWest: function() { return new LatLng(this.getNorth(), this.getWest()); },\n\n /**\n * Get southeast corner\n * @returns {LatLng} southeast\n */\n getSouthEast: function() { return new LatLng(this.getSouth(), this.getEast()); },\n\n /**\n * Get west edge longitude\n * @returns {number} west\n */\n getWest: function() { return this._sw.lng; },\n\n /**\n * Get south edge latitude\n * @returns {number} south\n */\n getSouth: function() { return this._sw.lat; },\n\n /**\n * Get east edge longitude\n * @returns {number} east\n */\n getEast: function() { return this._ne.lng; },\n\n /**\n * Get north edge latitude\n * @returns {number} north\n */\n getNorth: function() { return this._ne.lat; }\n}","path":"js/geo/lat_lng_bounds.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/geo/lat_lng_bounds.js#L75-L77"},"returns":[{"title":"returns","description":"centerpoint","type":{"type":"NameExpression","name":"LatLng"}}],"name":"getCenter","memberof":"LatLngBounds","scope":"instance","members":{"instance":[],"static":[]},"path":["LatLngBounds","getCenter"]},{"description":"Get east edge longitude","tags":[{"title":"returns","description":"east","type":{"type":"NameExpression","name":"number"}},{"title":"name","name":"getEast"},{"title":"memberof","description":"LatLngBounds"},{"title":"instance"}],"context":{"loc":{"start":{"line":119,"column":4},"end":{"line":119,"column":49}},"file":"/Users/tmcw/src/mapbox-gl-js/js/geo/lat_lng_bounds.js","code":"{\n\n /**\n * Extend the bounds to include a given LatLng or LatLngBounds.\n *\n * @param {LatLng|LatLngBounds} obj object to extend to\n * @returns {LatLngBounds} `this`\n */\n extend: function(obj) {\n var sw = this._sw,\n ne = this._ne,\n sw2, ne2;\n\n if (obj instanceof LatLng) {\n sw2 = obj;\n ne2 = obj;\n\n } else if (obj instanceof LatLngBounds) {\n sw2 = obj._sw;\n ne2 = obj._ne;\n\n if (!sw2 || !ne2) return this;\n\n } else {\n return obj ? this.extend(LatLng.convert(obj) || LatLngBounds.convert(obj)) : this;\n }\n\n if (!sw && !ne) {\n this._sw = new LatLng(sw2.lat, sw2.lng);\n this._ne = new LatLng(ne2.lat, ne2.lng);\n\n } else {\n sw.lat = Math.min(sw2.lat, sw.lat);\n sw.lng = Math.min(sw2.lng, sw.lng);\n ne.lat = Math.max(ne2.lat, ne.lat);\n ne.lng = Math.max(ne2.lng, ne.lng);\n }\n\n return this;\n },\n\n /**\n * Get the point equidistant from this box's corners\n * @returns {LatLng} centerpoint\n */\n getCenter: function() {\n return new LatLng((this._sw.lat + this._ne.lat) / 2, (this._sw.lng + this._ne.lng) / 2);\n },\n\n /**\n * Get southwest corner\n * @returns {LatLng} southwest\n */\n getSouthWest: function() { return this._sw; },\n\n /**\n * Get northeast corner\n * @returns {LatLng} northeast\n */\n getNorthEast: function() { return this._ne; },\n\n /**\n * Get northwest corner\n * @returns {LatLng} northwest\n */\n getNorthWest: function() { return new LatLng(this.getNorth(), this.getWest()); },\n\n /**\n * Get southeast corner\n * @returns {LatLng} southeast\n */\n getSouthEast: function() { return new LatLng(this.getSouth(), this.getEast()); },\n\n /**\n * Get west edge longitude\n * @returns {number} west\n */\n getWest: function() { return this._sw.lng; },\n\n /**\n * Get south edge latitude\n * @returns {number} south\n */\n getSouth: function() { return this._sw.lat; },\n\n /**\n * Get east edge longitude\n * @returns {number} east\n */\n getEast: function() { return this._ne.lng; },\n\n /**\n * Get north edge latitude\n * @returns {number} north\n */\n getNorth: function() { return this._ne.lat; }\n}","path":"js/geo/lat_lng_bounds.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/geo/lat_lng_bounds.js#L119-L119"},"returns":[{"title":"returns","description":"east","type":{"type":"NameExpression","name":"number"}}],"name":"getEast","memberof":"LatLngBounds","scope":"instance","members":{"instance":[],"static":[]},"path":["LatLngBounds","getEast"]},{"description":"Get north edge latitude","tags":[{"title":"returns","description":"north","type":{"type":"NameExpression","name":"number"}},{"title":"name","name":"getNorth"},{"title":"memberof","description":"LatLngBounds"},{"title":"instance"}],"context":{"loc":{"start":{"line":125,"column":4},"end":{"line":125,"column":49}},"file":"/Users/tmcw/src/mapbox-gl-js/js/geo/lat_lng_bounds.js","code":"{\n\n /**\n * Extend the bounds to include a given LatLng or LatLngBounds.\n *\n * @param {LatLng|LatLngBounds} obj object to extend to\n * @returns {LatLngBounds} `this`\n */\n extend: function(obj) {\n var sw = this._sw,\n ne = this._ne,\n sw2, ne2;\n\n if (obj instanceof LatLng) {\n sw2 = obj;\n ne2 = obj;\n\n } else if (obj instanceof LatLngBounds) {\n sw2 = obj._sw;\n ne2 = obj._ne;\n\n if (!sw2 || !ne2) return this;\n\n } else {\n return obj ? this.extend(LatLng.convert(obj) || LatLngBounds.convert(obj)) : this;\n }\n\n if (!sw && !ne) {\n this._sw = new LatLng(sw2.lat, sw2.lng);\n this._ne = new LatLng(ne2.lat, ne2.lng);\n\n } else {\n sw.lat = Math.min(sw2.lat, sw.lat);\n sw.lng = Math.min(sw2.lng, sw.lng);\n ne.lat = Math.max(ne2.lat, ne.lat);\n ne.lng = Math.max(ne2.lng, ne.lng);\n }\n\n return this;\n },\n\n /**\n * Get the point equidistant from this box's corners\n * @returns {LatLng} centerpoint\n */\n getCenter: function() {\n return new LatLng((this._sw.lat + this._ne.lat) / 2, (this._sw.lng + this._ne.lng) / 2);\n },\n\n /**\n * Get southwest corner\n * @returns {LatLng} southwest\n */\n getSouthWest: function() { return this._sw; },\n\n /**\n * Get northeast corner\n * @returns {LatLng} northeast\n */\n getNorthEast: function() { return this._ne; },\n\n /**\n * Get northwest corner\n * @returns {LatLng} northwest\n */\n getNorthWest: function() { return new LatLng(this.getNorth(), this.getWest()); },\n\n /**\n * Get southeast corner\n * @returns {LatLng} southeast\n */\n getSouthEast: function() { return new LatLng(this.getSouth(), this.getEast()); },\n\n /**\n * Get west edge longitude\n * @returns {number} west\n */\n getWest: function() { return this._sw.lng; },\n\n /**\n * Get south edge latitude\n * @returns {number} south\n */\n getSouth: function() { return this._sw.lat; },\n\n /**\n * Get east edge longitude\n * @returns {number} east\n */\n getEast: function() { return this._ne.lng; },\n\n /**\n * Get north edge latitude\n * @returns {number} north\n */\n getNorth: function() { return this._ne.lat; }\n}","path":"js/geo/lat_lng_bounds.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/geo/lat_lng_bounds.js#L125-L125"},"returns":[{"title":"returns","description":"north","type":{"type":"NameExpression","name":"number"}}],"name":"getNorth","memberof":"LatLngBounds","scope":"instance","members":{"instance":[],"static":[]},"path":["LatLngBounds","getNorth"]}],"static":[]},"path":["LatLngBounds"]},{"description":"Create a Video data source instance given an options object","tags":[{"title":"class","description":null,"type":null,"name":"VideoSource"},{"title":"name","name":"VideoSource"},{"title":"kind","kind":"class"}],"context":{"loc":{"start":{"line":35,"column":0},"end":{"line":66,"column":1}},"file":"/Users/tmcw/src/mapbox-gl-js/js/source/video_source.js","code":"'use strict';\n\nvar util = require('../util/util');\nvar Tile = require('./tile');\nvar TileCoord = require('./tile_coord');\nvar LatLng = require('../geo/lat_lng');\nvar Point = require('point-geometry');\nvar Evented = require('../util/evented');\nvar ajax = require('../util/ajax');\n\nmodule.exports = VideoSource;\n\n/**\n * Create a Video data source instance given an options object\n * @class VideoSource\n * @param {Object} [options]\n * @param {String|Array} options.url A string or array of URL(s) to video files\n * @param {Array} options.coordinates lat,lng coordinates in order clockwise starting at the top left: tl, tr, br, bl\n * @example\n * var sourceObj = new mapboxgl.VideoSource({\n * url: [\n * 'https://www.mapbox.com/videos/baltimore-smoke.mp4',\n * 'https://www.mapbox.com/videos/baltimore-smoke.webm'\n * ],\n * coordinates: [\n * [39.18579907229748, -76.54335737228394],\n * [39.1838364847587, -76.52803659439087],\n * [39.17683392507606, -76.5295386314392],\n * [39.17876344106642, -76.54520273208618]\n * ]\n * });\n * map.addSource('some id', sourceObj); // add\n * map.removeSource('some id'); // remove\n */\nfunction VideoSource(options) {\n this.coordinates = options.coordinates;\n\n ajax.getVideo(options.url, function(err, video) {\n // @TODO handle errors via event.\n if (err) return;\n\n this.video = video;\n this.video.loop = true;\n\n var loopID;\n\n // start repainting when video starts playing\n this.video.addEventListener('playing', function() {\n loopID = this.map.style.animationLoop.set(Infinity);\n this.map._rerender();\n }.bind(this));\n\n // stop repainting when video stops\n this.video.addEventListener('pause', function() {\n this.map.style.animationLoop.cancel(loopID);\n }.bind(this));\n\n this._loaded = true;\n\n if (this.map) {\n this.video.play();\n this.createTile();\n this.fire('change');\n }\n }.bind(this));\n}\n\nVideoSource.prototype = util.inherit(Evented, {\n onAdd: function(map) {\n this.map = map;\n if (this.video) {\n this.video.play();\n this.createTile();\n }\n },\n\n createTile: function() {\n /*\n * Calculate which mercator tile is suitable for rendering the video in\n * and create a buffer with the corner coordinates. These coordinates\n * may be outside the tile, because raster tiles aren't clipped when rendering.\n */\n var map = this.map;\n var coords = this.coordinates.map(function(latlng) {\n var loc = LatLng.convert(latlng);\n return TileCoord.zoomTo(map.transform.locationCoordinate(loc), 0);\n });\n\n var minX = Infinity;\n var minY = Infinity;\n var maxX = -Infinity;\n var maxY = -Infinity;\n\n for (var i = 0; i < coords.length; i++) {\n minX = Math.min(minX, coords[i].column);\n minY = Math.min(minY, coords[i].row);\n maxX = Math.max(maxX, coords[i].column);\n maxY = Math.max(maxY, coords[i].row);\n }\n\n var dx = maxX - minX;\n var dy = maxY - minY;\n var dMax = Math.max(dx, dy);\n var center = TileCoord.zoomTo({\n column: (minX + maxX) / 2,\n row: (minY + maxY) / 2,\n zoom: 0\n }, Math.floor(-Math.log(dMax) / Math.LN2));\n\n var tileExtent = 4096;\n var tileCoords = coords.map(function(coord) {\n var zoomedCoord = TileCoord.zoomTo(coord, center.zoom);\n return new Point(\n Math.round((zoomedCoord.column - center.column) * tileExtent),\n Math.round((zoomedCoord.row - center.row) * tileExtent));\n });\n\n var gl = map.painter.gl;\n var maxInt16 = 32767;\n var array = new Int16Array([\n tileCoords[0].x, tileCoords[0].y, 0, 0,\n tileCoords[1].x, tileCoords[1].y, maxInt16, 0,\n tileCoords[3].x, tileCoords[3].y, 0, maxInt16,\n tileCoords[2].x, tileCoords[2].y, maxInt16, maxInt16\n ]);\n\n this.tile = new Tile();\n this.tile.buckets = {};\n\n this.tile.boundsBuffer = gl.createBuffer();\n gl.bindBuffer(gl.ARRAY_BUFFER, this.tile.boundsBuffer);\n gl.bufferData(gl.ARRAY_BUFFER, array, gl.STATIC_DRAW);\n\n this.center = center;\n },\n\n loaded: function() {\n return this.video && this.video.readyState >= 2;\n },\n\n update: function() {\n // noop\n },\n\n render: function(layers, painter) {\n if (!this._loaded) return;\n if (this.video.readyState < 2) return; // not enough data for current position\n\n var c = this.center;\n this.tile.calculateMatrices(c.zoom, c.column, c.row, this.map.transform, painter);\n\n var gl = painter.gl;\n if (!this.tile.texture) {\n this.tile.texture = gl.createTexture();\n gl.bindTexture(gl.TEXTURE_2D, this.tile.texture);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this.video);\n } else {\n gl.bindTexture(gl.TEXTURE_2D, this.tile.texture);\n gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, this.video);\n }\n\n painter.drawLayers(layers, this.tile.posMatrix, this.tile);\n },\n\n featuresAt: function(point, params, callback) {\n return callback(null, []);\n }\n});","path":"js/source/video_source.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/source/video_source.js#L35-L66"},"name":"VideoSource","kind":"class","members":{"instance":[],"static":[]},"path":["VideoSource"]},{"description":"","tags":[{"title":"typedef","description":"[animOptions]","type":{"type":"NameExpression","name":"Object"}},{"title":"name","name":"extend"},{"title":"kind","kind":"typedef"}],"context":{"loc":{"start":{"line":17,"column":0},"end":{"line":494,"column":3}},"file":"/Users/tmcw/src/mapbox-gl-js/js/ui/easings.js","code":"'use strict';\n\nvar util = require('../util/util');\nvar interpolate = require('../util/interpolate');\nvar browser = require('../util/browser');\nvar LatLng = require('../geo/lat_lng');\nvar LatLngBounds = require('../geo/lat_lng_bounds');\nvar Point = require('point-geometry');\n\n/**\n * @typedef {Object} [animOptions]\n * @param {Number} [animOptions.duration=500] Number in milliseconds\n * @param {Function} animOptions.easing\n * @param {Array} [animOptions.offset=[0,0]] point, origin of movement relative to map center\n * @param {Boolean} [animOptions.animate=true] When set to false, no animation happens\n */\nutil.extend(exports, /** @lends Map.prototype */{\n isEasing: function() {\n return !!this._abortFn;\n },\n\n /**\n * Stop current animation\n *\n * @returns {this}\n */\n stop: function() {\n if (this._abortFn) {\n this._abortFn.call(this);\n delete this._abortFn;\n\n this._finishFn.call(this);\n delete this._finishFn;\n }\n return this;\n },\n\n _ease: function(frame, finish, options) {\n this._finishFn = finish;\n this._abortFn = browser.timed(function (t) {\n frame.call(this, options.easing(t));\n if (t === 1) {\n delete this._abortFn;\n this._finishFn.call(this);\n delete this._finishFn;\n }\n }, options.animate === false ? 0 : options.duration, this);\n },\n\n /**\n * Pan by a certain number of pixels\n *\n * @param {Array} offset [x, y]\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n panBy: function(offset, options) {\n this.panTo(this.transform.center, util.extend({offset: Point.convert(offset).mult(-1)}, options));\n return this;\n },\n\n /**\n * Pan to a certain location with easing\n *\n * @param {Object} latlng a `LatLng` object\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n panTo: function(latlng, options) {\n this.stop();\n\n latlng = LatLng.convert(latlng);\n\n options = util.extend({\n duration: 500,\n easing: util.ease,\n offset: [0, 0]\n }, options);\n\n var tr = this.transform,\n offset = Point.convert(options.offset).rotate(-tr.angle),\n from = tr.point,\n to = tr.project(latlng).sub(offset);\n\n if (!options.noMoveStart) {\n this.fire('movestart');\n }\n\n this._ease(function(k) {\n tr.center = tr.unproject(from.add(to.sub(from).mult(k)));\n this._move();\n }, function() {\n this.fire('moveend');\n }, options);\n\n return this;\n },\n\n /**\n * Zooms to a certain zoom level with easing.\n *\n * @param {Number} zoom\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n zoomTo: function(zoom, options) {\n this.stop();\n\n options = util.extend({\n duration: 500\n }, options);\n\n options.easing = this._updateEasing(options.duration, zoom, options.easing);\n\n var tr = this.transform,\n around = tr.center,\n startZoom = tr.zoom;\n\n if (options.around) {\n around = LatLng.convert(options.around);\n } else if (options.offset) {\n around = tr.pointLocation(tr.centerPoint.add(Point.convert(options.offset)));\n }\n\n if (options.animate === false) options.duration = 0;\n\n if (!this.zooming) {\n this.zooming = true;\n this.fire('movestart');\n }\n\n this._ease(function(k) {\n tr.setZoomAround(interpolate(startZoom, zoom, k), around);\n this.animationLoop.set(300); // text fading\n this._move(true);\n }, function() {\n this.ease = null;\n if (options.duration >= 200) {\n this.zooming = false;\n this.fire('moveend');\n }\n }, options);\n\n if (options.duration < 200) {\n clearTimeout(this._onZoomEnd);\n this._onZoomEnd = setTimeout(function() {\n this.zooming = false;\n this._rerender();\n this.fire('moveend');\n }.bind(this), 200);\n }\n\n return this;\n },\n\n /**\n * Zoom in by 1 level\n *\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n zoomIn: function(options) {\n this.zoomTo(this.getZoom() + 1, options);\n },\n\n /**\n * Zoom out by 1 level\n *\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n zoomOut: function(options) {\n this.zoomTo(this.getZoom() - 1, options);\n },\n\n /**\n * Rotate bearing by a certain number of degrees with easing\n *\n * @param {Number} bearing\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n rotateTo: function(bearing, options) {\n this.stop();\n\n options = util.extend({\n duration: 500,\n easing: util.ease\n }, options);\n\n var tr = this.transform,\n start = this.getBearing(),\n around = tr.center;\n\n if (options.around) {\n around = LatLng.convert(options.around);\n } else if (options.offset) {\n around = tr.pointLocation(tr.centerPoint.add(Point.convert(options.offset)));\n }\n\n bearing = this._normalizeBearing(bearing, start);\n\n this.rotating = true;\n this.fire('movestart');\n\n this._ease(function(k) {\n tr.setBearingAround(interpolate(start, bearing, k), around);\n this._move(false, true);\n }, function() {\n this.rotating = false;\n this.fire('moveend');\n }, options);\n\n return this;\n },\n\n /**\n * Sets map bearing to 0 (north) with easing\n *\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n resetNorth: function(options) {\n return this.rotateTo(0, util.extend({duration: 1000}, options));\n },\n\n /**\n * Zoom to contain certain geographical bounds\n *\n * @param {Array} bounds [[minLat, minLng], [maxLat, maxLng]]\n * @param {Object} options\n * @param {Number} [options.speed=1.2] How fast animation occurs\n * @param {Number} [options.curve=1.42] How much zooming out occurs during animation\n * @param {Function} options.easing\n * @param {Number} options.padding how much padding there is around the given bounds on each side in pixels\n * @param {Number} options.maxZoom\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n fitBounds: function(bounds, options) {\n\n options = util.extend({\n padding: 0,\n offset: [0, 0],\n maxZoom: Infinity\n }, options);\n\n bounds = LatLngBounds.convert(bounds);\n\n var offset = Point.convert(options.offset),\n tr = this.transform,\n nw = tr.project(bounds.getNorthWest()),\n se = tr.project(bounds.getSouthEast()),\n size = se.sub(nw),\n center = tr.unproject(nw.add(se).div(2)),\n\n scaleX = (tr.width - options.padding * 2 - Math.abs(offset.x) * 2) / size.x,\n scaleY = (tr.height - options.padding * 2 - Math.abs(offset.y) * 2) / size.y,\n\n zoom = Math.min(tr.scaleZoom(tr.scale * Math.min(scaleX, scaleY)), options.maxZoom);\n\n return options.linear ?\n this.easeTo(center, zoom, 0, options) :\n this.flyTo(center, zoom, 0, options);\n },\n\n /**\n * Easing animation to a specified location/zoom/bearing\n *\n * @param {Object} latlng a `LatLng` object\n * @param {Number} zoom\n * @param {Number} bearing\n * @param {Number} pitch\n * @param {animOptions}\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n easeTo: function(latlng, zoom, bearing, pitch, options) {\n this.stop();\n\n options = util.extend({\n offset: [0, 0],\n duration: 500,\n easing: util.ease\n }, options);\n\n var tr = this.transform,\n offset = Point.convert(options.offset).rotate(-tr.angle),\n startZoom = this.getZoom(),\n startBearing = this.getBearing(),\n startPitch = this.getPitch();\n\n latlng = LatLng.convert(latlng);\n zoom = zoom === undefined ? startZoom : zoom;\n bearing = bearing === undefined ? startBearing : this._normalizeBearing(bearing, startBearing);\n pitch = pitch === undefined ? startPitch : pitch;\n\n var scale = tr.zoomScale(zoom - startZoom),\n from = tr.point,\n to = latlng ? tr.project(latlng).sub(offset.div(scale)) : tr.point,\n around;\n\n if (zoom !== startZoom) {\n around = tr.pointLocation(tr.centerPoint.add(to.sub(from).div(1 - 1 / scale)));\n this.zooming = true;\n }\n if (startBearing !== bearing) this.rotating = true;\n\n this.fire('movestart');\n\n this._ease(function (k) {\n if (zoom !== startZoom) {\n tr.setZoomAround(interpolate(startZoom, zoom, k), around);\n } else {\n tr.center = tr.unproject(from.add(to.sub(from).mult(k)));\n }\n\n if (bearing !== startBearing) {\n tr.bearing = interpolate(startBearing, bearing, k);\n }\n\n if (pitch !== startPitch) {\n tr.pitch = interpolate(startPitch, pitch, k);\n }\n\n this.animationLoop.set(300); // text fading\n this._move(zoom !== startZoom, bearing !== startBearing);\n }, function() {\n this.zooming = false;\n this.rotating = false;\n this.fire('moveend');\n }, options);\n\n return this;\n },\n\n /**\n * Flying animation to a specified location/zoom/bearing with automatic curve\n *\n * @param {Object} latlng a `LatLng` object\n * @param {Number} zoom\n * @param {Number} bearing\n * @param {Object} options\n * @param {Number} [options.speed=1.2] How fast animation occurs\n * @param {Number} [options.curve=1.42] How much zooming out occurs during animation\n * @param {Function} options.easing\n * @fires movestart\n * @fires moveend\n * @returns {this}\n */\n flyTo: function(latlng, zoom, bearing, options) {\n this.stop();\n\n options = util.extend({\n offset: [0, 0],\n speed: 1.2,\n curve: 1.42,\n easing: util.ease\n }, options);\n\n latlng = LatLng.convert(latlng);\n\n var offset = Point.convert(options.offset),\n tr = this.transform,\n startZoom = this.getZoom(),\n startBearing = this.getBearing();\n\n zoom = zoom === undefined ? startZoom : zoom;\n bearing = bearing === undefined ? startBearing : this._normalizeBearing(bearing, startBearing);\n\n var scale = tr.zoomScale(zoom - startZoom),\n from = tr.point,\n to = tr.project(latlng).sub(offset.div(scale));\n\n if (options.animate === false) {\n return this.setView(latlng, zoom, bearing, this.getPitch());\n }\n\n var startWorldSize = tr.worldSize,\n rho = options.curve,\n V = options.speed,\n\n w0 = Math.max(tr.width, tr.height),\n w1 = w0 / scale,\n u1 = to.sub(from).mag(),\n rho2 = rho * rho;\n\n function r(i) {\n var b = (w1 * w1 - w0 * w0 + (i ? -1 : 1) * rho2 * rho2 * u1 * u1) / (2 * (i ? w1 : w0) * rho2 * u1);\n return Math.log(Math.sqrt(b * b + 1) - b);\n }\n\n function sinh(n) { return (Math.exp(n) - Math.exp(-n)) / 2; }\n function cosh(n) { return (Math.exp(n) + Math.exp(-n)) / 2; }\n function tanh(n) { return sinh(n) / cosh(n); }\n\n var r0 = r(0),\n w = function (s) { return (cosh(r0) / cosh(r0 + rho * s)); },\n u = function (s) { return w0 * ((cosh(r0) * tanh(r0 + rho * s) - sinh(r0)) / rho2) / u1; },\n S = (r(1) - r0) / rho;\n\n if (Math.abs(u1) < 0.000001) {\n if (Math.abs(w0 - w1) < 0.000001) return this;\n\n var k = w1 < w0 ? -1 : 1;\n S = Math.abs(Math.log(w1 / w0)) / rho;\n\n u = function() { return 0; };\n w = function(s) { return Math.exp(k * rho * s); };\n }\n\n options.duration = 1000 * S / V;\n\n this.zooming = true;\n if (startBearing !== bearing) this.rotating = true;\n\n this.fire('movestart');\n\n this._ease(function (k) {\n var s = k * S,\n us = u(s);\n\n tr.zoom = startZoom + tr.scaleZoom(1 / w(s));\n tr.center = tr.unproject(from.add(to.sub(from).mult(us)), startWorldSize);\n\n if (bearing !== startBearing) {\n tr.bearing = interpolate(startBearing, bearing, k);\n }\n\n this.animationLoop.set(300); // text fading\n\n this._move(true, bearing !== startBearing);\n }, function() {\n this.zooming = false;\n this.rotating = false;\n this.fire('moveend');\n }, options);\n\n return this;\n },\n\n // convert bearing so that it's numerically close to the current one so that it interpolates properly\n _normalizeBearing: function(bearing, currentBearing) {\n bearing = util.wrap(bearing, -180, 180);\n var diff = Math.abs(bearing - currentBearing);\n if (Math.abs(bearing - 360 - currentBearing) < diff) bearing -= 360;\n if (Math.abs(bearing + 360 - currentBearing) < diff) bearing += 360;\n return bearing;\n },\n\n _updateEasing: function(duration, zoom, bezier) {\n var easing;\n\n if (this.ease) {\n var ease = this.ease,\n t = (Date.now() - ease.start) / ease.duration,\n speed = ease.easing(t + 0.01) - ease.easing(t),\n\n // Quick hack to make new bezier that is continuous with last\n x = 0.27 / Math.sqrt(speed * speed + 0.0001) * 0.01,\n y = Math.sqrt(0.27 * 0.27 - x * x);\n\n easing = util.bezier(x, y, 0.25, 1);\n } else {\n easing = bezier ? util.bezier.apply(util, bezier) : util.ease;\n }\n\n // store information on current easing\n this.ease = {\n start: (new Date()).getTime(),\n to: Math.pow(2, zoom),\n duration: duration,\n easing: easing\n };\n\n return easing;\n }\n});","path":"js/ui/easings.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/ui/easings.js#L17-L494"},"name":"extend","kind":"typedef","members":{"instance":[],"static":[]},"path":["extend"]},{"description":"latitude to absolute y coord","tags":[{"title":"param","description":null,"type":{"type":"NameExpression","name":"Number"},"name":"lat"},{"title":"name","name":"latY"},{"title":"memberof","description":"Transform"},{"title":"instance"}],"context":{"loc":{"start":{"line":131,"column":4},"end":{"line":134,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/geo/transform.js","code":"{\n get minZoom() { return this._minZoom; },\n set minZoom(zoom) {\n this._minZoom = zoom;\n this.zoom = Math.max(this.zoom, zoom);\n },\n\n get maxZoom() { return this._maxZoom; },\n set maxZoom(zoom) {\n this._maxZoom = zoom;\n this.zoom = Math.min(this.zoom, zoom);\n },\n\n get worldSize() {\n return this.tileSize * this.scale;\n },\n\n get centerPoint() {\n return this.size._div(2);\n },\n\n get size() {\n return new Point(this.width, this.height);\n },\n\n get bearing() {\n return -this.angle / Math.PI * 180;\n },\n set bearing(bearing) {\n this.angle = -wrap(bearing, -180, 180) * Math.PI / 180;\n },\n\n get pitch() {\n return this._pitch / Math.PI * 180;\n },\n set pitch(pitch) {\n this._pitch = Math.min(60, pitch) / 180 * Math.PI;\n },\n\n get altitude() {\n return this._altitude;\n },\n set altitude(altitude) {\n this._altitude = Math.max(0.75, altitude);\n },\n\n get zoom() { return this._zoom; },\n set zoom(zoom) {\n zoom = Math.min(Math.max(zoom, this.minZoom), this.maxZoom);\n this._zoom = zoom;\n this.scale = this.zoomScale(zoom);\n this.tileZoom = Math.floor(zoom);\n this.zoomFraction = zoom - this.tileZoom;\n this._constrain();\n },\n\n zoomScale: function(zoom) { return Math.pow(2, zoom); },\n scaleZoom: function(scale) { return Math.log(scale) / Math.LN2; },\n\n project: function(latlng, worldSize) {\n return new Point(\n this.lngX(latlng.lng, worldSize),\n this.latY(latlng.lat, worldSize));\n },\n\n unproject: function(point, worldSize) {\n return new LatLng(\n this.yLat(point.y, worldSize),\n this.xLng(point.x, worldSize));\n },\n\n get x() { return this.lngX(this.center.lng); },\n get y() { return this.latY(this.center.lat); },\n\n get point() { return new Point(this.x, this.y); },\n\n /**\n * lat/lon <-> absolute pixel coords conversion\n * @param {Number} lon\n * @param {Number} [worldSize=this.worldSize]\n * @returns {Number} pixel coordinate\n * @private\n */\n lngX: function(lon, worldSize) {\n return (180 + lon) * (worldSize || this.worldSize) / 360;\n },\n /**\n * latitude to absolute y coord\n *\n * @param {Number} lat\n * @param {Number} [worldSize=this.worldSize]\n * @returns {Number} pixel coordinate\n * @private\n */\n latY: function(lat, worldSize) {\n var y = 180 / Math.PI * Math.log(Math.tan(Math.PI / 4 + lat * Math.PI / 360));\n return (180 - y) * (worldSize || this.worldSize) / 360;\n },\n\n xLng: function(x, worldSize) {\n return x * 360 / (worldSize || this.worldSize) - 180;\n },\n yLat: function(y, worldSize) {\n var y2 = 180 - y * 360 / (worldSize || this.worldSize);\n return 360 / Math.PI * Math.atan(Math.exp(y2 * Math.PI / 180)) - 90;\n },\n\n panBy: function(offset) {\n var point = this.centerPoint._add(offset);\n this.center = this.pointLocation(point);\n this._constrain();\n },\n\n setLocationAtPoint: function(latlng, point) {\n var c = this.locationCoordinate(latlng);\n var coordAtPoint = this.pointCoordinate(point);\n var coordCenter = this.pointCoordinate(this.centerPoint);\n\n var translate = coordAtPoint._sub(c);\n this.center = this.coordinateLocation(coordCenter._sub(translate));\n\n this._constrain();\n },\n\n setZoomAround: function(zoom, center) {\n var p = this.locationPoint(center);\n this.zoom = zoom;\n this.setLocationAtPoint(center, p);\n },\n\n setBearingAround: function(bearing, center) {\n var p = this.locationPoint(center);\n this.bearing = bearing;\n this.setLocationAtPoint(center, p);\n },\n\n locationPoint: function(latlng) {\n return this.coordinatePoint(this.locationCoordinate(latlng));\n },\n\n pointLocation: function(p) {\n return this.coordinateLocation(this.pointCoordinate(p));\n },\n\n locationCoordinate: function(latlng) {\n var k = this.zoomScale(this.tileZoom) / this.worldSize;\n return new Coordinate(\n this.lngX(latlng.lng) * k,\n this.latY(latlng.lat) * k,\n this.tileZoom);\n },\n\n coordinateLocation: function(coord) {\n var worldSize = this.zoomScale(coord.zoom);\n return new LatLng(\n this.yLat(coord.row, worldSize),\n this.xLng(coord.column, worldSize));\n },\n\n pointCoordinate: function(p, targetZ) {\n\n if (targetZ === undefined) targetZ = 0;\n\n var matrix = this.coordinatePointMatrix(this.tileZoom);\n var inverted = mat4.invert(new Float64Array(16), matrix);\n\n if (!inverted) throw \"failed to invert matrix\";\n\n // since we don't know the correct projected z value for the point,\n // unproject two points to get a line and then find the point on that\n // line with z=0\n\n var coord0 = vec4.transformMat4([], [p.x, p.y, 0, 1], inverted);\n var coord1 = vec4.transformMat4([], [p.x, p.y, 1, 1], inverted);\n\n var w0 = coord0[3];\n var w1 = coord1[3];\n var x0 = coord0[0] / w0;\n var x1 = coord1[0] / w1;\n var y0 = coord0[1] / w0;\n var y1 = coord1[1] / w1;\n var z0 = coord0[2] / w0;\n var z1 = coord1[2] / w1;\n\n\n var t = z0 === z1 ? 0 : (targetZ - z0) / (z1 - z0);\n\n return new Coordinate(\n interp(x0, x1, t),\n interp(y0, y1, t),\n this.tileZoom);\n },\n\n coordinatePoint: function(coord) {\n var matrix = this.coordinatePointMatrix(coord.zoom);\n var p = vec4.transformMat4([], [coord.column, coord.row, 0, 1], matrix);\n return new Point(p[0] / p[3], p[1] / p[3]);\n },\n\n coordinatePointMatrix: function(z) {\n var proj = this.getProjMatrix();\n var scale = this.worldSize / this.zoomScale(z);\n mat4.scale(proj, proj, [scale, scale, 1]);\n mat4.multiply(proj, this.getPixelMatrix(), proj);\n return proj;\n },\n\n // converts gl coordinates -1..1 to pixels 0..width\n getPixelMatrix: function() {\n var m = mat4.create();\n mat4.scale(m, m, [this.width / 2, -this.height / 2, 1]);\n mat4.translate(m, m, [1, -1, 0]);\n return m;\n },\n\n _constrain: function() {\n if (!this.center) return;\n\n var minY, maxY, minX, maxX, sy, sx, x2, y2,\n size = this.size;\n\n if (this.latRange) {\n minY = this.latY(this.latRange[1]);\n maxY = this.latY(this.latRange[0]);\n sy = maxY - minY < size.y ? size.y / (maxY - minY) : 0;\n }\n\n if (this.lngRange) {\n minX = this.lngX(this.lngRange[0]);\n maxX = this.lngX(this.lngRange[1]);\n sx = maxX - minX < size.x ? size.x / (maxX - minX) : 0;\n }\n\n // how much the map should scale to fit the screen into given latitude/longitude ranges\n var s = Math.max(sx || 0, sy || 0);\n\n if (s) {\n this.center = this.unproject(new Point(\n sx ? (maxX + minX) / 2 : this.x,\n sy ? (maxY + minY) / 2 : this.y));\n this.zoom += this.scaleZoom(s);\n return;\n }\n\n if (this.latRange) {\n var y = this.y,\n h2 = size.y / 2;\n\n if (y - h2 < minY) y2 = minY + h2;\n if (y + h2 > maxY) y2 = maxY - h2;\n }\n\n if (this.lngRange) {\n var x = this.x,\n w2 = size.x / 2;\n\n if (x - w2 < minX) x2 = minX + w2;\n if (x + w2 > maxX) x2 = maxX - w2;\n }\n\n // pan the map if the screen goes off the range\n if (x2 !== undefined || y2 !== undefined) {\n this.center = this.unproject(new Point(\n x2 !== undefined ? x2 : this.x,\n y2 !== undefined ? y2 : this.y));\n }\n },\n\n getProjMatrix: function() {\n var m = new Float64Array(16);\n mat4.perspective(m, 2 * Math.atan((this.height / 2) / this.altitude), this.width / this.height, 0.1, this.altitude + 1);\n\n mat4.translate(m, m, [0, 0, -this.altitude]);\n\n // After the rotateX, z values are in pixel units. Convert them to\n // altitude unites. 1 altitude unit = the screen height.\n mat4.scale(m, m, [1, -1, 1 / this.height]);\n\n mat4.rotateX(m, m, this._pitch);\n mat4.rotateZ(m, m, this.angle);\n mat4.translate(m, m, [-this.x, -this.y, 0]);\n return m;\n }\n}","path":"js/geo/transform.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/geo/transform.js#L131-L134"},"params":[{"title":"param","description":null,"type":{"type":"NameExpression","name":"Number"},"name":"lat"}],"name":"latY","memberof":"Transform","scope":"instance","members":{"instance":[],"static":[]},"path":["latY"]},{"description":"Test whether the basic JavaScript and DOM features required for Mapbox GL are present.","tags":[{"title":"param","description":null,"type":{"type":"NameExpression","name":"Object"},"name":"options"},{"title":"name","name":"supported"},{"title":"memberof","description":"exports"},{"title":"static"}],"context":{"loc":{"start":{"line":55,"column":0},"end":{"line":109,"column":2}},"file":"/Users/tmcw/src/mapbox-gl-js/js/util/browser/browser.js","code":"'use strict';\n\nvar Canvas = require('./canvas');\n\nvar frame = window.requestAnimationFrame ||\n window.mozRequestAnimationFrame ||\n window.webkitRequestAnimationFrame ||\n window.msRequestAnimationFrame;\n\nexports.frame = function(fn) {\n return frame(fn);\n};\n\nvar cancel = window.cancelAnimationFrame ||\n window.mozCancelAnimationFrame ||\n window.webkitCancelAnimationFrame ||\n window.msCancelAnimationFrame;\n\nexports.cancelFrame = function(id) {\n cancel(id);\n};\n\nexports.timed = function (fn, dur, ctx) {\n if (!dur) {\n fn.call(ctx, 1);\n return null;\n }\n\n var abort = false,\n start = window.performance ? window.performance.now() : Date.now();\n\n function tick(now) {\n if (abort) return;\n if (!window.performance) now = Date.now();\n\n if (now >= start + dur) {\n fn.call(ctx, 1);\n } else {\n fn.call(ctx, (now - start) / dur);\n exports.frame(tick);\n }\n }\n\n exports.frame(tick);\n\n return function() { abort = true; };\n};\n\n/**\n * Test whether the basic JavaScript and DOM features required for Mapbox GL are present.\n * @param {Object} options\n * @param {Boolean} [options.failIfMajorPerformanceCaveat=false] If `true`, map creation will fail if the implementation determines that the performance of the created WebGL context would be dramatically lower than expected.\n * @return {Boolean} Returns true if Mapbox GL should be expected to work, and false if not.\n */\nexports.supported = function(options) {\n\n var supports = [\n\n function() { return typeof window !== 'undefined'; },\n\n function() { return typeof document !== 'undefined'; },\n\n function () {\n return !!(Array.prototype &&\n Array.prototype.every &&\n Array.prototype.filter &&\n Array.prototype.forEach &&\n Array.prototype.indexOf &&\n Array.prototype.lastIndexOf &&\n Array.prototype.map &&\n Array.prototype.some &&\n Array.prototype.reduce &&\n Array.prototype.reduceRight &&\n Array.isArray);\n },\n\n function() {\n return !!(Function.prototype && Function.prototype.bind) &&\n !!(Object.keys &&\n Object.create &&\n Object.getPrototypeOf &&\n Object.getOwnPropertyNames &&\n Object.isSealed &&\n Object.isFrozen &&\n Object.isExtensible &&\n Object.getOwnPropertyDescriptor &&\n Object.defineProperty &&\n Object.defineProperties &&\n Object.seal &&\n Object.freeze &&\n Object.preventExtensions);\n },\n\n function() {\n return 'JSON' in window && 'parse' in JSON && 'stringify' in JSON;\n },\n\n function() {\n return new Canvas().supportsWebGLContext((options && options.failIfMajorPerformanceCaveat) || false);\n },\n\n function() { return 'Worker' in window; }\n ];\n\n for (var i = 0; i < supports.length; i++) {\n if (!supports[i]()) return false;\n }\n return true;\n};\n\nexports.hardwareConcurrency = navigator.hardwareConcurrency || 8;\n\nObject.defineProperty(exports, 'devicePixelRatio', {\n get: function() { return window.devicePixelRatio; }\n});","path":"js/util/browser/browser.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/util/browser/browser.js#L55-L109"},"params":[{"title":"param","description":null,"type":{"type":"NameExpression","name":"Object"},"name":"options"}],"name":"supported","memberof":"exports","scope":"static","members":{"instance":[],"static":[]},"path":["supported"]},{"description":"mapboxgl is a A WebGL JavaScript interactive maps library that can render\n[Mapbox vector tiles](https://www.mapbox.com/blog/vector-tiles/).","tags":[{"title":"module","description":null,"type":null,"name":"mapboxgl"},{"title":"summary","description":"WebGL JavaScript map library"},{"title":"name","name":"window"},{"title":"kind","kind":"module"}],"context":{"loc":{"start":{"line":10,"column":0},"end":{"line":46,"column":1}},"file":"/Users/tmcw/src/mapbox-gl-js","code":"'use strict';\n\n/**\n * mapboxgl is a A WebGL JavaScript interactive maps library that can render\n * [Mapbox vector tiles](https://www.mapbox.com/blog/vector-tiles/).\n *\n * @module mapboxgl\n * @summary WebGL JavaScript map library\n */\nif (typeof window === 'undefined') {\n new (require('./source/worker'))(self); /*eslint no-new: 0*/\n} else {\n // jshint -W079\n var mapboxgl = module.exports = window.mapboxgl = {};\n\n mapboxgl.Map = require('./ui/map');\n mapboxgl.Navigation = require('./ui/control/navigation');\n mapboxgl.Attribution = require('./ui/control/attribution');\n mapboxgl.Popup = require('./ui/popup');\n\n mapboxgl.GeoJSONSource = require('./source/geojson_source');\n mapboxgl.VideoSource = require('./source/video_source');\n\n mapboxgl.Style = require('./style/style');\n\n mapboxgl.LatLng = require('./geo/lat_lng');\n mapboxgl.LatLngBounds = require('./geo/lat_lng_bounds');\n mapboxgl.Point = require('point-geometry');\n\n mapboxgl.Evented = require('./util/evented');\n mapboxgl.util = require('./util/util');\n\n mapboxgl.supported = require('./util/browser').supported;\n\n var ajax = require('./util/ajax');\n mapboxgl.util.getJSON = ajax.getJSON;\n mapboxgl.util.getArrayBuffer = ajax.getArrayBuffer;\n\n var config = require('./util/config');\n mapboxgl.config = config;\n\n Object.defineProperty(mapboxgl, 'accessToken', {\n get: function() { return config.ACCESS_TOKEN; },\n set: function(token) { config.ACCESS_TOKEN = token; }\n });\n}","path":"/Users/tmcw/src/mapbox-gl-js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05//Users/tmcw/src/mapbox-gl-js#L10-L46"},"name":"window","kind":"module","members":{"instance":[],"static":[]},"path":["window"]},{"description":"lat/lon <-> absolute pixel coords conversion","tags":[{"title":"param","description":null,"type":{"type":"NameExpression","name":"Number"},"name":"lon"},{"title":"name","name":"lngX"},{"title":"memberof","description":"Transform"},{"title":"instance"}],"context":{"loc":{"start":{"line":120,"column":4},"end":{"line":122,"column":5}},"file":"/Users/tmcw/src/mapbox-gl-js/js/geo/transform.js","code":"{\n get minZoom() { return this._minZoom; },\n set minZoom(zoom) {\n this._minZoom = zoom;\n this.zoom = Math.max(this.zoom, zoom);\n },\n\n get maxZoom() { return this._maxZoom; },\n set maxZoom(zoom) {\n this._maxZoom = zoom;\n this.zoom = Math.min(this.zoom, zoom);\n },\n\n get worldSize() {\n return this.tileSize * this.scale;\n },\n\n get centerPoint() {\n return this.size._div(2);\n },\n\n get size() {\n return new Point(this.width, this.height);\n },\n\n get bearing() {\n return -this.angle / Math.PI * 180;\n },\n set bearing(bearing) {\n this.angle = -wrap(bearing, -180, 180) * Math.PI / 180;\n },\n\n get pitch() {\n return this._pitch / Math.PI * 180;\n },\n set pitch(pitch) {\n this._pitch = Math.min(60, pitch) / 180 * Math.PI;\n },\n\n get altitude() {\n return this._altitude;\n },\n set altitude(altitude) {\n this._altitude = Math.max(0.75, altitude);\n },\n\n get zoom() { return this._zoom; },\n set zoom(zoom) {\n zoom = Math.min(Math.max(zoom, this.minZoom), this.maxZoom);\n this._zoom = zoom;\n this.scale = this.zoomScale(zoom);\n this.tileZoom = Math.floor(zoom);\n this.zoomFraction = zoom - this.tileZoom;\n this._constrain();\n },\n\n zoomScale: function(zoom) { return Math.pow(2, zoom); },\n scaleZoom: function(scale) { return Math.log(scale) / Math.LN2; },\n\n project: function(latlng, worldSize) {\n return new Point(\n this.lngX(latlng.lng, worldSize),\n this.latY(latlng.lat, worldSize));\n },\n\n unproject: function(point, worldSize) {\n return new LatLng(\n this.yLat(point.y, worldSize),\n this.xLng(point.x, worldSize));\n },\n\n get x() { return this.lngX(this.center.lng); },\n get y() { return this.latY(this.center.lat); },\n\n get point() { return new Point(this.x, this.y); },\n\n /**\n * lat/lon <-> absolute pixel coords conversion\n * @param {Number} lon\n * @param {Number} [worldSize=this.worldSize]\n * @returns {Number} pixel coordinate\n * @private\n */\n lngX: function(lon, worldSize) {\n return (180 + lon) * (worldSize || this.worldSize) / 360;\n },\n /**\n * latitude to absolute y coord\n *\n * @param {Number} lat\n * @param {Number} [worldSize=this.worldSize]\n * @returns {Number} pixel coordinate\n * @private\n */\n latY: function(lat, worldSize) {\n var y = 180 / Math.PI * Math.log(Math.tan(Math.PI / 4 + lat * Math.PI / 360));\n return (180 - y) * (worldSize || this.worldSize) / 360;\n },\n\n xLng: function(x, worldSize) {\n return x * 360 / (worldSize || this.worldSize) - 180;\n },\n yLat: function(y, worldSize) {\n var y2 = 180 - y * 360 / (worldSize || this.worldSize);\n return 360 / Math.PI * Math.atan(Math.exp(y2 * Math.PI / 180)) - 90;\n },\n\n panBy: function(offset) {\n var point = this.centerPoint._add(offset);\n this.center = this.pointLocation(point);\n this._constrain();\n },\n\n setLocationAtPoint: function(latlng, point) {\n var c = this.locationCoordinate(latlng);\n var coordAtPoint = this.pointCoordinate(point);\n var coordCenter = this.pointCoordinate(this.centerPoint);\n\n var translate = coordAtPoint._sub(c);\n this.center = this.coordinateLocation(coordCenter._sub(translate));\n\n this._constrain();\n },\n\n setZoomAround: function(zoom, center) {\n var p = this.locationPoint(center);\n this.zoom = zoom;\n this.setLocationAtPoint(center, p);\n },\n\n setBearingAround: function(bearing, center) {\n var p = this.locationPoint(center);\n this.bearing = bearing;\n this.setLocationAtPoint(center, p);\n },\n\n locationPoint: function(latlng) {\n return this.coordinatePoint(this.locationCoordinate(latlng));\n },\n\n pointLocation: function(p) {\n return this.coordinateLocation(this.pointCoordinate(p));\n },\n\n locationCoordinate: function(latlng) {\n var k = this.zoomScale(this.tileZoom) / this.worldSize;\n return new Coordinate(\n this.lngX(latlng.lng) * k,\n this.latY(latlng.lat) * k,\n this.tileZoom);\n },\n\n coordinateLocation: function(coord) {\n var worldSize = this.zoomScale(coord.zoom);\n return new LatLng(\n this.yLat(coord.row, worldSize),\n this.xLng(coord.column, worldSize));\n },\n\n pointCoordinate: function(p, targetZ) {\n\n if (targetZ === undefined) targetZ = 0;\n\n var matrix = this.coordinatePointMatrix(this.tileZoom);\n var inverted = mat4.invert(new Float64Array(16), matrix);\n\n if (!inverted) throw \"failed to invert matrix\";\n\n // since we don't know the correct projected z value for the point,\n // unproject two points to get a line and then find the point on that\n // line with z=0\n\n var coord0 = vec4.transformMat4([], [p.x, p.y, 0, 1], inverted);\n var coord1 = vec4.transformMat4([], [p.x, p.y, 1, 1], inverted);\n\n var w0 = coord0[3];\n var w1 = coord1[3];\n var x0 = coord0[0] / w0;\n var x1 = coord1[0] / w1;\n var y0 = coord0[1] / w0;\n var y1 = coord1[1] / w1;\n var z0 = coord0[2] / w0;\n var z1 = coord1[2] / w1;\n\n\n var t = z0 === z1 ? 0 : (targetZ - z0) / (z1 - z0);\n\n return new Coordinate(\n interp(x0, x1, t),\n interp(y0, y1, t),\n this.tileZoom);\n },\n\n coordinatePoint: function(coord) {\n var matrix = this.coordinatePointMatrix(coord.zoom);\n var p = vec4.transformMat4([], [coord.column, coord.row, 0, 1], matrix);\n return new Point(p[0] / p[3], p[1] / p[3]);\n },\n\n coordinatePointMatrix: function(z) {\n var proj = this.getProjMatrix();\n var scale = this.worldSize / this.zoomScale(z);\n mat4.scale(proj, proj, [scale, scale, 1]);\n mat4.multiply(proj, this.getPixelMatrix(), proj);\n return proj;\n },\n\n // converts gl coordinates -1..1 to pixels 0..width\n getPixelMatrix: function() {\n var m = mat4.create();\n mat4.scale(m, m, [this.width / 2, -this.height / 2, 1]);\n mat4.translate(m, m, [1, -1, 0]);\n return m;\n },\n\n _constrain: function() {\n if (!this.center) return;\n\n var minY, maxY, minX, maxX, sy, sx, x2, y2,\n size = this.size;\n\n if (this.latRange) {\n minY = this.latY(this.latRange[1]);\n maxY = this.latY(this.latRange[0]);\n sy = maxY - minY < size.y ? size.y / (maxY - minY) : 0;\n }\n\n if (this.lngRange) {\n minX = this.lngX(this.lngRange[0]);\n maxX = this.lngX(this.lngRange[1]);\n sx = maxX - minX < size.x ? size.x / (maxX - minX) : 0;\n }\n\n // how much the map should scale to fit the screen into given latitude/longitude ranges\n var s = Math.max(sx || 0, sy || 0);\n\n if (s) {\n this.center = this.unproject(new Point(\n sx ? (maxX + minX) / 2 : this.x,\n sy ? (maxY + minY) / 2 : this.y));\n this.zoom += this.scaleZoom(s);\n return;\n }\n\n if (this.latRange) {\n var y = this.y,\n h2 = size.y / 2;\n\n if (y - h2 < minY) y2 = minY + h2;\n if (y + h2 > maxY) y2 = maxY - h2;\n }\n\n if (this.lngRange) {\n var x = this.x,\n w2 = size.x / 2;\n\n if (x - w2 < minX) x2 = minX + w2;\n if (x + w2 > maxX) x2 = maxX - w2;\n }\n\n // pan the map if the screen goes off the range\n if (x2 !== undefined || y2 !== undefined) {\n this.center = this.unproject(new Point(\n x2 !== undefined ? x2 : this.x,\n y2 !== undefined ? y2 : this.y));\n }\n },\n\n getProjMatrix: function() {\n var m = new Float64Array(16);\n mat4.perspective(m, 2 * Math.atan((this.height / 2) / this.altitude), this.width / this.height, 0.1, this.altitude + 1);\n\n mat4.translate(m, m, [0, 0, -this.altitude]);\n\n // After the rotateX, z values are in pixel units. Convert them to\n // altitude unites. 1 altitude unit = the screen height.\n mat4.scale(m, m, [1, -1, 1 / this.height]);\n\n mat4.rotateX(m, m, this._pitch);\n mat4.rotateZ(m, m, this.angle);\n mat4.translate(m, m, [-this.x, -this.y, 0]);\n return m;\n }\n}","path":"js/geo/transform.js","github":"https://github.com/mapbox/mapbox-gl-js/blob/f23285cc5fc760921f455f601d113a52d7401a05/js/geo/transform.js#L120-L122"},"params":[{"title":"param","description":null,"type":{"type":"NameExpression","name":"Number"},"name":"lon"}],"name":"lngX","memberof":"Transform","scope":"instance","members":{"instance":[],"static":[]},"path":["lngX"]}]