tg-map-core 4.1.2 → 4.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,13 +4,13 @@ var maptalks = require('maptalks');
4
4
  var tgCommons = require('tg-commons');
5
5
  var coordtransform = require('coordtransform');
6
6
  var deepmerge = require('deepmerge');
7
- var BHeatMapOverlay = require('bmaplib.heatmap');
8
- var GMarkerClusterer = require('@google/markerclusterer');
9
- var BMarkerClusterer = require('bmaplib.markerclusterer');
10
7
  var isPlainObject = require('is-plain-object');
11
8
  require('maptalks/dist/maptalks.css');
12
9
 
13
- function _interopNamespaceDefault(e) {
10
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
11
+
12
+ function _interopNamespace(e) {
13
+ if (e && e.__esModule) return e;
14
14
  var n = Object.create(null);
15
15
  if (e) {
16
16
  Object.keys(e).forEach(function (k) {
@@ -27,7 +27,10 @@ function _interopNamespaceDefault(e) {
27
27
  return Object.freeze(n);
28
28
  }
29
29
 
30
- var maptalks__namespace = /*#__PURE__*/_interopNamespaceDefault(maptalks);
30
+ var maptalks__namespace = /*#__PURE__*/_interopNamespace(maptalks);
31
+ var coordtransform__default = /*#__PURE__*/_interopDefault(coordtransform);
32
+ var deepmerge__default = /*#__PURE__*/_interopDefault(deepmerge);
33
+ var isPlainObject__default = /*#__PURE__*/_interopDefault(isPlainObject);
31
34
 
32
35
  function bindEvents(listeners, target, excludes) {
33
36
  Object.keys(listeners).forEach(eventName => {
@@ -310,24 +313,24 @@ class LatLng {
310
313
  switch (this.coord) {
311
314
  case exports.CoordType.bd09:
312
315
  if (targetCoord === exports.CoordType.gcj02) {
313
- return coordtransform.bd09ToGcj02(this.lng, this.lat);
316
+ return coordtransform__default.default.bd09ToGcj02(this.lng, this.lat);
314
317
  }
315
318
  else {
316
- return coordtransform.bd09ToWgs84(this.lng, this.lat);
319
+ return coordtransform__default.default.bd09ToWgs84(this.lng, this.lat);
317
320
  }
318
321
  case exports.CoordType.gcj02:
319
322
  if (targetCoord === exports.CoordType.wgs84) {
320
- return coordtransform.gcj02ToWgs84(this.lng, this.lat);
323
+ return coordtransform__default.default.gcj02ToWgs84(this.lng, this.lat);
321
324
  }
322
325
  else {
323
- return coordtransform.gcj02ToBd09(this.lng, this.lat);
326
+ return coordtransform__default.default.gcj02ToBd09(this.lng, this.lat);
324
327
  }
325
328
  case exports.CoordType.wgs84:
326
329
  if (targetCoord === exports.CoordType.bd09) {
327
- return coordtransform.wgs84ToBd09(this.lng, this.lat);
330
+ return coordtransform__default.default.wgs84ToBd09(this.lng, this.lat);
328
331
  }
329
332
  else {
330
- return coordtransform.wgs84ToGcj02(this.lng, this.lat);
333
+ return coordtransform__default.default.wgs84ToGcj02(this.lng, this.lat);
331
334
  }
332
335
  }
333
336
  throw new Error(`不支持的坐标转换: ${this.coord}=>${targetCoord}`);
@@ -786,7 +789,7 @@ function getTgMapConfig() {
786
789
  }
787
790
  function setTgMapConfig(config) {
788
791
  if (config != null) {
789
- tgMapConfig = deepmerge(defaultConfig, config);
792
+ tgMapConfig = deepmerge__default.default(defaultConfig, config);
790
793
  }
791
794
  }
792
795
 
@@ -1559,6 +1562,1023 @@ class BaiduAutocomplete extends Autocomplete {
1559
1562
  }
1560
1563
  }
1561
1564
 
1565
+ function getDefaultExportFromCjs (x) {
1566
+ return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
1567
+ }
1568
+
1569
+ var bmaplib_heatmap$1 = {exports: {}};
1570
+
1571
+ /*
1572
+ * heatmap.js v2.0.0 | JavaScript Heatmap Library
1573
+ *
1574
+ * Copyright 2008-2014 Patrick Wied <heatmapjs@patrick-wied.at> - All rights reserved.
1575
+ * Dual licensed under MIT and Beerware license
1576
+ *
1577
+ * :: 2014-10-31 21:16
1578
+ */
1579
+ var bmaplib_heatmap = bmaplib_heatmap$1.exports;
1580
+
1581
+ var hasRequiredBmaplib_heatmap;
1582
+
1583
+ function requireBmaplib_heatmap () {
1584
+ if (hasRequiredBmaplib_heatmap) return bmaplib_heatmap$1.exports;
1585
+ hasRequiredBmaplib_heatmap = 1;
1586
+ (function (module, exports) {
1587
+ (function (root, factory) {
1588
+ {
1589
+ module.exports = factory();
1590
+ }
1591
+ })(bmaplib_heatmap, function () {
1592
+ const heatmapFactory = (function () {
1593
+ // Heatmap Config stores default values and will be merged with instance config
1594
+ var HeatmapConfig = {
1595
+ defaultRadius: 40,
1596
+ defaultRenderer: 'canvas2d',
1597
+ defaultGradient: { 0.45: "rgb(0,0,255)", 0.55: "rgb(0,255,255)", 0.65: "rgb(0,255,0)", 0.95: "yellow", 1.0: "rgb(255,0,0)" },
1598
+ defaultMaxOpacity: 1,
1599
+ defaultMinOpacity: 0,
1600
+ defaultBlur: .85,
1601
+ defaultXField: 'x',
1602
+ defaultYField: 'y',
1603
+ defaultValueField: 'value',
1604
+ plugins: {}
1605
+ };
1606
+ var Store = (function StoreClosure() {
1607
+
1608
+ var Store = function Store(config) {
1609
+ this._coordinator = {};
1610
+ this._data = [];
1611
+ this._radi = [];
1612
+ this._min = 0;
1613
+ this._max = 1;
1614
+ this._xField = config['xField'] || config.defaultXField;
1615
+ this._yField = config['yField'] || config.defaultYField;
1616
+ this._valueField = config['valueField'] || config.defaultValueField;
1617
+
1618
+ if (config["radius"]) {
1619
+ this._cfgRadius = config["radius"];
1620
+ }
1621
+ };
1622
+
1623
+ var defaultRadius = HeatmapConfig.defaultRadius;
1624
+
1625
+ Store.prototype = {
1626
+ // when forceRender = false -> called from setData, omits renderall event
1627
+ _organiseData: function (dataPoint, forceRender) {
1628
+ var x = dataPoint[this._xField];
1629
+ var y = dataPoint[this._yField];
1630
+ var radi = this._radi;
1631
+ var store = this._data;
1632
+ var max = this._max;
1633
+ var min = this._min;
1634
+ var value = dataPoint[this._valueField] || 1;
1635
+ var radius = dataPoint.radius || this._cfgRadius || defaultRadius;
1636
+
1637
+ if (!store[x]) {
1638
+ store[x] = [];
1639
+ radi[x] = [];
1640
+ }
1641
+
1642
+ if (!store[x][y]) {
1643
+ store[x][y] = value;
1644
+ radi[x][y] = radius;
1645
+ } else {
1646
+ store[x][y] += value;
1647
+ }
1648
+
1649
+ if (store[x][y] > max) {
1650
+ if (!forceRender) {
1651
+ this._max = store[x][y];
1652
+ } else {
1653
+ this.setDataMax(store[x][y]);
1654
+ }
1655
+ return false;
1656
+ } else {
1657
+ return {
1658
+ x: x,
1659
+ y: y,
1660
+ value: value,
1661
+ radius: radius,
1662
+ min: min,
1663
+ max: max
1664
+ };
1665
+ }
1666
+ },
1667
+ _unOrganizeData: function () {
1668
+ var unorganizedData = [];
1669
+ var data = this._data;
1670
+ var radi = this._radi;
1671
+
1672
+ for (var x in data) {
1673
+ for (var y in data[x]) {
1674
+
1675
+ unorganizedData.push({
1676
+ x: x,
1677
+ y: y,
1678
+ radius: radi[x][y],
1679
+ value: data[x][y]
1680
+ });
1681
+
1682
+ }
1683
+ }
1684
+ return {
1685
+ min: this._min,
1686
+ max: this._max,
1687
+ data: unorganizedData
1688
+ };
1689
+ },
1690
+ _onExtremaChange: function () {
1691
+ this._coordinator.emit('extremachange', {
1692
+ min: this._min,
1693
+ max: this._max
1694
+ });
1695
+ },
1696
+ addData: function () {
1697
+ if (arguments[0].length > 0) {
1698
+ var dataArr = arguments[0];
1699
+ var dataLen = dataArr.length;
1700
+ while (dataLen--) {
1701
+ this.addData.call(this, dataArr[dataLen]);
1702
+ }
1703
+ } else {
1704
+ // add to store
1705
+ var organisedEntry = this._organiseData(arguments[0], true);
1706
+ if (organisedEntry) {
1707
+ this._coordinator.emit('renderpartial', {
1708
+ min: this._min,
1709
+ max: this._max,
1710
+ data: [organisedEntry]
1711
+ });
1712
+ }
1713
+ }
1714
+ return this;
1715
+ },
1716
+ setData: function (data) {
1717
+ var dataPoints = data.data;
1718
+ var pointsLen = dataPoints.length;
1719
+
1720
+
1721
+ // reset data arrays
1722
+ this._data = [];
1723
+ this._radi = [];
1724
+
1725
+ for (var i = 0; i < pointsLen; i++) {
1726
+ this._organiseData(dataPoints[i], false);
1727
+ }
1728
+ this._max = data.max;
1729
+ this._min = data.min || 0;
1730
+
1731
+ this._onExtremaChange();
1732
+ this._coordinator.emit('renderall', this._getInternalData());
1733
+ return this;
1734
+ },
1735
+ removeData: function () {
1736
+ // TODO: implement
1737
+ },
1738
+ setDataMax: function (max) {
1739
+ this._max = max;
1740
+ this._onExtremaChange();
1741
+ this._coordinator.emit('renderall', this._getInternalData());
1742
+ return this;
1743
+ },
1744
+ setDataMin: function (min) {
1745
+ this._min = min;
1746
+ this._onExtremaChange();
1747
+ this._coordinator.emit('renderall', this._getInternalData());
1748
+ return this;
1749
+ },
1750
+ setCoordinator: function (coordinator) {
1751
+ this._coordinator = coordinator;
1752
+ },
1753
+ _getInternalData: function () {
1754
+ return {
1755
+ max: this._max,
1756
+ min: this._min,
1757
+ data: this._data,
1758
+ radi: this._radi
1759
+ };
1760
+ },
1761
+ getData: function () {
1762
+ return this._unOrganizeData();
1763
+ }/*,
1764
+
1765
+ // TODO: rethink.
1766
+ getValueAt: function (point) {
1767
+ var value;
1768
+ var radius = 100;
1769
+ var x = point.x;
1770
+ var y = point.y;
1771
+ var data = this._data;
1772
+
1773
+ if (data[x] && data[x][y]) {
1774
+ return data[x][y];
1775
+ } else {
1776
+ var values = [];
1777
+ // radial search for datapoints based on default radius
1778
+ for (var distance = 1; distance < radius; distance++) {
1779
+ var neighbors = distance * 2 + 1;
1780
+ var startX = x - distance;
1781
+ var startY = y - distance;
1782
+
1783
+ for (var i = 0; i < neighbors; i++) {
1784
+ for (var o = 0; o < neighbors; o++) {
1785
+ if ((i == 0 || i == neighbors - 1) || (o == 0 || o == neighbors - 1)) {
1786
+ if (data[startY + i] && data[startY + i][startX + o]) {
1787
+ values.push(data[startY + i][startX + o]);
1788
+ }
1789
+ } else {
1790
+ continue;
1791
+ }
1792
+ }
1793
+ }
1794
+ }
1795
+ if (values.length > 0) {
1796
+ return Math.max.apply(Math, values);
1797
+ }
1798
+ }
1799
+ return false;
1800
+ }*/
1801
+ };
1802
+
1803
+
1804
+ return Store;
1805
+ })();
1806
+
1807
+ var Canvas2dRenderer = (function Canvas2dRendererClosure() {
1808
+
1809
+ var _getColorPalette = function (config) {
1810
+ var gradientConfig = config.gradient || config.defaultGradient;
1811
+ var paletteCanvas = document.createElement('canvas');
1812
+ var paletteCtx = paletteCanvas.getContext('2d');
1813
+
1814
+ paletteCanvas.width = 256;
1815
+ paletteCanvas.height = 1;
1816
+
1817
+ var gradient = paletteCtx.createLinearGradient(0, 0, 256, 1);
1818
+ for (var key in gradientConfig) {
1819
+ gradient.addColorStop(key, gradientConfig[key]);
1820
+ }
1821
+
1822
+ paletteCtx.fillStyle = gradient;
1823
+ paletteCtx.fillRect(0, 0, 256, 1);
1824
+
1825
+ return paletteCtx.getImageData(0, 0, 256, 1).data;
1826
+ };
1827
+
1828
+ var _getPointTemplate = function (radius, blurFactor) {
1829
+ var tplCanvas = document.createElement('canvas');
1830
+ var tplCtx = tplCanvas.getContext('2d');
1831
+ var x = radius;
1832
+ var y = radius;
1833
+ tplCanvas.width = tplCanvas.height = radius * 2;
1834
+
1835
+ if (blurFactor == 1) {
1836
+ tplCtx.beginPath();
1837
+ tplCtx.arc(x, y, radius, 0, 2 * Math.PI, false);
1838
+ tplCtx.fillStyle = 'rgba(0,0,0,1)';
1839
+ tplCtx.fill();
1840
+ } else {
1841
+ var gradient = tplCtx.createRadialGradient(x, y, radius * blurFactor, x, y, radius);
1842
+ gradient.addColorStop(0, 'rgba(0,0,0,1)');
1843
+ gradient.addColorStop(1, 'rgba(0,0,0,0)');
1844
+ tplCtx.fillStyle = gradient;
1845
+ tplCtx.fillRect(0, 0, 2 * radius, 2 * radius);
1846
+ }
1847
+
1848
+
1849
+
1850
+ return tplCanvas;
1851
+ };
1852
+
1853
+ var _prepareData = function (data) {
1854
+ var renderData = [];
1855
+ var min = data.min;
1856
+ var max = data.max;
1857
+ var radi = data.radi;
1858
+ var data = data.data;
1859
+
1860
+ var xValues = Object.keys(data);
1861
+ var xValuesLen = xValues.length;
1862
+
1863
+ while (xValuesLen--) {
1864
+ var xValue = xValues[xValuesLen];
1865
+ var yValues = Object.keys(data[xValue]);
1866
+ var yValuesLen = yValues.length;
1867
+ while (yValuesLen--) {
1868
+ var yValue = yValues[yValuesLen];
1869
+ var value = data[xValue][yValue];
1870
+ var radius = radi[xValue][yValue];
1871
+ renderData.push({
1872
+ x: xValue,
1873
+ y: yValue,
1874
+ value: value,
1875
+ radius: radius
1876
+ });
1877
+ }
1878
+ }
1879
+
1880
+ return {
1881
+ min: min,
1882
+ max: max,
1883
+ data: renderData
1884
+ };
1885
+ };
1886
+
1887
+
1888
+ function Canvas2dRenderer(config) {
1889
+ var container = config.element;
1890
+ var shadowCanvas = this.shadowCanvas = document.createElement('canvas');
1891
+ var canvas = this.canvas = config.canvas || document.createElement('canvas');
1892
+ this._renderBoundaries = [10000, 10000, 0, 0];
1893
+
1894
+ var computed = getComputedStyle(config.element) || {};
1895
+
1896
+ canvas.className = 'heatmap-canvas';
1897
+
1898
+ this._width = canvas.width = shadowCanvas.width = +(computed.width.replace(/px/, ''));
1899
+ this._height = canvas.height = shadowCanvas.height = +(computed.height.replace(/px/, ''));
1900
+
1901
+ this.shadowCtx = shadowCanvas.getContext('2d');
1902
+ this.ctx = canvas.getContext('2d');
1903
+
1904
+ // @TODO:
1905
+ // conditional wrapper
1906
+
1907
+ canvas.style.cssText = shadowCanvas.style.cssText = 'position:absolute;left:0;top:0;';
1908
+
1909
+ container.style.position = 'relative';
1910
+ container.appendChild(canvas);
1911
+
1912
+ this._palette = _getColorPalette(config);
1913
+ this._templates = {};
1914
+
1915
+ this._setStyles(config);
1916
+ }
1917
+ Canvas2dRenderer.prototype = {
1918
+ renderPartial: function (data) {
1919
+ this._drawAlpha(data);
1920
+ this._colorize();
1921
+ },
1922
+ renderAll: function (data) {
1923
+ // reset render boundaries
1924
+ this._clear();
1925
+ this._drawAlpha(_prepareData(data));
1926
+ this._colorize();
1927
+ },
1928
+ _updateGradient: function (config) {
1929
+ this._palette = _getColorPalette(config);
1930
+ },
1931
+ updateConfig: function (config, oldConfig) {
1932
+ if (config.gradient !== oldConfig.gradient) {
1933
+ this._updateGradient(config);
1934
+ }
1935
+ this._setStyles(config);
1936
+ },
1937
+ setDimensions: function (width, height) {
1938
+ this._width = width;
1939
+ this._height = height;
1940
+ this.canvas.width = this.shadowCanvas.width = width;
1941
+ this.canvas.height = this.shadowCanvas.height = height;
1942
+ },
1943
+ _clear: function () {
1944
+ this.shadowCtx.clearRect(0, 0, this._width, this._height);
1945
+ this.ctx.clearRect(0, 0, this._width, this._height);
1946
+ },
1947
+ _setStyles: function (config) {
1948
+ this._blur = (config.blur == 0) ? 0 : (config.blur || config.defaultBlur);
1949
+
1950
+ if (config.backgroundColor) {
1951
+ this.canvas.style.backgroundColor = config.backgroundColor;
1952
+ }
1953
+
1954
+ this._opacity = (config.opacity || 0) * 255;
1955
+ this._maxOpacity = (config.maxOpacity || config.defaultMaxOpacity) * 255;
1956
+ this._minOpacity = (config.minOpacity || config.defaultMinOpacity) * 255;
1957
+ this._useGradientOpacity = !!config.useGradientOpacity;
1958
+ },
1959
+ _drawAlpha: function (data) {
1960
+ var min = this._min = data.min;
1961
+ var max = this._max = data.max;
1962
+ var data = data.data || [];
1963
+ var dataLen = data.length;
1964
+ // on a point basis?
1965
+ var blur = 1 - this._blur;
1966
+
1967
+ while (dataLen--) {
1968
+
1969
+ var point = data[dataLen];
1970
+
1971
+ var x = point.x;
1972
+ var y = point.y;
1973
+ var radius = point.radius;
1974
+ // if value is bigger than max
1975
+ // use max as value
1976
+ var value = Math.min(point.value, max);
1977
+ var rectX = x - radius;
1978
+ var rectY = y - radius;
1979
+ var shadowCtx = this.shadowCtx;
1980
+
1981
+
1982
+
1983
+
1984
+ var tpl;
1985
+ if (!this._templates[radius]) {
1986
+ this._templates[radius] = tpl = _getPointTemplate(radius, blur);
1987
+ } else {
1988
+ tpl = this._templates[radius];
1989
+ }
1990
+ // value from minimum / value range
1991
+ // => [0, 1]
1992
+ shadowCtx.globalAlpha = (value - min) / (max - min);
1993
+
1994
+ shadowCtx.drawImage(tpl, rectX, rectY);
1995
+
1996
+ // update renderBoundaries
1997
+ if (rectX < this._renderBoundaries[0]) {
1998
+ this._renderBoundaries[0] = rectX;
1999
+ }
2000
+ if (rectY < this._renderBoundaries[1]) {
2001
+ this._renderBoundaries[1] = rectY;
2002
+ }
2003
+ if (rectX + 2 * radius > this._renderBoundaries[2]) {
2004
+ this._renderBoundaries[2] = rectX + 2 * radius;
2005
+ }
2006
+ if (rectY + 2 * radius > this._renderBoundaries[3]) {
2007
+ this._renderBoundaries[3] = rectY + 2 * radius;
2008
+ }
2009
+
2010
+ }
2011
+ },
2012
+ _colorize: function () {
2013
+ var x = this._renderBoundaries[0];
2014
+ var y = this._renderBoundaries[1];
2015
+ var width = this._renderBoundaries[2] - x;
2016
+ var height = this._renderBoundaries[3] - y;
2017
+ var maxWidth = this._width;
2018
+ var maxHeight = this._height;
2019
+ var opacity = this._opacity;
2020
+ var maxOpacity = this._maxOpacity;
2021
+ var minOpacity = this._minOpacity;
2022
+ var useGradientOpacity = this._useGradientOpacity;
2023
+
2024
+ if (x < 0) {
2025
+ x = 0;
2026
+ }
2027
+ if (y < 0) {
2028
+ y = 0;
2029
+ }
2030
+ if (x + width > maxWidth) {
2031
+ width = maxWidth - x;
2032
+ }
2033
+ if (y + height > maxHeight) {
2034
+ height = maxHeight - y;
2035
+ }
2036
+
2037
+ var img = this.shadowCtx.getImageData(x, y, width, height);
2038
+ var imgData = img.data;
2039
+ var len = imgData.length;
2040
+ var palette = this._palette;
2041
+
2042
+
2043
+ for (var i = 3; i < len; i += 4) {
2044
+ var alpha = imgData[i];
2045
+ var offset = alpha * 4;
2046
+
2047
+
2048
+ if (!offset) {
2049
+ continue;
2050
+ }
2051
+
2052
+ var finalAlpha;
2053
+ if (opacity > 0) {
2054
+ finalAlpha = opacity;
2055
+ } else {
2056
+ if (alpha < maxOpacity) {
2057
+ if (alpha < minOpacity) {
2058
+ finalAlpha = minOpacity;
2059
+ } else {
2060
+ finalAlpha = alpha;
2061
+ }
2062
+ } else {
2063
+ finalAlpha = maxOpacity;
2064
+ }
2065
+ }
2066
+
2067
+ imgData[i - 3] = palette[offset];
2068
+ imgData[i - 2] = palette[offset + 1];
2069
+ imgData[i - 1] = palette[offset + 2];
2070
+ imgData[i] = useGradientOpacity ? palette[offset + 3] : finalAlpha;
2071
+
2072
+ }
2073
+
2074
+ this.ctx.putImageData(img, x, y);
2075
+
2076
+ this._renderBoundaries = [1000, 1000, 0, 0];
2077
+
2078
+ },
2079
+ getValueAt: function (point) {
2080
+ var value;
2081
+ var shadowCtx = this.shadowCtx;
2082
+ var img = shadowCtx.getImageData(point.x, point.y, 1, 1);
2083
+ var data = img.data[3];
2084
+ var max = this._max;
2085
+ var min = this._min;
2086
+
2087
+ value = (Math.abs(max - min) * (data / 255)) >> 0;
2088
+
2089
+ return value;
2090
+ },
2091
+ getDataURL: function () {
2092
+ return this.canvas.toDataURL();
2093
+ }
2094
+ };
2095
+
2096
+
2097
+ return Canvas2dRenderer;
2098
+ })();
2099
+
2100
+ var Renderer = (function RendererClosure() {
2101
+
2102
+ var rendererFn = false;
2103
+
2104
+ if (HeatmapConfig['defaultRenderer'] === 'canvas2d') {
2105
+ rendererFn = Canvas2dRenderer;
2106
+ }
2107
+
2108
+ return rendererFn;
2109
+ })();
2110
+
2111
+
2112
+ var Util = {
2113
+ merge: function () {
2114
+ var merged = {};
2115
+ var argsLen = arguments.length;
2116
+ for (var i = 0; i < argsLen; i++) {
2117
+ var obj = arguments[i];
2118
+ for (var key in obj) {
2119
+ merged[key] = obj[key];
2120
+ }
2121
+ }
2122
+ return merged;
2123
+ }
2124
+ };
2125
+ // Heatmap Constructor
2126
+ var Heatmap = (function HeatmapClosure() {
2127
+
2128
+ var Coordinator = (function CoordinatorClosure() {
2129
+
2130
+ function Coordinator() {
2131
+ this.cStore = {};
2132
+ }
2133
+ Coordinator.prototype = {
2134
+ on: function (evtName, callback, scope) {
2135
+ var cStore = this.cStore;
2136
+
2137
+ if (!cStore[evtName]) {
2138
+ cStore[evtName] = [];
2139
+ }
2140
+ cStore[evtName].push((function (data) {
2141
+ return callback.call(scope, data);
2142
+ }));
2143
+ },
2144
+ emit: function (evtName, data) {
2145
+ var cStore = this.cStore;
2146
+ if (cStore[evtName]) {
2147
+ var len = cStore[evtName].length;
2148
+ for (var i = 0; i < len; i++) {
2149
+ var callback = cStore[evtName][i];
2150
+ callback(data);
2151
+ }
2152
+ }
2153
+ }
2154
+ };
2155
+
2156
+ return Coordinator;
2157
+ })();
2158
+
2159
+
2160
+ var _connect = function (scope) {
2161
+ var renderer = scope._renderer;
2162
+ var coordinator = scope._coordinator;
2163
+ var store = scope._store;
2164
+
2165
+ coordinator.on('renderpartial', renderer.renderPartial, renderer);
2166
+ coordinator.on('renderall', renderer.renderAll, renderer);
2167
+ coordinator.on('extremachange', function (data) {
2168
+ scope._config.onExtremaChange &&
2169
+ scope._config.onExtremaChange({
2170
+ min: data.min,
2171
+ max: data.max,
2172
+ gradient: scope._config['gradient'] || scope._config['defaultGradient']
2173
+ });
2174
+ });
2175
+ store.setCoordinator(coordinator);
2176
+ };
2177
+
2178
+
2179
+ function Heatmap() {
2180
+ var config = this._config = Util.merge(HeatmapConfig, arguments[0] || {});
2181
+ this._coordinator = new Coordinator();
2182
+ if (config['plugin']) {
2183
+ var pluginToLoad = config['plugin'];
2184
+ if (!HeatmapConfig.plugins[pluginToLoad]) {
2185
+ throw new Error('Plugin \'' + pluginToLoad + '\' not found. Maybe it was not registered.');
2186
+ } else {
2187
+ var plugin = HeatmapConfig.plugins[pluginToLoad];
2188
+ // set plugin renderer and store
2189
+ this._renderer = new plugin.renderer(config);
2190
+ this._store = new plugin.store(config);
2191
+ }
2192
+ } else {
2193
+ this._renderer = new Renderer(config);
2194
+ this._store = new Store(config);
2195
+ }
2196
+ _connect(this);
2197
+ }
2198
+ // @TODO:
2199
+ // add API documentation
2200
+ Heatmap.prototype = {
2201
+ addData: function () {
2202
+ this._store.addData.apply(this._store, arguments);
2203
+ return this;
2204
+ },
2205
+ removeData: function () {
2206
+ this._store.removeData && this._store.removeData.apply(this._store, arguments);
2207
+ return this;
2208
+ },
2209
+ setData: function () {
2210
+ this._store.setData.apply(this._store, arguments);
2211
+ return this;
2212
+ },
2213
+ setDataMax: function () {
2214
+ this._store.setDataMax.apply(this._store, arguments);
2215
+ return this;
2216
+ },
2217
+ setDataMin: function () {
2218
+ this._store.setDataMin.apply(this._store, arguments);
2219
+ return this;
2220
+ },
2221
+ configure: function (config) {
2222
+ const oldConfig = this._config;
2223
+ this._config = Util.merge(this._config, config);
2224
+ this._renderer.updateConfig(this._config, oldConfig);
2225
+ this._coordinator.emit('renderall', this._store._getInternalData());
2226
+ return this;
2227
+ },
2228
+ repaint: function () {
2229
+ this._coordinator.emit('renderall', this._store._getInternalData());
2230
+ return this;
2231
+ },
2232
+ getData: function () {
2233
+ return this._store.getData();
2234
+ },
2235
+ getDataURL: function () {
2236
+ return this._renderer.getDataURL();
2237
+ },
2238
+ getValueAt: function (point) {
2239
+
2240
+ if (this._store.getValueAt) {
2241
+ return this._store.getValueAt(point);
2242
+ } else if (this._renderer.getValueAt) {
2243
+ return this._renderer.getValueAt(point);
2244
+ } else {
2245
+ return null;
2246
+ }
2247
+ }
2248
+ };
2249
+
2250
+ return Heatmap;
2251
+
2252
+ })();
2253
+
2254
+
2255
+ // core
2256
+ var heatmapFactory = {
2257
+ create: function (config) {
2258
+ return new Heatmap(config);
2259
+ },
2260
+ register: function (pluginKey, plugin) {
2261
+ HeatmapConfig.plugins[pluginKey] = plugin;
2262
+ }
2263
+ };
2264
+
2265
+ return heatmapFactory;
2266
+
2267
+
2268
+ })();
2269
+
2270
+
2271
+
2272
+
2273
+
2274
+
2275
+ /*==============================以上部分为heatmap.js的核心代码,只负责热力图的展现====================================*/
2276
+
2277
+
2278
+ /*==============================以下部分为专为百度地图打造的覆盖物===================================================*/
2279
+ /**
2280
+ * @fileoverview 百度地图的热力图功能,对外开放。
2281
+ * 主要基于http://www.patrick-wied.at/static/heatmapjs/index.html 修改而得
2282
+
2283
+ * 主入口类是<a href="symbols/BMapLib.Heatmap.html">Heatmap</a>,
2284
+ * 基于Baidu Map API 2.0。
2285
+ *
2286
+ * @author Baidu Map Api Group
2287
+ * @version 1.0
2288
+ */
2289
+
2290
+ /**
2291
+ * 热力图的覆盖物
2292
+ * @class 热力图的覆盖物
2293
+ * 实例化该类后,使用map.addOverlay即可以添加热力图
2294
+ *
2295
+ * @constructor
2296
+ * @param {Json Object} opts 可选的输入参数,非必填项。可输入选项包括:<br />
2297
+ * {"<b>radius</b>" : {String} 热力图的半径,
2298
+ * <br />"<b>visible</b>" : {Number} 热力图是否显示,
2299
+ * <br />"<b>gradient</b>" : {JSON} 热力图的渐变区间,
2300
+ * <br />"<b>opacity</b>" : {Number} 热力的透明度,
2301
+ *
2302
+ * @example <b>参考示例:</b><br />
2303
+ * var map = new BMap.Map("container");<br />map.centerAndZoom(new BMap.Point(116.404, 39.915), 15);<br />var heatmapOverlay = new BMapLib.HeatmapOverlay({"radius":10, "visible":true, "opacity":70});<br />heatmapOverlay.setDataSet(data);//data是热力图的详细数据
2304
+ */
2305
+
2306
+ var HeatmapOverlay = function (opts) {
2307
+ if (Reflect.getPrototypeOf(HeatmapOverlay.prototype) !== BMap.Overlay.prototype) {
2308
+ // 保证让HeatmapOverlay继承BMap.Overlay
2309
+ // 根据文档, 修改原型链会降低访问属性的速度, 但这种写法对代码的修改最少, 故采用
2310
+ // @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/setPrototypeOf
2311
+ Reflect.setPrototypeOf(HeatmapOverlay.prototype, BMap.Overlay.prototype);
2312
+ }
2313
+ this.conf = opts;
2314
+ this.conf.visible = opts.visible === undefined ? true : opts.visible;
2315
+ this.heatmap = null;
2316
+ this.latlngs = [];
2317
+ this.bounds = null;
2318
+ };
2319
+
2320
+ HeatmapOverlay.prototype = Object.create(typeof BMap === 'undefined' ? null : BMap.Overlay.prototype);
2321
+
2322
+ HeatmapOverlay.prototype.initialize = function (map) {
2323
+
2324
+ this._map = map;
2325
+ var el = document.createElement("div");
2326
+ el.style.position = "absolute";
2327
+ el.style.top = 0;
2328
+ el.style.left = 0;
2329
+ el.style.border = 0;
2330
+ el.style.width = this._map.getSize().width + "px";
2331
+ el.style.height = this._map.getSize().height + "px";
2332
+ this.conf.element = el;
2333
+
2334
+
2335
+ if (!isSupportCanvas()) {//判断是否支持Canvas.
2336
+ return el;
2337
+ }
2338
+ map.getPanes().mapPane.appendChild(el);
2339
+ this.conf.valueField = this.conf.valueField || "count";
2340
+ this.heatmap = heatmapFactory.create(this.conf);
2341
+
2342
+ var that = this;
2343
+ map.addEventListener('resize', function (e) {
2344
+ var size = e.size;
2345
+ el.style.width = size.width + "px";
2346
+ el.style.height = size.height + "px";
2347
+ that.heatmap._renderer.setDimensions(size.width, size.height);
2348
+ that.draw();
2349
+ });
2350
+
2351
+ this._div = el;
2352
+ return el;
2353
+ };
2354
+
2355
+ HeatmapOverlay.prototype.draw = function () {
2356
+ if (!isSupportCanvas()) {//判断是否支持Canvas.
2357
+ return;
2358
+ }
2359
+ var currentBounds = this._map.getBounds();
2360
+
2361
+ if (currentBounds.equals(this.bounds)) {
2362
+ return;
2363
+ }
2364
+ this.bounds = currentBounds;
2365
+
2366
+ var ne = this._map.pointToOverlayPixel(currentBounds.getNorthEast()),
2367
+ sw = this._map.pointToOverlayPixel(currentBounds.getSouthWest()),
2368
+ topY = ne.y,
2369
+ leftX = sw.x,
2370
+ h = sw.y - ne.y,
2371
+ w = ne.x - sw.x;
2372
+
2373
+ this.conf.element.style.left = leftX + 'px';
2374
+ this.conf.element.style.top = topY + 'px';
2375
+ this.conf.element.style.width = w + 'px';
2376
+ this.conf.element.style.height = h + 'px';
2377
+ //this.heatmap.store.get("heatmap").resize();
2378
+
2379
+ if (this.latlngs.length > 0) {
2380
+ this.heatmap.removeData();
2381
+
2382
+ var len = this.latlngs.length;
2383
+ const d = {
2384
+ max: this.heatmap._store.getData().max,
2385
+ data: []
2386
+ };
2387
+
2388
+ while (len--) {
2389
+ var latlng = this.latlngs[len].latlng;
2390
+
2391
+ if (!currentBounds.containsPoint(latlng)) {
2392
+ continue;
2393
+ }
2394
+
2395
+ var divPixel = this._map.pointToOverlayPixel(latlng),
2396
+ leftX = this._map.pointToOverlayPixel(currentBounds.getSouthWest()).x,
2397
+ topY = this._map.pointToOverlayPixel(currentBounds.getNorthEast()).y,
2398
+ screenPixel = new BMap.Pixel(divPixel.x - leftX, divPixel.y - topY);
2399
+ var roundedPoint = this.pixelTransform(screenPixel);
2400
+ d.data.push({
2401
+ x: roundedPoint.x,
2402
+ y: roundedPoint.y,
2403
+ count: this.latlngs[len].c
2404
+ });
2405
+ }
2406
+
2407
+ if (this.conf.radiusChangeByZoom) {
2408
+ this.heatmap._store._cfgRadius = this.conf.radiusChangeByZoom(this._map.getZoom());
2409
+ }
2410
+ this.heatmap.setData(d);
2411
+ }
2412
+ };
2413
+
2414
+
2415
+ //内部使用的坐标转化
2416
+ HeatmapOverlay.prototype.pixelTransform = function (p) {
2417
+ var w = this.heatmap.width,
2418
+ h = this.heatmap.height;
2419
+
2420
+ while (p.x < 0) {
2421
+ p.x += w;
2422
+ }
2423
+
2424
+ while (p.x > w) {
2425
+ p.x -= w;
2426
+ }
2427
+
2428
+ while (p.y < 0) {
2429
+ p.y += h;
2430
+ }
2431
+
2432
+ while (p.y > h) {
2433
+ p.y -= h;
2434
+ }
2435
+
2436
+ p.x = (p.x >> 0);
2437
+ p.y = (p.y >> 0);
2438
+
2439
+ return p;
2440
+ };
2441
+
2442
+ /**
2443
+ * 设置热力图展现的详细数据, 实现之后,即可以立刻展现
2444
+ * @param {Json Object } data
2445
+ * {"<b>max</b>" : {Number} 权重的最大值,
2446
+ * <br />"<b>data</b>" : {Array} 坐标详细数据,格式如下 <br/>
2447
+ * {"lng":116.421969,"lat":39.913527,"count":3}, 其中<br/>
2448
+ * lng lat分别为经纬度, count权重值
2449
+ */
2450
+ HeatmapOverlay.prototype.setDataSet = function (data) {
2451
+ this.data = data;
2452
+ if (!isSupportCanvas()) {//判断是否支持Canvas.
2453
+ return;
2454
+ }
2455
+ var currentBounds = this._map.getBounds();
2456
+ var mapdata = {
2457
+ max: data.max,
2458
+ data: []
2459
+ };
2460
+ var d = data.data,
2461
+ dlen = d.length;
2462
+
2463
+
2464
+ this.latlngs = [];
2465
+ this.heatmap.removeData();
2466
+
2467
+ if (this.conf.radiusChangeByZoom) {
2468
+ this.heatmap._store._cfgRadius = this.conf.radiusChangeByZoom(this._map.getZoom());
2469
+ }
2470
+
2471
+ while (dlen--) {
2472
+ var latlng = new BMap.Point(d[dlen].lng, d[dlen].lat);
2473
+ this.latlngs.push({
2474
+ latlng: latlng,
2475
+ c: d[dlen].count
2476
+ });
2477
+
2478
+ if (!currentBounds.containsPoint(latlng)) {
2479
+ continue;
2480
+ }
2481
+
2482
+ var divPixel = this._map.pointToOverlayPixel(latlng),
2483
+ leftX = this._map.pointToOverlayPixel(currentBounds.getSouthWest()).x,
2484
+ topY = this._map.pointToOverlayPixel(currentBounds.getNorthEast()).y,
2485
+ screenPixel = new BMap.Pixel(divPixel.x - leftX, divPixel.y - topY);
2486
+ var point = this.pixelTransform(screenPixel);
2487
+
2488
+ mapdata.data.push({
2489
+ x: point.x,
2490
+ y: point.y,
2491
+ count: d[dlen].count
2492
+ });
2493
+ }
2494
+ this.heatmap.setData(mapdata);
2495
+ };
2496
+
2497
+ /**
2498
+ * 添加热力图的详细坐标点
2499
+ * @param {Number} lng 经度坐标
2500
+ * @param {Number} lat 纬度坐标
2501
+ * @param {Number} count 权重
2502
+ */
2503
+ HeatmapOverlay.prototype.addDataPoint = function (lng, lat, count) {
2504
+
2505
+ if (!isSupportCanvas()) {
2506
+ return;
2507
+ }
2508
+ if (this.data && this.data.data) {
2509
+ this.data.data.push({
2510
+ lng: lng,
2511
+ lat: lat,
2512
+ count: count
2513
+ });
2514
+ }
2515
+
2516
+ var latlng = new BMap.Point(lng, lat),
2517
+ point = this.pixelTransform(this._map.pointToOverlayPixel(latlng));
2518
+
2519
+ this.heatmap.store.addDataPoint(point.x, point.y, count);
2520
+ this.latlngs.push({
2521
+ latlng: latlng,
2522
+ c: count
2523
+ });
2524
+ };
2525
+
2526
+ /**
2527
+ * 更改热力图的展现或者关闭
2528
+ */
2529
+
2530
+ HeatmapOverlay.prototype.toggle = function () {
2531
+ if (!isSupportCanvas()) {//判断是否支持Canvas.
2532
+ return;
2533
+ }
2534
+ if (this.conf.visible === true) {
2535
+ this.conf.visible = false;
2536
+ } else {
2537
+ this.conf.visible = true;
2538
+ } if (this.conf.visible) {
2539
+ this.conf.element.style.display = "block";
2540
+ } else {
2541
+ this.conf.element.style.display = "none";
2542
+ }
2543
+ };
2544
+ /**
2545
+ * 设置热力图展现的配置
2546
+ * @param {Json Object} options 可选的输入参数,非必填项。可输入选项包括:<br />
2547
+ * {"<b>radius</b>" : {String} 热力图的半径,
2548
+ * <br />"<b>visible</b>" : {Number} 热力图是否显示,
2549
+ * <br />"<b>gradient</b>" : {JSON} 热力图的渐变区间,
2550
+ * <br />"<b>opacity</b>" : {Number} 热力的透明度,}
2551
+ */
2552
+ HeatmapOverlay.prototype.setOptions = function (options) {
2553
+ if (!isSupportCanvas()) {//判断是否支持Canvas.
2554
+ return;
2555
+ }
2556
+ for (var key in options) {
2557
+ if (key == "radius") {
2558
+ this.heatmap._store._cfgRadius = options[key];
2559
+ }
2560
+ }
2561
+ this.heatmap.configure(options);
2562
+ if (this.data) {
2563
+ this.setDataSet(this.data);//重新渲染
2564
+ }
2565
+ };
2566
+
2567
+
2568
+ function isSupportCanvas() {
2569
+ var elem = document.createElement('canvas');
2570
+ return !!(elem.getContext && elem.getContext('2d'));
2571
+ }
2572
+
2573
+ return HeatmapOverlay
2574
+ });
2575
+ } (bmaplib_heatmap$1));
2576
+ return bmaplib_heatmap$1.exports;
2577
+ }
2578
+
2579
+ var bmaplib_heatmapExports = requireBmaplib_heatmap();
2580
+ var BHeatMapOverlay = /*@__PURE__*/getDefaultExportFromCjs(bmaplib_heatmapExports);
2581
+
1562
2582
  /** 默认半径 */
1563
2583
  const RADIUS_DEFAULT = 10;
1564
2584
  const HeatmapOptions = {
@@ -1862,6 +2882,3027 @@ class BaiduMapUrls extends MapUrls {
1862
2882
  }
1863
2883
  }
1864
2884
 
2885
+ /**
2886
+ * Copyright 2019 Google LLC. All Rights Reserved.
2887
+ *
2888
+ * Licensed under the Apache License, Version 2.0 (the "License");
2889
+ * you may not use this file except in compliance with the License.
2890
+ * You may obtain a copy of the License at
2891
+ *
2892
+ * http://www.apache.org/licenses/LICENSE-2.0
2893
+ *
2894
+ * Unless required by applicable law or agreed to in writing, software
2895
+ * distributed under the License is distributed on an "AS IS" BASIS,
2896
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2897
+ * See the License for the specific language governing permissions and
2898
+ * limitations under the License.
2899
+ */
2900
+
2901
+ /**
2902
+ * @name MarkerClusterer for Google Maps v3
2903
+ * @author Luke Mahe
2904
+ * @fileoverview
2905
+ * The library creates and manages per-zoom-level clusters for large amounts of
2906
+ * markers.
2907
+ */
2908
+
2909
+ /**
2910
+ * A Marker Clusterer that clusters markers.
2911
+ *
2912
+ * @param {google.maps.Map} map The Google map to attach to.
2913
+ * @param {Array.<google.maps.Marker>=} opt_markers Optional markers to add to
2914
+ * the cluster.
2915
+ * @param {Object=} opt_options support the following options:
2916
+ * 'gridSize': (number) The grid size of a cluster in pixels.
2917
+ * 'maxZoom': (number) The maximum zoom level that a marker can be part of a
2918
+ * cluster.
2919
+ * 'zoomOnClick': (boolean) Whether the default behaviour of clicking on a
2920
+ * cluster is to zoom into it.
2921
+ * 'imagePath': (string) The base URL where the images representing
2922
+ * clusters will be found. The full URL will be:
2923
+ * {imagePath}[1-5].{imageExtension}
2924
+ * Default: '../images/m'.
2925
+ * 'imageExtension': (string) The suffix for images URL representing
2926
+ * clusters will be found. See _imagePath_ for details.
2927
+ * Default: 'png'.
2928
+ * 'averageCenter': (boolean) Whether the center of each cluster should be
2929
+ * the average of all markers in the cluster.
2930
+ * 'minimumClusterSize': (number) The minimum number of markers to be in a
2931
+ * cluster before the markers are hidden and a count
2932
+ * is shown.
2933
+ * 'zIndex': (number) the z-index of a cluster.
2934
+ * Default: google.maps.Marker.MAX_ZINDEX + 1
2935
+ * 'styles': (Array.<Object>) An Array of single object that has style properties for all cluster:
2936
+ * 'url': (string) The image url.
2937
+ * 'height': (number) The image height.
2938
+ * 'width': (number) The image width.
2939
+ * 'anchor': (Array) The anchor position of the label text.
2940
+ * 'textColor': (string) The text color.
2941
+ * 'textSize': (number) The text size.
2942
+ * 'backgroundPosition': (string) The position of the backgound x, y.
2943
+ * @constructor
2944
+ * @extends google.maps.OverlayView
2945
+ */
2946
+
2947
+ let MarkerClusterer$2 = class MarkerClusterer {
2948
+ constructor(map, opt_markers, opt_options) {
2949
+ this.extend(MarkerClusterer, google.maps.OverlayView);
2950
+ this.map_ = map;
2951
+
2952
+ /**
2953
+ * The marker cluster image path.
2954
+ *
2955
+ * @type {string}
2956
+ * @private
2957
+ */
2958
+ this.MARKER_CLUSTER_IMAGE_PATH_ = "../images/m";
2959
+
2960
+ /**
2961
+ * The marker cluster image path.
2962
+ *
2963
+ * @type {string}
2964
+ * @private
2965
+ */
2966
+ this.MARKER_CLUSTER_IMAGE_EXTENSION_ = "png";
2967
+ /**
2968
+ * @type {Array.<google.maps.Marker>}
2969
+ * @private
2970
+ */
2971
+ this.markers_ = [];
2972
+
2973
+ /**
2974
+ * @type {Array.<Cluster>}
2975
+ */
2976
+ this.clusters_ = [];
2977
+
2978
+ this.sizes = [53, 56, 66, 78, 90];
2979
+
2980
+ /**
2981
+ * @type {Array.<Object>}
2982
+ * @private
2983
+ */
2984
+ this.styles_ = [];
2985
+
2986
+ /**
2987
+ * @type {boolean}
2988
+ * @private
2989
+ */
2990
+ this.ready_ = false;
2991
+
2992
+ var options = opt_options || {};
2993
+
2994
+ /**
2995
+ * @type {number}
2996
+ */
2997
+ this.zIndex_ = options["zIndex"] || google.maps.Marker.MAX_ZINDEX + 1;
2998
+
2999
+ /**
3000
+ * @type {number}
3001
+ * @private
3002
+ */
3003
+ this.gridSize_ = options["gridSize"] || 60;
3004
+
3005
+ /**
3006
+ * @private
3007
+ */
3008
+ this.minClusterSize_ = options["minimumClusterSize"] || 2;
3009
+
3010
+ /**
3011
+ * @type {?number}
3012
+ * @private
3013
+ */
3014
+ this.maxZoom_ = options["maxZoom"] || null;
3015
+
3016
+ this.styles_ = options["styles"] || [];
3017
+
3018
+ /**
3019
+ * @type {string}
3020
+ * @private
3021
+ */
3022
+ this.imagePath_ = options["imagePath"] || this.MARKER_CLUSTER_IMAGE_PATH_;
3023
+
3024
+ /**
3025
+ * @type {string}
3026
+ * @private
3027
+ */
3028
+ this.imageExtension_ =
3029
+ options["imageExtension"] || this.MARKER_CLUSTER_IMAGE_EXTENSION_;
3030
+
3031
+ /**
3032
+ * @type {boolean}
3033
+ * @private
3034
+ */
3035
+ this.zoomOnClick_ = true;
3036
+
3037
+ if (options["zoomOnClick"] != undefined) {
3038
+ this.zoomOnClick_ = options["zoomOnClick"];
3039
+ }
3040
+
3041
+ /**
3042
+ * @type {boolean}
3043
+ * @private
3044
+ */
3045
+ this.averageCenter_ = false;
3046
+
3047
+ if (options["averageCenter"] != undefined) {
3048
+ this.averageCenter_ = options["averageCenter"];
3049
+ }
3050
+
3051
+ this.setupStyles_();
3052
+
3053
+ this.setMap(map);
3054
+
3055
+ /**
3056
+ * @type {number}
3057
+ * @private
3058
+ */
3059
+ this.prevZoom_ = this.map_.getZoom();
3060
+
3061
+ // Add the map event listeners
3062
+ var that = this;
3063
+ google.maps.event.addListener(this.map_, "zoom_changed", function() {
3064
+ // Determines map type and prevent illegal zoom levels
3065
+ var zoom = that.map_.getZoom();
3066
+ var minZoom = that.map_.minZoom || 0;
3067
+ var maxZoom = Math.min(
3068
+ that.map_.maxZoom || 100,
3069
+ that.map_.mapTypes[that.map_.getMapTypeId()].maxZoom
3070
+ );
3071
+ zoom = Math.min(Math.max(zoom, minZoom), maxZoom);
3072
+
3073
+ if (that.prevZoom_ != zoom) {
3074
+ that.prevZoom_ = zoom;
3075
+ that.resetViewport();
3076
+ }
3077
+ });
3078
+
3079
+ google.maps.event.addListener(this.map_, "idle", function() {
3080
+ that.redraw();
3081
+ });
3082
+
3083
+ // Finally, add the markers
3084
+ if (
3085
+ opt_markers &&
3086
+ (opt_markers.length || Object.keys(opt_markers).length)
3087
+ ) {
3088
+ this.addMarkers(opt_markers, false);
3089
+ }
3090
+ }
3091
+
3092
+ /**
3093
+ * Extends a objects prototype by anothers.
3094
+ *
3095
+ * @param {Object} obj1 The object to be extended.
3096
+ * @param {Object} obj2 The object to extend with.
3097
+ * @return {Object} The new extended object.
3098
+ * @ignore
3099
+ */
3100
+ extend(obj1, obj2) {
3101
+ return function(object) {
3102
+ for (var property in object.prototype) {
3103
+ this.prototype[property] = object.prototype[property];
3104
+ }
3105
+ return this;
3106
+ }.apply(obj1, [obj2]);
3107
+ }
3108
+
3109
+ /**
3110
+ * Implementaion of the interface method.
3111
+ * @ignore
3112
+ */
3113
+ onAdd() {
3114
+ this.setReady_(true);
3115
+ }
3116
+
3117
+ /**
3118
+ * Implementaion of the interface method.
3119
+ * @ignore
3120
+ */
3121
+ draw() {}
3122
+
3123
+ /**
3124
+ * Sets up the styles object.
3125
+ *
3126
+ * @private
3127
+ */
3128
+ setupStyles_() {
3129
+ if (this.styles_.length) {
3130
+ return;
3131
+ }
3132
+
3133
+ for (var i = 0, size; (size = this.sizes[i]); i++) {
3134
+ this.styles_.push({
3135
+ url: this.imagePath_ + (i + 1) + "." + this.imageExtension_,
3136
+ height: size,
3137
+ width: size
3138
+ });
3139
+ }
3140
+ }
3141
+
3142
+ /**
3143
+ * Fit the map to the bounds of the markers in the clusterer.
3144
+ */
3145
+ fitMapToMarkers() {
3146
+ var markers = this.getMarkers();
3147
+ var bounds = new google.maps.LatLngBounds();
3148
+ for (var i = 0, marker; (marker = markers[i]); i++) {
3149
+ bounds.extend(marker.getPosition());
3150
+ }
3151
+
3152
+ this.map_.fitBounds(bounds);
3153
+ }
3154
+
3155
+ /**
3156
+ * @param {number} zIndex
3157
+ */
3158
+ setZIndex(zIndex) {
3159
+ this.zIndex_ = zIndex;
3160
+ }
3161
+
3162
+ /**
3163
+ * @return {number}
3164
+ */
3165
+ getZIndex() {
3166
+ return this.zIndex_;
3167
+ }
3168
+
3169
+ /**
3170
+ * Sets the styles.
3171
+ *
3172
+ * @param {Object} styles The style to set.
3173
+ */
3174
+ setStyles(styles) {
3175
+ this.styles_ = styles;
3176
+ }
3177
+
3178
+ /**
3179
+ * Gets the styles.
3180
+ *
3181
+ * @return {Object} The styles object.
3182
+ */
3183
+ getStyles() {
3184
+ return this.styles_;
3185
+ }
3186
+
3187
+ /**
3188
+ * Whether zoom on click is set.
3189
+ *
3190
+ * @return {boolean} True if zoomOnClick_ is set.
3191
+ */
3192
+ isZoomOnClick() {
3193
+ return this.zoomOnClick_;
3194
+ }
3195
+
3196
+ /**
3197
+ * Whether average center is set.
3198
+ *
3199
+ * @return {boolean} True if averageCenter_ is set.
3200
+ */
3201
+ isAverageCenter() {
3202
+ return this.averageCenter_;
3203
+ }
3204
+
3205
+ /**
3206
+ * Returns the array of markers in the clusterer.
3207
+ *
3208
+ * @return {Array.<google.maps.Marker>} The markers.
3209
+ */
3210
+ getMarkers() {
3211
+ return this.markers_;
3212
+ }
3213
+
3214
+ /**
3215
+ * Returns the number of markers in the clusterer
3216
+ *
3217
+ * @return {Number} The number of markers.
3218
+ */
3219
+ getTotalMarkers() {
3220
+ return this.markers_.length;
3221
+ }
3222
+
3223
+ /**
3224
+ * Sets the max zoom for the clusterer.
3225
+ *
3226
+ * @param {number} maxZoom The max zoom level.
3227
+ */
3228
+ setMaxZoom(maxZoom) {
3229
+ this.maxZoom_ = maxZoom;
3230
+ }
3231
+
3232
+ /**
3233
+ * Gets the max zoom for the clusterer.
3234
+ *
3235
+ * @return {number} The max zoom level.
3236
+ */
3237
+ getMaxZoom() {
3238
+ return this.maxZoom_;
3239
+ }
3240
+
3241
+ /**
3242
+ * The function for calculating the cluster icon image.
3243
+ *
3244
+ * @param {Array.<google.maps.Marker>} markers The markers in the clusterer.
3245
+ * @param {number} numStyles The number of styles available.
3246
+ * @return {Object} A object properties: 'text' (string) and 'index' (number).
3247
+ * @private
3248
+ */
3249
+ calculator_(markers, numStyles) {
3250
+ var index = 0;
3251
+ var count = markers.length;
3252
+ var dv = count;
3253
+ while (dv !== 0) {
3254
+ dv = parseInt(dv / 10, 10);
3255
+ index++;
3256
+ }
3257
+
3258
+ index = Math.min(index, numStyles);
3259
+ return {
3260
+ text: count,
3261
+ index: index
3262
+ };
3263
+ }
3264
+
3265
+ /**
3266
+ * Set the calculator function.
3267
+ *
3268
+ * @param {function(Array, number)} calculator The function to set as the
3269
+ * calculator. The function should return a object properties:
3270
+ * 'text' (string) and 'index' (number).
3271
+ *
3272
+ */
3273
+ setCalculator(calculator) {
3274
+ this.calculator_ = calculator;
3275
+ }
3276
+
3277
+ /**
3278
+ * Get the calculator function.
3279
+ *
3280
+ * @return {function(Array, number)} the calculator function.
3281
+ */
3282
+ getCalculator() {
3283
+ return this.calculator_;
3284
+ }
3285
+
3286
+ /**
3287
+ * Add an array of markers to the clusterer.
3288
+ *
3289
+ * @param {Array.<google.maps.Marker>} markers The markers to add.
3290
+ * @param {boolean=} opt_nodraw Whether to redraw the clusters.
3291
+ */
3292
+ addMarkers(markers, opt_nodraw) {
3293
+ if (markers.length) {
3294
+ for (let i = 0, marker; (marker = markers[i]); i++) {
3295
+ this.pushMarkerTo_(marker);
3296
+ }
3297
+ } else if (Object.keys(markers).length) {
3298
+ for (let marker in markers) {
3299
+ this.pushMarkerTo_(markers[marker]);
3300
+ }
3301
+ }
3302
+ if (!opt_nodraw) {
3303
+ this.redraw();
3304
+ }
3305
+ }
3306
+
3307
+ /**
3308
+ * Pushes a marker to the clusterer.
3309
+ *
3310
+ * @param {google.maps.Marker} marker The marker to add.
3311
+ * @private
3312
+ */
3313
+ pushMarkerTo_(marker) {
3314
+ marker.isAdded = false;
3315
+ if (marker["draggable"]) {
3316
+ // If the marker is draggable add a listener so we update the clusters on
3317
+ // the drag end.
3318
+ var that = this;
3319
+ google.maps.event.addListener(marker, "dragend", function() {
3320
+ marker.isAdded = false;
3321
+ that.repaint();
3322
+ });
3323
+ }
3324
+ this.markers_.push(marker);
3325
+ }
3326
+
3327
+ /**
3328
+ * Adds a marker to the clusterer and redraws if needed.
3329
+ *
3330
+ * @param {google.maps.Marker} marker The marker to add.
3331
+ * @param {boolean=} opt_nodraw Whether to redraw the clusters.
3332
+ */
3333
+ addMarker(marker, opt_nodraw) {
3334
+ this.pushMarkerTo_(marker);
3335
+ if (!opt_nodraw) {
3336
+ this.redraw();
3337
+ }
3338
+ }
3339
+
3340
+ /**
3341
+ * Removes a marker and returns true if removed, false if not
3342
+ *
3343
+ * @param {google.maps.Marker} marker The marker to remove
3344
+ * @return {boolean} Whether the marker was removed or not
3345
+ * @private
3346
+ */
3347
+ removeMarker_(marker) {
3348
+ var index = -1;
3349
+ if (this.markers_.indexOf) {
3350
+ index = this.markers_.indexOf(marker);
3351
+ } else {
3352
+ for (var i = 0, m; (m = this.markers_[i]); i++) {
3353
+ if (m == marker) {
3354
+ index = i;
3355
+ break;
3356
+ }
3357
+ }
3358
+ }
3359
+
3360
+ if (index == -1) {
3361
+ // Marker is not in our list of markers.
3362
+ return false;
3363
+ }
3364
+
3365
+ marker.setMap(null);
3366
+
3367
+ this.markers_.splice(index, 1);
3368
+
3369
+ return true;
3370
+ }
3371
+
3372
+ /**
3373
+ * Remove a marker from the cluster.
3374
+ *
3375
+ * @param {google.maps.Marker} marker The marker to remove.
3376
+ * @param {boolean=} opt_nodraw Optional boolean to force no redraw.
3377
+ * @return {boolean} True if the marker was removed.
3378
+ */
3379
+ removeMarker(marker, opt_nodraw) {
3380
+ var removed = this.removeMarker_(marker);
3381
+
3382
+ if (!opt_nodraw && removed) {
3383
+ this.resetViewport();
3384
+ this.redraw();
3385
+ return true;
3386
+ } else {
3387
+ return false;
3388
+ }
3389
+ }
3390
+
3391
+ /**
3392
+ * Removes an array of markers from the cluster.
3393
+ *
3394
+ * @param {Array.<google.maps.Marker>} markers The markers to remove.
3395
+ * @param {boolean=} opt_nodraw Optional boolean to force no redraw.
3396
+ */
3397
+ removeMarkers(markers, opt_nodraw) {
3398
+ // create a local copy of markers if required
3399
+ // (removeMarker_ modifies the getMarkers() array in place)
3400
+ var markersCopy = markers === this.getMarkers() ? markers.slice() : markers;
3401
+ var removed = false;
3402
+
3403
+ for (var i = 0, marker; (marker = markersCopy[i]); i++) {
3404
+ var r = this.removeMarker_(marker);
3405
+ removed = removed || r;
3406
+ }
3407
+
3408
+ if (!opt_nodraw && removed) {
3409
+ this.resetViewport();
3410
+ this.redraw();
3411
+ return true;
3412
+ }
3413
+ }
3414
+
3415
+ /**
3416
+ * Sets the clusterer's ready state.
3417
+ *
3418
+ * @param {boolean} ready The state.
3419
+ * @private
3420
+ */
3421
+ setReady_(ready) {
3422
+ if (!this.ready_) {
3423
+ this.ready_ = ready;
3424
+ this.createClusters_();
3425
+ }
3426
+ }
3427
+
3428
+ /**
3429
+ * Returns the number of clusters in the clusterer.
3430
+ *
3431
+ * @return {number} The number of clusters.
3432
+ */
3433
+ getTotalClusters() {
3434
+ return this.clusters_.length;
3435
+ }
3436
+
3437
+ /**
3438
+ * Returns the google map that the clusterer is associated with.
3439
+ *
3440
+ * @return {google.maps.Map} The map.
3441
+ */
3442
+ getMap() {
3443
+ return this.map_;
3444
+ }
3445
+
3446
+ /**
3447
+ * Sets the google map that the clusterer is associated with.
3448
+ *
3449
+ * @param {google.maps.Map} map The map.
3450
+ */
3451
+ setMap(map) {
3452
+ this.map_ = map;
3453
+ }
3454
+
3455
+ /**
3456
+ * Returns the size of the grid.
3457
+ *
3458
+ * @return {number} The grid size.
3459
+ */
3460
+ getGridSize() {
3461
+ return this.gridSize_;
3462
+ }
3463
+
3464
+ /**
3465
+ * Sets the size of the grid.
3466
+ *
3467
+ * @param {number} size The grid size.
3468
+ */
3469
+ setGridSize(size) {
3470
+ this.gridSize_ = size;
3471
+ }
3472
+
3473
+ /**
3474
+ * Returns the min cluster size.
3475
+ *
3476
+ * @return {number} The grid size.
3477
+ */
3478
+ getMinClusterSize() {
3479
+ return this.minClusterSize_;
3480
+ }
3481
+
3482
+ /**
3483
+ * Sets the min cluster size.
3484
+ *
3485
+ * @param {number} size The grid size.
3486
+ */
3487
+ setMinClusterSize(size) {
3488
+ this.minClusterSize_ = size;
3489
+ }
3490
+
3491
+ /**
3492
+ * Extends a bounds object by the grid size.
3493
+ *
3494
+ * @param {google.maps.LatLngBounds} bounds The bounds to extend.
3495
+ * @return {google.maps.LatLngBounds} The extended bounds.
3496
+ */
3497
+ getExtendedBounds(bounds) {
3498
+ var projection = this.getProjection();
3499
+
3500
+ // Turn the bounds into latlng.
3501
+ var tr = new google.maps.LatLng(
3502
+ bounds.getNorthEast().lat(),
3503
+ bounds.getNorthEast().lng()
3504
+ );
3505
+ var bl = new google.maps.LatLng(
3506
+ bounds.getSouthWest().lat(),
3507
+ bounds.getSouthWest().lng()
3508
+ );
3509
+
3510
+ // Convert the points to pixels and the extend out by the grid size.
3511
+ var trPix = projection.fromLatLngToDivPixel(tr);
3512
+ trPix.x += this.gridSize_;
3513
+ trPix.y -= this.gridSize_;
3514
+
3515
+ var blPix = projection.fromLatLngToDivPixel(bl);
3516
+ blPix.x -= this.gridSize_;
3517
+ blPix.y += this.gridSize_;
3518
+
3519
+ // Convert the pixel points back to LatLng
3520
+ var ne = projection.fromDivPixelToLatLng(trPix);
3521
+ var sw = projection.fromDivPixelToLatLng(blPix);
3522
+
3523
+ // Extend the bounds to contain the new bounds.
3524
+ bounds.extend(ne);
3525
+ bounds.extend(sw);
3526
+
3527
+ return bounds;
3528
+ }
3529
+
3530
+ /**
3531
+ * Determins if a marker is contained in a bounds.
3532
+ *
3533
+ * @param {google.maps.Marker} marker The marker to check.
3534
+ * @param {google.maps.LatLngBounds} bounds The bounds to check against.
3535
+ * @return {boolean} True if the marker is in the bounds.
3536
+ * @private
3537
+ */
3538
+ isMarkerInBounds_(marker, bounds) {
3539
+ return bounds.contains(marker.getPosition());
3540
+ }
3541
+
3542
+ /**
3543
+ * Clears all clusters and markers from the clusterer.
3544
+ */
3545
+ clearMarkers() {
3546
+ this.resetViewport(true);
3547
+
3548
+ // Set the markers a empty array.
3549
+ this.markers_ = [];
3550
+ }
3551
+
3552
+ /**
3553
+ * Clears all existing clusters and recreates them.
3554
+ * @param {boolean} opt_hide To also hide the marker.
3555
+ */
3556
+ resetViewport(opt_hide) {
3557
+ // Remove all the clusters
3558
+ for (let i = 0, cluster; (cluster = this.clusters_[i]); i++) {
3559
+ cluster.remove();
3560
+ }
3561
+
3562
+ // Reset the markers to not be added and to be invisible.
3563
+ for (let i = 0, marker; (marker = this.markers_[i]); i++) {
3564
+ marker.isAdded = false;
3565
+ if (opt_hide) {
3566
+ marker.setMap(null);
3567
+ }
3568
+ }
3569
+
3570
+ this.clusters_ = [];
3571
+ }
3572
+
3573
+ /**
3574
+ *
3575
+ */
3576
+ repaint() {
3577
+ var oldClusters = this.clusters_.slice();
3578
+ this.clusters_.length = 0;
3579
+ this.resetViewport();
3580
+ this.redraw();
3581
+
3582
+ // Remove the old clusters.
3583
+ // Do it in a timeout so the other clusters have been drawn first.
3584
+ setTimeout(function() {
3585
+ for (var i = 0, cluster; (cluster = oldClusters[i]); i++) {
3586
+ cluster.remove();
3587
+ }
3588
+ }, 0);
3589
+ }
3590
+
3591
+ /**
3592
+ * Redraws the clusters.
3593
+ */
3594
+ redraw() {
3595
+ this.createClusters_();
3596
+ }
3597
+
3598
+ /**
3599
+ * Calculates the distance between two latlng locations in km.
3600
+ * @see http://www.movable-type.co.uk/scripts/latlong.html
3601
+ *
3602
+ * @param {google.maps.LatLng} p1 The first lat lng point.
3603
+ * @param {google.maps.LatLng} p2 The second lat lng point.
3604
+ * @return {number} The distance between the two points in km.
3605
+ * @private
3606
+ */
3607
+ distanceBetweenPoints_(p1, p2) {
3608
+ if (!p1 || !p2) {
3609
+ return 0;
3610
+ }
3611
+
3612
+ var R = 6371; // Radius of the Earth in km
3613
+ var dLat = ((p2.lat() - p1.lat()) * Math.PI) / 180;
3614
+ var dLon = ((p2.lng() - p1.lng()) * Math.PI) / 180;
3615
+ var a =
3616
+ Math.sin(dLat / 2) * Math.sin(dLat / 2) +
3617
+ Math.cos((p1.lat() * Math.PI) / 180) *
3618
+ Math.cos((p2.lat() * Math.PI) / 180) *
3619
+ Math.sin(dLon / 2) *
3620
+ Math.sin(dLon / 2);
3621
+ var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
3622
+ var d = R * c;
3623
+ return d;
3624
+ }
3625
+
3626
+ /**
3627
+ * Add a marker to a cluster, or creates a new cluster.
3628
+ *
3629
+ * @param {google.maps.Marker} marker The marker to add.
3630
+ * @private
3631
+ */
3632
+ addToClosestCluster_(marker) {
3633
+ var distance = 40000; // Some large number
3634
+ var clusterToAddTo = null;
3635
+ for (var i = 0, cluster; (cluster = this.clusters_[i]); i++) {
3636
+ var center = cluster.getCenter();
3637
+ if (center) {
3638
+ var d = this.distanceBetweenPoints_(center, marker.getPosition());
3639
+ if (d < distance) {
3640
+ distance = d;
3641
+ clusterToAddTo = cluster;
3642
+ }
3643
+ }
3644
+ }
3645
+
3646
+ if (clusterToAddTo && clusterToAddTo.isMarkerInClusterBounds(marker)) {
3647
+ clusterToAddTo.addMarker(marker);
3648
+ } else {
3649
+ var newCluster = new Cluster$1(this);
3650
+ newCluster.addMarker(marker);
3651
+ this.clusters_.push(newCluster);
3652
+ }
3653
+ }
3654
+
3655
+ /**
3656
+ * Creates the clusters.
3657
+ *
3658
+ * @private
3659
+ */
3660
+ createClusters_() {
3661
+ if (!this.ready_) {
3662
+ return;
3663
+ }
3664
+
3665
+ // Get our current map view bounds.
3666
+ // Create a new bounds object so we don't affect the map.
3667
+ var mapBounds = new google.maps.LatLngBounds(
3668
+ this.map_.getBounds().getSouthWest(),
3669
+ this.map_.getBounds().getNorthEast()
3670
+ );
3671
+ var bounds = this.getExtendedBounds(mapBounds);
3672
+
3673
+ for (var i = 0, marker; (marker = this.markers_[i]); i++) {
3674
+ if (!marker.isAdded && this.isMarkerInBounds_(marker, bounds)) {
3675
+ this.addToClosestCluster_(marker);
3676
+ }
3677
+ }
3678
+ }
3679
+ };
3680
+
3681
+ /**
3682
+ * A cluster that contains markers.
3683
+ *
3684
+ * @param {MarkerClusterer} markerClusterer The markerclusterer that this
3685
+ * cluster is associated with.
3686
+ * @constructor
3687
+ * @ignore
3688
+ */
3689
+ let Cluster$1 = class Cluster {
3690
+ constructor(markerClusterer) {
3691
+ this.markerClusterer_ = markerClusterer;
3692
+ this.map_ = markerClusterer.getMap();
3693
+ this.gridSize_ = markerClusterer.getGridSize();
3694
+ this.minClusterSize_ = markerClusterer.getMinClusterSize();
3695
+ this.averageCenter_ = markerClusterer.isAverageCenter();
3696
+ this.center_ = null;
3697
+ this.markers_ = [];
3698
+ this.bounds_ = null;
3699
+ this.clusterIcon_ = new ClusterIcon(
3700
+ this,
3701
+ markerClusterer.getStyles(),
3702
+ markerClusterer.getGridSize()
3703
+ );
3704
+ }
3705
+
3706
+ /**
3707
+ * Determins if a marker is already added to the cluster.
3708
+ *
3709
+ * @param {google.maps.Marker} marker The marker to check.
3710
+ * @return {boolean} True if the marker is already added.
3711
+ */
3712
+ isMarkerAlreadyAdded(marker) {
3713
+ if (this.markers_.indexOf) {
3714
+ return this.markers_.indexOf(marker) != -1;
3715
+ } else {
3716
+ for (var i = 0, m; (m = this.markers_[i]); i++) {
3717
+ if (m == marker) {
3718
+ return true;
3719
+ }
3720
+ }
3721
+ }
3722
+ return false;
3723
+ }
3724
+
3725
+ /**
3726
+ * Add a marker the cluster.
3727
+ *
3728
+ * @param {google.maps.Marker} marker The marker to add.
3729
+ * @return {boolean} True if the marker was added.
3730
+ */
3731
+ addMarker(marker) {
3732
+ if (this.isMarkerAlreadyAdded(marker)) {
3733
+ return false;
3734
+ }
3735
+
3736
+ if (!this.center_) {
3737
+ this.center_ = marker.getPosition();
3738
+ this.calculateBounds_();
3739
+ } else {
3740
+ if (this.averageCenter_) {
3741
+ var l = this.markers_.length + 1;
3742
+ var lat =
3743
+ (this.center_.lat() * (l - 1) + marker.getPosition().lat()) / l;
3744
+ var lng =
3745
+ (this.center_.lng() * (l - 1) + marker.getPosition().lng()) / l;
3746
+ this.center_ = new google.maps.LatLng(lat, lng);
3747
+ this.calculateBounds_();
3748
+ }
3749
+ }
3750
+
3751
+ marker.isAdded = true;
3752
+ this.markers_.push(marker);
3753
+
3754
+ var len = this.markers_.length;
3755
+ if (len < this.minClusterSize_ && marker.getMap() != this.map_) {
3756
+ // Min cluster size not reached so show the marker.
3757
+ marker.setMap(this.map_);
3758
+ }
3759
+
3760
+ if (len == this.minClusterSize_) {
3761
+ // Hide the markers that were showing.
3762
+ for (var i = 0; i < len; i++) {
3763
+ this.markers_[i].setMap(null);
3764
+ }
3765
+ }
3766
+
3767
+ if (len >= this.minClusterSize_) {
3768
+ marker.setMap(null);
3769
+ }
3770
+
3771
+ this.updateIcon();
3772
+ return true;
3773
+ }
3774
+
3775
+ /**
3776
+ * Returns the marker clusterer that the cluster is associated with.
3777
+ *
3778
+ * @return {MarkerClusterer} The associated marker clusterer.
3779
+ */
3780
+ getMarkerClusterer() {
3781
+ return this.markerClusterer_;
3782
+ }
3783
+
3784
+ /**
3785
+ * Returns the bounds of the cluster.
3786
+ *
3787
+ * @return {google.maps.LatLngBounds} the cluster bounds.
3788
+ */
3789
+ getBounds() {
3790
+ var bounds = new google.maps.LatLngBounds(this.center_, this.center_);
3791
+ var markers = this.getMarkers();
3792
+ for (var i = 0, marker; (marker = markers[i]); i++) {
3793
+ bounds.extend(marker.getPosition());
3794
+ }
3795
+ return bounds;
3796
+ }
3797
+
3798
+ /**
3799
+ * Removes the cluster
3800
+ */
3801
+ remove() {
3802
+ this.clusterIcon_.remove();
3803
+ this.markers_.length = 0;
3804
+ delete this.markers_;
3805
+ }
3806
+
3807
+ /**
3808
+ * Returns the number of markers in the cluster.
3809
+ *
3810
+ * @return {number} The number of markers in the cluster.
3811
+ */
3812
+ getSize() {
3813
+ return this.markers_.length;
3814
+ }
3815
+
3816
+ /**
3817
+ * Returns a list of the markers in the cluster.
3818
+ *
3819
+ * @return {Array.<google.maps.Marker>} The markers in the cluster.
3820
+ */
3821
+ getMarkers() {
3822
+ return this.markers_;
3823
+ }
3824
+
3825
+ /**
3826
+ * Returns the center of the cluster.
3827
+ *
3828
+ * @return {google.maps.LatLng} The cluster center.
3829
+ */
3830
+ getCenter() {
3831
+ return this.center_;
3832
+ }
3833
+
3834
+ /**
3835
+ * Calculated the extended bounds of the cluster with the grid.
3836
+ *
3837
+ * @private
3838
+ */
3839
+ calculateBounds_() {
3840
+ var bounds = new google.maps.LatLngBounds(this.center_, this.center_);
3841
+ this.bounds_ = this.markerClusterer_.getExtendedBounds(bounds);
3842
+ }
3843
+
3844
+ /**
3845
+ * Determines if a marker lies in the clusters bounds.
3846
+ *
3847
+ * @param {google.maps.Marker} marker The marker to check.
3848
+ * @return {boolean} True if the marker lies in the bounds.
3849
+ */
3850
+ isMarkerInClusterBounds(marker) {
3851
+ return this.bounds_.contains(marker.getPosition());
3852
+ }
3853
+
3854
+ /**
3855
+ * Returns the map that the cluster is associated with.
3856
+ *
3857
+ * @return {google.maps.Map} The map.
3858
+ */
3859
+ getMap() {
3860
+ return this.map_;
3861
+ }
3862
+
3863
+ /**
3864
+ * Updates the cluster icon
3865
+ */
3866
+ updateIcon() {
3867
+ var zoom = this.map_.getZoom();
3868
+ var mz = this.markerClusterer_.getMaxZoom();
3869
+
3870
+ if (mz && zoom > mz) {
3871
+ // The zoom is greater than our max zoom so show all the markers in cluster.
3872
+ for (var i = 0, marker; (marker = this.markers_[i]); i++) {
3873
+ marker.setMap(this.map_);
3874
+ }
3875
+ return;
3876
+ }
3877
+
3878
+ if (this.markers_.length < this.minClusterSize_) {
3879
+ // Min cluster size not yet reached.
3880
+ this.clusterIcon_.hide();
3881
+ return;
3882
+ }
3883
+
3884
+ var numStyles = this.markerClusterer_.getStyles().length;
3885
+ var sums = this.markerClusterer_.getCalculator()(this.markers_, numStyles);
3886
+ this.clusterIcon_.setCenter(this.center_);
3887
+ this.clusterIcon_.setSums(sums);
3888
+ this.clusterIcon_.show();
3889
+ }
3890
+ };
3891
+
3892
+ /**
3893
+ * A cluster icon
3894
+ *
3895
+ * @param {Cluster} cluster The cluster to be associated with.
3896
+ * @param {Object} styles An object that has style properties:
3897
+ * 'url': (string) The image url.
3898
+ * 'height': (number) The image height.
3899
+ * 'width': (number) The image width.
3900
+ * 'anchor': (Array) The anchor position of the label text.
3901
+ * 'textColor': (string) The text color.
3902
+ * 'textSize': (number) The text size.
3903
+ * 'backgroundPosition: (string) The background postition x, y.
3904
+ * @param {number=} opt_padding Optional padding to apply to the cluster icon.
3905
+ * @constructor
3906
+ * @extends google.maps.OverlayView
3907
+ * @ignore
3908
+ */
3909
+ class ClusterIcon {
3910
+ constructor(cluster, styles, opt_padding) {
3911
+ cluster.getMarkerClusterer().extend(ClusterIcon, google.maps.OverlayView);
3912
+
3913
+ this.styles_ = styles;
3914
+ this.padding_ = opt_padding || 0;
3915
+ this.cluster_ = cluster;
3916
+ this.center_ = null;
3917
+ this.map_ = cluster.getMap();
3918
+ this.div_ = null;
3919
+ this.sums_ = null;
3920
+ this.visible_ = false;
3921
+
3922
+ this.setMap(this.map_);
3923
+ }
3924
+
3925
+ /**
3926
+ * Triggers the clusterclick event and zoom's if the option is set.
3927
+ */
3928
+ triggerClusterClick() {
3929
+ var clusterBounds = this.cluster_.getBounds();
3930
+ var markerClusterer = this.cluster_.getMarkerClusterer();
3931
+
3932
+ // Trigger the clusterclick event.
3933
+ google.maps.event.trigger(
3934
+ markerClusterer.map_,
3935
+ "clusterclick",
3936
+ this.cluster_
3937
+ );
3938
+
3939
+ if (markerClusterer.isZoomOnClick()) {
3940
+ // Zoom into the cluster.
3941
+ this.map_.fitBounds(clusterBounds);
3942
+ this.map_.setCenter(clusterBounds.getCenter());
3943
+ }
3944
+ }
3945
+
3946
+ /**
3947
+ * Adding the cluster icon to the dom.
3948
+ * @ignore
3949
+ */
3950
+ onAdd() {
3951
+ this.div_ = document.createElement("DIV");
3952
+ if (this.visible_) {
3953
+ var pos = this.getPosFromLatLng_(this.center_);
3954
+ this.div_.style.cssText = this.createCss(pos);
3955
+ this.div_.innerHTML = this.sums_.text;
3956
+ }
3957
+
3958
+ var panes = this.getPanes();
3959
+ panes.overlayMouseTarget.appendChild(this.div_);
3960
+
3961
+ var that = this;
3962
+ google.maps.event.addDomListener(this.div_, "click", function() {
3963
+ that.triggerClusterClick();
3964
+ });
3965
+ }
3966
+
3967
+ /**
3968
+ * Returns the position to place the div dending on the latlng.
3969
+ *
3970
+ * @param {google.maps.LatLng} latlng The position in latlng.
3971
+ * @return {google.maps.Point} The position in pixels.
3972
+ * @private
3973
+ */
3974
+ getPosFromLatLng_(latlng) {
3975
+ var pos = this.getProjection().fromLatLngToDivPixel(latlng);
3976
+ pos.x -= parseInt(this.width_ / 2, 10);
3977
+ pos.y -= parseInt(this.height_ / 2, 10);
3978
+ return pos;
3979
+ }
3980
+
3981
+ /**
3982
+ * Draw the icon.
3983
+ * @ignore
3984
+ */
3985
+ draw() {
3986
+ if (this.visible_) {
3987
+ var pos = this.getPosFromLatLng_(this.center_);
3988
+ this.div_.style.top = pos.y + "px";
3989
+ this.div_.style.left = pos.x + "px";
3990
+ }
3991
+ }
3992
+
3993
+ /**
3994
+ * Hide the icon.
3995
+ */
3996
+ hide() {
3997
+ if (this.div_) {
3998
+ this.div_.style.display = "none";
3999
+ }
4000
+ this.visible_ = false;
4001
+ }
4002
+
4003
+ /**
4004
+ * Position and show the icon.
4005
+ */
4006
+ show() {
4007
+ if (this.div_) {
4008
+ var pos = this.getPosFromLatLng_(this.center_);
4009
+ this.div_.style.cssText = this.createCss(pos);
4010
+ this.div_.style.display = "";
4011
+ }
4012
+ this.visible_ = true;
4013
+ }
4014
+
4015
+ /**
4016
+ * Remove the icon from the map
4017
+ */
4018
+ remove() {
4019
+ this.setMap(null);
4020
+ }
4021
+
4022
+ /**
4023
+ * Implementation of the onRemove interface.
4024
+ * @ignore
4025
+ */
4026
+ onRemove() {
4027
+ if (this.div_ && this.div_.parentNode) {
4028
+ this.hide();
4029
+ this.div_.parentNode.removeChild(this.div_);
4030
+ this.div_ = null;
4031
+ }
4032
+ }
4033
+
4034
+ /**
4035
+ * Set the sums of the icon.
4036
+ *
4037
+ * @param {Object} sums The sums containing:
4038
+ * 'text': (string) The text to display in the icon.
4039
+ * 'index': (number) The style index of the icon.
4040
+ */
4041
+ setSums(sums) {
4042
+ this.sums_ = sums;
4043
+ this.text_ = sums.text;
4044
+ this.index_ = sums.index;
4045
+ if (this.div_) {
4046
+ this.div_.innerHTML = sums.text;
4047
+ }
4048
+
4049
+ this.useStyle();
4050
+ }
4051
+
4052
+ /**
4053
+ * Sets the icon to the the styles.
4054
+ */
4055
+ useStyle() {
4056
+ var index = Math.max(0, this.sums_.index - 1);
4057
+ index = Math.min(this.styles_.length - 1, index);
4058
+ var style = this.styles_[index];
4059
+ this.url_ = style["url"];
4060
+ this.height_ = style["height"];
4061
+ this.width_ = style["width"];
4062
+ this.textColor_ = style["textColor"];
4063
+ this.anchor_ = style["anchor"];
4064
+ this.textSize_ = style["textSize"];
4065
+ this.backgroundPosition_ = style["backgroundPosition"];
4066
+ }
4067
+
4068
+ /**
4069
+ * Sets the center of the icon.
4070
+ *
4071
+ * @param {google.maps.LatLng} center The latlng to set as the center.
4072
+ */
4073
+ setCenter(center) {
4074
+ this.center_ = center;
4075
+ }
4076
+
4077
+ /**
4078
+ * Create the css text based on the position of the icon.
4079
+ *
4080
+ * @param {google.maps.Point} pos The position.
4081
+ * @return {string} The css style text.
4082
+ */
4083
+ createCss(pos) {
4084
+ var style = [];
4085
+ style.push("z-index:" + this.cluster_.markerClusterer_.getZIndex() + ";");
4086
+ style.push("background-image:url(" + this.url_ + ");");
4087
+ var backgroundPosition = this.backgroundPosition_
4088
+ ? this.backgroundPosition_
4089
+ : "0 0";
4090
+ style.push("background-position:" + backgroundPosition + ";");
4091
+
4092
+ if (typeof this.anchor_ === "object") {
4093
+ if (
4094
+ typeof this.anchor_[0] === "number" &&
4095
+ this.anchor_[0] > 0 &&
4096
+ this.anchor_[0] < this.height_
4097
+ ) {
4098
+ style.push(
4099
+ "height:" +
4100
+ (this.height_ - this.anchor_[0]) +
4101
+ "px; padding-top:" +
4102
+ this.anchor_[0] +
4103
+ "px;"
4104
+ );
4105
+ } else {
4106
+ style.push(
4107
+ "height:" + this.height_ + "px; line-height:" + this.height_ + "px;"
4108
+ );
4109
+ }
4110
+ if (
4111
+ typeof this.anchor_[1] === "number" &&
4112
+ this.anchor_[1] > 0 &&
4113
+ this.anchor_[1] < this.width_
4114
+ ) {
4115
+ style.push(
4116
+ "width:" +
4117
+ (this.width_ - this.anchor_[1]) +
4118
+ "px; padding-left:" +
4119
+ this.anchor_[1] +
4120
+ "px;"
4121
+ );
4122
+ } else {
4123
+ style.push("width:" + this.width_ + "px; text-align:center;");
4124
+ }
4125
+ } else {
4126
+ style.push(
4127
+ "height:" +
4128
+ this.height_ +
4129
+ "px; line-height:" +
4130
+ this.height_ +
4131
+ "px; width:" +
4132
+ this.width_ +
4133
+ "px; text-align:center;"
4134
+ );
4135
+ }
4136
+
4137
+ var txtColor = this.textColor_ ? this.textColor_ : "black";
4138
+ var txtSize = this.textSize_ ? this.textSize_ : 11;
4139
+
4140
+ style.push(
4141
+ "cursor:pointer; top:" +
4142
+ pos.y +
4143
+ "px; left:" +
4144
+ pos.x +
4145
+ "px; color:" +
4146
+ txtColor +
4147
+ "; position:absolute; font-size:" +
4148
+ txtSize +
4149
+ "px; font-family:Arial,sans-serif; font-weight:bold"
4150
+ );
4151
+ return style.join("");
4152
+ }
4153
+ }
4154
+
4155
+ var bmaplib_texticonoverlay$1 = {exports: {}};
4156
+
4157
+ var bmaplib_texticonoverlay = bmaplib_texticonoverlay$1.exports;
4158
+
4159
+ var hasRequiredBmaplib_texticonoverlay;
4160
+
4161
+ function requireBmaplib_texticonoverlay () {
4162
+ if (hasRequiredBmaplib_texticonoverlay) return bmaplib_texticonoverlay$1.exports;
4163
+ hasRequiredBmaplib_texticonoverlay = 1;
4164
+ (function (module, exports) {
4165
+ (function (root, factory) {
4166
+ {
4167
+ module.exports = factory();
4168
+ }
4169
+ })(bmaplib_texticonoverlay, function() {
4170
+ var T,
4171
+ baidu = T = baidu || {version: "1.3.8"};
4172
+ var context = {};
4173
+ //提出guid,防止在与老版本Tangram混用时
4174
+ //在下一行错误的修改context[undefined]
4175
+ baidu.guid = "$BAIDU$";
4176
+
4177
+ //Tangram可能被放在闭包中
4178
+ //一些页面级别唯一的属性,需要挂载在context[baidu.guid]上
4179
+ context[baidu.guid] = context[baidu.guid] || {};
4180
+
4181
+ /**
4182
+ * @ignore
4183
+ * @namespace baidu.dom 操作dom的方法。
4184
+ */
4185
+ baidu.dom = baidu.dom || {};
4186
+
4187
+
4188
+ /**
4189
+ * 从文档中获取指定的DOM元素
4190
+ * @name baidu.dom.g
4191
+ * @function
4192
+ * @grammar baidu.dom.g(id)
4193
+ * @param {string|HTMLElement} id 元素的id或DOM元素
4194
+ * @shortcut g,T.G
4195
+ * @meta standard
4196
+ * @see baidu.dom.q
4197
+ *
4198
+ * @returns {HTMLElement|null} 获取的元素,查找不到时返回null,如果参数不合法,直接返回参数
4199
+ */
4200
+ baidu.dom.g = function (id) {
4201
+ if ('string' == typeof id || id instanceof String) {
4202
+ return document.getElementById(id);
4203
+ } else if (id && id.nodeName && (id.nodeType == 1 || id.nodeType == 9)) {
4204
+ return id;
4205
+ }
4206
+ return null;
4207
+ };
4208
+
4209
+ // 声明快捷方法
4210
+ baidu.g = baidu.G = baidu.dom.g;
4211
+
4212
+ /**
4213
+ * 获取目标元素所属的document对象
4214
+ * @name baidu.dom.getDocument
4215
+ * @function
4216
+ * @grammar baidu.dom.getDocument(element)
4217
+ * @param {HTMLElement|string} element 目标元素或目标元素的id
4218
+ * @meta standard
4219
+ * @see baidu.dom.getWindow
4220
+ *
4221
+ * @returns {HTMLDocument} 目标元素所属的document对象
4222
+ */
4223
+ baidu.dom.getDocument = function (element) {
4224
+ element = baidu.dom.g(element);
4225
+ return element.nodeType == 9 ? element : element.ownerDocument || element.document;
4226
+ };
4227
+
4228
+ /**
4229
+ * @ignore
4230
+ * @namespace baidu.lang 对语言层面的封装,包括类型判断、模块扩展、继承基类以及对象自定义事件的支持。
4231
+ */
4232
+ baidu.lang = baidu.lang || {};
4233
+
4234
+ /**
4235
+ * 判断目标参数是否string类型或String对象
4236
+ * @name baidu.lang.isString
4237
+ * @function
4238
+ * @grammar baidu.lang.isString(source)
4239
+ * @param {Any} source 目标参数
4240
+ * @shortcut isString
4241
+ * @meta standard
4242
+ * @see baidu.lang.isObject,baidu.lang.isNumber,baidu.lang.isArray,baidu.lang.isElement,baidu.lang.isBoolean,baidu.lang.isDate
4243
+ *
4244
+ * @returns {boolean} 类型判断结果
4245
+ */
4246
+ baidu.lang.isString = function (source) {
4247
+ return '[object String]' == Object.prototype.toString.call(source);
4248
+ };
4249
+
4250
+ // 声明快捷方法
4251
+ baidu.isString = baidu.lang.isString;
4252
+
4253
+ /**
4254
+ * 从文档中获取指定的DOM元素
4255
+ * **内部方法**
4256
+ *
4257
+ * @param {string|HTMLElement} id 元素的id或DOM元素
4258
+ * @meta standard
4259
+ * @return {HTMLElement} DOM元素,如果不存在,返回null,如果参数不合法,直接返回参数
4260
+ */
4261
+ baidu.dom._g = function (id) {
4262
+ if (baidu.lang.isString(id)) {
4263
+ return document.getElementById(id);
4264
+ }
4265
+ return id;
4266
+ };
4267
+
4268
+ // 声明快捷方法
4269
+ baidu._g = baidu.dom._g;
4270
+
4271
+ /**
4272
+ * @ignore
4273
+ * @namespace baidu.browser 判断浏览器类型和特性的属性。
4274
+ */
4275
+ baidu.browser = baidu.browser || {};
4276
+
4277
+ if (/msie (\d+\.\d)/i.test(navigator.userAgent)) {
4278
+ //IE 8下,以documentMode为准
4279
+ //在百度模板中,可能会有$,防止冲突,将$1 写成 \x241
4280
+ /**
4281
+ * 判断是否为ie浏览器
4282
+ * @property ie ie版本号
4283
+ * @grammar baidu.browser.ie
4284
+ * @meta standard
4285
+ * @shortcut ie
4286
+ * @see baidu.browser.firefox,baidu.browser.safari,baidu.browser.opera,baidu.browser.chrome,baidu.browser.maxthon
4287
+ */
4288
+ baidu.browser.ie = baidu.ie = document.documentMode || + RegExp['\x241'];
4289
+ }
4290
+
4291
+ /**
4292
+ * 获取目标元素的computed style值。如果元素的样式值不能被浏览器计算,则会返回空字符串(IE)
4293
+ *
4294
+ * @author berg
4295
+ * @name baidu.dom.getComputedStyle
4296
+ * @function
4297
+ * @grammar baidu.dom.getComputedStyle(element, key)
4298
+ * @param {HTMLElement|string} element 目标元素或目标元素的id
4299
+ * @param {string} key 要获取的样式名
4300
+ *
4301
+ * @see baidu.dom.getStyle
4302
+ *
4303
+ * @returns {string} 目标元素的computed style值
4304
+ */
4305
+
4306
+ baidu.dom.getComputedStyle = function(element, key){
4307
+ element = baidu.dom._g(element);
4308
+ var doc = baidu.dom.getDocument(element),
4309
+ styles;
4310
+ if (doc.defaultView && doc.defaultView.getComputedStyle) {
4311
+ styles = doc.defaultView.getComputedStyle(element, null);
4312
+ if (styles) {
4313
+ return styles[key] || styles.getPropertyValue(key);
4314
+ }
4315
+ }
4316
+ return '';
4317
+ };
4318
+
4319
+ /**
4320
+ * 提供给setStyle与getStyle使用
4321
+ */
4322
+ baidu.dom._styleFixer = baidu.dom._styleFixer || {};
4323
+
4324
+ /**
4325
+ * 提供给setStyle与getStyle使用
4326
+ */
4327
+ baidu.dom._styleFilter = baidu.dom._styleFilter || [];
4328
+
4329
+ /**
4330
+ * 为获取和设置样式的过滤器
4331
+ * @private
4332
+ * @meta standard
4333
+ */
4334
+ baidu.dom._styleFilter.filter = function (key, value, method) {
4335
+ for (var i = 0, filters = baidu.dom._styleFilter, filter; filter = filters[i]; i++) {
4336
+ if (filter = filter[method]) {
4337
+ value = filter(key, value);
4338
+ }
4339
+ }
4340
+ return value;
4341
+ };
4342
+
4343
+ /**
4344
+ * @ignore
4345
+ * @namespace baidu.string 操作字符串的方法。
4346
+ */
4347
+ baidu.string = baidu.string || {};
4348
+
4349
+ /**
4350
+ * 将目标字符串进行驼峰化处理
4351
+ * @name baidu.string.toCamelCase
4352
+ * @function
4353
+ * @grammar baidu.string.toCamelCase(source)
4354
+ * @param {string} source 目标字符串
4355
+ * @remark
4356
+ * 支持单词以“-_”分隔
4357
+ * @meta standard
4358
+ *
4359
+ * @returns {string} 驼峰化处理后的字符串
4360
+ */
4361
+ baidu.string.toCamelCase = function (source) {
4362
+ //提前判断,提高getStyle等的效率 thanks xianwei
4363
+ if (source.indexOf('-') < 0 && source.indexOf('_') < 0) {
4364
+ return source;
4365
+ }
4366
+ return source.replace(/[-_][^-_]/g, function (match) {
4367
+ return match.charAt(1).toUpperCase();
4368
+ });
4369
+ };
4370
+
4371
+ /**
4372
+ * 获取目标元素的样式值
4373
+ * @name baidu.dom.getStyle
4374
+ * @function
4375
+ * @grammar baidu.dom.getStyle(element, key)
4376
+ * @param {HTMLElement|string} element 目标元素或目标元素的id
4377
+ * @param {string} key 要获取的样式名
4378
+ * @remark
4379
+ *
4380
+ * 为了精简代码,本模块默认不对任何浏览器返回值进行归一化处理(如使用getStyle时,不同浏览器下可能返回rgb颜色或hex颜色),也不会修复浏览器的bug和差异性(如设置IE的float属性叫styleFloat,firefox则是cssFloat)。<br />
4381
+ * baidu.dom._styleFixer和baidu.dom._styleFilter可以为本模块提供支持。<br />
4382
+ * 其中_styleFilter能对颜色和px进行归一化处理,_styleFixer能对display,float,opacity,textOverflow的浏览器兼容性bug进行处理。
4383
+ * @shortcut getStyle
4384
+ * @meta standard
4385
+ * @see baidu.dom.setStyle,baidu.dom.setStyles, baidu.dom.getComputedStyle
4386
+ *
4387
+ * @returns {string} 目标元素的样式值
4388
+ */
4389
+ baidu.dom.getStyle = function (element, key) {
4390
+ var dom = baidu.dom;
4391
+
4392
+ element = dom.g(element);
4393
+ key = baidu.string.toCamelCase(key);
4394
+ //computed style, then cascaded style, then explicitly set style.
4395
+ var value = element.style[key] ||
4396
+ (element.currentStyle ? element.currentStyle[key] : "") ||
4397
+ dom.getComputedStyle(element, key);
4398
+
4399
+ // 在取不到值的时候,用fixer进行修正
4400
+ if (!value) {
4401
+ var fixer = dom._styleFixer[key];
4402
+ if(fixer){
4403
+ value = fixer.get ? fixer.get(element) : baidu.dom.getStyle(element, fixer);
4404
+ }
4405
+ }
4406
+
4407
+ /* 检查结果过滤器 */
4408
+ if (fixer = dom._styleFilter) {
4409
+ value = fixer.filter(key, value, 'get');
4410
+ }
4411
+
4412
+ return value;
4413
+ };
4414
+
4415
+ // 声明快捷方法
4416
+ baidu.getStyle = baidu.dom.getStyle;
4417
+
4418
+
4419
+ if (/opera\/(\d+\.\d)/i.test(navigator.userAgent)) {
4420
+ /**
4421
+ * 判断是否为opera浏览器
4422
+ * @property opera opera版本号
4423
+ * @grammar baidu.browser.opera
4424
+ * @meta standard
4425
+ * @see baidu.browser.ie,baidu.browser.firefox,baidu.browser.safari,baidu.browser.chrome
4426
+ */
4427
+ baidu.browser.opera = + RegExp['\x241'];
4428
+ }
4429
+
4430
+ /**
4431
+ * 判断是否为webkit内核
4432
+ * @property isWebkit
4433
+ * @grammar baidu.browser.isWebkit
4434
+ * @meta standard
4435
+ * @see baidu.browser.isGecko
4436
+ */
4437
+ baidu.browser.isWebkit = /webkit/i.test(navigator.userAgent);
4438
+
4439
+ /**
4440
+ * 判断是否为gecko内核
4441
+ * @property isGecko
4442
+ * @grammar baidu.browser.isGecko
4443
+ * @meta standard
4444
+ * @see baidu.browser.isWebkit
4445
+ */
4446
+ baidu.browser.isGecko = /gecko/i.test(navigator.userAgent) && !/like gecko/i.test(navigator.userAgent);
4447
+
4448
+ /**
4449
+ * 判断是否严格标准的渲染模式
4450
+ * @property isStrict
4451
+ * @grammar baidu.browser.isStrict
4452
+ * @meta standard
4453
+ */
4454
+ baidu.browser.isStrict = document.compatMode == "CSS1Compat";
4455
+
4456
+ /**
4457
+ * 获取目标元素相对于整个文档左上角的位置
4458
+ * @name baidu.dom.getPosition
4459
+ * @function
4460
+ * @grammar baidu.dom.getPosition(element)
4461
+ * @param {HTMLElement|string} element 目标元素或目标元素的id
4462
+ * @meta standard
4463
+ *
4464
+ * @returns {Object} 目标元素的位置,键值为top和left的Object。
4465
+ */
4466
+ baidu.dom.getPosition = function (element) {
4467
+ element = baidu.dom.g(element);
4468
+ var doc = baidu.dom.getDocument(element),
4469
+ browser = baidu.browser,
4470
+ getStyle = baidu.dom.getStyle;
4471
+ // Gecko 1.9版本以下用getBoxObjectFor计算位置
4472
+ // 但是某些情况下是有bug的
4473
+ // 对于这些有bug的情况
4474
+ // 使用递归查找的方式
4475
+ browser.isGecko > 0 &&
4476
+ doc.getBoxObjectFor &&
4477
+ getStyle(element, 'position') == 'absolute' &&
4478
+ (element.style.top === '' || element.style.left === '');
4479
+ var pos = {"left":0,"top":0},
4480
+ viewport = (browser.ie && !browser.isStrict) ? doc.body : doc.documentElement,
4481
+ parent,
4482
+ box;
4483
+
4484
+ if(element == viewport){
4485
+ return pos;
4486
+ }
4487
+
4488
+ if(element.getBoundingClientRect){ // IE and Gecko 1.9+
4489
+
4490
+ //当HTML或者BODY有border width时, 原生的getBoundingClientRect返回值是不符合预期的
4491
+ //考虑到通常情况下 HTML和BODY的border只会设成0px,所以忽略该问题.
4492
+ box = element.getBoundingClientRect();
4493
+
4494
+ pos.left = Math.floor(box.left) + Math.max(doc.documentElement.scrollLeft, doc.body.scrollLeft);
4495
+ pos.top = Math.floor(box.top) + Math.max(doc.documentElement.scrollTop, doc.body.scrollTop);
4496
+
4497
+ // IE会给HTML元素添加一个border,默认是medium(2px)
4498
+ // 但是在IE 6 7 的怪异模式下,可以被html { border: 0; } 这条css规则覆盖
4499
+ // 在IE7的标准模式下,border永远是2px,这个值通过clientLeft 和 clientTop取得
4500
+ // 但是。。。在IE 6 7的怪异模式,如果用户使用css覆盖了默认的medium
4501
+ // clientTop和clientLeft不会更新
4502
+ pos.left -= doc.documentElement.clientLeft;
4503
+ pos.top -= doc.documentElement.clientTop;
4504
+
4505
+ var htmlDom = doc.body,
4506
+ // 在这里,不使用element.style.borderLeftWidth,只有computedStyle是可信的
4507
+ htmlBorderLeftWidth = parseInt(getStyle(htmlDom, 'borderLeftWidth')),
4508
+ htmlBorderTopWidth = parseInt(getStyle(htmlDom, 'borderTopWidth'));
4509
+ if(browser.ie && !browser.isStrict){
4510
+ pos.left -= isNaN(htmlBorderLeftWidth) ? 2 : htmlBorderLeftWidth;
4511
+ pos.top -= isNaN(htmlBorderTopWidth) ? 2 : htmlBorderTopWidth;
4512
+ }
4513
+ } else {
4514
+ // safari/opera/firefox
4515
+ parent = element;
4516
+
4517
+ do {
4518
+ pos.left += parent.offsetLeft;
4519
+ pos.top += parent.offsetTop;
4520
+
4521
+ // safari里面,如果遍历到了一个fixed的元素,后面的offset都不准了
4522
+ if (browser.isWebkit > 0 && getStyle(parent, 'position') == 'fixed') {
4523
+ pos.left += doc.body.scrollLeft;
4524
+ pos.top += doc.body.scrollTop;
4525
+ break;
4526
+ }
4527
+
4528
+ parent = parent.offsetParent;
4529
+ } while (parent && parent != element);
4530
+
4531
+ // 对body offsetTop的修正
4532
+ if(browser.opera > 0 || (browser.isWebkit > 0 && getStyle(element, 'position') == 'absolute')){
4533
+ pos.top -= doc.body.offsetTop;
4534
+ }
4535
+
4536
+ // 计算除了body的scroll
4537
+ parent = element.offsetParent;
4538
+ while (parent && parent != doc.body) {
4539
+ pos.left -= parent.scrollLeft;
4540
+ // see https://bugs.opera.com/show_bug.cgi?id=249965
4541
+ if (!browser.opera || parent.tagName != 'TR') {
4542
+ pos.top -= parent.scrollTop;
4543
+ }
4544
+ parent = parent.offsetParent;
4545
+ }
4546
+ }
4547
+
4548
+ return pos;
4549
+ };
4550
+
4551
+ /**
4552
+ * @ignore
4553
+ * @namespace baidu.event 屏蔽浏览器差异性的事件封装。
4554
+ * @property target 事件的触发元素
4555
+ * @property pageX 鼠标事件的鼠标x坐标
4556
+ * @property pageY 鼠标事件的鼠标y坐标
4557
+ * @property keyCode 键盘事件的键值
4558
+ */
4559
+ baidu.event = baidu.event || {};
4560
+
4561
+ /**
4562
+ * 事件监听器的存储表
4563
+ * @private
4564
+ * @meta standard
4565
+ */
4566
+ baidu.event._listeners = baidu.event._listeners || [];
4567
+
4568
+ /**
4569
+ * 为目标元素添加事件监听器
4570
+ * @name baidu.event.on
4571
+ * @function
4572
+ * @grammar baidu.event.on(element, type, listener)
4573
+ * @param {HTMLElement|string|window} element 目标元素或目标元素id
4574
+ * @param {string} type 事件类型
4575
+ * @param {Function} listener 需要添加的监听器
4576
+ * @remark
4577
+ *
4578
+ 1. 不支持跨浏览器的鼠标滚轮事件监听器添加<br>
4579
+ 2. 改方法不为监听器灌入事件对象,以防止跨iframe事件挂载的事件对象获取失败
4580
+
4581
+ * @shortcut on
4582
+ * @meta standard
4583
+ * @see baidu.event.un
4584
+ *
4585
+ * @returns {HTMLElement|window} 目标元素
4586
+ */
4587
+ baidu.event.on = function (element, type, listener) {
4588
+ type = type.replace(/^on/i, '');
4589
+ element = baidu.dom._g(element);
4590
+
4591
+ var realListener = function (ev) {
4592
+ // 1. 这里不支持EventArgument, 原因是跨frame的事件挂载
4593
+ // 2. element是为了修正this
4594
+ listener.call(element, ev);
4595
+ },
4596
+ lis = baidu.event._listeners,
4597
+ filter = baidu.event._eventFilter,
4598
+ afterFilter,
4599
+ realType = type;
4600
+ type = type.toLowerCase();
4601
+ // filter过滤
4602
+ if(filter && filter[type]){
4603
+ afterFilter = filter[type](element, type, realListener);
4604
+ realType = afterFilter.type;
4605
+ realListener = afterFilter.listener;
4606
+ }
4607
+
4608
+ // 事件监听器挂载
4609
+ if (element.addEventListener) {
4610
+ element.addEventListener(realType, realListener, false);
4611
+ } else if (element.attachEvent) {
4612
+ element.attachEvent('on' + realType, realListener);
4613
+ }
4614
+
4615
+ // 将监听器存储到数组中
4616
+ lis[lis.length] = [element, type, listener, realListener, realType];
4617
+ return element;
4618
+ };
4619
+
4620
+ // 声明快捷方法
4621
+ baidu.on = baidu.event.on;
4622
+
4623
+ /**
4624
+ * 返回一个当前页面的唯一标识字符串。
4625
+ * @name baidu.lang.guid
4626
+ * @function
4627
+ * @grammar baidu.lang.guid()
4628
+ * @version 1.1.1
4629
+ * @meta standard
4630
+ *
4631
+ * @returns {String} 当前页面的唯一标识字符串
4632
+ */
4633
+
4634
+ (function(){
4635
+ //不直接使用window,可以提高3倍左右性能
4636
+ var guid = context[baidu.guid];
4637
+
4638
+ baidu.lang.guid = function() {
4639
+ return "TANGRAM__" + (guid._counter ++).toString(36);
4640
+ };
4641
+
4642
+ guid._counter = guid._counter || 1;
4643
+ })();
4644
+
4645
+ /**
4646
+ * 所有类的实例的容器
4647
+ * key为每个实例的guid
4648
+ * @meta standard
4649
+ */
4650
+
4651
+ context[baidu.guid]._instances = context[baidu.guid]._instances || {};
4652
+
4653
+ /**
4654
+ * 判断目标参数是否为function或Function实例
4655
+ * @name baidu.lang.isFunction
4656
+ * @function
4657
+ * @grammar baidu.lang.isFunction(source)
4658
+ * @param {Any} source 目标参数
4659
+ * @version 1.2
4660
+ * @see baidu.lang.isString,baidu.lang.isObject,baidu.lang.isNumber,baidu.lang.isArray,baidu.lang.isElement,baidu.lang.isBoolean,baidu.lang.isDate
4661
+ * @meta standard
4662
+ * @returns {boolean} 类型判断结果
4663
+ */
4664
+ baidu.lang.isFunction = function (source) {
4665
+ // chrome下,'function' == typeof /a/ 为true.
4666
+ return '[object Function]' == Object.prototype.toString.call(source);
4667
+ };
4668
+
4669
+ /**
4670
+ *
4671
+ * @ignore
4672
+ * @class Tangram继承机制提供的一个基类,用户可以通过继承baidu.lang.Class来获取它的属性及方法。
4673
+ * @name baidu.lang.Class
4674
+ * @grammar baidu.lang.Class(guid)
4675
+ * @param {string} guid 对象的唯一标识
4676
+ * @meta standard
4677
+ * @remark baidu.lang.Class和它的子类的实例均包含一个全局唯一的标识guid。guid是在构造函数中生成的,因此,继承自baidu.lang.Class的类应该直接或者间接调用它的构造函数。<br>baidu.lang.Class的构造函数中产生guid的方式可以保证guid的唯一性,及每个实例都有一个全局唯一的guid。
4678
+ * @meta standard
4679
+ * @see baidu.lang.inherits,baidu.lang.Event
4680
+ */
4681
+ baidu.lang.Class = function(guid) {
4682
+ this.guid = guid || baidu.lang.guid();
4683
+ context[baidu.guid]._instances[this.guid] = this;
4684
+ };
4685
+ context[baidu.guid]._instances = context[baidu.guid]._instances || {};
4686
+
4687
+ /**
4688
+ * 释放对象所持有的资源,主要是自定义事件。
4689
+ * @name dispose
4690
+ * @grammar obj.dispose()
4691
+ */
4692
+ baidu.lang.Class.prototype.dispose = function(){
4693
+ delete context[baidu.guid]._instances[this.guid];
4694
+
4695
+ for(var property in this){
4696
+ if (!baidu.lang.isFunction(this[property])) {
4697
+ delete this[property];
4698
+ }
4699
+ }
4700
+ this.disposed = true;
4701
+ };
4702
+
4703
+ /**
4704
+ * 重载了默认的toString方法,使得返回信息更加准确一些。
4705
+ * @return {string} 对象的String表示形式
4706
+ */
4707
+ baidu.lang.Class.prototype.toString = function(){
4708
+ return "[object " + (this._className || "Object" ) + "]";
4709
+ };
4710
+
4711
+ /**
4712
+ * @ignore
4713
+ * @class 自定义的事件对象。
4714
+ * @name baidu.lang.Event
4715
+ * @grammar baidu.lang.Event(type[, target])
4716
+ * @param {string} type 事件类型名称。为了方便区分事件和一个普通的方法,事件类型名称必须以"on"(小写)开头。
4717
+ * @param {Object} [target]触发事件的对象
4718
+ * @meta standard
4719
+ * @remark 引入该模块,会自动为Class引入3个事件扩展方法:addEventListener、removeEventListener和dispatchEvent。
4720
+ * @meta standard
4721
+ * @see baidu.lang.Class
4722
+ */
4723
+ baidu.lang.Event = function (type, target) {
4724
+ this.type = type;
4725
+ this.returnValue = true;
4726
+ this.target = target || null;
4727
+ this.currentTarget = null;
4728
+ };
4729
+
4730
+ /**
4731
+ * 注册对象的事件监听器。引入baidu.lang.Event后,Class的子类实例才会获得该方法。
4732
+ * @grammar obj.addEventListener(type, handler[, key])
4733
+ * @param {string} type 自定义事件的名称
4734
+ * @param {Function} handler 自定义事件被触发时应该调用的回调函数
4735
+ * @param {string} [key] 为事件监听函数指定的名称,可在移除时使用。如果不提供,方法会默认为它生成一个全局唯一的key。
4736
+ * @remark 事件类型区分大小写。如果自定义事件名称不是以小写"on"开头,该方法会给它加上"on"再进行判断,即"click"和"onclick"会被认为是同一种事件。
4737
+ */
4738
+ baidu.lang.Class.prototype.addEventListener = function (type, handler, key) {
4739
+ if (!baidu.lang.isFunction(handler)) {
4740
+ return;
4741
+ }
4742
+
4743
+ !this.__listeners && (this.__listeners = {});
4744
+
4745
+ var t = this.__listeners, id;
4746
+ if (typeof key == "string" && key) {
4747
+ if (/[^\w\-]/.test(key)) {
4748
+ throw("nonstandard key:" + key);
4749
+ } else {
4750
+ handler.hashCode = key;
4751
+ id = key;
4752
+ }
4753
+ }
4754
+ type.indexOf("on") != 0 && (type = "on" + type);
4755
+
4756
+ typeof t[type] != "object" && (t[type] = {});
4757
+ id = id || baidu.lang.guid();
4758
+ handler.hashCode = id;
4759
+ t[type][id] = handler;
4760
+ };
4761
+
4762
+ /**
4763
+ * 移除对象的事件监听器。引入baidu.lang.Event后,Class的子类实例才会获得该方法。
4764
+ * @grammar obj.removeEventListener(type, handler)
4765
+ * @param {string} type 事件类型
4766
+ * @param {Function|string} handler 要移除的事件监听函数或者监听函数的key
4767
+ * @remark 如果第二个参数handler没有被绑定到对应的自定义事件中,什么也不做。
4768
+ */
4769
+ baidu.lang.Class.prototype.removeEventListener = function (type, handler) {
4770
+ if (typeof handler != "undefined") {
4771
+ if ( (baidu.lang.isFunction(handler) && ! (handler = handler.hashCode))
4772
+ || (! baidu.lang.isString(handler))
4773
+ ){
4774
+ return;
4775
+ }
4776
+ }
4777
+
4778
+ !this.__listeners && (this.__listeners = {});
4779
+
4780
+ type.indexOf("on") != 0 && (type = "on" + type);
4781
+
4782
+ var t = this.__listeners;
4783
+ if (!t[type]) {
4784
+ return;
4785
+ }
4786
+ if (typeof handler != "undefined") {
4787
+ t[type][handler] && delete t[type][handler];
4788
+ } else {
4789
+ for(var guid in t[type]){
4790
+ delete t[type][guid];
4791
+ }
4792
+ }
4793
+ };
4794
+
4795
+ /**
4796
+ * 派发自定义事件,使得绑定到自定义事件上面的函数都会被执行。引入baidu.lang.Event后,Class的子类实例才会获得该方法。
4797
+ * @grammar obj.dispatchEvent(event, options)
4798
+ * @param {baidu.lang.Event|String} event Event对象,或事件名称(1.1.1起支持)
4799
+ * @param {Object} options 扩展参数,所含属性键值会扩展到Event对象上(1.2起支持)
4800
+ * @remark 处理会调用通过addEventListenr绑定的自定义事件回调函数之外,还会调用直接绑定到对象上面的自定义事件。例如:<br>
4801
+ myobj.onMyEvent = function(){}<br>
4802
+ myobj.addEventListener("onMyEvent", function(){});
4803
+ */
4804
+ baidu.lang.Class.prototype.dispatchEvent = function (event, options) {
4805
+ if (baidu.lang.isString(event)) {
4806
+ event = new baidu.lang.Event(event);
4807
+ }
4808
+ !this.__listeners && (this.__listeners = {});
4809
+
4810
+ // 20100603 添加本方法的第二个参数,将 options extend到event中去传递
4811
+ options = options || {};
4812
+ for (var i in options) {
4813
+ event[i] = options[i];
4814
+ }
4815
+
4816
+ var i, t = this.__listeners, p = event.type;
4817
+ event.target = event.target || this;
4818
+ event.currentTarget = this;
4819
+
4820
+ p.indexOf("on") != 0 && (p = "on" + p);
4821
+
4822
+ baidu.lang.isFunction(this[p]) && this[p].apply(this, arguments);
4823
+
4824
+ if (typeof t[p] == "object") {
4825
+ for (i in t[p]) {
4826
+ t[p][i].apply(this, arguments);
4827
+ }
4828
+ }
4829
+ return event.returnValue;
4830
+ };
4831
+
4832
+
4833
+ baidu.lang.inherits = function (subClass, superClass, className) {
4834
+ var key, proto,
4835
+ selfProps = subClass.prototype,
4836
+ clazz = new Function();
4837
+
4838
+ clazz.prototype = superClass.prototype;
4839
+ proto = subClass.prototype = new clazz();
4840
+ for (key in selfProps) {
4841
+ proto[key] = selfProps[key];
4842
+ }
4843
+ subClass.prototype.constructor = subClass;
4844
+ subClass.superClass = superClass.prototype;
4845
+
4846
+ // 类名标识,兼容Class的toString,基本没用
4847
+ if ("string" == typeof className) {
4848
+ proto._className = className;
4849
+ }
4850
+ };
4851
+ // 声明快捷方法
4852
+ baidu.inherits = baidu.lang.inherits;
4853
+
4854
+
4855
+ /**
4856
+
4857
+ * 图片的路径
4858
+
4859
+ * @private
4860
+ * @type {String}
4861
+
4862
+ */
4863
+ var _IMAGE_PATH = 'http://api.map.baidu.com/library/TextIconOverlay/1.2/src/images/m';
4864
+
4865
+ /**
4866
+
4867
+ * 图片的后缀名
4868
+
4869
+ * @private
4870
+ * @type {String}
4871
+
4872
+ */
4873
+ var _IMAGE_EXTENSION = 'png';
4874
+
4875
+ /**
4876
+ *@exports TextIconOverlay as BMapLib.TextIconOverlay
4877
+ */
4878
+
4879
+ /**
4880
+ * TextIconOverlay
4881
+ * @class 此类表示地图上的一个覆盖物,该覆盖物由文字和图标组成,从Overlay继承。文字通常是数字(0-9)或字母(A-Z ),而文字与图标之间有一定的映射关系。
4882
+ * 该覆盖物适用于以下类似的场景:需要在地图上添加一系列覆盖物,这些覆盖物之间用不同的图标和文字来区分,文字可能表示了该覆盖物的某一属性值,根据该文字和一定的映射关系,自动匹配相应颜色和大小的图标。
4883
+ *
4884
+ * @constructor
4885
+ * @param {Point} position 表示一个经纬度坐标位置。
4886
+ * @param {string} text 表示该覆盖物显示的文字信息。
4887
+ * @param {TextIconOverlayOptions=} options 选项。
4888
+ *
4889
+ * @typedef {object} TextIconOverlayOptions
4890
+ * @property {IconStyle[]=} styles 一组图标风格。
4891
+ * @property {number=} zIndex 等同与CSS中的z-index属性
4892
+ *
4893
+ * @typedef {object} IconStyle
4894
+ * @property {string} url 图片的url地址。
4895
+ * @property {Size} size 图片的大小。
4896
+ * @property {Size=} anchor 图标定位在地图上的位置相对于图标左上角的偏移值,默认偏移值为图标的中心位置。
4897
+ * @property {Size=} offset 图片相对于可视区域的偏移值,此功能的作用等同于CSS中的background-position属性。
4898
+ * @property {number=} [textSize=10] 文字的大小。
4899
+ * @property {string} [textColor='black'] 文字的颜色。
4900
+ */
4901
+ var TextIconOverlay = function(position, text, options){
4902
+ try {
4903
+ BMap;
4904
+ } catch (e) {
4905
+ throw Error('Baidu Map JS API is not ready yet!');
4906
+ }
4907
+ T.lang.inherits(TextIconOverlay, BMap.Overlay, "TextIconOverlay");
4908
+ this._position = position;
4909
+ this._text = text;
4910
+ this._options = options || {};
4911
+ this._styles = this._options['styles'] || [];
4912
+ /** @type {number | undefined} */
4913
+ this._zIndex = this._options['zIndex'];
4914
+ (!this._styles.length) && this._setupDefaultStyles();
4915
+ };
4916
+
4917
+
4918
+ TextIconOverlay.prototype._setupDefaultStyles = function(){
4919
+ var sizes = [53, 56, 66, 78, 90];
4920
+ for(var i = 0, size; size = sizes[i]; i++){
4921
+ this._styles.push({
4922
+ url:_IMAGE_PATH + i + '.' + _IMAGE_EXTENSION,
4923
+ size: new BMap.Size(size, size)
4924
+ });
4925
+ }//for循环的简洁写法
4926
+ };
4927
+
4928
+ /**
4929
+ *继承Overlay的intialize方法,自定义覆盖物时必须。
4930
+ *@param {Map} map BMap.Map的实例化对象。
4931
+ *@return {HTMLElement} 返回覆盖物对应的HTML元素。
4932
+ */
4933
+ TextIconOverlay.prototype.initialize = function(map){
4934
+ this._map = map;
4935
+
4936
+ this._domElement = document.createElement('div');
4937
+ this._updateCss();
4938
+ this._updateText();
4939
+ this._updatePosition();
4940
+
4941
+ this._bind();
4942
+
4943
+ this._map.getPanes().markerMouseTarget.appendChild(this._domElement);
4944
+ return this._domElement;
4945
+ };
4946
+
4947
+ /**
4948
+ *继承Overlay的draw方法,自定义覆盖物时必须。
4949
+ *@return 无返回值。
4950
+ */
4951
+ TextIconOverlay.prototype.draw = function(){
4952
+ this._map && this._updatePosition();
4953
+ };
4954
+
4955
+ /**
4956
+ *获取该覆盖物上的文字。
4957
+ *@return {String} 该覆盖物上的文字。
4958
+ */
4959
+ TextIconOverlay.prototype.getText = function(){
4960
+ return this._text;
4961
+ };
4962
+
4963
+ /**
4964
+ *设置该覆盖物上的文字。
4965
+ *@param {String} text 要设置的文字,通常是字母A-Z或数字0-9。
4966
+ *@return 无返回值。
4967
+ */
4968
+ TextIconOverlay.prototype.setText = function(text){
4969
+ if(text && (!this._text || (this._text.toString() != text.toString()))){
4970
+ this._text = text;
4971
+ this._updateText();
4972
+ this._updateCss();
4973
+ this._updatePosition();
4974
+ }
4975
+ };
4976
+
4977
+ /**
4978
+ *获取该覆盖物的位置。
4979
+ *@return {Point} 该覆盖物的经纬度坐标。
4980
+ */
4981
+ TextIconOverlay.prototype.getPosition = function () {
4982
+ return this._position;
4983
+ };
4984
+
4985
+ /**
4986
+ *设置该覆盖物的位置。
4987
+ *@param {Point} position 要设置的经纬度坐标。
4988
+ *@return 无返回值。
4989
+ */
4990
+ TextIconOverlay.prototype.setPosition = function (position) {
4991
+ if(position && (!this._position || !this._position.equals(position))){
4992
+ this._position = position;
4993
+ this._updatePosition();
4994
+ }
4995
+ };
4996
+
4997
+ /**
4998
+ *由文字信息获取风格数组的对应索引值。
4999
+ *内部默认的对应函数为文字转换为数字除以10的结果,比如文字8返回索引0,文字25返回索引2.
5000
+ *如果需要自定义映射关系,请覆盖该函数。
5001
+ *@param {String} text 文字。
5002
+ *@param {Array<IconStyle>} styles 一组图标风格。
5003
+ *@return {Number} 对应的索引值。
5004
+ */
5005
+ TextIconOverlay.prototype.getStyleByText = function(text, styles){
5006
+ var count = parseInt(text);
5007
+ var index = parseInt(count / 10);
5008
+ index = Math.max(0, index);
5009
+ index = Math.min(index, styles.length - 1);
5010
+ return styles[index];
5011
+ };
5012
+
5013
+ /**
5014
+ *更新相应的CSS。
5015
+ *@return 无返回值。
5016
+ */
5017
+ TextIconOverlay.prototype._updateCss = function(){
5018
+ if (!this._domElement) {
5019
+ return
5020
+ }
5021
+ var style = this.getStyleByText(this._text, this._styles);
5022
+ this._domElement.style.cssText = this._buildCssText(style);
5023
+ };
5024
+
5025
+ /**
5026
+ *更新覆盖物的显示文字。
5027
+ *@return 无返回值。
5028
+ */
5029
+ TextIconOverlay.prototype._updateText = function(){
5030
+ if (this._domElement) {
5031
+ this._domElement.innerHTML = this._text;
5032
+ }
5033
+ };
5034
+
5035
+ /**
5036
+ *调整覆盖物在地图上的位置更新覆盖物的显示文字。
5037
+ *@return 无返回值。
5038
+ */
5039
+ TextIconOverlay.prototype._updatePosition = function(){
5040
+ if (this._domElement && this._position) {
5041
+ var style = this._domElement.style;
5042
+ var pixelPosition= this._map.pointToOverlayPixel(this._position);
5043
+ pixelPosition.x -= Math.ceil(parseInt(style.width) / 2);
5044
+ pixelPosition.y -= Math.ceil(parseInt(style.height) / 2);
5045
+ style.left = pixelPosition.x + "px";
5046
+ style.top = pixelPosition.y + "px";
5047
+ }
5048
+ };
5049
+
5050
+ /**
5051
+ * 为该覆盖物的HTML元素构建CSS
5052
+ * @param {IconStyle} 一个图标的风格。
5053
+ * @return {String} 构建完成的CSSTEXT。
5054
+ */
5055
+ TextIconOverlay.prototype._buildCssText = function(style) {
5056
+ //根据style来确定一些默认值
5057
+ var url = style['url'];
5058
+ var size = style['size'];
5059
+ var anchor = style['anchor'];
5060
+ var offset = style['offset'];
5061
+ var textColor = style['textColor'] || 'black';
5062
+ var textSize = style['textSize'] || 10;
5063
+
5064
+ var csstext = [];
5065
+ if (this._zIndex) {
5066
+ csstext.push('z-index:' + this._zIndex + ';');
5067
+ }
5068
+ if (T.browser["ie"] < 7) {
5069
+ csstext.push('filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(' +
5070
+ 'sizingMethod=scale,src="' + url + '");');
5071
+ } else {
5072
+ csstext.push('background-image:url(' + url + ');');
5073
+ var backgroundPosition = '0 0';
5074
+ (offset instanceof BMap.Size) && (backgroundPosition = offset.width + 'px' + ' ' + offset.height + 'px');
5075
+ csstext.push('background-position:' + backgroundPosition + ';');
5076
+ }
5077
+
5078
+ if (size instanceof BMap.Size){
5079
+ if (anchor instanceof BMap.Size) {
5080
+ if (anchor.height > 0 && anchor.height < size.height) {
5081
+ csstext.push('height:' + (size.height - anchor.height) + 'px; padding-top:' + anchor.height + 'px;');
5082
+ }
5083
+ if(anchor.width > 0 && anchor.width < size.width){
5084
+ csstext.push('width:' + (size.width - anchor.width) + 'px; padding-left:' + anchor.width + 'px;');
5085
+ }
5086
+ } else {
5087
+ csstext.push('height:' + size.height + 'px; line-height:' + size.height + 'px;');
5088
+ csstext.push('width:' + size.width + 'px; text-align:center;');
5089
+ }
5090
+ }
5091
+
5092
+ csstext.push('cursor:pointer; color:' + textColor + '; position:absolute; font-size:' +
5093
+ textSize + 'px; font-family:Arial,sans-serif; font-weight:bold');
5094
+ return csstext.join('');
5095
+ };
5096
+
5097
+
5098
+ /**
5099
+
5100
+ * 当鼠标点击该覆盖物时会触发该事件
5101
+
5102
+ * @name TextIconOverlay#click
5103
+
5104
+ * @event
5105
+
5106
+ * @param {Event Object} e 回调函数会返回event参数,包括以下返回值:
5107
+
5108
+ * <br />"<b>type</b> : {String} 事件类型
5109
+
5110
+ * <br />"<b>target</b>:{BMapLib.TextIconOverlay} 事件目标
5111
+
5112
+ *
5113
+
5114
+ */
5115
+
5116
+ /**
5117
+
5118
+ * 当鼠标进入该覆盖物区域时会触发该事件
5119
+
5120
+ * @name TextIconOverlay#mouseover
5121
+
5122
+ * @event
5123
+ * @param {Event Object} e 回调函数会返回event参数,包括以下返回值:
5124
+
5125
+ * <br />"<b>type</b> : {String} 事件类型
5126
+
5127
+ * <br />"<b>target</b>:{BMapLib.TextIconOverlay} 事件目标
5128
+
5129
+ * <br />"<b>point</b> : {BMap.Point} 最新添加上的节点BMap.Point对象
5130
+
5131
+ * <br />"<b>pixel</b>:{BMap.pixel} 最新添加上的节点BMap.Pixel对象
5132
+
5133
+ *
5134
+
5135
+ * @example <b>参考示例:</b><br />
5136
+
5137
+ * myTextIconOverlay.addEventListener("mouseover", function(e) { alert(e.point); });
5138
+
5139
+ */
5140
+
5141
+ /**
5142
+
5143
+ * 当鼠标离开该覆盖物区域时会触发该事件
5144
+
5145
+ * @name TextIconOverlay#mouseout
5146
+
5147
+ * @event
5148
+
5149
+ * @param {Event Object} e 回调函数会返回event参数,包括以下返回值:
5150
+
5151
+ * <br />"<b>type</b> : {String} 事件类型
5152
+
5153
+ * <br />"<b>target</b>:{BMapLib.TextIconOverlay} 事件目标
5154
+
5155
+ * <br />"<b>point</b> : {BMap.Point} 最新添加上的节点BMap.Point对象
5156
+
5157
+ * <br />"<b>pixel</b>:{BMap.pixel} 最新添加上的节点BMap.Pixel对象
5158
+
5159
+ *
5160
+
5161
+ * @example <b>参考示例:</b><br />
5162
+
5163
+ * myTextIconOverlay.addEventListener("mouseout", function(e) { alert(e.point); });
5164
+
5165
+ */
5166
+
5167
+
5168
+ /**
5169
+ * 为该覆盖物绑定一系列事件
5170
+ * 当前支持click mouseover mouseout
5171
+ * @return 无返回值。
5172
+ */
5173
+ TextIconOverlay.prototype._bind = function(){
5174
+ if (!this._domElement){
5175
+ return;
5176
+ }
5177
+
5178
+ var me = this;
5179
+ var map = this._map;
5180
+
5181
+ var BaseEvent = T.lang.Event;
5182
+ function eventExtend(e, be){
5183
+ var elem = e.srcElement || e.target;
5184
+ var x = e.clientX || e.pageX;
5185
+ var y = e.clientY || e.pageY;
5186
+ if (e && be && x && y && elem){
5187
+ var offset = T.dom.getPosition(map.getContainer());
5188
+ be.pixel = new BMap.Pixel(x - offset.left, y - offset.top);
5189
+ be.point = map.pixelToPoint(be.pixel);
5190
+ }
5191
+ return be;
5192
+ }//给事件参数增加pixel和point两个值
5193
+
5194
+ T.event.on(this._domElement,"mouseover", function(e){
5195
+ me.dispatchEvent(eventExtend(e, new BaseEvent("onmouseover")));
5196
+ });
5197
+ T.event.on(this._domElement,"mouseout", function(e){
5198
+ me.dispatchEvent(eventExtend(e, new BaseEvent("onmouseout")));
5199
+ });
5200
+ T.event.on(this._domElement,"click", function(e){
5201
+ me.dispatchEvent(eventExtend(e, new BaseEvent("onclick")));
5202
+ });
5203
+ };
5204
+
5205
+ return TextIconOverlay;
5206
+ });
5207
+ } (bmaplib_texticonoverlay$1));
5208
+ return bmaplib_texticonoverlay$1.exports;
5209
+ }
5210
+
5211
+ var bmaplib_texticonoverlayExports = requireBmaplib_texticonoverlay();
5212
+ var TextIconOverlay = /*@__PURE__*/getDefaultExportFromCjs(bmaplib_texticonoverlayExports);
5213
+
5214
+ /**
5215
+ * 获取一个扩展的视图范围,把上下左右都扩大一样的像素值。
5216
+ * @param {BMap.Map} map BMap.Map的实例化对象
5217
+ * @param {BMap.Bounds} bounds BMap.Bounds的实例化对象
5218
+ * @param {Number} gridSize 要扩大的像素值
5219
+ *
5220
+ * @return {BMap.Bounds} 返回扩大后的视图范围。
5221
+ */
5222
+ var getExtendedBounds = function(map, bounds, gridSize){
5223
+ bounds = cutBoundsInRange(bounds);
5224
+ var pixelNE = map.pointToPixel(bounds.getNorthEast());
5225
+ var pixelSW = map.pointToPixel(bounds.getSouthWest());
5226
+ pixelNE.x += gridSize;
5227
+ pixelNE.y -= gridSize;
5228
+ pixelSW.x -= gridSize;
5229
+ pixelSW.y += gridSize;
5230
+ var newNE = map.pixelToPoint(pixelNE);
5231
+ var newSW = map.pixelToPoint(pixelSW);
5232
+ return new BMap.Bounds(newSW, newNE);
5233
+ };
5234
+
5235
+ /**
5236
+ * 按照百度地图支持的世界范围对bounds进行边界处理
5237
+ * @param {BMap.Bounds} bounds BMap.Bounds的实例化对象
5238
+ *
5239
+ * @return {BMap.Bounds} 返回不越界的视图范围
5240
+ */
5241
+ var cutBoundsInRange = function (bounds) {
5242
+ var maxX = getRange(bounds.getNorthEast().lng, -180, 180);
5243
+ var minX = getRange(bounds.getSouthWest().lng, -180, 180);
5244
+ var maxY = getRange(bounds.getNorthEast().lat, -74, 74);
5245
+ var minY = getRange(bounds.getSouthWest().lat, -74, 74);
5246
+ return new BMap.Bounds(new BMap.Point(minX, minY), new BMap.Point(maxX, maxY));
5247
+ };
5248
+
5249
+ /**
5250
+ * 对单个值进行边界处理。
5251
+ * @param {Number} i 要处理的数值
5252
+ * @param {Number} min 下边界值
5253
+ * @param {Number} max 上边界值
5254
+ *
5255
+ * @return {Number} 返回不越界的数值
5256
+ */
5257
+ var getRange = function (i, mix, max) {
5258
+ mix && (i = Math.max(i, mix));
5259
+ max && (i = Math.min(i, max));
5260
+ return i;
5261
+ };
5262
+
5263
+ /**
5264
+ * 判断给定的对象是否为数组
5265
+ * @param {Object} source 要测试的对象
5266
+ *
5267
+ * @return {Boolean} 如果是数组返回true,否则返回false
5268
+ */
5269
+ var isArray = function (source) {
5270
+ return '[object Array]' === Object.prototype.toString.call(source);
5271
+ };
5272
+
5273
+ /**
5274
+ * 返回item在source中的索引位置
5275
+ * @param {Object} item 要测试的对象
5276
+ * @param {Array} source 数组
5277
+ *
5278
+ * @return {Number} 如果在数组内,返回索引,否则返回-1
5279
+ */
5280
+ var indexOf = function(item, source){
5281
+ var index = -1;
5282
+ if(isArray(source)){
5283
+ if (source.indexOf) {
5284
+ index = source.indexOf(item);
5285
+ } else {
5286
+ for (var i = 0, m; m = source[i]; i++) {
5287
+ if (m === item) {
5288
+ index = i;
5289
+ break;
5290
+ }
5291
+ }
5292
+ }
5293
+ }
5294
+ return index;
5295
+ };
5296
+
5297
+ /**
5298
+ *@exports MarkerClusterer as BMapLib.MarkerClusterer
5299
+ */
5300
+
5301
+ /**
5302
+ * MarkerClusterer
5303
+ * @class 用来解决加载大量点要素到地图上产生覆盖现象的问题,并提高性能
5304
+ * @constructor
5305
+ * @param {BMap.Map} map 地图的一个实例。
5306
+ * @param {MarkerClustererOptions=} options 可选参数
5307
+ *
5308
+ * @typedef {object} MarkerClustererOptions
5309
+ * @property {Marker[]=} markers 要聚合的标记数组
5310
+ * @property {number=} [gridSize=60] 聚合计算时网格的像素大小,默认60
5311
+ * @property {number=} maxZoom 最大的聚合级别,大于该级别就不进行相应的聚合
5312
+ * @property {number=} [minClusterSize=2] 最小的聚合数量,小于该数量的不能成为一个聚合,默认为2
5313
+ * @property {boolean=} [isAverageCenter=false] 聚合点的落脚位置是否是所有聚合在内点的平均值,默认为否,落脚在聚合内的第一个点
5314
+ * @property {IconStyle[]=} styles 自定义聚合后的图标风格,请参考TextIconOverlay类
5315
+ * @property {number=} zIndex 聚合图标的z-index
5316
+ */
5317
+ var MarkerClusterer$1 = function(map, options){
5318
+ try {
5319
+ BMap;
5320
+ } catch (e) {
5321
+ throw Error('Baidu Map JS API is not ready yet!');
5322
+ }
5323
+ if (!map){
5324
+ return;
5325
+ }
5326
+ this._map = map;
5327
+ this._markers = [];
5328
+ this._clusters = [];
5329
+
5330
+ var opts = options || {};
5331
+ this._zIndex = opts["zIndex"];
5332
+ this._gridSize = opts["gridSize"] || 60;
5333
+ this._maxZoom = opts["maxZoom"] || 18;
5334
+ this._minClusterSize = opts["minClusterSize"] || 2;
5335
+ this._isAverageCenter = false;
5336
+ if (opts['isAverageCenter'] != undefined) {
5337
+ this._isAverageCenter = opts['isAverageCenter'];
5338
+ }
5339
+ this._styles = opts["styles"] || [];
5340
+
5341
+ var that = this;
5342
+ this._map.addEventListener("zoomend",function(){
5343
+ that._redraw();
5344
+ });
5345
+
5346
+ this._map.addEventListener("moveend",function(){
5347
+ that._redraw();
5348
+ });
5349
+
5350
+ var mkrs = opts["markers"];
5351
+ isArray(mkrs) && this.addMarkers(mkrs);
5352
+ };
5353
+
5354
+ /**
5355
+ * 添加要聚合的标记数组。
5356
+ * @param {Array<Marker>} markers 要聚合的标记数组
5357
+ *
5358
+ * @return 无返回值。
5359
+ */
5360
+ MarkerClusterer$1.prototype.addMarkers = function(markers){
5361
+ if (!markers.length) {
5362
+ return
5363
+ }
5364
+ for(var i = 0, len = markers.length; i <len ; i++){
5365
+ this._pushMarkerTo(markers[i]);
5366
+ }
5367
+ this._createClusters();
5368
+ };
5369
+
5370
+ /**
5371
+ * 把一个标记添加到要聚合的标记数组中
5372
+ * @param {BMap.Marker} marker 要添加的标记
5373
+ *
5374
+ * @return 无返回值。
5375
+ */
5376
+ MarkerClusterer$1.prototype._pushMarkerTo = function(marker){
5377
+ var index = indexOf(marker, this._markers);
5378
+ if(index === -1){
5379
+ marker.isInCluster = false;
5380
+ this._markers.push(marker);//Marker拖放后enableDragging不做变化,忽略
5381
+ }
5382
+ };
5383
+
5384
+ /**
5385
+ * 添加一个聚合的标记。
5386
+ * @param {BMap.Marker} marker 要聚合的单个标记。
5387
+ * @return 无返回值。
5388
+ */
5389
+ MarkerClusterer$1.prototype.addMarker = function(marker) {
5390
+ this._pushMarkerTo(marker);
5391
+ this._createClusters();
5392
+ };
5393
+
5394
+ /**
5395
+ * 根据所给定的标记,创建聚合点
5396
+ * @return 无返回值
5397
+ */
5398
+ MarkerClusterer$1.prototype._createClusters = function(){
5399
+ var mapBounds = this._map.getBounds();
5400
+ if (!mapBounds.getCenter()) {
5401
+ return
5402
+ }
5403
+ var extendedBounds = getExtendedBounds(this._map, mapBounds, this._gridSize);
5404
+ for(var i = 0, marker; marker = this._markers[i]; i++){
5405
+ if(!marker.isInCluster && extendedBounds.containsPoint(marker.getPosition()) ){
5406
+ this._addToClosestCluster(marker);
5407
+ }
5408
+ }
5409
+ var len = this._markers.length;
5410
+ for (var i = 0; i < len; i++) {
5411
+ if(this._clusters[i]){
5412
+ this._clusters[i].render();
5413
+ }
5414
+ }
5415
+ };
5416
+
5417
+ /**
5418
+ * 根据标记的位置,把它添加到最近的聚合中
5419
+ * @param {BMap.Marker} marker 要进行聚合的单个标记
5420
+ *
5421
+ * @return 无返回值。
5422
+ */
5423
+ MarkerClusterer$1.prototype._addToClosestCluster = function (marker){
5424
+ var distance = 4000000;
5425
+ var clusterToAddTo = null;
5426
+ marker.getPosition();
5427
+ for(var i = 0, cluster; cluster = this._clusters[i]; i++){
5428
+ var center = cluster.getCenter();
5429
+ if(center){
5430
+ var d = this._map.getDistance(center, marker.getPosition());
5431
+ if(d < distance){
5432
+ distance = d;
5433
+ clusterToAddTo = cluster;
5434
+ }
5435
+ }
5436
+ }
5437
+
5438
+ if (clusterToAddTo && clusterToAddTo.isMarkerInClusterBounds(marker)){
5439
+ clusterToAddTo.addMarker(marker);
5440
+ } else {
5441
+ var cluster = new Cluster(this);
5442
+ cluster.addMarker(marker);
5443
+ this._clusters.push(cluster);
5444
+ }
5445
+ };
5446
+
5447
+ /**
5448
+ * 清除上一次的聚合的结果
5449
+ * @return 无返回值。
5450
+ */
5451
+ MarkerClusterer$1.prototype._clearLastClusters = function(){
5452
+ for(var i = 0, cluster; cluster = this._clusters[i]; i++){
5453
+ cluster.remove();
5454
+ }
5455
+ this._clusters = [];//置空Cluster数组
5456
+ this._removeMarkersFromCluster();//把Marker的cluster标记设为false
5457
+ };
5458
+
5459
+ /**
5460
+ * 清除某个聚合中的所有标记
5461
+ * @return 无返回值
5462
+ */
5463
+ MarkerClusterer$1.prototype._removeMarkersFromCluster = function(){
5464
+ for(var i = 0, marker; marker = this._markers[i]; i++){
5465
+ marker.isInCluster = false;
5466
+ }
5467
+ };
5468
+
5469
+ /**
5470
+ * 把所有的标记从地图上清除
5471
+ * @return 无返回值
5472
+ */
5473
+ MarkerClusterer$1.prototype._removeMarkersFromMap = function(){
5474
+ for(var i = 0, marker; marker = this._markers[i]; i++){
5475
+ marker.isInCluster = false;
5476
+ var label = marker.getLabel();
5477
+ this._map.removeOverlay(marker);
5478
+ marker.setLabel(label);
5479
+ }
5480
+ };
5481
+
5482
+ /**
5483
+ * 删除单个标记
5484
+ * @param {BMap.Marker} marker 需要被删除的marker
5485
+ *
5486
+ * @return {Boolean} 删除成功返回true,否则返回false
5487
+ */
5488
+ MarkerClusterer$1.prototype._removeMarker = function(marker) {
5489
+ var index = indexOf(marker, this._markers);
5490
+ if (index === -1) {
5491
+ return false;
5492
+ }
5493
+ this._map.removeOverlay(marker);
5494
+ this._markers.splice(index, 1);
5495
+ return true;
5496
+ };
5497
+
5498
+ /**
5499
+ * 删除单个标记
5500
+ * @param {BMap.Marker} marker 需要被删除的marker
5501
+ *
5502
+ * @return {Boolean} 删除成功返回true,否则返回false
5503
+ */
5504
+ MarkerClusterer$1.prototype.removeMarker = function(marker) {
5505
+ var success = this._removeMarker(marker);
5506
+ if (success) {
5507
+ this._clearLastClusters();
5508
+ this._createClusters();
5509
+ }
5510
+ return success;
5511
+ };
5512
+
5513
+ /**
5514
+ * 删除一组标记
5515
+ * @param {Array<BMap.Marker>} markers 需要被删除的marker数组
5516
+ *
5517
+ * @return {Boolean} 删除成功返回true,否则返回false
5518
+ */
5519
+ MarkerClusterer$1.prototype.removeMarkers = function(markers) {
5520
+ var success = false;
5521
+ for (var i = 0; i < markers.length; i++) {
5522
+ var r = this._removeMarker(markers[i]);
5523
+ success = success || r;
5524
+ }
5525
+
5526
+ if (success) {
5527
+ this._clearLastClusters();
5528
+ this._createClusters();
5529
+ }
5530
+ return success;
5531
+ };
5532
+
5533
+ /**
5534
+ * 从地图上彻底清除所有的标记
5535
+ * @return 无返回值
5536
+ */
5537
+ MarkerClusterer$1.prototype.clearMarkers = function() {
5538
+ this._clearLastClusters();
5539
+ this._removeMarkersFromMap();
5540
+ this._markers = [];
5541
+ };
5542
+
5543
+ /**
5544
+ * 重新生成,比如改变了属性等
5545
+ * @return 无返回值
5546
+ */
5547
+ MarkerClusterer$1.prototype._redraw = function () {
5548
+ this._clearLastClusters();
5549
+ this._createClusters();
5550
+ };
5551
+
5552
+ /**
5553
+ * 获取网格大小
5554
+ * @return {Number} 网格大小
5555
+ */
5556
+ MarkerClusterer$1.prototype.getGridSize = function() {
5557
+ return this._gridSize;
5558
+ };
5559
+
5560
+ /**
5561
+ * 设置网格大小
5562
+ * @param {Number} size 网格大小
5563
+ * @return 无返回值
5564
+ */
5565
+ MarkerClusterer$1.prototype.setGridSize = function(size) {
5566
+ this._gridSize = size;
5567
+ this._redraw();
5568
+ };
5569
+
5570
+ /**
5571
+ * 获取聚合的最大缩放级别。
5572
+ * @return {Number} 聚合的最大缩放级别。
5573
+ */
5574
+ MarkerClusterer$1.prototype.getMaxZoom = function() {
5575
+ return this._maxZoom;
5576
+ };
5577
+
5578
+ /**
5579
+ * 设置聚合的最大缩放级别
5580
+ * @param {Number} maxZoom 聚合的最大缩放级别
5581
+ * @return 无返回值
5582
+ */
5583
+ MarkerClusterer$1.prototype.setMaxZoom = function(maxZoom) {
5584
+ this._maxZoom = maxZoom;
5585
+ this._redraw();
5586
+ };
5587
+
5588
+ /**
5589
+ * 获取聚合图标的z-index
5590
+ * @return {number | undefined}
5591
+ */
5592
+ MarkerClusterer$1.prototype.getZIndex = function () {
5593
+ return this._zIndex;
5594
+ };
5595
+
5596
+ /**
5597
+ * 设置聚合图标的z-index
5598
+ * @param {number} zIndex
5599
+ */
5600
+ MarkerClusterer$1.prototype.setZIndex = function (zIndex) {
5601
+ if (this._zIndex != zIndex) {
5602
+ this.zIndex = zIndex;
5603
+ this._redraw();
5604
+ }
5605
+ };
5606
+
5607
+ /**
5608
+ * 获取聚合的样式风格集合
5609
+ * @return {Array<IconStyle>} 聚合的样式风格集合
5610
+ */
5611
+ MarkerClusterer$1.prototype.getStyles = function() {
5612
+ return this._styles;
5613
+ };
5614
+
5615
+ /**
5616
+ * 设置聚合的样式风格集合
5617
+ * @param {Array<IconStyle>} styles 样式风格数组
5618
+ * @return 无返回值
5619
+ */
5620
+ MarkerClusterer$1.prototype.setStyles = function(styles) {
5621
+ this._styles = styles;
5622
+ this._redraw();
5623
+ };
5624
+
5625
+ /**
5626
+ * 获取单个聚合的最小数量。
5627
+ * @return {Number} 单个聚合的最小数量。
5628
+ */
5629
+ MarkerClusterer$1.prototype.getMinClusterSize = function() {
5630
+ return this._minClusterSize;
5631
+ };
5632
+
5633
+ /**
5634
+ * 设置单个聚合的最小数量。
5635
+ * @param {Number} size 单个聚合的最小数量。
5636
+ * @return 无返回值。
5637
+ */
5638
+ MarkerClusterer$1.prototype.setMinClusterSize = function(size) {
5639
+ this._minClusterSize = size;
5640
+ this._redraw();
5641
+ };
5642
+
5643
+ /**
5644
+ * 获取单个聚合的落脚点是否是聚合内所有标记的平均中心。
5645
+ * @return {Boolean} true或false。
5646
+ */
5647
+ MarkerClusterer$1.prototype.isAverageCenter = function() {
5648
+ return this._isAverageCenter;
5649
+ };
5650
+
5651
+ /**
5652
+ * 获取聚合的Map实例。
5653
+ * @return {BMap.Map} Map的示例。
5654
+ */
5655
+ MarkerClusterer$1.prototype.getMap = function() {
5656
+ return this._map;
5657
+ };
5658
+
5659
+ /**
5660
+ * 获取所有的标记数组。
5661
+ * @return {Array<Marker>} 标记数组。
5662
+ */
5663
+ MarkerClusterer$1.prototype.getMarkers = function() {
5664
+ return this._markers;
5665
+ };
5666
+
5667
+ /**
5668
+ * 获取聚合的总数量。
5669
+ * @return {Number} 聚合的总数量。
5670
+ */
5671
+ MarkerClusterer$1.prototype.getClustersCount = function() {
5672
+ var count = 0;
5673
+ for(var i = 0, cluster; cluster = this._clusters[i]; i++){
5674
+ cluster.isReal() && count++;
5675
+ }
5676
+ return count;
5677
+ };
5678
+
5679
+ /**
5680
+ * 用于计算cluster的文本
5681
+ * @param {Array<BMap.Marker>} markers cluster的markers
5682
+ * @return {String}
5683
+ */
5684
+ MarkerClusterer$1.prototype._textCalculator = function(markers){
5685
+ return markers.length.toString();
5686
+ };
5687
+
5688
+ /**
5689
+ * 用于计算cluster的styles的索引
5690
+ * @param {Array<BMap.Marker>} markers cluster的markers
5691
+ * @param {Number} stylesLength styles的总长度
5692
+ * @return {Number} styles的索引
5693
+ */
5694
+ MarkerClusterer$1.prototype._stylesIndexCalculator = null;/* function(markers, stylesLength){
5695
+ return -1;
5696
+ }*/
5697
+
5698
+ /**
5699
+ * 设置计算cluster的文本的计算函数
5700
+ * @param {function(Array<BMap.Marker>)} calculator
5701
+ */
5702
+ MarkerClusterer$1.prototype.setTextCalculator = function(calculator){
5703
+ this._textCalculator = calculator;
5704
+ };
5705
+
5706
+ /**
5707
+ * 设置计算cluster的styles的索引的计算函数
5708
+ * @param {function(Array<BMap.Marker>, Number)} calculator
5709
+ */
5710
+ MarkerClusterer$1.prototype.setStylesIndexCalculator = function(calculator){
5711
+ this._stylesIndexCalculator = calculator;
5712
+ };
5713
+
5714
+ /**
5715
+ * @ignore
5716
+ * Cluster
5717
+ * @class 表示一个聚合对象,该聚合,包含有N个标记,这N个标记组成的范围,并有予以显示在Map上的TextIconOverlay等。
5718
+ * @constructor
5719
+ * @param {MarkerClusterer} markerClusterer 一个标记聚合器示例。
5720
+ */
5721
+ function Cluster(markerClusterer){
5722
+ var that = this;
5723
+ this._markerClusterer = markerClusterer;
5724
+ this._map = markerClusterer.getMap();
5725
+ this._minClusterSize = markerClusterer.getMinClusterSize();
5726
+ this._isAverageCenter = markerClusterer.isAverageCenter();
5727
+ this._center = null;//落脚位置
5728
+ this._markers = [];//这个Cluster中所包含的markers
5729
+ this._gridBounds = null;//以中心点为准,向四边扩大gridSize个像素的范围,也即网格范围
5730
+ this._isReal = false; //真的是个聚合
5731
+
5732
+ this._clusterMarker = new TextIconOverlay(this._center, this._markers.length, {
5733
+ "styles": this._markerClusterer.getStyles(),
5734
+ zIndex: markerClusterer._zIndex
5735
+ });
5736
+ this._clusterMarker.getStyleByText = function (text, styles) {
5737
+ if (that._markerClusterer._stylesIndexCalculator) {
5738
+ var index = that._markerClusterer._stylesIndexCalculator(that._markers, styles.length);
5739
+ return styles[index];
5740
+ }
5741
+ return TextIconOverlay.prototype.getStyleByText.call(this, text, styles);
5742
+ };
5743
+ //this._map.addOverlay(this._clusterMarker);
5744
+ this._clusterMarker.addEventListener && this._clusterMarker.addEventListener("click", function (event) {
5745
+ that._map.setViewport(that.getBounds());
5746
+ });
5747
+ }
5748
+
5749
+ /**
5750
+ * 向该聚合添加一个标记。
5751
+ * @param {Marker} marker 要添加的标记。
5752
+ * @return 无返回值。
5753
+ */
5754
+ Cluster.prototype.addMarker = function(marker){
5755
+ if(this.isMarkerInCluster(marker)){
5756
+ return false;
5757
+ }//也可用marker.isInCluster判断,外面判断OK,这里基本不会命中
5758
+
5759
+ if (!this._center){
5760
+ this._center = marker.getPosition();
5761
+ this.updateGridBounds();//
5762
+ } else {
5763
+ if(this._isAverageCenter){
5764
+ var l = this._markers.length + 1;
5765
+ var lat = (this._center.lat * (l - 1) + marker.getPosition().lat) / l;
5766
+ var lng = (this._center.lng * (l - 1) + marker.getPosition().lng) / l;
5767
+ this._center = new BMap.Point(lng, lat);
5768
+ this.updateGridBounds();
5769
+ }//计算新的Center
5770
+ }
5771
+
5772
+ marker.isInCluster = true;
5773
+ this._markers.push(marker);
5774
+
5775
+ // var len = this._markers.length;
5776
+ // if(len < this._minClusterSize ){
5777
+ // this._map.addOverlay(marker);
5778
+ // //this.updateClusterMarker();
5779
+ // return true;
5780
+ // } else if (len === this._minClusterSize) {
5781
+ // for (var i = 0; i < len; i++) {
5782
+ // var label = this._markers[i].getLabel();
5783
+ // this._markers[i].getMap() && this._map.removeOverlay(this._markers[i]);
5784
+ // this._markers[i].setLabel(label);
5785
+ // }
5786
+
5787
+ // }
5788
+ // this._map.addOverlay(this._clusterMarker);
5789
+ // this._isReal = true;
5790
+ // this.updateClusterMarker();
5791
+ return true;
5792
+ };
5793
+
5794
+ Cluster.prototype.render = function(){
5795
+ var len = this._markers.length;
5796
+
5797
+ if (len < this._minClusterSize) {
5798
+ for (var i = 0; i < len; i++) {
5799
+ this._map.addOverlay(this._markers[i]);
5800
+ }
5801
+ } else {
5802
+ this._map.addOverlay(this._clusterMarker);
5803
+ this._isReal = true;
5804
+ this.updateClusterMarker();
5805
+ }
5806
+ };
5807
+
5808
+ /**
5809
+ * 判断一个标记是否在该聚合中。
5810
+ * @param {Marker} marker 要判断的标记。
5811
+ * @return {Boolean} true或false。
5812
+ */
5813
+ Cluster.prototype.isMarkerInCluster= function(marker){
5814
+ if (this._markers.indexOf) {
5815
+ return this._markers.indexOf(marker) != -1;
5816
+ } else {
5817
+ for (var i = 0, m; m = this._markers[i]; i++) {
5818
+ if (m === marker) {
5819
+ return true;
5820
+ }
5821
+ }
5822
+ }
5823
+ return false;
5824
+ };
5825
+
5826
+ /**
5827
+ * 判断一个标记是否在该聚合网格范围中。
5828
+ * @param {Marker} marker 要判断的标记。
5829
+ * @return {Boolean} true或false。
5830
+ */
5831
+ Cluster.prototype.isMarkerInClusterBounds = function(marker) {
5832
+ return this._gridBounds.containsPoint(marker.getPosition());
5833
+ };
5834
+
5835
+ Cluster.prototype.isReal = function(marker) {
5836
+ return this._isReal;
5837
+ };
5838
+
5839
+ /**
5840
+ * 更新该聚合的网格范围。
5841
+ * @return 无返回值。
5842
+ */
5843
+ Cluster.prototype.updateGridBounds = function() {
5844
+ var bounds = new BMap.Bounds(this._center, this._center);
5845
+ this._gridBounds = getExtendedBounds(this._map, bounds, this._markerClusterer.getGridSize());
5846
+ };
5847
+
5848
+ /**
5849
+ * 更新该聚合的显示样式,也即TextIconOverlay。
5850
+ * @return 无返回值。
5851
+ */
5852
+ Cluster.prototype.updateClusterMarker = function () {
5853
+ if (this._map.getZoom() > this._markerClusterer.getMaxZoom()) {
5854
+ this._clusterMarker && this._map.removeOverlay(this._clusterMarker);
5855
+ for (var i = 0, marker; marker = this._markers[i]; i++) {
5856
+ this._map.addOverlay(marker);
5857
+ }
5858
+ return;
5859
+ }
5860
+
5861
+ if (this._markers.length < this._minClusterSize) {
5862
+ this._clusterMarker.hide();
5863
+ return;
5864
+ }
5865
+
5866
+ this._clusterMarker.setPosition(this._center);
5867
+
5868
+ this._clusterMarker.setText(this._markerClusterer._textCalculator(this._markers));
5869
+ };
5870
+
5871
+ /**
5872
+ * 删除该聚合。
5873
+ * @return 无返回值。
5874
+ */
5875
+ Cluster.prototype.remove = function(){
5876
+ for (var i = 0, m; m = this._markers[i]; i++) {
5877
+ var label = this._markers[i].getLabel();
5878
+ this._markers[i].getMap() && this._map.removeOverlay(this._markers[i]);
5879
+ this._markers[i].setLabel(label);
5880
+ }//清除散的标记点
5881
+ this._map.removeOverlay(this._clusterMarker);
5882
+ this._markers.length = 0;
5883
+ delete this._markers;
5884
+ };
5885
+
5886
+ /**
5887
+ * 获取该聚合所包含的所有标记的最小外接矩形的范围。
5888
+ * @return {BMap.Bounds} 计算出的范围。
5889
+ */
5890
+ Cluster.prototype.getBounds = function() {
5891
+ var bounds = new BMap.Bounds(this._center,this._center);
5892
+ for (var i = 0, marker; marker = this._markers[i]; i++) {
5893
+ bounds.extend(marker.getPosition());
5894
+ }
5895
+ return bounds;
5896
+ };
5897
+
5898
+ /**
5899
+ * 获取该聚合的落脚点。
5900
+ * @return {BMap.Point} 该聚合的落脚点。
5901
+ */
5902
+ Cluster.prototype.getCenter = function() {
5903
+ return this._center;
5904
+ };
5905
+
1865
5906
  // cspell: ignore bmaplib, markerclusterer, texticonoverlay
1866
5907
  var ClusterIconStyle;
1867
5908
  (function (ClusterIconStyle) {
@@ -1949,7 +5990,7 @@ class BaiduMarkerClusterer extends MarkerClusterer {
1949
5990
  // ## vite:
1950
5991
  // import导入是异步的, 故无法写在这里, 改成在模块顶部直接导入
1951
5992
  // TODO: 2023/03/16 ipcjs 会不会有初始化时机的问题?
1952
- this.inner = new BMarkerClusterer(map.innerMap, {
5993
+ this.inner = new MarkerClusterer$1(map.innerMap, {
1953
5994
  // baidu的构造器中的markers, 会触发重绘, 会导致使用旧的calculator计算cluster
1954
5995
  // markers: options.markers?.map(it => (it as BaiduMarker).innerOverlay),
1955
5996
  gridSize: options.gridSize,
@@ -1978,7 +6019,7 @@ class GoogleMarkerClusterer extends MarkerClusterer {
1978
6019
  inner;
1979
6020
  constructor(map, options) {
1980
6021
  super(map);
1981
- this.inner = new GMarkerClusterer(map.innerMap,
6022
+ this.inner = new MarkerClusterer$2(map.innerMap,
1982
6023
  // google的构造器中的markers,不会触发重绘, 第一次绘制通过监听地图的'idle'事件触发, 可以直接设置
1983
6024
  options.markers?.map(it => it.innerOverlay), {
1984
6025
  gridSize: options.gridSize,
@@ -2291,7 +6332,7 @@ exports.Objects = void 0;
2291
6332
  Objects.toJsonSafely = toJsonSafely;
2292
6333
  /** 删除obj中纯对象上的值为undefined的属性 */
2293
6334
  function deleteUndefinedPropertyOnPlainObjectDeeply(obj) {
2294
- if (isPlainObject(obj)) {
6335
+ if (isPlainObject__default.default(obj)) {
2295
6336
  Object.keys(obj).forEach((key) => {
2296
6337
  if (obj[key] === undefined) {
2297
6338
  delete obj[key];
@@ -2402,9 +6443,9 @@ exports.MapOptions = void 0;
2402
6443
  exports.Objects.deleteUndefinedPropertyOnPlainObjectDeeply(options);
2403
6444
  const defaultOptions = { center: LatLng.ZERO, zoom: 5 };
2404
6445
  const mergeOptions = {
2405
- isMergeableObject: isPlainObject,
6446
+ isMergeableObject: isPlainObject__default.default,
2406
6447
  };
2407
- return deepmerge(defaultOptions, options || {}, mergeOptions);
6448
+ return deepmerge__default.default(defaultOptions, options || {}, mergeOptions);
2408
6449
  }
2409
6450
  MapOptions.create = create;
2410
6451
  })(exports.MapOptions || (exports.MapOptions = {}));