372 lines
12 KiB
JavaScript
Executable File
372 lines
12 KiB
JavaScript
Executable File
!function (t) {
|
||
var e = {modules: t.ymaps.modules};
|
||
!function (t) {
|
||
if ("undefined" == typeof t && "function" == typeof require)var t = require("ym");
|
||
t.define("util.providePackage", ["system.mergeImports"], function (t, e) {
|
||
t(function (t, n) {
|
||
var o = n[0], r = Array.prototype.slice.call(n, 1), a = e.joinImports(t.name, {}, t.deps, r);
|
||
o(a)
|
||
})
|
||
})
|
||
}(e.modules);
|
||
|
||
|
||
e.modules.define('PieChartClusterer', [
|
||
'Clusterer',
|
||
'util.defineClass',
|
||
'util.extend',
|
||
'PieChartClusterer.icon.params',
|
||
'PieChartClusterer.component.Canvas'
|
||
], function (provide,
|
||
Clusterer,
|
||
defineClass,
|
||
extend,
|
||
iconParams,
|
||
PieChartClustererCanvas) {
|
||
|
||
var STYLE_REG_EXP = /#(.+?)(?=Icon|DotIcon|StretchyIcon|CircleIcon|CircleDotIcon)/;
|
||
|
||
var PieChartClusterer = defineClass(function (options) {
|
||
PieChartClusterer.superclass.constructor.call(this, options);
|
||
|
||
this._canvas = new PieChartClustererCanvas(iconParams.icons.large.size);
|
||
this._canvas.options.setParent(this.options);
|
||
}, Clusterer, {
|
||
createCluster: function (center, geoObjects) {
|
||
// Создаем метку-кластер с помощью стандартной реализации метода.
|
||
var clusterPlacemark = PieChartClusterer.superclass.createCluster.call(this, center, geoObjects);
|
||
var styleGroups = geoObjects.reduce(function (groups, geoObject) {
|
||
// получаем в style цвет указаный в iconColor
|
||
var style = geoObject.options.get('iconColor', null);
|
||
// eсли iconColor не указан - берем значение из preset'а
|
||
if (style === null) {
|
||
var style = getIconStyle(geoObject.options.get('preset', 'islands#blueIcon'));
|
||
};
|
||
//document.write( style + "<br>" );
|
||
|
||
groups[style] = ++groups[style] || 1;
|
||
|
||
return groups;
|
||
}, {});
|
||
var iconUrl = this._canvas.generateIconDataURL(styleGroups, geoObjects.length);
|
||
var clusterOptions = {
|
||
clusterIcons: [
|
||
extend({href: iconUrl}, iconParams.icons.small),
|
||
extend({href: iconUrl}, iconParams.icons.medium),
|
||
extend({href: iconUrl}, iconParams.icons.large)
|
||
],
|
||
clusterNumbers: iconParams.numbers
|
||
};
|
||
|
||
clusterPlacemark.options.set(clusterOptions);
|
||
|
||
return clusterPlacemark;
|
||
}
|
||
});
|
||
|
||
function getIconStyle(preset) {
|
||
return preset.match(STYLE_REG_EXP)[1];
|
||
}
|
||
|
||
provide(PieChartClusterer);
|
||
});
|
||
|
||
|
||
e.modules.define('RandomPointsGenerator', [
|
||
'coordSystem.geo'
|
||
], function (provide, coordSystem) {
|
||
/**
|
||
* Random-генератор меток.
|
||
* @class
|
||
* @name RandomPointsGenerator
|
||
* @param {Number} count Количество меток которые надо создать.
|
||
* @example
|
||
var placemarks = RandomPointsGenerator.generate(200).atBounds(myMap.getBounds());
|
||
*/
|
||
function RandomPointsGenerator(count) {
|
||
this.count = count || 0;
|
||
}
|
||
|
||
/**
|
||
* Статический метод для удобства инстанцирования.
|
||
* @static
|
||
* @function
|
||
* @name RandomPointsGenerator.generate
|
||
* @param {Number} count Количество меток которые надо создать.
|
||
* @returns {RandomPointsGenerator} Экземпляр генератора меток.
|
||
*/
|
||
RandomPointsGenerator.generate = function (count) {
|
||
return new RandomPointsGenerator(count);
|
||
};
|
||
|
||
/**
|
||
* Устанавливает количество меток для генерации.
|
||
* @function
|
||
* @name RandomPointsGenerator.generate
|
||
* @param {Number} count Количество меток которые надо создать.
|
||
* @returns {RandomPointsGenerator} Экземпляр генератора меток.
|
||
*/
|
||
RandomPointsGenerator.prototype.generate = function (count) {
|
||
this.count = count;
|
||
|
||
return this;
|
||
};
|
||
|
||
/**
|
||
* Генерит случайным образом метки в области bounds.
|
||
* @function
|
||
* @name RandomPointsGenerator.atBounds
|
||
* @param {Number[][]} bounds Область видимости меток.
|
||
* @returns {ymaps.Placemark[]} Массив меток.
|
||
*/
|
||
RandomPointsGenerator.prototype.atBounds = function (bounds) {
|
||
// протяженность области просмотра в градусах
|
||
var span = [bounds[1][0] - bounds[0][0], bounds[1][1] - bounds[0][1]];
|
||
var points = [];
|
||
|
||
for (var i = 0; i < this.count; i++) {
|
||
points[i] = this.createPlacemark(
|
||
[Math.random() * span[0] + bounds[0][0], Math.random() * span[1] + bounds[0][1]], i
|
||
);
|
||
}
|
||
|
||
return points;
|
||
};
|
||
|
||
/**
|
||
* Генерит случайным образом метки внутри окружности с данным центром и радиусом.
|
||
* @function
|
||
* @name RandomPointsGenerator.atCenterAndRadius
|
||
* @param {Number[]} center Координаты центра окружности.
|
||
* @param {Number} radius Радиус окружности в метрах.
|
||
* @returns {ymaps.Placemark[]} Массив меток.
|
||
*/
|
||
RandomPointsGenerator.prototype.atCenterAndRadius = function (center, radius) {
|
||
var points = [];
|
||
|
||
for (var i = 0; i < this.count; i++) {
|
||
var direction = [Math.random() - Math.random(), Math.random() - Math.random()];
|
||
var distance = radius * Math.random();
|
||
var coords = coordSystem.solveDirectProblem(center, direction, distance).endPoint;
|
||
points[i] = this.createPlacemark(coords, i);
|
||
}
|
||
|
||
return points;
|
||
};
|
||
|
||
/**
|
||
* TODO
|
||
* Генерит случайным образом метки внутри области с данным центром и линейными размерами.
|
||
* @function
|
||
* @name RandomPointsGenerator.atCenterAndSize
|
||
* @param {Number[]} center Координаты центра области.
|
||
* @param {Number[]} size Линейные размеры области в метрах.
|
||
* @returns {ymaps.Placemark[]} Массив меток.
|
||
*/
|
||
RandomPointsGenerator.prototype.atCenterAndSize = function (center, size) {
|
||
};
|
||
|
||
/**
|
||
* Создает метку по координатам.
|
||
* @function
|
||
* @name RandomPointsGenerator.createPlacemark
|
||
* @param {Number[]} coordinates Массив координат.
|
||
* @param {Number} index Индекс метки.
|
||
* @returns {ymaps.Placemark} Метка.
|
||
*/
|
||
RandomPointsGenerator.prototype.createPlacemark = function (coordinates, index) {
|
||
return new ymaps.GeoObject({
|
||
geometry: {
|
||
type: 'Point',
|
||
coordinates: coordinates
|
||
},
|
||
properties: this.getPointData(index)
|
||
}, this.getPointOptions(index));
|
||
};
|
||
|
||
/**
|
||
* Метод для перекрытия. Возвращает объект с данными,
|
||
* который передается как поле properties в конструктор геообъекта.
|
||
* @function
|
||
* @name RandomPointsGenerator.getPointData
|
||
* @param {Number} index Индекс метки.
|
||
* @returns {Object} Данные метки.
|
||
*/
|
||
RandomPointsGenerator.prototype.getPointData = function (index) {
|
||
return {};
|
||
};
|
||
|
||
/**
|
||
* Метод для перекрытия. Возвращает объект с опциями,
|
||
* который передается как параметр options в конструктор геообъекта.
|
||
* @function
|
||
* @name RandomPointsGenerator.getPointOptions
|
||
* @param {Number} index Индекс метки.
|
||
* @returns {Object} Опции метки.
|
||
* @example
|
||
var generator = RandomPointsGenerator.generate(200);
|
||
// Перекрываем метод для создания меток со случайным хначением опции preset.
|
||
generator.getPointOptions = function (i) {
|
||
var presets = ['islands#blueIcon', 'islands#orangeIcon', 'islands#darkblueIcon', 'islands#pinkIcon'];
|
||
return {
|
||
preset: presets[Math.floor(Math.random() * presets.length)]
|
||
};
|
||
};
|
||
*/
|
||
RandomPointsGenerator.prototype.getPointOptions = function (index) {
|
||
return {};
|
||
};
|
||
|
||
provide(RandomPointsGenerator);
|
||
});
|
||
|
||
|
||
e.modules.define('PieChartClusterer.component.Canvas', [
|
||
'option.Manager',
|
||
'PieChartClusterer.icon.colors'
|
||
], function (provide, OptionManager, iconColors) {
|
||
var DEFAULT_OPTIONS = {
|
||
canvasIconStrokeStyle: 'white',
|
||
canvasIconLineWidth: 2,
|
||
canvasIconCoreRadius: 23,
|
||
canvasIconCoreFillStyle: 'white'
|
||
};
|
||
|
||
var Canvas = function (size) {
|
||
this._canvas = document.createElement('canvas');
|
||
this._canvas.width = size[0];
|
||
this._canvas.height = size[1];
|
||
|
||
this._context = this._canvas.getContext('2d');
|
||
this.options = new OptionManager({});
|
||
};
|
||
|
||
Canvas.prototype.generateIconDataURL = function (styleGroups, total) {
|
||
this._drawIcon(styleGroups, total);
|
||
|
||
return this._canvas.toDataURL();
|
||
};
|
||
|
||
Canvas.prototype._drawIcon = function (styleGroups, total) {
|
||
var startAt = 0;
|
||
var endAt = 360;
|
||
var ctx = this._context;
|
||
var x = this._canvas.width / 2;
|
||
var y = this._canvas.height / 2;
|
||
var lineWidth = this.options.get('canvasIconLineWidth', DEFAULT_OPTIONS.canvasIconLineWidth);
|
||
var strokeStyle = this.options.get('canvasIconStrokeStyle', DEFAULT_OPTIONS.canvasIconStrokeStyle);
|
||
var radius = Math.floor((x + y - lineWidth) / 2);
|
||
|
||
ctx.strokeStyle = strokeStyle;
|
||
ctx.lineWidth = lineWidth;
|
||
|
||
Object.keys(styleGroups).forEach(function (style) {
|
||
var num = styleGroups[style];
|
||
|
||
endAt = startAt + (num * 360 / total);
|
||
ctx.fillStyle = this._getStyleColor(style);
|
||
|
||
if (total > num) {
|
||
startAt = this._drawSector(x, y, radius, startAt, endAt);
|
||
} else {
|
||
this._drawCircle(x, y, radius);
|
||
}
|
||
}, this);
|
||
|
||
this._drawCore(x, y);
|
||
};
|
||
|
||
Canvas.prototype._drawCore = function (x, y) {
|
||
var ctx = this._context;
|
||
var fillStyle = this.options.get('canvasIconCoreFillStyle', DEFAULT_OPTIONS.canvasIconCoreFillStyle);
|
||
var radius = this.options.get('canvasIconCoreRadius', DEFAULT_OPTIONS.canvasIconCoreRadius);
|
||
|
||
ctx.fillStyle = fillStyle;
|
||
this._drawCircle(x, y, radius);
|
||
};
|
||
|
||
Canvas.prototype._drawCircle = function (x, y, radius) {
|
||
var ctx = this._context;
|
||
|
||
ctx.beginPath();
|
||
ctx.arc(x, y, radius, 0, 2 * Math.PI);
|
||
ctx.fill();
|
||
ctx.stroke();
|
||
};
|
||
|
||
Canvas.prototype._drawSector = function (x, y, radius, startAt, endAt) {
|
||
var ctx = this._context;
|
||
|
||
ctx.beginPath();
|
||
ctx.moveTo(x, y);
|
||
ctx.arc(x, y, radius, this._toRadians(startAt), this._toRadians(endAt));
|
||
ctx.lineTo(x, y);
|
||
ctx.closePath();
|
||
ctx.fill();
|
||
ctx.stroke();
|
||
|
||
return endAt;
|
||
};
|
||
|
||
Canvas.prototype._toRadians = function (deg) {
|
||
return deg * Math.PI / 180;
|
||
};
|
||
|
||
Canvas.prototype._getStyleColor = function (style) {
|
||
return (iconColors[style] === undefined)? style: iconColors[style];
|
||
};
|
||
|
||
provide(Canvas);
|
||
});
|
||
|
||
|
||
e.modules.define('PieChartClusterer.icon.colors', [], function (provide) {
|
||
var colors = {
|
||
blue: '#1E98FF',
|
||
red: '#ED4543',
|
||
darkOrange: '#E6761B',
|
||
night: '#0E4779',
|
||
darkBlue: '#177BC9',
|
||
pink: '#F371D1',
|
||
gray: '#B3B3B3',
|
||
brown: '#793D0E',
|
||
darkGreen: '#1BAD03',
|
||
violet: '#B51EFF',
|
||
black: '#595959',
|
||
yellow: '#FFD21E',
|
||
green: '#56DB40',
|
||
orange: '#FF931E',
|
||
lightBlue: '#82CDFF',
|
||
olive: '#97A100'
|
||
};
|
||
|
||
provide(colors);
|
||
});
|
||
|
||
|
||
e.modules.define('PieChartClusterer.icon.params', [
|
||
'shape.Circle',
|
||
'geometry.pixel.Circle'
|
||
], function (provide, CircleShape, PixelCircleGeometry) {
|
||
provide({
|
||
icons: {
|
||
small: {
|
||
size: [46, 46],
|
||
offset: [-23, -23],
|
||
shape: new CircleShape(new PixelCircleGeometry([0, 2], 21.5))
|
||
},
|
||
medium: {
|
||
size: [58, 58],
|
||
offset: [-29, -29],
|
||
shape: new CircleShape(new PixelCircleGeometry([0, 2], 27.5))
|
||
},
|
||
large: {
|
||
size: [71, 71],
|
||
offset: [-35.5, -35.5],
|
||
shape: new CircleShape(new PixelCircleGeometry([0, 2], 34))
|
||
}
|
||
},
|
||
numbers: [10, 100]
|
||
});
|
||
});
|
||
}(this); |