2126 lines
90 KiB
JavaScript
2126 lines
90 KiB
JavaScript
/**
|
|
* Kendo UI v2016.1.226 (http://www.telerik.com/kendo-ui)
|
|
* Copyright 2016 Telerik AD. All rights reserved.
|
|
*
|
|
* Kendo UI commercial licenses may be obtained at
|
|
* http://www.telerik.com/purchase/license-agreement/kendo-ui-complete
|
|
* If you do not own a commercial license, this file shall be governed by the trial license terms.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/
|
|
(function (f, define) {
|
|
define('util/main', ['kendo.core'], f);
|
|
}(function () {
|
|
(function () {
|
|
var math = Math, kendo = window.kendo, deepExtend = kendo.deepExtend;
|
|
var DEG_TO_RAD = math.PI / 180, MAX_NUM = Number.MAX_VALUE, MIN_NUM = -Number.MAX_VALUE, UNDEFINED = 'undefined';
|
|
function defined(value) {
|
|
return typeof value !== UNDEFINED;
|
|
}
|
|
function round(value, precision) {
|
|
var power = pow(precision);
|
|
return math.round(value * power) / power;
|
|
}
|
|
function pow(p) {
|
|
if (p) {
|
|
return math.pow(10, p);
|
|
} else {
|
|
return 1;
|
|
}
|
|
}
|
|
function limitValue(value, min, max) {
|
|
return math.max(math.min(value, max), min);
|
|
}
|
|
function rad(degrees) {
|
|
return degrees * DEG_TO_RAD;
|
|
}
|
|
function deg(radians) {
|
|
return radians / DEG_TO_RAD;
|
|
}
|
|
function isNumber(val) {
|
|
return typeof val === 'number' && !isNaN(val);
|
|
}
|
|
function valueOrDefault(value, defaultValue) {
|
|
return defined(value) ? value : defaultValue;
|
|
}
|
|
function sqr(value) {
|
|
return value * value;
|
|
}
|
|
function objectKey(object) {
|
|
var parts = [];
|
|
for (var key in object) {
|
|
parts.push(key + object[key]);
|
|
}
|
|
return parts.sort().join('');
|
|
}
|
|
function hashKey(str) {
|
|
var hash = 2166136261;
|
|
for (var i = 0; i < str.length; ++i) {
|
|
hash += (hash << 1) + (hash << 4) + (hash << 7) + (hash << 8) + (hash << 24);
|
|
hash ^= str.charCodeAt(i);
|
|
}
|
|
return hash >>> 0;
|
|
}
|
|
function hashObject(object) {
|
|
return hashKey(objectKey(object));
|
|
}
|
|
var now = Date.now;
|
|
if (!now) {
|
|
now = function () {
|
|
return new Date().getTime();
|
|
};
|
|
}
|
|
function arrayLimits(arr) {
|
|
var length = arr.length, i, min = MAX_NUM, max = MIN_NUM;
|
|
for (i = 0; i < length; i++) {
|
|
max = math.max(max, arr[i]);
|
|
min = math.min(min, arr[i]);
|
|
}
|
|
return {
|
|
min: min,
|
|
max: max
|
|
};
|
|
}
|
|
function arrayMin(arr) {
|
|
return arrayLimits(arr).min;
|
|
}
|
|
function arrayMax(arr) {
|
|
return arrayLimits(arr).max;
|
|
}
|
|
function sparseArrayMin(arr) {
|
|
return sparseArrayLimits(arr).min;
|
|
}
|
|
function sparseArrayMax(arr) {
|
|
return sparseArrayLimits(arr).max;
|
|
}
|
|
function sparseArrayLimits(arr) {
|
|
var min = MAX_NUM, max = MIN_NUM;
|
|
for (var i = 0, length = arr.length; i < length; i++) {
|
|
var n = arr[i];
|
|
if (n !== null && isFinite(n)) {
|
|
min = math.min(min, n);
|
|
max = math.max(max, n);
|
|
}
|
|
}
|
|
return {
|
|
min: min === MAX_NUM ? undefined : min,
|
|
max: max === MIN_NUM ? undefined : max
|
|
};
|
|
}
|
|
function last(array) {
|
|
if (array) {
|
|
return array[array.length - 1];
|
|
}
|
|
}
|
|
function append(first, second) {
|
|
first.push.apply(first, second);
|
|
return first;
|
|
}
|
|
function renderTemplate(text) {
|
|
return kendo.template(text, {
|
|
useWithBlock: false,
|
|
paramName: 'd'
|
|
});
|
|
}
|
|
function renderAttr(name, value) {
|
|
return defined(value) && value !== null ? ' ' + name + '=\'' + value + '\' ' : '';
|
|
}
|
|
function renderAllAttr(attrs) {
|
|
var output = '';
|
|
for (var i = 0; i < attrs.length; i++) {
|
|
output += renderAttr(attrs[i][0], attrs[i][1]);
|
|
}
|
|
return output;
|
|
}
|
|
function renderStyle(attrs) {
|
|
var output = '';
|
|
for (var i = 0; i < attrs.length; i++) {
|
|
var value = attrs[i][1];
|
|
if (defined(value)) {
|
|
output += attrs[i][0] + ':' + value + ';';
|
|
}
|
|
}
|
|
if (output !== '') {
|
|
return output;
|
|
}
|
|
}
|
|
function renderSize(size) {
|
|
if (typeof size !== 'string') {
|
|
size += 'px';
|
|
}
|
|
return size;
|
|
}
|
|
function renderPos(pos) {
|
|
var result = [];
|
|
if (pos) {
|
|
var parts = kendo.toHyphens(pos).split('-');
|
|
for (var i = 0; i < parts.length; i++) {
|
|
result.push('k-pos-' + parts[i]);
|
|
}
|
|
}
|
|
return result.join(' ');
|
|
}
|
|
function isTransparent(color) {
|
|
return color === '' || color === null || color === 'none' || color === 'transparent' || !defined(color);
|
|
}
|
|
function arabicToRoman(n) {
|
|
var literals = {
|
|
1: 'i',
|
|
10: 'x',
|
|
100: 'c',
|
|
2: 'ii',
|
|
20: 'xx',
|
|
200: 'cc',
|
|
3: 'iii',
|
|
30: 'xxx',
|
|
300: 'ccc',
|
|
4: 'iv',
|
|
40: 'xl',
|
|
400: 'cd',
|
|
5: 'v',
|
|
50: 'l',
|
|
500: 'd',
|
|
6: 'vi',
|
|
60: 'lx',
|
|
600: 'dc',
|
|
7: 'vii',
|
|
70: 'lxx',
|
|
700: 'dcc',
|
|
8: 'viii',
|
|
80: 'lxxx',
|
|
800: 'dccc',
|
|
9: 'ix',
|
|
90: 'xc',
|
|
900: 'cm',
|
|
1000: 'm'
|
|
};
|
|
var values = [
|
|
1000,
|
|
900,
|
|
800,
|
|
700,
|
|
600,
|
|
500,
|
|
400,
|
|
300,
|
|
200,
|
|
100,
|
|
90,
|
|
80,
|
|
70,
|
|
60,
|
|
50,
|
|
40,
|
|
30,
|
|
20,
|
|
10,
|
|
9,
|
|
8,
|
|
7,
|
|
6,
|
|
5,
|
|
4,
|
|
3,
|
|
2,
|
|
1
|
|
];
|
|
var roman = '';
|
|
while (n > 0) {
|
|
if (n < values[0]) {
|
|
values.shift();
|
|
} else {
|
|
roman += literals[values[0]];
|
|
n -= values[0];
|
|
}
|
|
}
|
|
return roman;
|
|
}
|
|
function romanToArabic(r) {
|
|
r = r.toLowerCase();
|
|
var digits = {
|
|
i: 1,
|
|
v: 5,
|
|
x: 10,
|
|
l: 50,
|
|
c: 100,
|
|
d: 500,
|
|
m: 1000
|
|
};
|
|
var value = 0, prev = 0;
|
|
for (var i = 0; i < r.length; ++i) {
|
|
var v = digits[r.charAt(i)];
|
|
if (!v) {
|
|
return null;
|
|
}
|
|
value += v;
|
|
if (v > prev) {
|
|
value -= 2 * prev;
|
|
}
|
|
prev = v;
|
|
}
|
|
return value;
|
|
}
|
|
function memoize(f) {
|
|
var cache = Object.create(null);
|
|
return function () {
|
|
var id = '';
|
|
for (var i = arguments.length; --i >= 0;) {
|
|
id += ':' + arguments[i];
|
|
}
|
|
if (id in cache) {
|
|
return cache[id];
|
|
}
|
|
return f.apply(this, arguments);
|
|
};
|
|
}
|
|
function ucs2decode(string) {
|
|
var output = [], counter = 0, length = string.length, value, extra;
|
|
while (counter < length) {
|
|
value = string.charCodeAt(counter++);
|
|
if (value >= 55296 && value <= 56319 && counter < length) {
|
|
extra = string.charCodeAt(counter++);
|
|
if ((extra & 64512) == 56320) {
|
|
output.push(((value & 1023) << 10) + (extra & 1023) + 65536);
|
|
} else {
|
|
output.push(value);
|
|
counter--;
|
|
}
|
|
} else {
|
|
output.push(value);
|
|
}
|
|
}
|
|
return output;
|
|
}
|
|
function ucs2encode(array) {
|
|
return array.map(function (value) {
|
|
var output = '';
|
|
if (value > 65535) {
|
|
value -= 65536;
|
|
output += String.fromCharCode(value >>> 10 & 1023 | 55296);
|
|
value = 56320 | value & 1023;
|
|
}
|
|
output += String.fromCharCode(value);
|
|
return output;
|
|
}).join('');
|
|
}
|
|
deepExtend(kendo, {
|
|
util: {
|
|
MAX_NUM: MAX_NUM,
|
|
MIN_NUM: MIN_NUM,
|
|
append: append,
|
|
arrayLimits: arrayLimits,
|
|
arrayMin: arrayMin,
|
|
arrayMax: arrayMax,
|
|
defined: defined,
|
|
deg: deg,
|
|
hashKey: hashKey,
|
|
hashObject: hashObject,
|
|
isNumber: isNumber,
|
|
isTransparent: isTransparent,
|
|
last: last,
|
|
limitValue: limitValue,
|
|
now: now,
|
|
objectKey: objectKey,
|
|
round: round,
|
|
rad: rad,
|
|
renderAttr: renderAttr,
|
|
renderAllAttr: renderAllAttr,
|
|
renderPos: renderPos,
|
|
renderSize: renderSize,
|
|
renderStyle: renderStyle,
|
|
renderTemplate: renderTemplate,
|
|
sparseArrayLimits: sparseArrayLimits,
|
|
sparseArrayMin: sparseArrayMin,
|
|
sparseArrayMax: sparseArrayMax,
|
|
sqr: sqr,
|
|
valueOrDefault: valueOrDefault,
|
|
romanToArabic: romanToArabic,
|
|
arabicToRoman: arabicToRoman,
|
|
memoize: memoize,
|
|
ucs2encode: ucs2encode,
|
|
ucs2decode: ucs2decode
|
|
}
|
|
});
|
|
kendo.drawing.util = kendo.util;
|
|
kendo.dataviz.util = kendo.util;
|
|
}());
|
|
return window.kendo;
|
|
}, typeof define == 'function' && define.amd ? define : function (a1, a2, a3) {
|
|
(a3 || a2)();
|
|
}));
|
|
(function (f, define) {
|
|
define('util/text-metrics', [
|
|
'kendo.core',
|
|
'util/main'
|
|
], f);
|
|
}(function () {
|
|
(function ($) {
|
|
var doc = document, kendo = window.kendo, Class = kendo.Class, util = kendo.util, defined = util.defined;
|
|
var LRUCache = Class.extend({
|
|
init: function (size) {
|
|
this._size = size;
|
|
this._length = 0;
|
|
this._map = {};
|
|
},
|
|
put: function (key, value) {
|
|
var lru = this, map = lru._map, entry = {
|
|
key: key,
|
|
value: value
|
|
};
|
|
map[key] = entry;
|
|
if (!lru._head) {
|
|
lru._head = lru._tail = entry;
|
|
} else {
|
|
lru._tail.newer = entry;
|
|
entry.older = lru._tail;
|
|
lru._tail = entry;
|
|
}
|
|
if (lru._length >= lru._size) {
|
|
map[lru._head.key] = null;
|
|
lru._head = lru._head.newer;
|
|
lru._head.older = null;
|
|
} else {
|
|
lru._length++;
|
|
}
|
|
},
|
|
get: function (key) {
|
|
var lru = this, entry = lru._map[key];
|
|
if (entry) {
|
|
if (entry === lru._head && entry !== lru._tail) {
|
|
lru._head = entry.newer;
|
|
lru._head.older = null;
|
|
}
|
|
if (entry !== lru._tail) {
|
|
if (entry.older) {
|
|
entry.older.newer = entry.newer;
|
|
entry.newer.older = entry.older;
|
|
}
|
|
entry.older = lru._tail;
|
|
entry.newer = null;
|
|
lru._tail.newer = entry;
|
|
lru._tail = entry;
|
|
}
|
|
return entry.value;
|
|
}
|
|
}
|
|
});
|
|
var defaultMeasureBox = $('<div style=\'position: absolute !important; top: -4000px !important; width: auto !important; height: auto !important;' + 'padding: 0 !important; margin: 0 !important; border: 0 !important;' + 'line-height: normal !important; visibility: hidden !important; white-space: nowrap!important;\' />')[0];
|
|
function zeroSize() {
|
|
return {
|
|
width: 0,
|
|
height: 0,
|
|
baseline: 0
|
|
};
|
|
}
|
|
var TextMetrics = Class.extend({
|
|
init: function (options) {
|
|
this._cache = new LRUCache(1000);
|
|
this._initOptions(options);
|
|
},
|
|
options: { baselineMarkerSize: 1 },
|
|
measure: function (text, style, box) {
|
|
if (!text) {
|
|
return zeroSize();
|
|
}
|
|
var styleKey = util.objectKey(style), cacheKey = util.hashKey(text + styleKey), cachedResult = this._cache.get(cacheKey);
|
|
if (cachedResult) {
|
|
return cachedResult;
|
|
}
|
|
var size = zeroSize();
|
|
var measureBox = box ? box : defaultMeasureBox;
|
|
var baselineMarker = this._baselineMarker().cloneNode(false);
|
|
for (var key in style) {
|
|
var value = style[key];
|
|
if (defined(value)) {
|
|
measureBox.style[key] = value;
|
|
}
|
|
}
|
|
$(measureBox).text(text);
|
|
measureBox.appendChild(baselineMarker);
|
|
doc.body.appendChild(measureBox);
|
|
if ((text + '').length) {
|
|
size.width = measureBox.offsetWidth - this.options.baselineMarkerSize;
|
|
size.height = measureBox.offsetHeight;
|
|
size.baseline = baselineMarker.offsetTop + this.options.baselineMarkerSize;
|
|
}
|
|
if (size.width > 0 && size.height > 0) {
|
|
this._cache.put(cacheKey, size);
|
|
}
|
|
measureBox.parentNode.removeChild(measureBox);
|
|
return size;
|
|
},
|
|
_baselineMarker: function () {
|
|
return $('<div class=\'k-baseline-marker\' ' + 'style=\'display: inline-block; vertical-align: baseline;' + 'width: ' + this.options.baselineMarkerSize + 'px; height: ' + this.options.baselineMarkerSize + 'px;' + 'overflow: hidden;\' />')[0];
|
|
}
|
|
});
|
|
TextMetrics.current = new TextMetrics();
|
|
function measureText(text, style, measureBox) {
|
|
return TextMetrics.current.measure(text, style, measureBox);
|
|
}
|
|
function loadFonts(fonts, callback) {
|
|
var promises = [];
|
|
if (fonts.length > 0 && document.fonts) {
|
|
try {
|
|
promises = fonts.map(function (font) {
|
|
return document.fonts.load(font);
|
|
});
|
|
} catch (e) {
|
|
kendo.logToConsole(e);
|
|
}
|
|
Promise.all(promises).then(callback, callback);
|
|
} else {
|
|
callback();
|
|
}
|
|
}
|
|
kendo.util.TextMetrics = TextMetrics;
|
|
kendo.util.LRUCache = LRUCache;
|
|
kendo.util.loadFonts = loadFonts;
|
|
kendo.util.measureText = measureText;
|
|
}(window.kendo.jQuery));
|
|
}, typeof define == 'function' && define.amd ? define : function (a1, a2, a3) {
|
|
(a3 || a2)();
|
|
}));
|
|
(function (f, define) {
|
|
define('util/base64', ['util/main'], f);
|
|
}(function () {
|
|
(function () {
|
|
var kendo = window.kendo, deepExtend = kendo.deepExtend, fromCharCode = String.fromCharCode;
|
|
var KEY_STR = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
|
|
function encodeBase64(input) {
|
|
var output = '';
|
|
var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
|
|
var i = 0;
|
|
input = encodeUTF8(input);
|
|
while (i < input.length) {
|
|
chr1 = input.charCodeAt(i++);
|
|
chr2 = input.charCodeAt(i++);
|
|
chr3 = input.charCodeAt(i++);
|
|
enc1 = chr1 >> 2;
|
|
enc2 = (chr1 & 3) << 4 | chr2 >> 4;
|
|
enc3 = (chr2 & 15) << 2 | chr3 >> 6;
|
|
enc4 = chr3 & 63;
|
|
if (isNaN(chr2)) {
|
|
enc3 = enc4 = 64;
|
|
} else if (isNaN(chr3)) {
|
|
enc4 = 64;
|
|
}
|
|
output = output + KEY_STR.charAt(enc1) + KEY_STR.charAt(enc2) + KEY_STR.charAt(enc3) + KEY_STR.charAt(enc4);
|
|
}
|
|
return output;
|
|
}
|
|
function encodeUTF8(input) {
|
|
var output = '';
|
|
for (var i = 0; i < input.length; i++) {
|
|
var c = input.charCodeAt(i);
|
|
if (c < 128) {
|
|
output += fromCharCode(c);
|
|
} else if (c < 2048) {
|
|
output += fromCharCode(192 | c >>> 6);
|
|
output += fromCharCode(128 | c & 63);
|
|
} else if (c < 65536) {
|
|
output += fromCharCode(224 | c >>> 12);
|
|
output += fromCharCode(128 | c >>> 6 & 63);
|
|
output += fromCharCode(128 | c & 63);
|
|
}
|
|
}
|
|
return output;
|
|
}
|
|
deepExtend(kendo.util, {
|
|
encodeBase64: encodeBase64,
|
|
encodeUTF8: encodeUTF8
|
|
});
|
|
}());
|
|
return window.kendo;
|
|
}, typeof define == 'function' && define.amd ? define : function (a1, a2, a3) {
|
|
(a3 || a2)();
|
|
}));
|
|
(function (f, define) {
|
|
define('mixins/observers', ['kendo.core'], f);
|
|
}(function () {
|
|
(function ($) {
|
|
var math = Math, kendo = window.kendo, deepExtend = kendo.deepExtend, inArray = $.inArray;
|
|
var ObserversMixin = {
|
|
observers: function () {
|
|
this._observers = this._observers || [];
|
|
return this._observers;
|
|
},
|
|
addObserver: function (element) {
|
|
if (!this._observers) {
|
|
this._observers = [element];
|
|
} else {
|
|
this._observers.push(element);
|
|
}
|
|
return this;
|
|
},
|
|
removeObserver: function (element) {
|
|
var observers = this.observers();
|
|
var index = inArray(element, observers);
|
|
if (index != -1) {
|
|
observers.splice(index, 1);
|
|
}
|
|
return this;
|
|
},
|
|
trigger: function (methodName, event) {
|
|
var observers = this._observers;
|
|
var observer;
|
|
var idx;
|
|
if (observers && !this._suspended) {
|
|
for (idx = 0; idx < observers.length; idx++) {
|
|
observer = observers[idx];
|
|
if (observer[methodName]) {
|
|
observer[methodName](event);
|
|
}
|
|
}
|
|
}
|
|
return this;
|
|
},
|
|
optionsChange: function (e) {
|
|
this.trigger('optionsChange', e);
|
|
},
|
|
geometryChange: function (e) {
|
|
this.trigger('geometryChange', e);
|
|
},
|
|
suspend: function () {
|
|
this._suspended = (this._suspended || 0) + 1;
|
|
return this;
|
|
},
|
|
resume: function () {
|
|
this._suspended = math.max((this._suspended || 0) - 1, 0);
|
|
return this;
|
|
},
|
|
_observerField: function (field, value) {
|
|
if (this[field]) {
|
|
this[field].removeObserver(this);
|
|
}
|
|
this[field] = value;
|
|
value.addObserver(this);
|
|
}
|
|
};
|
|
deepExtend(kendo, { mixins: { ObserversMixin: ObserversMixin } });
|
|
}(window.kendo.jQuery));
|
|
return window.kendo;
|
|
}, typeof define == 'function' && define.amd ? define : function (a1, a2, a3) {
|
|
(a3 || a2)();
|
|
}));
|
|
(function (f, define) {
|
|
define('kendo.dataviz.gauge', [
|
|
'kendo.dataviz.core',
|
|
'kendo.drawing',
|
|
'kendo.dataviz.themes'
|
|
], f);
|
|
}(function () {
|
|
var __meta__ = {
|
|
id: 'dataviz.gauge',
|
|
name: 'Gauge',
|
|
category: 'dataviz',
|
|
description: 'Radial and Linear gauges.',
|
|
depends: [
|
|
'dataviz.core',
|
|
'dataviz.themes'
|
|
]
|
|
};
|
|
(function ($, undefined) {
|
|
var math = Math, kendo = window.kendo, util = kendo.util, Widget = kendo.ui.Widget, deepExtend = kendo.deepExtend, dataviz = kendo.dataviz, autoMajorUnit = dataviz.autoMajorUnit, ChartElement = dataviz.ChartElement, NumericAxis = dataviz.NumericAxis, Axis = dataviz.Axis, Box2D = dataviz.Box2D, Class = kendo.Class, defined = util.defined, isNumber = util.isNumber, interpolateValue = dataviz.interpolateValue, getSpacing = dataviz.getSpacing, round = dataviz.round, geo = dataviz.geometry, draw = dataviz.drawing, Point = geo.Point, Group = draw.Group, Path = draw.Path, Rect = geo.Rect, Text = draw.Text;
|
|
var ANGULAR_SPEED = 150, LINEAR_SPEED = 250, ARROW = 'arrow', ARROW_POINTER = 'arrowPointer', BAR_POINTER = 'barPointer', BLACK = '#000', CAP_SIZE = 0.05, COORD_PRECISION = dataviz.COORD_PRECISION, MAX_VALUE = Number.MAX_VALUE, MIN_VALUE = -Number.MAX_VALUE, DEFAULT_HEIGHT = 200, DEFAULT_LINE_WIDTH = 0.5, DEFAULT_WIDTH = 200, DEFAULT_MIN_WIDTH = 60, DEFAULT_MIN_HEIGHT = 60, DEFAULT_MARGIN = 5, DEGREE = math.PI / 180, GEO_ARC_ADJUST_ANGLE = 180, INSIDE = 'inside', LINEAR = 'linear', NEEDLE = 'needle', OUTSIDE = 'outside', RADIAL_POINTER = 'radialPointer', X = 'x', Y = 'y';
|
|
var Pointer = Class.extend({
|
|
init: function (scale, options) {
|
|
var pointer = this;
|
|
var scaleOptions = scale.options;
|
|
ChartElement.fn.init.call(pointer, options);
|
|
options = pointer.options;
|
|
options.fill = options.color;
|
|
pointer.scale = scale;
|
|
if (defined(options.value)) {
|
|
options.value = math.min(math.max(options.value, scaleOptions.min), scaleOptions.max);
|
|
} else {
|
|
options.value = scaleOptions.min;
|
|
}
|
|
},
|
|
options: { color: BLACK },
|
|
value: function (newValue) {
|
|
var that = this;
|
|
var options = that.options;
|
|
var value = options.value;
|
|
var scaleOptions = that.scale.options;
|
|
if (arguments.length === 0) {
|
|
return value;
|
|
}
|
|
options._oldValue = options._oldValue !== undefined ? options.value : scaleOptions.min;
|
|
options.value = math.min(math.max(newValue, scaleOptions.min), scaleOptions.max);
|
|
if (that.elements) {
|
|
that.repaint();
|
|
}
|
|
}
|
|
});
|
|
var RadialPointer = Pointer.extend({
|
|
options: {
|
|
shape: NEEDLE,
|
|
cap: { size: CAP_SIZE },
|
|
arrow: {
|
|
width: 16,
|
|
height: 14
|
|
},
|
|
animation: {
|
|
type: RADIAL_POINTER,
|
|
duration: ANGULAR_SPEED
|
|
}
|
|
},
|
|
setRadius: function (radius) {
|
|
var that = this;
|
|
if (radius) {
|
|
that.elements.clear();
|
|
that.render(that.parent, that.center, radius);
|
|
}
|
|
},
|
|
setAngle: function (angle) {
|
|
this.elements.transform(geo.transform().rotate(angle, this.center));
|
|
},
|
|
repaint: function () {
|
|
var that = this;
|
|
var scale = that.scale;
|
|
var options = that.options;
|
|
var oldAngle = scale.slotAngle(options._oldValue);
|
|
var newAngle = scale.slotAngle(options.value);
|
|
if (options.animation.transitions === false) {
|
|
that.setAngle(newAngle);
|
|
} else {
|
|
new RadialPointerAnimation(that.elements, deepExtend(options.animation, {
|
|
oldAngle: oldAngle,
|
|
newAngle: newAngle
|
|
})).play();
|
|
}
|
|
},
|
|
render: function () {
|
|
var that = this;
|
|
var scale = that.scale;
|
|
var center = scale.arc.center;
|
|
var options = that.options;
|
|
var elements = new Group();
|
|
if (options.animation !== false) {
|
|
deepExtend(options.animation, {
|
|
startAngle: 0,
|
|
center: center,
|
|
reverse: scale.options.reverse
|
|
});
|
|
}
|
|
if (options.shape === NEEDLE) {
|
|
elements.append(that._renderNeedle(), that._renderCap());
|
|
} else {
|
|
elements.append(that._renderArrow());
|
|
}
|
|
that.elements = elements;
|
|
that.setAngle(DEGREE);
|
|
return elements;
|
|
},
|
|
reflow: function (arc) {
|
|
var that = this;
|
|
var center = that.center = arc.center;
|
|
var radius = that.radius = arc.getRadiusX();
|
|
var capSize = that.capSize = Math.round(radius * that.options.cap.size);
|
|
that.bbox = Rect.fromPoints(new Point(center.x - capSize, center.y - capSize), new Point(center.x + capSize, center.y + capSize));
|
|
},
|
|
_renderNeedle: function () {
|
|
var that = this;
|
|
var options = that.options;
|
|
var minorTickSize = that.scale.options.minorTicks.size;
|
|
var center = that.center;
|
|
var needleColor = options.color;
|
|
var needlePath = new Path({
|
|
fill: { color: needleColor },
|
|
stroke: {
|
|
color: needleColor,
|
|
width: DEFAULT_LINE_WIDTH
|
|
}
|
|
});
|
|
needlePath.moveTo(center.x + that.radius - minorTickSize, center.y).lineTo(center.x, center.y - that.capSize / 2).lineTo(center.x, center.y + that.capSize / 2).close();
|
|
return needlePath;
|
|
},
|
|
_renderCap: function () {
|
|
var that = this;
|
|
var options = that.options;
|
|
var capColor = options.cap.color || options.color;
|
|
var circle = new geo.Circle(that.center, that.capSize);
|
|
var cap = new draw.Circle(circle, {
|
|
fill: { color: capColor },
|
|
stroke: { color: capColor }
|
|
});
|
|
return cap;
|
|
}
|
|
});
|
|
var RadialScale = NumericAxis.extend({
|
|
init: function (options) {
|
|
var scale = this;
|
|
scale.options = deepExtend({}, scale.options, options);
|
|
scale.options.majorUnit = scale.options.majorUnit || autoMajorUnit(scale.options.min, scale.options.max);
|
|
scale.options.minorUnit = scale.options.minorUnit || scale.options.majorUnit / 10;
|
|
Axis.fn.init.call(scale, scale.options);
|
|
},
|
|
options: {
|
|
min: 0,
|
|
max: 100,
|
|
majorTicks: {
|
|
size: 15,
|
|
align: INSIDE,
|
|
color: BLACK,
|
|
width: DEFAULT_LINE_WIDTH,
|
|
visible: true
|
|
},
|
|
minorTicks: {
|
|
size: 10,
|
|
align: INSIDE,
|
|
color: BLACK,
|
|
width: DEFAULT_LINE_WIDTH,
|
|
visible: true
|
|
},
|
|
startAngle: -30,
|
|
endAngle: 210,
|
|
labels: {
|
|
position: INSIDE,
|
|
padding: 2
|
|
}
|
|
},
|
|
render: function (center, radius) {
|
|
var that = this;
|
|
var arc = that.renderArc(center, radius);
|
|
that.bbox = arc.bbox();
|
|
that.labelElements = that.renderLabels();
|
|
that.ticks = that.renderTicks();
|
|
that.ranges = that.renderRanges();
|
|
},
|
|
reflow: function (bbox) {
|
|
var that = this;
|
|
var center = bbox.center();
|
|
var radius = math.min(bbox.height(), bbox.width()) / 2;
|
|
if (that.bbox !== undefined) {
|
|
that.bbox = that.arc.bbox();
|
|
that.radius(that.arc.getRadiusX());
|
|
that.repositionRanges();
|
|
that.renderLabels();
|
|
} else {
|
|
return that.render(center, radius);
|
|
}
|
|
},
|
|
slotAngle: function (value) {
|
|
var options = this.options;
|
|
var startAngle = options.startAngle;
|
|
var reverse = options.reverse;
|
|
var angle = options.endAngle - startAngle;
|
|
var min = options.min;
|
|
var max = options.max;
|
|
var result;
|
|
if (reverse) {
|
|
result = options.endAngle - (value - min) / (max - min) * angle;
|
|
} else {
|
|
result = (value - min) / (max - min) * angle + startAngle;
|
|
}
|
|
return result + GEO_ARC_ADJUST_ANGLE;
|
|
},
|
|
renderLabels: function () {
|
|
var that = this;
|
|
var options = that.options;
|
|
var majorTickSize = options.majorTicks.size;
|
|
var arc = that.arc.clone();
|
|
var radius = arc.getRadiusX();
|
|
var tickAngles = that.tickAngles(arc, options.majorUnit);
|
|
var labels = that.labels;
|
|
var count = labels.length;
|
|
var labelsOptions = options.labels;
|
|
var padding = labelsOptions.padding;
|
|
var rangeDistance = radius * 0.05;
|
|
var rangeSize = options.rangeSize = options.rangeSize || radius * 0.1;
|
|
var ranges = options.ranges || [];
|
|
var halfWidth, halfHeight, labelAngle;
|
|
var angle, label, lp, i, cx, cy, isInside;
|
|
var labelsGroup = new Group();
|
|
var lbl, labelPos, prevLabelPos, labelTransform;
|
|
if (that.options.rangeDistance !== undefined) {
|
|
rangeDistance = that.options.rangeDistance;
|
|
} else {
|
|
that.options.rangeDistance = rangeDistance;
|
|
}
|
|
if (labelsOptions.position === INSIDE) {
|
|
radius -= majorTickSize;
|
|
if (ranges.length && that.labelElements === undefined) {
|
|
radius -= rangeSize + rangeDistance;
|
|
}
|
|
arc.setRadiusX(radius).setRadiusY(radius);
|
|
}
|
|
for (i = 0; i < count; i++) {
|
|
label = labels[i];
|
|
halfWidth = label.box.width() / 2;
|
|
halfHeight = label.box.height() / 2;
|
|
angle = tickAngles[i];
|
|
labelAngle = (angle - GEO_ARC_ADJUST_ANGLE) * DEGREE;
|
|
isInside = labelsOptions.position === INSIDE;
|
|
lp = arc.pointAt(angle);
|
|
cx = lp.x + math.cos(labelAngle) * (halfWidth + padding) * (isInside ? 1 : -1);
|
|
cy = lp.y + math.sin(labelAngle) * (halfHeight + padding) * (isInside ? 1 : -1);
|
|
label.reflow(new dataviz.Box2D(cx - halfWidth, cy - halfHeight, cx + halfWidth, cy + halfHeight));
|
|
labelPos = new Point(label.box.x1, label.box.y1);
|
|
if (that.labelElements === undefined) {
|
|
lbl = _buildLabel(label, options.labels);
|
|
labelsGroup.append(lbl);
|
|
} else {
|
|
lbl = that.labelElements.children[i];
|
|
prevLabelPos = lbl.bbox().origin;
|
|
labelTransform = lbl.transform() || geo.transform();
|
|
labelTransform.translate(labelPos.x - prevLabelPos.x, labelPos.y - prevLabelPos.y);
|
|
lbl.transform(labelTransform);
|
|
}
|
|
that.bbox = Rect.union(that.bbox, lbl.bbox());
|
|
}
|
|
return labelsGroup;
|
|
},
|
|
repositionRanges: function () {
|
|
var that = this;
|
|
var ranges = that.ranges.children;
|
|
var rangeSize = that.options.rangeSize;
|
|
var rangeDistance = that.options.rangeDistance;
|
|
var rangeRadius, newRadius;
|
|
if (ranges.length > 0) {
|
|
rangeRadius = that.getRangeRadius();
|
|
if (that.options.labels.position === INSIDE) {
|
|
rangeRadius += rangeSize + rangeDistance;
|
|
}
|
|
newRadius = rangeRadius + rangeSize / 2;
|
|
for (var i = 0; i < ranges.length; i++) {
|
|
ranges[i]._geometry.setRadiusX(newRadius).setRadiusY(newRadius);
|
|
}
|
|
that.bbox = Rect.union(that.bbox, that.ranges.bbox());
|
|
}
|
|
},
|
|
renderRanges: function () {
|
|
var that = this;
|
|
var arc = that.arc;
|
|
var result = new Group();
|
|
var from, to;
|
|
var segments = that.rangeSegments();
|
|
var segmentsCount = segments.length;
|
|
var reverse = that.options.reverse;
|
|
var rangeSize = that.options.rangeSize;
|
|
var rangeDistance = that.options.rangeDistance;
|
|
var segment, rangeRadius, rangeGeom, i;
|
|
if (segmentsCount) {
|
|
rangeRadius = that.getRangeRadius();
|
|
that.radius(that.radius() - rangeSize - rangeDistance);
|
|
for (i = 0; i < segmentsCount; i++) {
|
|
segment = segments[i];
|
|
from = that.slotAngle(segment[reverse ? 'to' : 'from']);
|
|
to = that.slotAngle(segment[!reverse ? 'to' : 'from']);
|
|
if (to - from !== 0) {
|
|
rangeGeom = new geo.Arc(arc.center, {
|
|
radiusX: rangeRadius + rangeSize / 2,
|
|
radiusY: rangeRadius + rangeSize / 2,
|
|
startAngle: from,
|
|
endAngle: to
|
|
});
|
|
result.append(new draw.Arc(rangeGeom, {
|
|
stroke: {
|
|
width: rangeSize,
|
|
color: segment.color,
|
|
opacity: segment.opacity
|
|
}
|
|
}));
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
},
|
|
rangeSegments: function () {
|
|
var gauge = this;
|
|
var options = gauge.options;
|
|
var ranges = options.ranges || [];
|
|
var count = ranges.length;
|
|
var range;
|
|
var segmentsCount;
|
|
var defaultColor = options.rangePlaceholderColor;
|
|
var segments = [];
|
|
var segment;
|
|
var min = options.min;
|
|
var max = options.max;
|
|
var i, j;
|
|
function rangeSegment(from, to, color, opacity) {
|
|
return {
|
|
from: from,
|
|
to: to,
|
|
color: color,
|
|
opacity: opacity
|
|
};
|
|
}
|
|
if (count) {
|
|
segments.push(rangeSegment(min, max, defaultColor));
|
|
for (i = 0; i < count; i++) {
|
|
range = getRange(ranges[i], min, max);
|
|
segmentsCount = segments.length;
|
|
for (j = 0; j < segmentsCount; j++) {
|
|
segment = segments[j];
|
|
if (segment.from <= range.from && range.from <= segment.to) {
|
|
segments.push(rangeSegment(range.from, range.to, range.color, range.opacity));
|
|
if (segment.from <= range.to && range.to <= segment.to) {
|
|
segments.push(rangeSegment(range.to, segment.to, defaultColor, range.opacity));
|
|
}
|
|
segment.to = range.from;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return segments;
|
|
},
|
|
getRangeRadius: function () {
|
|
var that = this;
|
|
var options = that.options;
|
|
var majorTickSize = options.majorTicks.size;
|
|
var rangeSize = options.rangeSize;
|
|
var rangeDistance = options.rangeDistance;
|
|
var arc = that.arc;
|
|
var r;
|
|
if (options.labels.position === OUTSIDE) {
|
|
r = arc.getRadiusX() - majorTickSize - rangeDistance - rangeSize;
|
|
} else {
|
|
r = arc.getRadiusX() - rangeSize;
|
|
}
|
|
return r;
|
|
},
|
|
renderArc: function (center, radius) {
|
|
var that = this;
|
|
var options = that.options;
|
|
var arc = that.arc = new geo.Arc(center, {
|
|
radiusX: radius,
|
|
radiusY: radius,
|
|
startAngle: options.startAngle + GEO_ARC_ADJUST_ANGLE,
|
|
endAngle: options.endAngle + GEO_ARC_ADJUST_ANGLE
|
|
});
|
|
return arc;
|
|
},
|
|
renderTicks: function () {
|
|
var that = this;
|
|
var arc = that.arc;
|
|
var options = that.options;
|
|
var labelsPosition = options.labels.position;
|
|
var allTicks = new Group();
|
|
var majorTickSize = options.majorTicks.size;
|
|
var minorTickSize = options.minorTicks.size;
|
|
var tickArc = arc.clone();
|
|
var radius = tickArc.getRadiusX();
|
|
function drawTicks(arc, tickAngles, unit, tickOptions) {
|
|
var ticks = new Group(), center = arc.center, radius = arc.getRadiusX(), i, tickStart, tickEnd, visible = tickOptions.visible;
|
|
if (visible) {
|
|
for (i = 0; i < tickAngles.length; i++) {
|
|
tickStart = arc.pointAt(tickAngles[i]);
|
|
tickEnd = new Point(center.x + radius - tickOptions.size, center.y).rotate(tickAngles[i], center);
|
|
ticks.append(new Path({
|
|
stroke: {
|
|
color: tickOptions.color,
|
|
width: tickOptions.width
|
|
}
|
|
}).moveTo(tickStart).lineTo(tickEnd));
|
|
}
|
|
}
|
|
return ticks;
|
|
}
|
|
that.majorTickAngles = that.tickAngles(arc, options.majorUnit);
|
|
that.majorTicks = drawTicks(tickArc, that.majorTickAngles, options.majorUnit, options.majorTicks);
|
|
allTicks.append(that.majorTicks);
|
|
that._tickDifference = majorTickSize - minorTickSize;
|
|
if (labelsPosition === OUTSIDE) {
|
|
tickArc.setRadiusX(radius - majorTickSize + minorTickSize).setRadiusY(radius - majorTickSize + minorTickSize);
|
|
}
|
|
that.minorTickAngles = that.normalizeTickAngles(that.tickAngles(arc, options.minorUnit));
|
|
that.minorTicks = drawTicks(tickArc, that.minorTickAngles, options.minorUnit, options.minorTicks, options.majorUnit);
|
|
allTicks.append(that.minorTicks);
|
|
return allTicks;
|
|
},
|
|
normalizeTickAngles: function (angles) {
|
|
var that = this;
|
|
var options = that.options;
|
|
var skip = options.majorUnit / options.minorUnit;
|
|
for (var i = angles.length - 1; i >= 0; i--) {
|
|
if (i % skip === 0) {
|
|
angles.splice(i, 1);
|
|
}
|
|
}
|
|
return angles;
|
|
},
|
|
tickAngles: function (ring, stepValue) {
|
|
var scale = this;
|
|
var options = scale.options;
|
|
var reverse = options.reverse;
|
|
var range = options.max - options.min;
|
|
var angle = ring.endAngle - ring.startAngle;
|
|
var pos = ring.startAngle;
|
|
var tickCount = range / stepValue;
|
|
var step = angle / tickCount;
|
|
var positions = [];
|
|
var i;
|
|
if (reverse) {
|
|
pos += angle;
|
|
step = -step;
|
|
}
|
|
for (i = 0; i < tickCount; i++) {
|
|
positions.push(round(pos, COORD_PRECISION));
|
|
pos += step;
|
|
}
|
|
if (round(pos) <= ring.endAngle) {
|
|
positions.push(pos);
|
|
}
|
|
return positions;
|
|
},
|
|
radius: function (radius) {
|
|
var that = this;
|
|
if (radius) {
|
|
that.arc.setRadiusX(radius).setRadiusY(radius);
|
|
that.repositionTicks(that.majorTicks.children, that.majorTickAngles);
|
|
that.repositionTicks(that.minorTicks.children, that.minorTickAngles, true);
|
|
} else {
|
|
return that.arc.getRadiusX();
|
|
}
|
|
},
|
|
repositionTicks: function (ticks, tickAngles, minor) {
|
|
var that = this;
|
|
var diff = minor ? that._tickDifference || 0 : 0;
|
|
var tickArc = that.arc;
|
|
var radius = tickArc.getRadiusX();
|
|
if (minor && that.options.labels.position === OUTSIDE && diff !== 0) {
|
|
tickArc = that.arc.clone();
|
|
tickArc.setRadiusX(radius - diff).setRadiusY(radius - diff);
|
|
}
|
|
for (var i = 0; i < ticks.length; i++) {
|
|
var newPoint = tickArc.pointAt(tickAngles[i]);
|
|
var segments = ticks[i].segments;
|
|
var xDiff = newPoint.x - segments[0].anchor().x;
|
|
var yDiff = newPoint.y - segments[0].anchor().y;
|
|
ticks[i].transform(new geo.Transformation().translate(xDiff, yDiff));
|
|
}
|
|
}
|
|
});
|
|
var Gauge = Widget.extend({
|
|
init: function (element, userOptions) {
|
|
var gauge = this;
|
|
var options;
|
|
var themeOptions;
|
|
var themeName;
|
|
var themes = dataviz.ui.themes || {};
|
|
var theme;
|
|
kendo.destroy(element);
|
|
$(element).empty();
|
|
Widget.fn.init.call(gauge, element);
|
|
gauge.wrapper = gauge.element;
|
|
gauge._originalOptions = deepExtend({}, userOptions);
|
|
options = deepExtend({}, gauge.options, userOptions);
|
|
themeName = options.theme;
|
|
theme = themes[themeName] || themes[themeName.toLowerCase()];
|
|
themeOptions = themeName && theme ? theme.gauge : {};
|
|
gauge.options = deepExtend({}, themeOptions, options);
|
|
if ($.isArray(options.pointer)) {
|
|
for (var i = 0; i < options.pointer.length; i++) {
|
|
gauge.options.pointer[i] = deepExtend({}, themeOptions.pointer, options.pointer[i]);
|
|
}
|
|
}
|
|
gauge.element.addClass('k-gauge');
|
|
gauge.surface = gauge._createSurface();
|
|
gauge.redraw();
|
|
},
|
|
options: {
|
|
plotArea: {},
|
|
theme: 'default',
|
|
renderAs: '',
|
|
pointer: {},
|
|
scale: {},
|
|
gaugeArea: {}
|
|
},
|
|
destroy: function () {
|
|
this.surface.destroy();
|
|
Widget.fn.destroy.call(this);
|
|
},
|
|
value: function (value) {
|
|
var that = this;
|
|
var pointer = that.pointers[0];
|
|
if (arguments.length === 0) {
|
|
return pointer.value();
|
|
}
|
|
pointer.value(value);
|
|
that._setValueOptions(value);
|
|
},
|
|
_draw: function () {
|
|
var surface = this.surface;
|
|
surface.clear();
|
|
surface.draw(this._visuals);
|
|
},
|
|
exportVisual: function () {
|
|
return this._visuals;
|
|
},
|
|
allValues: function (values) {
|
|
var that = this;
|
|
var pointers = that.pointers;
|
|
var allValues = [];
|
|
var i;
|
|
if (arguments.length === 0) {
|
|
for (i = 0; i < pointers.length; i++) {
|
|
allValues.push(pointers[i].value());
|
|
}
|
|
return allValues;
|
|
}
|
|
if ($.isArray(values)) {
|
|
for (i = 0; i < values.length; i++) {
|
|
if (isNumber(values[i])) {
|
|
pointers[i].value(values[i]);
|
|
}
|
|
}
|
|
}
|
|
that._setValueOptions(values);
|
|
},
|
|
_setValueOptions: function (values) {
|
|
var pointers = [].concat(this.options.pointer);
|
|
values = [].concat(values);
|
|
for (var i = 0; i < values.length; i++) {
|
|
pointers[i].value = values[i];
|
|
}
|
|
},
|
|
_resize: function () {
|
|
var that = this;
|
|
var t = that.options.transitions;
|
|
var i;
|
|
that.options.transitions = false;
|
|
for (i = 0; i < that.pointers.length; i++) {
|
|
that.pointers[i].options.animation.transitions = false;
|
|
}
|
|
that.redraw();
|
|
that.options.transitions = t;
|
|
for (i = 0; i < that.pointers.length; i++) {
|
|
that.pointers[i].options.animation.transitions = t;
|
|
}
|
|
},
|
|
redraw: function () {
|
|
var that = this;
|
|
var size = deepExtend(that._getSize(), that.options.gaugeArea);
|
|
var wrapper = new Rect([
|
|
0,
|
|
0
|
|
], [
|
|
size.width,
|
|
size.height
|
|
]);
|
|
var bbox;
|
|
that.surface.clear();
|
|
that.gaugeArea = that._createGaugeArea();
|
|
that.surface.element.css({
|
|
width: size.width,
|
|
height: size.height
|
|
});
|
|
that._createModel();
|
|
bbox = _unpad(wrapper.bbox(), that._gaugeAreaMargin);
|
|
that.reflow(bbox);
|
|
},
|
|
_createGaugeArea: function () {
|
|
var that = this;
|
|
var options = that.options.gaugeArea;
|
|
var size = that.surface.size();
|
|
var border = options.border || {};
|
|
var areaGeometry = new Rect([
|
|
0,
|
|
0
|
|
], [
|
|
size.width,
|
|
size.height
|
|
]);
|
|
that._gaugeAreaMargin = options.margin || DEFAULT_MARGIN;
|
|
if (border.width > 0) {
|
|
areaGeometry = _unpad(areaGeometry, border.width);
|
|
}
|
|
var gaugeArea = Path.fromRect(areaGeometry, {
|
|
stroke: {
|
|
color: border.width ? border.color : '',
|
|
width: border.width,
|
|
dashType: border.dashType,
|
|
lineJoin: 'round',
|
|
lineCap: 'round'
|
|
},
|
|
fill: { color: options.background }
|
|
});
|
|
return gaugeArea;
|
|
},
|
|
_createSurface: function () {
|
|
var that = this;
|
|
var options = that.options;
|
|
var size = that._getSize();
|
|
size = options.gaugeArea ? deepExtend(size, options.gaugeArea) : size;
|
|
var wrap = $('<div></div>').appendTo(that.element).css({
|
|
width: size.width,
|
|
height: size.height
|
|
});
|
|
return new draw.Surface.create(wrap, { type: options.renderAs });
|
|
},
|
|
getSize: function () {
|
|
return this._getSize();
|
|
},
|
|
_getSize: function () {
|
|
var that = this;
|
|
var element = that.element;
|
|
var width = element.width();
|
|
var height = element.height();
|
|
if (!width) {
|
|
width = DEFAULT_WIDTH;
|
|
}
|
|
if (!height) {
|
|
height = DEFAULT_HEIGHT;
|
|
}
|
|
return {
|
|
width: width,
|
|
height: height
|
|
};
|
|
}
|
|
});
|
|
var RadialGauge = Gauge.extend({
|
|
init: function (element, options) {
|
|
var radialGauge = this;
|
|
Gauge.fn.init.call(radialGauge, element, options);
|
|
kendo.notify(radialGauge, dataviz.ui);
|
|
},
|
|
options: {
|
|
name: 'RadialGauge',
|
|
transitions: true,
|
|
gaugeArea: { background: '' }
|
|
},
|
|
reflow: function (bbox) {
|
|
var that = this;
|
|
var pointers = that.pointers;
|
|
that.scale.reflow(bbox);
|
|
that._initialPlotArea = that.scale.bbox;
|
|
for (var i = 0; i < pointers.length; i++) {
|
|
pointers[i].reflow(that.scale.arc);
|
|
that._initialPlotArea = Rect.union(that._initialPlotArea, pointers[i].bbox);
|
|
}
|
|
that.fitScale(bbox);
|
|
that.alignScale(bbox);
|
|
that._buildVisual(that.gaugeArea, pointers, that.scale);
|
|
that._draw();
|
|
},
|
|
_buildVisual: function (gaugeArea, pointers, scale) {
|
|
var visuals = new Group();
|
|
var current;
|
|
visuals.append(gaugeArea);
|
|
visuals.append(scale.ticks);
|
|
visuals.append(scale.ranges);
|
|
for (var i = 0; i < pointers.length; i++) {
|
|
current = pointers[i];
|
|
current.render();
|
|
visuals.append(current.elements);
|
|
current.value(current.options.value);
|
|
}
|
|
visuals.append(scale.labelElements);
|
|
this._visuals = visuals;
|
|
},
|
|
fitScale: function (bbox) {
|
|
var that = this;
|
|
var scale = that.scale;
|
|
var arc = scale.arc;
|
|
var plotAreaBox = that._initialPlotArea;
|
|
var step = math.abs(that.getDiff(plotAreaBox, bbox));
|
|
var min = round(step, COORD_PRECISION);
|
|
var max = round(-step, COORD_PRECISION);
|
|
var minDiff, midDiff, maxDiff, mid, oldDiff;
|
|
var staleFlag = 0;
|
|
var i = 0;
|
|
while (i++ < 100) {
|
|
staleFlag = oldDiff === maxDiff ? staleFlag + 1 : 0;
|
|
if (staleFlag > 5) {
|
|
break;
|
|
}
|
|
if (min != mid) {
|
|
minDiff = that.getPlotBox(min, bbox, arc);
|
|
if (0 <= minDiff && minDiff <= 2) {
|
|
break;
|
|
}
|
|
}
|
|
if (max != mid) {
|
|
maxDiff = that.getPlotBox(max, bbox, arc);
|
|
if (0 <= maxDiff && maxDiff <= 2) {
|
|
break;
|
|
}
|
|
}
|
|
if (minDiff > 0 && maxDiff > 0) {
|
|
mid = min * 2;
|
|
} else if (minDiff < 0 && maxDiff < 0) {
|
|
mid = max * 2;
|
|
} else {
|
|
mid = round((min + max) / 2 || 1, COORD_PRECISION);
|
|
}
|
|
midDiff = that.getPlotBox(mid, bbox, arc);
|
|
if (0 <= midDiff && midDiff <= 2) {
|
|
break;
|
|
}
|
|
oldDiff = maxDiff;
|
|
if (midDiff > 0) {
|
|
max = mid;
|
|
maxDiff = midDiff;
|
|
} else {
|
|
min = mid;
|
|
minDiff = midDiff;
|
|
}
|
|
}
|
|
},
|
|
getPlotBox: function (step, bbox, arc) {
|
|
var that = this;
|
|
var scale = that.scale;
|
|
var pointers = that.pointers;
|
|
var radius = arc.getRadiusX();
|
|
arc = arc.clone();
|
|
arc.setRadiusX(radius + step).setRadiusY(radius + step);
|
|
scale.arc = arc;
|
|
scale.reflow(bbox);
|
|
that.plotBbox = scale.bbox;
|
|
for (var i = 0; i < pointers.length; i++) {
|
|
pointers[i].reflow(arc);
|
|
that.plotBbox = Rect.union(that.plotBbox, pointers[i].bbox);
|
|
}
|
|
return that.getDiff(that.plotBbox, bbox);
|
|
},
|
|
getDiff: function (plotBox, box) {
|
|
return math.min(box.width() - plotBox.width(), box.height() - plotBox.height());
|
|
},
|
|
alignScale: function (bbox) {
|
|
var that = this;
|
|
var plotBoxCenter = that.plotBbox.center();
|
|
var boxCenter = bbox.center();
|
|
var paddingX = plotBoxCenter.x - boxCenter.x;
|
|
var paddingY = plotBoxCenter.y - boxCenter.y;
|
|
var scale = that.scale;
|
|
var pointers = that.pointers;
|
|
scale.arc.center.x -= paddingX;
|
|
scale.arc.center.y -= paddingY;
|
|
scale.reflow(bbox);
|
|
for (var i = 0; i < pointers.length; i++) {
|
|
pointers[i].reflow(scale.arc);
|
|
that.plotBbox = Rect.union(scale.bbox, pointers[i].bbox);
|
|
}
|
|
},
|
|
_createModel: function () {
|
|
var that = this;
|
|
var options = that.options;
|
|
var pointers = options.pointer;
|
|
var scale = that.scale = new RadialScale(options.scale);
|
|
var current;
|
|
that.pointers = [];
|
|
pointers = $.isArray(pointers) ? pointers : [pointers];
|
|
for (var i = 0; i < pointers.length; i++) {
|
|
current = new RadialPointer(scale, deepExtend({}, pointers[i], { animation: { transitions: options.transitions } }));
|
|
that.pointers.push(current);
|
|
}
|
|
}
|
|
});
|
|
var LinearGauge = Gauge.extend({
|
|
init: function (element, options) {
|
|
var linearGauge = this;
|
|
Gauge.fn.init.call(linearGauge, element, options);
|
|
kendo.notify(linearGauge, dataviz.ui);
|
|
},
|
|
options: {
|
|
name: 'LinearGauge',
|
|
transitions: true,
|
|
gaugeArea: { background: '' },
|
|
scale: { vertical: true }
|
|
},
|
|
reflow: function (bbox) {
|
|
var that = this;
|
|
var pointers = that.pointers;
|
|
var bboxX = bbox.origin.x;
|
|
var bboxY = bbox.origin.y;
|
|
var bbox2D = new dataviz.Box2D(bboxX, bboxX, bboxX + bbox.width(), bboxY + bbox.height());
|
|
that.scale.reflow(bbox2D);
|
|
for (var i = 0; i < pointers.length; i++) {
|
|
pointers[i].reflow();
|
|
}
|
|
that.bbox = that._getBox(bbox2D);
|
|
that._alignElements();
|
|
that._shrinkElements();
|
|
that._buildVisual();
|
|
that._draw();
|
|
},
|
|
_buildVisual: function () {
|
|
var that = this;
|
|
var visuals = new Group();
|
|
var scaleElements = that.scale.render();
|
|
var pointers = that.pointers;
|
|
var current;
|
|
visuals.append(that.gaugeArea);
|
|
visuals.append(scaleElements);
|
|
for (var i = 0; i < pointers.length; i++) {
|
|
current = pointers[i];
|
|
visuals.append(current.render());
|
|
current.value(current.options.value);
|
|
}
|
|
that._visuals = visuals;
|
|
},
|
|
_createModel: function () {
|
|
var that = this;
|
|
var options = that.options;
|
|
var pointers = options.pointer;
|
|
var scale = that.scale = new LinearScale(options.scale);
|
|
var current, currentOptions;
|
|
that.pointers = [];
|
|
pointers = $.isArray(pointers) ? pointers : [pointers];
|
|
for (var i = 0; i < pointers.length; i++) {
|
|
currentOptions = deepExtend({}, pointers[i], { animation: { transitions: options.transitions } });
|
|
if (currentOptions.shape === ARROW) {
|
|
current = new ArrowLinearPointer(scale, currentOptions);
|
|
} else {
|
|
current = new BarLinearPointer(scale, currentOptions);
|
|
}
|
|
that.pointers.push(current);
|
|
}
|
|
},
|
|
_getSize: function () {
|
|
var gauge = this;
|
|
var element = gauge.element;
|
|
var width = element.width();
|
|
var height = element.height();
|
|
var vertical = gauge.options.scale.vertical;
|
|
if (!width) {
|
|
width = vertical ? DEFAULT_MIN_WIDTH : DEFAULT_WIDTH;
|
|
}
|
|
if (!height) {
|
|
height = vertical ? DEFAULT_HEIGHT : DEFAULT_MIN_HEIGHT;
|
|
}
|
|
return {
|
|
width: width,
|
|
height: height
|
|
};
|
|
},
|
|
_getBox: function (box) {
|
|
var that = this;
|
|
var scale = that.scale;
|
|
var pointers = that.pointers;
|
|
var boxCenter = box.center();
|
|
var plotAreaBox = pointers[0].box.clone().wrap(scale.box);
|
|
var size;
|
|
for (var i = 0; i < pointers.length; i++) {
|
|
plotAreaBox.wrap(pointers[i].box.clone());
|
|
}
|
|
if (scale.options.vertical) {
|
|
size = plotAreaBox.width() / 2;
|
|
plotAreaBox = new Box2D(boxCenter.x - size, box.y1, boxCenter.x + size, box.y2);
|
|
} else {
|
|
size = plotAreaBox.height() / 2;
|
|
plotAreaBox = new Box2D(box.x1, boxCenter.y - size, box.x2, boxCenter.y + size);
|
|
}
|
|
return plotAreaBox;
|
|
},
|
|
_alignElements: function () {
|
|
var that = this;
|
|
var scale = that.scale;
|
|
var pointers = that.pointers;
|
|
var scaleBox = scale.box;
|
|
var box = pointers[0].box.clone().wrap(scale.box);
|
|
var plotAreaBox = that.bbox;
|
|
var diff, i;
|
|
for (i = 0; i < pointers.length; i++) {
|
|
box.wrap(pointers[i].box.clone());
|
|
}
|
|
if (scale.options.vertical) {
|
|
diff = plotAreaBox.center().x - box.center().x;
|
|
scale.reflow(new Box2D(scaleBox.x1 + diff, plotAreaBox.y1, scaleBox.x2 + diff, plotAreaBox.y2));
|
|
} else {
|
|
diff = plotAreaBox.center().y - box.center().y;
|
|
scale.reflow(new Box2D(plotAreaBox.x1, scaleBox.y1 + diff, plotAreaBox.x2, scaleBox.y2 + diff));
|
|
}
|
|
for (i = 0; i < pointers.length; i++) {
|
|
pointers[i].reflow(that.bbox);
|
|
}
|
|
},
|
|
_shrinkElements: function () {
|
|
var that = this;
|
|
var scale = that.scale;
|
|
var pointers = that.pointers;
|
|
var scaleBox = scale.box.clone();
|
|
var pos = scale.options.vertical ? 'y' : 'x';
|
|
var pointerBox = pointers[0].box;
|
|
var i;
|
|
for (i = 0; i < pointers.length; i++) {
|
|
pointerBox.wrap(pointers[i].box.clone());
|
|
}
|
|
scaleBox[pos + 1] += math.max(scaleBox[pos + 1] - pointerBox[pos + 1], 0);
|
|
scaleBox[pos + 2] -= math.max(pointerBox[pos + 2] - scaleBox[pos + 2], 0);
|
|
scale.reflow(scaleBox);
|
|
for (i = 0; i < pointers.length; i++) {
|
|
pointers[i].reflow(that.bbox);
|
|
}
|
|
}
|
|
});
|
|
var LinearScale = NumericAxis.extend({
|
|
init: function (options) {
|
|
var scale = this;
|
|
scale.options = deepExtend({}, scale.options, options);
|
|
scale.options = deepExtend({}, scale.options, { labels: { mirror: scale.options.mirror } });
|
|
scale.options.majorUnit = scale.options.majorUnit || autoMajorUnit(scale.options.min, scale.options.max);
|
|
Axis.fn.init.call(scale, scale.options);
|
|
scale.options.minorUnit = scale.options.minorUnit || scale.options.majorUnit / 10;
|
|
},
|
|
options: {
|
|
min: 0,
|
|
max: 50,
|
|
majorTicks: {
|
|
size: 15,
|
|
align: INSIDE,
|
|
color: BLACK,
|
|
width: DEFAULT_LINE_WIDTH,
|
|
visible: true
|
|
},
|
|
minorTicks: {
|
|
size: 10,
|
|
align: INSIDE,
|
|
color: BLACK,
|
|
width: DEFAULT_LINE_WIDTH,
|
|
visible: true
|
|
},
|
|
line: { width: DEFAULT_LINE_WIDTH },
|
|
labels: {
|
|
position: INSIDE,
|
|
padding: 2
|
|
},
|
|
mirror: false,
|
|
_alignLines: false
|
|
},
|
|
render: function () {
|
|
var that = this;
|
|
var elements = that.elements = new Group();
|
|
var labels = that.renderLabels();
|
|
var scaleLine = that.renderLine();
|
|
var scaleTicks = that.renderTicks();
|
|
var ranges = that.renderRanges();
|
|
elements.append(scaleLine, labels, scaleTicks, ranges);
|
|
return elements;
|
|
},
|
|
renderRanges: function () {
|
|
var that = this;
|
|
var options = that.options;
|
|
var min = options.min;
|
|
var max = options.max;
|
|
var ranges = options.ranges || [];
|
|
var vertical = options.vertical;
|
|
var mirror = options.labels.mirror;
|
|
var elements = new Group();
|
|
var count = ranges.length;
|
|
var rangeSize = options.rangeSize || options.minorTicks.size / 2;
|
|
var range, slot, slotX, slotY, i;
|
|
if (count) {
|
|
for (i = 0; i < count; i++) {
|
|
range = getRange(ranges[i], min, max);
|
|
slot = that.getSlot(range.from, range.to);
|
|
slotX = vertical ? that.lineBox() : slot;
|
|
slotY = vertical ? slot : that.lineBox();
|
|
if (vertical) {
|
|
slotX.x1 -= rangeSize * (mirror ? -1 : 1);
|
|
} else {
|
|
slotY.y2 += rangeSize * (mirror ? -1 : 1);
|
|
}
|
|
elements.append(Path.fromRect(new Rect([
|
|
slotX.x1,
|
|
slotY.y1
|
|
], [
|
|
slotX.x2 - slotX.x1,
|
|
slotY.y2 - slotY.y1
|
|
]), {
|
|
fill: {
|
|
color: range.color,
|
|
opacity: range.opacity
|
|
},
|
|
stroke: {}
|
|
}));
|
|
}
|
|
}
|
|
return elements;
|
|
},
|
|
renderLabels: function () {
|
|
var that = this;
|
|
var options = that.options;
|
|
var labels = that.labels;
|
|
var elements = new Group();
|
|
for (var i = 0; i < labels.length; i++) {
|
|
elements.append(_buildLabel(labels[i], options.labels));
|
|
}
|
|
return elements;
|
|
},
|
|
renderLine: function () {
|
|
var that = this;
|
|
var options = that.options;
|
|
var line = options.line;
|
|
var lineBox = that.lineBox();
|
|
var linePath;
|
|
var elements = new Group();
|
|
if (line.width > 0 && line.visible) {
|
|
linePath = new Path({
|
|
stroke: {
|
|
color: line.color,
|
|
dashType: line.dashType,
|
|
width: line.width
|
|
}
|
|
});
|
|
linePath.moveTo(lineBox.x1, lineBox.y1).lineTo(lineBox.x2, lineBox.y2);
|
|
elements.append(linePath);
|
|
}
|
|
return elements;
|
|
},
|
|
renderTicks: function () {
|
|
var that = this;
|
|
var ticks = new Group();
|
|
var options = that.options;
|
|
var lineBox = that.lineBox();
|
|
var mirror = options.labels.mirror;
|
|
var majorUnit = options.majorTicks.visible ? options.majorUnit : 0;
|
|
var tickLineOptions = {
|
|
_alignLines: options._alignLines,
|
|
vertical: options.vertical
|
|
};
|
|
function render(tickPositions, tickOptions) {
|
|
var i, count = tickPositions.length;
|
|
if (tickOptions.visible) {
|
|
for (i = tickOptions.skip; i < count; i += tickOptions.step) {
|
|
if (i % tickOptions.skipUnit === 0) {
|
|
continue;
|
|
}
|
|
tickLineOptions.tickX = mirror ? lineBox.x2 : lineBox.x2 - tickOptions.size;
|
|
tickLineOptions.tickY = mirror ? lineBox.y1 - tickOptions.size : lineBox.y1;
|
|
tickLineOptions.position = tickPositions[i];
|
|
ticks.append(that.renderAxisTick(tickLineOptions, tickOptions));
|
|
}
|
|
}
|
|
}
|
|
render(that.getMajorTickPositions(), options.majorTicks);
|
|
render(that.getMinorTickPositions(), deepExtend({}, { skipUnit: majorUnit / options.minorUnit }, options.minorTicks));
|
|
return ticks;
|
|
},
|
|
renderAxisTick: function (options, tickOptions) {
|
|
var tickX = options.tickX;
|
|
var tickY = options.tickY;
|
|
var position = options.position;
|
|
var start, end, tickPath;
|
|
if (options.vertical) {
|
|
start = new Point(tickX, position);
|
|
end = new Point(tickX + tickOptions.size, position);
|
|
} else {
|
|
start = new Point(position, tickY);
|
|
end = new Point(position, tickY + tickOptions.size);
|
|
}
|
|
tickPath = new Path({
|
|
stroke: {
|
|
color: tickOptions.color,
|
|
width: tickOptions.width
|
|
}
|
|
}).moveTo(start).lineTo(end);
|
|
return tickPath;
|
|
}
|
|
});
|
|
var LinearPointer = Pointer.extend({
|
|
init: function (scale, options) {
|
|
var pointer = this;
|
|
Pointer.fn.init.call(pointer, scale, options);
|
|
pointer.options = deepExtend({ track: { visible: defined(options.track) } }, pointer.options);
|
|
},
|
|
options: {
|
|
shape: BAR_POINTER,
|
|
track: { border: { width: 1 } },
|
|
color: BLACK,
|
|
border: { width: 1 },
|
|
opacity: 1,
|
|
margin: getSpacing(3),
|
|
animation: { type: BAR_POINTER },
|
|
visible: true
|
|
},
|
|
reflow: function () {
|
|
var pointer = this;
|
|
var options = pointer.options;
|
|
var scale = pointer.scale;
|
|
var scaleLine = scale.lineBox();
|
|
var trackSize = options.track.size || options.size;
|
|
var pointerHalfSize = options.size / 2;
|
|
var mirror = scale.options.mirror;
|
|
var margin = getSpacing(options.margin);
|
|
var vertical = scale.options.vertical;
|
|
var space = vertical ? margin[mirror ? 'left' : 'right'] : margin[mirror ? 'bottom' : 'top'];
|
|
var pointerBox, pointerRangeBox, trackBox;
|
|
space = mirror ? -space : space;
|
|
if (vertical) {
|
|
trackBox = new Box2D(scaleLine.x1 + space, scaleLine.y1, scaleLine.x1 + space, scaleLine.y2);
|
|
if (mirror) {
|
|
trackBox.x1 -= trackSize;
|
|
} else {
|
|
trackBox.x2 += trackSize;
|
|
}
|
|
if (options.shape !== BAR_POINTER) {
|
|
pointerRangeBox = new Box2D(scaleLine.x2 + space, scaleLine.y1 - pointerHalfSize, scaleLine.x2 + space, scaleLine.y2 + pointerHalfSize);
|
|
pointerBox = pointerRangeBox;
|
|
}
|
|
} else {
|
|
trackBox = new Box2D(scaleLine.x1, scaleLine.y1 - space, scaleLine.x2, scaleLine.y1 - space);
|
|
if (mirror) {
|
|
trackBox.y2 += trackSize;
|
|
} else {
|
|
trackBox.y1 -= trackSize;
|
|
}
|
|
if (options.shape !== BAR_POINTER) {
|
|
pointerRangeBox = new Box2D(scaleLine.x1 - pointerHalfSize, scaleLine.y1 - space, scaleLine.x2 + pointerHalfSize, scaleLine.y1 - space);
|
|
pointerBox = pointerRangeBox;
|
|
}
|
|
}
|
|
pointer.trackBox = trackBox;
|
|
pointer.pointerRangeBox = pointerRangeBox;
|
|
pointer.box = pointerBox || trackBox.clone().pad(options.border.width);
|
|
},
|
|
getElementOptions: function () {
|
|
var options = this.options;
|
|
return {
|
|
fill: {
|
|
color: options.color,
|
|
opacity: options.opacity
|
|
},
|
|
stroke: defined(options.border) ? {
|
|
color: options.border.width ? options.border.color || options.color : '',
|
|
width: options.border.width,
|
|
dashType: options.border.dashType,
|
|
opacity: options.opacity
|
|
} : null
|
|
};
|
|
},
|
|
_margin: function () {
|
|
var pointer = this;
|
|
var options = pointer.options;
|
|
var scale = pointer.scale;
|
|
var mirror = scale.options.mirror;
|
|
var margin = getSpacing(options.margin);
|
|
var vertical = scale.options.vertical;
|
|
var space = vertical ? margin[mirror ? 'left' : 'right'] : margin[mirror ? 'bottom' : 'top'];
|
|
return space;
|
|
}
|
|
});
|
|
var ArrowLinearPointer = LinearPointer.extend({
|
|
init: function (scale, options) {
|
|
LinearPointer.fn.init.call(this, scale, options);
|
|
if (this.options.size === undefined) {
|
|
this.options.size = this.scale.options.majorTicks.size * 0.6;
|
|
}
|
|
},
|
|
pointerShape: function () {
|
|
var that = this;
|
|
var options = that.options;
|
|
var scale = that.scale;
|
|
var size = options.size;
|
|
var vertical = scale.options.vertical;
|
|
var halfSize = size / 2;
|
|
var sign = scale.options.mirror ? -1 : 1;
|
|
var reverse = scale.options.reverse;
|
|
var pos, shape;
|
|
if (vertical) {
|
|
pos = reverse ? 'y2' : 'y1';
|
|
shape = [
|
|
new Point(0, 0 - halfSize),
|
|
new Point(0 - sign * size, 0),
|
|
new Point(0, 0 + halfSize)
|
|
];
|
|
} else {
|
|
pos = reverse ? 'x1' : 'x2';
|
|
shape = [
|
|
new Point(0 - halfSize, 0),
|
|
new Point(0, 0 + sign * size),
|
|
new Point(0 + halfSize, 0)
|
|
];
|
|
}
|
|
return shape;
|
|
},
|
|
repaint: function () {
|
|
var that = this;
|
|
var scale = that.scale;
|
|
var options = that.options;
|
|
var animation = new ArrowLinearPointerAnimation(that.elements, deepExtend(options.animation, {
|
|
vertical: scale.options.vertical,
|
|
mirror: scale.options.mirror,
|
|
margin: that._margin(options.margin),
|
|
from: scale.getSlot(options._oldValue),
|
|
to: scale.getSlot(options.value)
|
|
}));
|
|
if (options.animation.transitions === false) {
|
|
animation.options.duration = 0;
|
|
}
|
|
animation.setup();
|
|
animation.play();
|
|
},
|
|
render: function () {
|
|
var that = this;
|
|
var options = that.options;
|
|
var elements = new Group();
|
|
var scale = that.scale;
|
|
var elementOptions = that.getElementOptions();
|
|
var shape = that.pointerShape(options.value);
|
|
options.animation.type = ARROW_POINTER;
|
|
elements = new Path({
|
|
stroke: elementOptions.stroke,
|
|
fill: elementOptions.fill
|
|
}).moveTo(shape[0]).lineTo(shape[1]).lineTo(shape[2]).close();
|
|
var slot = scale.getSlot(options.value);
|
|
elements.transform(geo.transform().translate(slot.x1, slot.y1));
|
|
that.elements = elements;
|
|
return elements;
|
|
}
|
|
});
|
|
var BarLinearPointer = LinearPointer.extend({
|
|
init: function (scale, options) {
|
|
LinearPointer.fn.init.call(this, scale, options);
|
|
if (this.options.size === undefined) {
|
|
this.options.size = this.scale.options.majorTicks.size * 0.3;
|
|
}
|
|
},
|
|
pointerShape: function (value) {
|
|
var that = this;
|
|
var options = that.options;
|
|
var scale = that.scale;
|
|
var vertical = scale.options.vertical;
|
|
var mirror = scale.options.mirror;
|
|
var dir = mirror == vertical ? -1 : 1;
|
|
var size = options.size * dir;
|
|
var minSlot = scale.getSlot(scale.options.min);
|
|
var slot = scale.getSlot(value);
|
|
var axis = vertical ? Y : X;
|
|
var sizeAxis = vertical ? X : Y;
|
|
var margin = that._margin() * dir;
|
|
var p1 = new Point();
|
|
p1[axis] = minSlot[axis + '1'];
|
|
p1[sizeAxis] = minSlot[sizeAxis + '1'];
|
|
var p2 = new Point();
|
|
p2[axis] = slot[axis + '1'];
|
|
p2[sizeAxis] = slot[sizeAxis + '1'];
|
|
if (vertical) {
|
|
p1.translate(margin, 0);
|
|
p2.translate(margin, 0);
|
|
} else {
|
|
p1.translate(0, margin);
|
|
p2.translate(0, margin);
|
|
}
|
|
var p3 = p2.clone();
|
|
var p4 = p1.clone();
|
|
if (vertical) {
|
|
p3.translate(size, 0);
|
|
p4.translate(size, 0);
|
|
} else {
|
|
p3.translate(0, size);
|
|
p4.translate(0, size);
|
|
}
|
|
return [
|
|
p1,
|
|
p2,
|
|
p3,
|
|
p4
|
|
];
|
|
},
|
|
repaint: function () {
|
|
var that = this;
|
|
var scale = that.scale;
|
|
var options = that.options;
|
|
var shape = that.pointerShape(options.value);
|
|
var pointerPath = that.elements.children[0];
|
|
var oldShape = that.pointerShape(options._oldValue);
|
|
pointerPath.moveTo(shape[0]).lineTo(shape[1]).lineTo(shape[2]).lineTo(shape[3]).close();
|
|
var animation = new BarLinearPointerAnimation(pointerPath, deepExtend(options.animation, {
|
|
reverse: scale.options.reverse,
|
|
vertical: scale.options.vertical,
|
|
oldPoints: [
|
|
oldShape[1],
|
|
oldShape[2]
|
|
],
|
|
newPoints: [
|
|
shape[1],
|
|
shape[2]
|
|
]
|
|
}));
|
|
if (options.animation.transitions === false) {
|
|
animation.options.duration = 0;
|
|
}
|
|
animation.setup();
|
|
animation.play();
|
|
},
|
|
render: function () {
|
|
var that = this;
|
|
var group = new Group();
|
|
var elementOptions = that.getElementOptions();
|
|
var pointer = new Path({
|
|
stroke: elementOptions.stroke,
|
|
fill: elementOptions.fill
|
|
});
|
|
group.append(pointer);
|
|
that.elements = group;
|
|
return group;
|
|
}
|
|
});
|
|
var RadialPointerAnimation = draw.Animation.extend({
|
|
init: function (element, options) {
|
|
draw.Animation.fn.init.call(this, element, options);
|
|
options = this.options;
|
|
options.duration = math.max(math.abs(options.newAngle - options.oldAngle) / options.duration * 1000, 1);
|
|
},
|
|
options: {
|
|
easing: LINEAR,
|
|
duration: ANGULAR_SPEED
|
|
},
|
|
step: function (pos) {
|
|
var anim = this;
|
|
var options = anim.options;
|
|
var angle = interpolateValue(options.oldAngle, options.newAngle, pos);
|
|
anim.element.transform(geo.transform().rotate(angle, options.center));
|
|
}
|
|
});
|
|
draw.AnimationFactory.current.register(RADIAL_POINTER, RadialPointerAnimation);
|
|
var ArrowLinearPointerAnimation = draw.Animation.extend({
|
|
options: {
|
|
easing: LINEAR,
|
|
duration: LINEAR_SPEED
|
|
},
|
|
setup: function () {
|
|
var options = this.options;
|
|
var margin = options.margin;
|
|
var from = options.from;
|
|
var to = options.to;
|
|
var axis = options.vertical ? 'x1' : 'y1';
|
|
if (options.mirror == options.vertical) {
|
|
from[axis] -= margin;
|
|
to[axis] -= margin;
|
|
} else {
|
|
from[axis] += margin;
|
|
to[axis] += margin;
|
|
}
|
|
var fromScale = this.fromScale = new Point(from.x1, from.y1);
|
|
var toScale = this.toScale = new Point(to.x1, to.y1);
|
|
if (options.duration !== 0) {
|
|
options.duration = math.max(fromScale.distanceTo(toScale) / options.duration * 1000, 1);
|
|
}
|
|
},
|
|
step: function (pos) {
|
|
var translateX = interpolateValue(this.fromScale.x, this.toScale.x, pos);
|
|
var translateY = interpolateValue(this.fromScale.y, this.toScale.y, pos);
|
|
this.element.transform(geo.transform().translate(translateX, translateY));
|
|
}
|
|
});
|
|
draw.AnimationFactory.current.register(ARROW_POINTER, ArrowLinearPointerAnimation);
|
|
var BarLinearPointerAnimation = draw.Animation.extend({
|
|
options: {
|
|
easing: LINEAR,
|
|
speed: LINEAR_SPEED
|
|
},
|
|
setup: function () {
|
|
var options = this.options;
|
|
var newPoints = options.newPoints;
|
|
var oldPoints = options.oldPoints;
|
|
var axis = this.axis = options.vertical ? Y : X;
|
|
var to = this.to = newPoints[0][axis];
|
|
var from = this.from = oldPoints[0][axis];
|
|
if (options.duration !== 0) {
|
|
options.duration = math.max(math.abs(to - from) / options.speed * 1000, 1);
|
|
}
|
|
this._set(from);
|
|
},
|
|
step: function (pos) {
|
|
var value = interpolateValue(this.from, this.to, pos);
|
|
this._set(value);
|
|
},
|
|
_set: function (value) {
|
|
var setter = 'set' + this.axis.toUpperCase();
|
|
var points = this.options.newPoints;
|
|
points[0][setter](value);
|
|
points[1][setter](value);
|
|
}
|
|
});
|
|
draw.AnimationFactory.current.register(BAR_POINTER, BarLinearPointerAnimation);
|
|
function _buildLabel(label, options) {
|
|
var labelBox = label.box;
|
|
var textBox = label.children[0].box;
|
|
var border = options.border || {};
|
|
var background = options.background || '';
|
|
var elements = new Group();
|
|
var styleBox, styleGeometry, wrapper;
|
|
wrapper = Path.fromRect(new Rect([
|
|
labelBox.x1,
|
|
labelBox.y1
|
|
], [
|
|
labelBox.width(),
|
|
labelBox.height()
|
|
]), { stroke: {} });
|
|
var text = new Text(label.text, new Point(textBox.x1, textBox.y1), {
|
|
font: options.font,
|
|
fill: { color: options.color }
|
|
});
|
|
styleGeometry = _pad(text.bbox().clone(), options.padding);
|
|
styleBox = Path.fromRect(styleGeometry, {
|
|
stroke: {
|
|
color: border.width ? border.color : '',
|
|
width: border.width,
|
|
dashType: border.dashType,
|
|
lineJoin: 'round',
|
|
lineCap: 'round'
|
|
},
|
|
fill: { color: background }
|
|
});
|
|
elements.append(wrapper);
|
|
elements.append(styleBox);
|
|
elements.append(text);
|
|
return elements;
|
|
}
|
|
function getRange(range, min, max) {
|
|
var from = defined(range.from) ? range.from : MIN_VALUE;
|
|
var to = defined(range.to) ? range.to : MAX_VALUE;
|
|
range.from = math.max(math.min(to, from), min);
|
|
range.to = math.min(math.max(to, from), max);
|
|
return range;
|
|
}
|
|
function _pad(bbox, value) {
|
|
var origin = bbox.getOrigin();
|
|
var size = bbox.getSize();
|
|
var spacing = getSpacing(value);
|
|
bbox.setOrigin([
|
|
origin.x - spacing.left,
|
|
origin.y - spacing.top
|
|
]);
|
|
bbox.setSize([
|
|
size.width + (spacing.left + spacing.right),
|
|
size.height + (spacing.top + spacing.bottom)
|
|
]);
|
|
return bbox;
|
|
}
|
|
function _unpad(bbox, value) {
|
|
var spacing = getSpacing(value);
|
|
spacing.left = -spacing.left;
|
|
spacing.top = -spacing.top;
|
|
spacing.right = -spacing.right;
|
|
spacing.bottom = -spacing.bottom;
|
|
return _pad(bbox, spacing);
|
|
}
|
|
dataviz.ui.plugin(RadialGauge);
|
|
dataviz.ui.plugin(LinearGauge);
|
|
dataviz.ExportMixin.extend(Gauge.fn);
|
|
deepExtend(dataviz, {
|
|
Gauge: Gauge,
|
|
RadialPointer: RadialPointer,
|
|
LinearPointer: LinearPointer,
|
|
ArrowLinearPointer: ArrowLinearPointer,
|
|
BarLinearPointer: BarLinearPointer,
|
|
LinearScale: LinearScale,
|
|
RadialScale: RadialScale,
|
|
LinearGauge: LinearGauge,
|
|
RadialGauge: RadialGauge
|
|
});
|
|
}(window.kendo.jQuery));
|
|
return window.kendo;
|
|
}, typeof define == 'function' && define.amd ? define : function (a1, a2, a3) {
|
|
(a3 || a2)();
|
|
})); |