UNPKG

@progress/kendo-charts

Version:

Kendo UI platform-independent Charts library

186 lines (150 loc) 4.43 kB
import { geometry as g, drawing as d } from '@progress/kendo-drawing'; import { defined, isFunction, getter, setDefaultOptions } from '../../common'; import { ShapeLayer } from './shape'; import { Location } from '../location'; export class BubbleLayer extends ShapeLayer { _readData() { const data = this.options.data || []; return data; } _load(data) { this._data = data; this.surface.clear(); if (data.length === 0) { return; } let options = this.options; let getValue = getter(options.valueField); let newData = data.slice(0); newData.sort(function(a, b) { return getValue(b) - getValue(a); }); let scaleType = this._scaleType(); let scale; let getLocation = getter(this.options.locationField); for (let i = 0; i < newData.length; i++) { let dataItem = newData[i]; let location = getLocation(dataItem); let value = getValue(dataItem); if (defined(location) && defined(value)) { if (!scale) { scale = new scaleType([ 0, value ], [ options.minSize, options.maxSize ]); } location = Location.create(location); let center = this.map.locationToView(location); let size = scale.map(value); let symbol = this._createSymbol({ center: center, size: size, style: options.style, dataItem: dataItem, location: location }); symbol.dataItem = dataItem; symbol.location = location; symbol.value = value; this._drawSymbol(symbol); } } } _scaleType() { let scale = this.options.scale; if (isFunction(scale)) { return scale; } return Scales[scale]; } _createSymbol(args) { let symbol = this.options.symbol; if (!isFunction(symbol)) { symbol = Symbols[symbol]; } return symbol(args); } _drawSymbol(shape) { let args = { layer: this, shape: shape }; let cancelled = this.map.trigger('shapeCreated', args); if (!cancelled) { this.surface.draw(shape); } } _tooltipContext(shape) { return { type: 'bubble', layerIndex: this._layerIndex(), className: 'k-map-bubble-tooltip', dataItem: shape.dataItem, location: shape.location, value: shape.value }; } _tooltipAnchor(e) { const shape = e.element; const center = shape.bbox().center(); return { top: center.y, left: center.x }; } } setDefaultOptions(BubbleLayer, { // autoBind: true, locationField: 'location', valueField: 'value', minSize: 0, maxSize: 100, scale: 'sqrt', symbol: 'circle', // ensure bubble layers are displayed over tile and shape layers zIndex: 200 }); class SqrtScale { constructor(domain, range) { this._domain = domain; this._range = range; let domainRange = Math.sqrt(domain[1]) - Math.sqrt(domain[0]); let outputRange = range[1] - range[0]; this._ratio = outputRange / domainRange; } map(value) { let rel = (Math.sqrt(value) - Math.sqrt(this._domain[0])) * this._ratio; return this._range[0] + rel; } } let Scales = { sqrt: SqrtScale }; let Symbols = { circle: function(args) { let geo = new g.Circle(args.center, args.size / 2); return new d.Circle(geo, args.style); }, square: function(args) { let path = new d.Path(args.style); let halfSize = args.size / 2; let center = args.center; path.moveTo(center.x - halfSize, center.y - halfSize).lineTo(center.x + halfSize, center.y - halfSize).lineTo(center.x + halfSize, center.y + halfSize).lineTo(center.x - halfSize, center.y + halfSize).close(); return path; } };