angular-sunburst-radar-chart
Version:
A Sunburst Radar chart with SVG,No Dependencies
948 lines (932 loc) • 49.9 kB
JavaScript
import { __read, __assign, __spread, __decorate } from 'tslib';
import { Input, Component, NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
function hashCode(obj) {
var h = 0;
obj = getOptionsOrEmpty(obj);
var s = JSON.stringify(obj);
for (var i = 0; i < s.length; i++) {
h = Math.imul(31, h) + s.charCodeAt(i) | 0;
}
return h;
}
function getOptionsOrEmpty(options) {
return options || {};
}
function getItemTitle(item) {
item = item || { name: '', value: '' };
var dash = item.name.length > 0 ? '-' : '';
return item.name + dash + item.value;
}
function clone(obj) {
return JSON.parse(JSON.stringify(obj));
}
function generateRandomColor() {
var letters = '0123456789ABCDEF';
var color = '#';
for (var i = 0; i < 6; i++) {
color += letters[(Math.floor(Math.random() * 16))];
}
return color;
}
function formatItems(items) {
return items.map(function (item) {
if (!!item.children && item.children.length > 0) {
}
else {
item['children'] = [];
item['children'].push({ name: '', value: 0 });
}
return item;
});
}
function getFormattedAngle(angle, center) {
var _a = __read([center.x, center.y], 2), centerX = _a[0], centerY = _a[1];
return 'rotate(' + angle + ' ' + centerX + ' ' + centerY + ')';
}
function getCurrentPointFromEvent(evt) {
var _a;
var _b = __read([evt.clientX, evt.clientY], 2), x = _b[0], y = _b[1];
if (evt.targetTouches && evt.targetTouches[0]) {
_a = __read([evt.targetTouches[0].pageX, evt.targetTouches[0].pageY], 2), x = _a[0], y = _a[1];
}
return { x: x, y: y };
}
function createCircle(options) {
var defaults = {
x: 0,
y: 0,
radius: 0,
fillColor: 'none',
'stroke-width': '1',
'stroke': '#000000',
'stroke-dasharray': 'none',
'stroke-opacity': '1',
'title': ''
};
options = __assign(__assign({}, defaults), (getOptionsOrEmpty(options)));
var circle = { name: 'circle', options: options, children: [] };
return circle;
}
function createLine(options) {
var defaults = { x1: 0, y1: 0, x2: 0, y2: 0, color: '#000000', width: '2', title: '' };
options = __assign(__assign({}, defaults), (getOptionsOrEmpty(options)));
var line = { name: 'line', options: options, children: [] };
return line;
}
function createPath(options) {
var defaults = { d: '', fill: 'none', stroke: 'none', 'stroke-width': '0', title: '', id: null };
options = __assign(__assign({}, defaults), (getOptionsOrEmpty(options)));
var d = options.d, color = options.color, borderColor = options.borderColor;
var path = { name: 'path', options: options, children: [] };
return path;
}
function createPathForBar(options) {
var defaults = {
d: '',
fill: 'none',
stroke: 'none',
'stroke-width': '0',
'stroke-opacity': '1.0',
'fill-opacity': '1.0',
title: '',
id: null
};
options = __assign(__assign({}, defaults), (getOptionsOrEmpty(options)));
var d = options.d, color = options.color, borderColor = options.borderColor;
var gradName = options['fill'];
gradName = gradName.replace('#', '');
options['gradientId'] = gradName;
options['fillUrl'] = 'url(#' + gradName + ')';
var path = { name: 'path-bar', options: options, children: [] };
return path;
}
function polarToCartesian(centerX, centerY, radius, angleInDegrees) {
var adjustedViewPortAngle = (angleInDegrees - 90);
var angleInRadians = adjustedViewPortAngle * Math.PI / 180.0;
return {
x: centerX + (radius * Math.cos(angleInRadians)),
y: centerY + (radius * Math.sin(angleInRadians))
};
}
function getLargeArcFlag(startAngle, endAngle) {
return (endAngle - startAngle) <= 180 ? '0' : '1';
}
function distanceBetweenTwoPoints(centerX, centerY, radius, startAngle, endAngle) {
var startPoint = polarToCartesian(centerX, centerY, radius, startAngle);
var endPoint = polarToCartesian(centerX, centerY, radius, endAngle);
var distFromStartToEnd = Math.sqrt(Math.pow((startPoint.x - endPoint.x), 2) + Math.pow((startPoint.y - endPoint.y), 2));
return Math.abs(distFromStartToEnd);
}
function calculateAngleRadian(_a) {
var x = _a.x, y = _a.y, centerX = _a.centerX, centerY = _a.centerY, maxRad = _a.maxRad;
var angleInRadian = Math.atan2(x - centerY, y - centerX);
angleInRadian = adjustAngleRadianDifference(angleInRadian, maxRad);
return angleInRadian;
}
function adjustAngleRadianDifference(input, maxRad) {
var angleInRadian = input;
angleInRadian += maxRad / 4;
if (angleInRadian < 0) {
angleInRadian += maxRad;
}
return angleInRadian;
}
function createArcToWriteText(_a) {
var startPoint = _a.startPoint, radius = _a.radius, id = _a.id, startAngle = _a.startAngle, endAngle = _a.endAngle;
var _b = __read([startPoint.x, startPoint.y], 2), centerX = _b[0], centerY = _b[1];
var start = polarToCartesian(centerX, centerY, radius, endAngle);
var end = polarToCartesian(centerX, centerY, radius, startAngle);
var largeArcFlag = getLargeArcFlag(startAngle, endAngle);
var d = [
'M', start.x, start.y,
'A', radius, radius, 0, largeArcFlag, 0, end.x, end.y
].join(' ');
return createPath({ d: d, borderColor: '', id: id });
}
function getTextForAngle(text, distance, fontSize) {
var result = text;
var perCharacter = 10.07;
if (fontSize < 18) {
perCharacter = 8.7;
}
var totalTextLength = Math.round(distance / perCharacter);
if (text.length > 0 && text.length > totalTextLength) {
result = text.substring(0, totalTextLength - 1) + '..';
}
return result;
}
function writeTextOnArc(options) {
var defaults = { text: '', label: '', pathId: '', 'font-size': '14px', };
options = __assign(__assign({}, defaults), (getOptionsOrEmpty(options)));
var text = options.text, pathId = options.pathId, label = options.label;
if (pathId !== '') {
options['href'] = '#' + pathId;
options['startOffset'] = '50%';
options['text-anchor'] = 'middle';
options['title'] = text;
}
var textOnArc = { name: 'text-on-arc', options: options, children: [] };
return textOnArc;
}
function createText(options) {
var defaults = {
content: '', x: 0, y: 0,
stroke: 'white',
'stroke-width': '1px',
'font-size': '6px',
'text-anchor': 'middle'
};
options = __assign(__assign({}, defaults), (getOptionsOrEmpty(options)));
var textElement = { name: 'text', options: options, children: [] };
return textElement;
}
function convertToPercentage(input) {
var plotMax = input.plotMax, actualScore = input.actualScore, maxScore = input.maxScore;
if (actualScore > maxScore) {
actualScore = maxScore;
}
var perValue = plotMax / maxScore;
return actualScore * perValue;
}
function createOuterChartBarWithInArc(_a) {
var item = _a.item, startAngle = _a.startAngle, endAngle = _a.endAngle, middleAngle = _a.middleAngle, color = _a.color, middleRadius = _a.middleRadius, maxScore = _a.maxScore, innerRadiusBorder = _a.innerRadiusBorder, center = _a.center;
var _b = __read([center.x, center.y], 2), centerX = _b[0], centerY = _b[1];
var currentVal = item.value;
var totalRadiusInside = middleRadius - innerRadiusBorder;
var innerRadius = convertToPercentage({ plotMax: totalRadiusInside, actualScore: currentVal, maxScore: maxScore });
var radiusFromCenter = innerRadius + innerRadiusBorder;
var firstPoint = polarToCartesian(centerX, centerY, radiusFromCenter, startAngle);
var secondPoint = polarToCartesian(centerX, centerY, radiusFromCenter, endAngle);
var startPoint = polarToCartesian(centerX, centerY, innerRadiusBorder, startAngle);
var endPoint = polarToCartesian(centerX, centerY, innerRadiusBorder, endAngle);
var startMiddlePoint = polarToCartesian(centerX, centerY, innerRadiusBorder, middleAngle);
var distFromStartToFirst = Math.sqrt(Math.pow((startPoint.x - firstPoint.x), 2) + Math.pow((startPoint.y - firstPoint.y), 2));
var distFromStartToSecond = Math.sqrt(Math.pow((startPoint.x - secondPoint.x), 2) + Math.pow((startPoint.y - secondPoint.y), 2));
var _c = getUpdatedPoints(firstPoint, secondPoint, distFromStartToFirst, distFromStartToSecond), updatedFirstPoint = _c.updatedFirstPoint, updatedSecondPoint = _c.updatedSecondPoint;
var d = getDrawPositions(updatedFirstPoint, middleRadius, updatedSecondPoint, endPoint, startMiddlePoint, startPoint);
var title = getItemTitle(item);
return createPathForBar({ d: d.join(' '), stroke: 'none', fill: color, "fill-opacity": '0.5', title: title });
}
function getDrawPositions(firstPoint, middleRadius, secondPoint, endPoint, startMiddlePoint, startPoint) {
var d = [
'M', firstPoint.x, firstPoint.y,
'A', middleRadius, middleRadius, 0, 0, 1, secondPoint.x, secondPoint.y,
'L', endPoint.x, endPoint.y,
'C', endPoint.x, endPoint.y, startMiddlePoint.x, startMiddlePoint.y, startPoint.x, startPoint.y,
'L', firstPoint.x, firstPoint.y,
'Z'
];
return d;
}
function getUpdatedPoints(firstPoint, secondPoint, distFromStartToFirst, distFromStartToSecond) {
var _a = __read([firstPoint, secondPoint], 2), updatedFirstPoint = _a[0], updatedSecondPoint = _a[1];
if (distFromStartToSecond < distFromStartToFirst) {
updatedSecondPoint = firstPoint;
updatedFirstPoint = secondPoint;
}
return { updatedSecondPoint: updatedSecondPoint, updatedFirstPoint: updatedFirstPoint };
}
function createInnerChartBarWithInArc(_a) {
var startPoint = _a.startPoint, item = _a.item, radius = _a.radius, startAngle = _a.startAngle, endAngle = _a.endAngle, maxScore = _a.maxScore;
var _b = __read([startPoint.x, startPoint.y], 2), centerX = _b[0], centerY = _b[1];
var currentVal = item.value;
var color = item.color;
var arcRadius = convertToPercentage({ plotMax: radius, actualScore: currentVal, maxScore: maxScore });
var start = polarToCartesian(centerX, centerY, arcRadius, endAngle);
var end = polarToCartesian(centerX, centerY, arcRadius, startAngle);
var largeArcFlag = getLargeArcFlag(startAngle, endAngle);
//const largeArcFlag = endAngle - startAngle <= 180 ? '0' : '1';
var d = [
'M', centerX, centerY,
'L', start.x, start.y,
'A', arcRadius, arcRadius, 0, largeArcFlag, 0, end.x, end.y
].join(' ');
var title = getItemTitle(item);
var arcForInnerChart = createPathForBar({ d: d, fill: color, title: title });
return arcForInnerChart;
}
function getRadiusForBorderAndText(radius, borderHeight) {
var borderRadius = radius + borderHeight;
var textRadius = radius + ((borderRadius - radius) / 2);
return [borderRadius, textRadius];
}
function getMaxDepth(items, currentLevel) {
if (currentLevel === void 0) { currentLevel = 0; }
var depths = [];
if (items && items.length > 0) {
var nextLevel_1 = currentLevel + 1;
depths = items
.filter(function (item) { return !!item.children; })
.filter(function (item) { return item.children.length > 0; })
.map(function (item) { return getMaxDepth(item.children, nextLevel_1); });
}
return depths.length !== 0 ? Math.max.apply(Math, __spread(depths)) : currentLevel;
}
function getGlobalPositions(_a) {
var size = _a.size, maxScore = _a.maxScore, items = _a.items;
var center = { x: size / 2, y: size / 2 };
var maxDepth = getMaxDepth(items);
var totalLevels = maxDepth + 1;
var innerCircleRadius = Math.abs(size / 5.33);
var totalRadiusToBeDrawn = 2 * Math.abs(size / 5.33);
var borderHeight = 0.0375 * size;
var everyLevelRadius = totalRadiusToBeDrawn / totalLevels;
var levels = [];
for (var i = 1; i <= totalLevels; i++) {
var startRadius = i * everyLevelRadius;
var _b = __read(getRadiusForBorderAndText(startRadius, borderHeight), 2), endRadius = _b[0], textRadius = _b[1];
levels.push({ startRadius: startRadius, endRadius: endRadius, textRadius: textRadius });
}
var innerRadius = innerCircleRadius;
var _c = __read(getRadiusForBorderAndText(innerRadius, borderHeight), 2), innerRadiusBorder = _c[0], innerTextRadius = _c[1];
var middleRadius = innerCircleRadius * 2;
var _d = __read(getRadiusForBorderAndText(middleRadius, borderHeight), 2), middleRadiusBorder = _d[0], middleTextRadius = _d[1];
var outerRadius = middleRadius + borderHeight;
var _e = __read(getRadiusForBorderAndText(outerRadius, borderHeight * 2), 2), outerRadiusBorder = _e[0], outerTextRadius = _e[1];
var textSize = 0.0175 * size;
var outerTextSize = 0.0225 * size;
var result = {
textSize: textSize,
outerTextSize: outerTextSize,
levels: levels,
innerRadius: innerRadius,
innerRadiusBorder: innerRadiusBorder,
innerTextRadius: innerTextRadius,
middleRadius: middleRadius,
middleTextRadius: middleTextRadius,
middleRadiusBorder: middleRadiusBorder,
outerRadius: outerRadius,
outerRadiusBorder: outerRadiusBorder,
outerTextRadius: outerTextRadius,
center: center
};
return result;
}
function calculatePointBetween(_a) {
var centerX = _a.centerX, centerY = _a.centerY, startAngle = _a.startAngle, middleAngle = _a.middleAngle, endAngle = _a.endAngle, radius = _a.radius;
var start = polarToCartesian(centerX, centerY, radius, startAngle);
var middle = polarToCartesian(centerX, centerY, radius, middleAngle);
var end = polarToCartesian(centerX, centerY, radius, endAngle);
return { start: start, middle: middle, end: end };
}
function createLegendWithOptions(_a) {
var startPoint = _a.startPoint, center = _a.center, startRadius = _a.startRadius, endRadius = _a.endRadius, degreeToBeDrawn = _a.degreeToBeDrawn, maxScore = _a.maxScore;
var _b = __read([center.x, center.y], 2), centerX = _b[0], centerY = _b[1];
var actRadius = endRadius - startRadius;
var axisIncrement = maxScore / 4;
var legendRadius = convertToPercentage({ plotMax: actRadius, actualScore: axisIncrement, maxScore: maxScore });
var smallCircleRadius = Math.round(0.083 * actRadius);
var smallCircleFontSize = Math.round(0.067 * actRadius);
var groups = [1, 2, 3]
.map(function (val) {
return { radius: val * legendRadius, content: Math.round(val * axisIncrement) };
})
.map(function (res) {
var radius = res.radius, content = res.content;
var _a = polarToCartesian(startPoint.x, startPoint.y, radius, degreeToBeDrawn), x = _a.x, y = _a.y;
var circle = createCircle({
x: x,
y: y,
radius: smallCircleRadius,
'fillColor': '#000000'
});
var legendCircle = createCircle({
x: centerX,
y: centerY,
radius: startRadius + radius,
'stroke-dasharray': 4,
'stroke-opacity': 0.3
});
var fontSize = smallCircleFontSize + "px";
//console.log("font-size",fontSize)
var text = createText({ content: content, x: x, y: y, 'stroke': 'white', 'font-size': fontSize });
return [circle, legendCircle, text];
});
return [].concat.apply([], groups);
}
function createLegends(_a) {
var startPoint = _a.startPoint, radius = _a.radius, degreeToBeDrawn = _a.degreeToBeDrawn, maxScore = _a.maxScore;
return createLegendWithOptions({ startPoint: startPoint, center: startPoint, startRadius: 0, endRadius: radius, degreeToBeDrawn: degreeToBeDrawn, maxScore: maxScore });
}
//Not Used now ,Might Use later
// function anglesBasedOnPercentage(items) {
//
// const total = items.reduce((prevValue, curValue) => prevValue +
//curValue, 0);
// if (Math.round(total) != 100) {
// console.error('Cannnot draw as the sum of values should be 100');
// throw new Error('Cannnot draw as the sum of values should be 100');
// }
// let prevDegree = 0;
// const results = [];
// for (let i = 0; i < items.length; i++) {
//
// const item = items[i];
// const currentDegree = item * 3.6;
//
// const degreeToBeDrawn = currentDegree + prevDegree;
// results.push(degreeToBeDrawn);
// prevDegree = prevDegree + currentDegree;
// }
//
//
// return results;
// }
//
function getInitialPosition(startLocation, totalDegrees, num) {
var perLocation = totalDegrees / num;
var middleLocation = perLocation / 2;
var startMiddle = startLocation + middleLocation;
return { startLocation: startLocation, perLocation: perLocation, middleLocation: middleLocation, startMiddle: startMiddle };
}
function getDegreeForIndexBasedOnSplitAngle(index, data) {
var perLocation = data.perLocation, middleLocation = data.middleLocation, startMiddle = data.startMiddle, startLocation = data.startLocation;
var position = index; // + 1;
var startDegree = startLocation + (position * perLocation);
var middleDegree = startMiddle + (position * perLocation);
var endDegree = startLocation + (position * perLocation) + perLocation;
return { startDegree: startDegree, middleDegree: middleDegree, endDegree: endDegree };
}
function getAllAnglesBasedOnChild(items) {
var num = items.length;
var results = [];
var totalChildren = items.filter(function (item) { return item.children; }).map(function (item) { return item.children.length; }).reduce((function (a, b) { return a + b; }), 0);
var childAngleDifference = 360 / totalChildren;
var currentStartLocation = 0;
for (var i = 0; i < items.length; i++) {
var item = items[i];
var childCount = item.children ? item.children.length : 0;
var totalDegrees = childCount * childAngleDifference;
var endDegree = currentStartLocation + (childCount * childAngleDifference);
var middleDegree = (endDegree - currentStartLocation) / 2;
var currentItem = {};
currentItem['item'] = item;
currentItem['startDegree'] = currentStartLocation;
currentItem['middleDegree'] = middleDegree;
currentItem['endDegree'] = endDegree;
if (childCount > 0) {
currentItem['children'] = iterateChildrenAndSetAngles({ children: item.children, currentItem: currentItem, angleDifference: totalDegrees });
}
currentStartLocation = currentStartLocation + (childCount * childAngleDifference);
results.push(currentItem);
}
return results;
}
function getAllAnglesBasedOnParent(items) {
var num = items.length;
var results = [];
var angleDifference = 360 / num;
var data = getInitialPosition(0, 360, num);
for (var i = 0; i < items.length; i++) {
var _a = getDegreeForIndexBasedOnSplitAngle(i, data), startDegree = _a.startDegree, middleDegree = _a.middleDegree, endDegree = _a.endDegree;
var item = items[i];
var currentItem = {};
currentItem['item'] = item;
currentItem['startDegree'] = startDegree;
currentItem['middleDegree'] = middleDegree;
currentItem['endDegree'] = endDegree;
var hasChildren = items.filter(function (item) { return !!item.children; }).length > 0;
if (hasChildren) {
currentItem['children'] = iterateChildrenAndSetAngles({ children: item.children, currentItem: currentItem, angleDifference: angleDifference });
}
results.push(currentItem);
}
return results;
}
function iterateChildrenAndSetAngles(_a) {
var children = _a.children, currentItem = _a.currentItem, angleDifference = _a.angleDifference;
var count = children.length;
var childItems = [];
var data = getInitialPosition(currentItem['startDegree'], angleDifference, count);
for (var j = 0; j < count; j++) {
var childItem = {};
childItem['item'] = children[j];
var _b = getDegreeForIndexBasedOnSplitAngle(j, data), startDegree = _b.startDegree, middleDegree = _b.middleDegree, endDegree = _b.endDegree;
childItem['startDegree'] = startDegree;
childItem['middleDegree'] = middleDegree;
childItem['endDegree'] = endDegree;
childItems.push(childItem);
}
return childItems;
}
function positionsOnAngles(centerX, centerY, radius, angels) {
var results = [];
for (var i = 0; i < angels.length; i++) {
var degreeToBeDrawn = angels[i];
results.push(polarToCartesian(centerX, centerY, radius, degreeToBeDrawn));
}
return results;
}
function getPointsOnCircleAtAngels(centerX, centerY, radius, angels) {
var results = [];
for (var i = 0; i < angels.length; i++) {
var degreeToBeDrawn = angels[i];
results.push(polarToCartesian(centerX, centerY, radius, degreeToBeDrawn));
}
return results;
}
function createSvgHandlerWithSelector(selectorName, center) {
var svg = document.querySelector(selectorName);
var pt = svg.createSVGPoint();
var maxRad = 6.283185307179586;
var maxDeg = 360;
return {
initPoint: 0,
cursorPoint: function (evt) {
var _a = getCurrentPointFromEvent(evt), x = _a.x, y = _a.y;
pt.x = x;
pt.y = y;
return pt.matrixTransform(svg.getScreenCTM().inverse());
},
startDrag: function (evt, initialPoint) {
this.previousPoint = this.angleFromCenter(evt);
this.initPoint = initialPoint;
},
updateInitPointFromCurrentPoint: function (currentPoint) {
var difference = Math.abs(this.previousPoint - currentPoint);
if (currentPoint < this.previousPoint) {
this.initPoint += difference;
}
else {
this.initPoint -= difference;
}
},
getRotationAngle: function (evt) {
var currentPoint = this.angleFromCenter(evt);
this.updateInitPointFromCurrentPoint(currentPoint);
this.previousPoint = currentPoint;
return this.initPoint;
},
angleFromCenter: function (evt) {
var _a = __read([center.x, center.y], 2), centerX = _a[0], centerY = _a[1];
var _b = this.cursorPoint(evt), x = _b.x, y = _b.y;
var angleInRadian = calculateAngleRadian({ x: x, y: y, centerX: centerX, centerY: centerY, maxRad: maxRad });
var currentDegree = maxDeg * angleInRadian / (2 * Math.PI);
return currentDegree;
}
};
}
var AngularSunburstRadarChartComponent = /** @class */ (function () {
function AngularSunburstRadarChartComponent() {
this.componentDisplayed = false;
this.showToolTip = false;
this.tooltipTopInPx = '0px';
this.tooltipLeftInPx = '0px';
this.tooltipText = '';
this.svgId = null;
this.svgGroupId = null;
this.svgHandler = null;
this.currentRotationAngle = 10;
this.svgCursor = 'default';
this.initialized = false;
this.innerBorderHeight = 30;
this.outerBorderHeight = 30;
this.elements = [];
this.hasChildren = false;
this.outerBorderCircleRef = 'outerBorderCircle';
this.error = null;
this.hasError = false;
this.startRotation = false;
}
AngularSunburstRadarChartComponent.prototype.showError = function (msg) {
this.error = msg;
this.hasError = true;
};
AngularSunburstRadarChartComponent.prototype.hideError = function () {
this.error = null;
this.hasError = false;
};
AngularSunburstRadarChartComponent.prototype.appendToSvg = function (element) {
this.elements.push(element);
};
AngularSunburstRadarChartComponent.prototype.ngOnChanges = function (changes) {
this.hideError();
var isFirstChange = Object.values(changes).some(function (c) { return c.isFirstChange(); });
this.modifyOnFirstChange(isFirstChange);
};
AngularSunburstRadarChartComponent.prototype.modifyOnFirstChange = function (isFirstChange) {
if (!isFirstChange) {
this.initialize();
}
};
AngularSunburstRadarChartComponent.prototype.ngOnInit = function () {
this.hideError();
this.initialize();
};
AngularSunburstRadarChartComponent.prototype.initialize = function () {
var _this = this;
var defaults = { size: 300, maxScore: 100, animateChart: true, splitBasedOnChildren: true, legendAxisLinePosition: 1 };
var options = __assign(__assign({}, defaults), (getOptionsOrEmpty(this.options)));
this.size = options.size;
this.maxScore = options.maxScore;
this.animateChart = options.animateChart;
this.splitBasedOnChildren = options.splitBasedOnChildren;
this.legendAxisLinePosition = options.legendAxisLinePosition;
if (!this.hasValidParameters()) {
this.showError('Input Values not set or Items was improper');
return;
}
this.initialized = false;
this.svgId = 'svg' + hashCode(this.items);
this.svgGroupId = 'svg-group' + hashCode(this.items);
this.viewBox = '0 0 ' + this.size + ' ' + this.size;
this.innerCircleRadius = Math.abs(this.size / 5.33);
this.innerBorderHeight = this.innerCircleRadius / 5;
this.outerBorderHeight = this.innerCircleRadius / 5;
this.globalPosition = getGlobalPositions({
size: this.size,
maxScore: this.maxScore,
items: this.items
});
this.hasChildren = this.items.filter(function (item) { return !!item.children; }).length > 0;
this.drawLayout();
var _a = this.globalPosition, innerRadius = _a.innerRadius, innerTextRadius = _a.innerTextRadius, textSize = _a.textSize, outerTextSize = _a.outerTextSize, outerRadiusBorder = _a.outerRadiusBorder, outerTextRadius = _a.outerTextRadius, center = _a.center;
var _b = __read([center.x, center.y], 2), centerX = _b[0], centerY = _b[1];
var items = this.items;
var allAngels = [];
var hasChildren = this.hasChildren;
if (this.splitBasedOnChildren) {
// Cannot have no children
items = formatItems(items);
allAngels = getAllAnglesBasedOnChild(items);
}
else {
allAngels = getAllAnglesBasedOnParent(items);
}
var angleDifference = 360 / items.length;
var angles = allAngels.map(function (value) { return value.startDegree; });
var middleAngles = allAngels.map(function (value) { return value.middleDegree; });
var points = positionsOnAngles(centerX, centerY, this.chartBorder, angles);
var lines = [];
var elements = [];
var nextLevelElements = [];
for (var i = 0; i < points.length; i++) {
var _c = points[i], x = _c.x, y = _c.y;
var endAngleIndex = i + 1;
if (endAngleIndex >= points.length) {
endAngleIndex = 0;
}
var endAngle = angles[endAngleIndex];
var startAngle = angles[i];
var middleAngle = middleAngles[i];
var item = items[i];
if (!!item.color === false) {
var colorDefaults = {
color: generateRandomColor()
};
item = __assign(__assign({}, colorDefaults), item);
}
if (this.hasChildren && item.children && item.children.length > 0) {
var childAngels = allAngels[i].children;
nextLevelElements = nextLevelElements.concat(this.drawOnLevel({
items: item.children,
totalDegrees: angleDifference,
childAngels: childAngels,
color: item.color
}));
}
lines.push(createLine({ x1: centerX, y1: centerY, x2: x, y2: y, width: 2 }));
// Create Arc for inner values
var barWithinArc = createInnerChartBarWithInArc({
startPoint: center,
item: item,
radius: innerRadius,
startAngle: startAngle,
endAngle: endAngle,
maxScore: this.maxScore
});
elements.push(barWithinArc);
var innerTextElements = this.addArcText({
arcForTextId: 'arc-text-inner' + this.getUniqueCode() + '-' + i,
radius: innerTextRadius,
fontSize: textSize,
startAngle: startAngle,
endAngle: endAngle,
perAngle: angleDifference,
item: item
});
elements = elements.concat(innerTextElements);
if (hasChildren) {
elements.push(this.drawOuterBackgroundWithMiddle({ item: item, startAngle: startAngle, middleAngle: middleAngle, endAngle: endAngle }));
var outerBackgroundTextElements = this.addArcText({
arcForTextId: 'arc-text-outer' + this.getUniqueCode() + '-' + i,
radius: outerTextRadius,
fontSize: outerTextSize,
perAngle: angleDifference,
startAngle: startAngle,
endAngle: endAngle,
item: item
});
elements = elements.concat(outerBackgroundTextElements);
}
}
nextLevelElements.forEach(function (line) {
_this.appendToSvg(line);
});
this.drawInnerBorders();
elements.forEach(function (line) {
_this.appendToSvg(line);
});
lines.forEach(function (line) {
_this.appendToSvg(line);
});
var legendAxisIndex = this.getLegendAxisIndex(angles);
this.drawLegends(angles[legendAxisIndex]);
this.addSmallCirclesAtCenter(centerX, centerY);
this.initialized = true;
this.currentRotationAngle = 10;
this.rotationPoint = getFormattedAngle(this.currentRotationAngle, center);
};
AngularSunburstRadarChartComponent.prototype.getLegendAxisIndex = function (angles) {
var legendAxisIndex = this.legendAxisLinePosition - 1;
if (legendAxisIndex < 0 || legendAxisIndex >= angles.length) {
legendAxisIndex = 0;
}
return legendAxisIndex;
};
AngularSunburstRadarChartComponent.prototype.hasValidParameters = function () {
return this.items && this.items.length > 1;
};
AngularSunburstRadarChartComponent.prototype.drawOuterBackgroundWithMiddle = function (_a) {
var item = _a.item, startAngle = _a.startAngle, middleAngle = _a.middleAngle, endAngle = _a.endAngle;
var color = item.color;
var _b = this.globalPosition, outerTextRadius = _b.outerTextRadius, center = _b.center;
var _c = __read([center.x, center.y], 2), centerX = _c[0], centerY = _c[1];
var middleCircle = calculatePointBetween({ centerX: centerX, centerY: centerY, startAngle: startAngle, middleAngle: middleAngle, endAngle: endAngle, radius: outerTextRadius });
var d = [
'M', middleCircle.start.x, middleCircle.start.y,
'A', outerTextRadius, outerTextRadius, 0, 0, 1, middleCircle.end.x, middleCircle.end.y
];
var title = item.name + '-' + item.value;
var strokeWidth = 0.0775 * this.size;
return createPath({ d: d.join(' '), stroke: color, 'stroke-width': strokeWidth, title: title });
};
AngularSunburstRadarChartComponent.prototype.drawOnLevel = function (_a) {
var items = _a.items, totalDegrees = _a.totalDegrees, childAngels = _a.childAngels, color = _a.color;
var _b = this.globalPosition, innerRadiusBorder = _b.innerRadiusBorder, middleRadius = _b.middleRadius, textSize = _b.textSize, middleTextRadius = _b.middleTextRadius, center = _b.center;
var _c = __read([center.x, center.y], 2), centerX = _c[0], centerY = _c[1];
var angles = childAngels.map(function (item) { return item.startDegree; });
var middleAngles = childAngels.map(function (item) { return item.middleDegree; });
var endAngles = childAngels.map(function (item) { return item.endDegree; });
var perAngle = totalDegrees / items.length;
var pointsOnInnerRadiusBorder = getPointsOnCircleAtAngels(centerX, centerY, innerRadiusBorder, angles);
var pointsOnMiddle = getPointsOnCircleAtAngels(centerX, centerY, middleRadius, angles);
var elements = [];
var lines = [];
var currentDegree = angles[0];
for (var i = 0; i < pointsOnInnerRadiusBorder.length; i++) {
var pointOnInnerRadiusBorder = pointsOnInnerRadiusBorder[i];
var pointOnMiddle = pointsOnMiddle[i];
lines.push(createLine({
x1: pointOnInnerRadiusBorder.x, y1: pointOnInnerRadiusBorder.y,
x2: pointOnMiddle.x, y2: pointOnMiddle.y, width: 0.5
}));
var startAngle = angles[i];
var middleAngle = middleAngles[i];
var endAngle = endAngles[i];
var item = items[i];
var params = {
startPoint: pointOnInnerRadiusBorder,
item: item,
startAngle: startAngle,
endAngle: endAngle,
middleAngle: middleAngle,
middleRadius: middleRadius,
innerRadiusBorder: innerRadiusBorder,
center: center,
maxScore: this.maxScore,
color: color,
index: i
};
var arcForChart = createOuterChartBarWithInArc(params);
elements.push(arcForChart);
var middleTextElements = this.addArcText({
arcForTextId: 'arc-text-middle' + this.getUniqueCode() + '-' + startAngle + i,
radius: middleTextRadius,
fontSize: textSize,
perAngle: perAngle,
startAngle: startAngle,
endAngle: endAngle,
item: item
});
elements = elements.concat(middleTextElements);
currentDegree = currentDegree + perAngle;
}
lines.forEach(function (line) {
elements.push(line);
});
return elements;
};
AngularSunburstRadarChartComponent.prototype.getUniqueCode = function () {
return hashCode(this.items) + '-' + this.size;
};
AngularSunburstRadarChartComponent.prototype.drawInnerBorders = function () {
var _a = this.globalPosition, innerRadius = _a.innerRadius, innerRadiusBorder = _a.innerRadiusBorder, center = _a.center;
var _b = __read([center.x, center.y], 2), centerX = _b[0], centerY = _b[1];
var innerContainer = createCircle({
x: centerX,
y: centerY,
radius: innerRadius,
fillColor: 'none'
});
var innerBorderContainer = createCircle({
x: centerX,
y: centerY,
radius: innerRadiusBorder,
fillColor: '#FFFFFF'
});
this.appendToSvg(innerBorderContainer);
this.appendToSvg(innerContainer);
};
AngularSunburstRadarChartComponent.prototype.addSmallCirclesAtCenter = function (centerX, centerY) {
var outerRadius = 0.0025 * 2 * this.size;
var innerRadius = 0.0005 * 2 * this.size;
this.appendToSvg(createCircle({
x: centerX,
y: centerY,
radius: outerRadius,
fillColor: '#FFFFFF'
}));
this.appendToSvg(createCircle({
x: centerX,
y: centerY,
radius: innerRadius,
fillColor: '#FFFFFF'
}));
};
AngularSunburstRadarChartComponent.prototype.drawLegends = function (degreeToBeDrawn) {
var _this = this;
var _a = this.globalPosition, innerRadius = _a.innerRadius, innerRadiusBorder = _a.innerRadiusBorder, middleRadius = _a.middleRadius, center = _a.center;
var _b = __read([center.x, center.y], 2), centerX = _b[0], centerY = _b[1];
var maxScore = this.maxScore;
var legends = createLegends({ startPoint: center, radius: innerRadius, degreeToBeDrawn: degreeToBeDrawn, maxScore: maxScore });
var startFrom = polarToCartesian(centerX, centerY, innerRadiusBorder, degreeToBeDrawn);
if (this.hasChildren) {
var nextLevelLegends = createLegendWithOptions({
startPoint: startFrom,
center: center,
startRadius: innerRadiusBorder,
endRadius: middleRadius,
maxScore: maxScore,
degreeToBeDrawn: degreeToBeDrawn
});
legends = legends.concat(nextLevelLegends);
}
legends.forEach(function (elem) {
_this.appendToSvg(elem);
});
};
AngularSunburstRadarChartComponent.prototype.addArcText = function (_a) {
var arcForTextId = _a.arcForTextId, radius = _a.radius, startAngle = _a.startAngle, fontSize = _a.fontSize, endAngle = _a.endAngle, perAngle = _a.perAngle, item = _a.item;
var elements = [];
var center = this.globalPosition.center;
var _b = __read([center.x, center.y], 2), centerX = _b[0], centerY = _b[1];
var arcForText = createArcToWriteText({ id: arcForTextId, startPoint: center, radius: radius, startAngle: startAngle, endAngle: endAngle });
elements.push(arcForText);
var distance = distanceBetweenTwoPoints(centerX, centerY, radius, startAngle, endAngle);
var label = getTextForAngle(item.name, distance, fontSize);
elements.push(writeTextOnArc({ label: label, text: item.name, pathId: arcForTextId, 'font-size': fontSize + 'px' }));
return elements;
};
AngularSunburstRadarChartComponent.prototype.drawLayout = function () {
var _a = this.globalPosition, innerRadius = _a.innerRadius, innerRadiusBorder = _a.innerRadiusBorder, middleRadius = _a.middleRadius, middleRadiusBorder = _a.middleRadiusBorder, outerRadius = _a.outerRadius, outerRadiusBorder = _a.outerRadiusBorder, center = _a.center;
var _b = __read([center.x, center.y], 2), centerX = _b[0], centerY = _b[1];
var innerRadiusEnd = innerRadius;
var innerRadiusBorderEnd = innerRadiusBorder;
this.chartBorder = innerRadiusBorder;
if (this.hasChildren) {
var outerBorderCircle = createCircle({
x: centerX,
y: centerY,
radius: outerRadiusBorder,
fillColor: 'none',
'stroke-width': '5',
ref: this.outerBorderCircleRef
});
this.appendToSvg(outerBorderCircle);
var outerCircle = createCircle({
x: centerX,
y: centerY,
radius: outerRadius,
fillColor: 'none'
});
this.appendToSvg(outerCircle);
innerRadiusEnd = middleRadius;
innerRadiusBorderEnd = middleRadiusBorder;
this.chartBorder = outerRadiusBorder;
}
this.appendToSvg(createCircle({ x: centerX, y: centerY, radius: innerRadiusEnd }));
this.appendToSvg(createCircle({ x: centerX, y: centerY, radius: innerRadiusBorderEnd }));
};
AngularSunburstRadarChartComponent.prototype.hideTooltip = function () {
this.showToolTip = false;
};
AngularSunburstRadarChartComponent.prototype.showTooltipText = function ($event, text) {
this.tooltipLeftInPx = $event.pageX + 10 + 'px';
this.tooltipTopInPx = $event.pageY + 10 + 'px';
this.tooltipText = text;
this.showToolTip = true;
};
AngularSunburstRadarChartComponent.prototype.onOutOfComponent = function () {
this.hideTooltip();
this.stopRotate();
};
AngularSunburstRadarChartComponent.prototype.stopRotate = function () {
this.svgCursor = 'default';
this.startRotation = false;
};
AngularSunburstRadarChartComponent.prototype.startRotate = function ($event) {
this.startRotation = true;
this.svgCursor = 'grab';
var _a = this.globalPosition, outerRadiusBorder = _a.outerRadiusBorder, center = _a.center;
this.svgHandler = createSvgHandlerWithSelector('#' + this.svgId, center);
this.svgHandler.startDrag($event, this.currentRotationAngle);
$event.preventDefault();
};
AngularSunburstRadarChartComponent.prototype.rotateChart = function ($event) {
if (this.startRotation == false) {
return;
}
this.svgCursor = 'grabbing';
var center = this.globalPosition.center;
this.currentRotationAngle = this.svgHandler.getRotationAngle($event);
this.rotationPoint = getFormattedAngle(Math.round(this.currentRotationAngle), center);
};
__decorate([
Input()
], AngularSunburstRadarChartComponent.prototype, "items", void 0);
__decorate([
Input()
], AngularSunburstRadarChartComponent.prototype, "options", void 0);
AngularSunburstRadarChartComponent = __decorate([
Component({
selector: 'lib-sunburst-radar-chart',
template: "<ng-container (mouseout)=\"onOutOfComponent();\">\n\n\n <div *ngIf=\"hasError\" style=\" color: #a94442;\n background-color: #f2dede;\n border-color: #ebccd1;\n margin-top: 5px;\npadding: 15px;\n margin-bottom: 20px;\n border: 1px solid transparent;\n border-radius: 4px;\n\">\n <strong>Error!</strong> {{error}}\n </div>\n\n\n\n<div class=\"app-tooltip\" *ngIf=\"showToolTip\" style=\"position: absolute; display: block;background: cornsilk; border: 1px solid black; border-radius: 5px; padding: 5px; z-index: 1002;\"\n\n [style.left]=\"tooltipLeftInPx\" [style.top]=\"tooltipTopInPx\" >\n {{tooltipText}}\n</div>\n\n<svg [attr.id]=\"svgId\"\n [attr.height]=\"size\"\n [attr.width]=\"size\"\n [attr.viewBox]=\"viewBox\"\n [style.cursor]=\"svgCursor\"\n xmlns=\"http://www.w3.org/2000/svg\">\n\n\n\n\n <animateTransform\n *ngIf=\"animateChart\"\n attributeName=\"transform\"\n begin=\"4s\"\n dur=\"500ms\"\n type=\"rotate\"\n from=\"0\"\n to=\"10\"\n\n additive=\"sum\"\n fill=\"freeze\"\n repeatCount=\"1\"\n />\n\n\n<g\n (mousemove)=\"rotateChart($event);\"\n (mousedown)=\"startRotate($event)\"\n (mouseup)=\"stopRotate()\"\n (touchmove)=\"rotateChart($event);\"\n (touchstart)=\"startRotate($event)\"\n (touchend)=\"stopRotate()\"\n [attr.transform]=\"rotationPoint\"\n [attr.id]=\"svgGroupId\"\n\n\n >\n <ng-container *ngFor=\"let element of elements\" >\n\n\n\n <ng-container [ngSwitch]=\"element.name\" >\n\n\n <circle *ngSwitchCase=\"'circle'\" [attr.cx]=\"element.options.x\" [attr.cy]=[element.options.y]\n [attr.r]=\"element.options.radius\"\n [attr.stroke-width]=\"element.options['stroke-width']\"\n [attr.stroke]=\"element.options['stroke']\"\n [attr.stroke-dasharray]=\"element.options['stroke-dasharray']\"\n [attr.stroke-opacity]=\"element.options['stroke-opacity']\"\n [attr.fill]=\"element.options['fillColor']\"\n >\n\n\n\n\n </circle>\n\n <path *ngSwitchCase=\"'path'\" [attr.d]=\"element.options.d\" [attr.fill]=[element.options.fill]\n\n [attr.stroke]=\"element.options['stroke']\"\n [attr.stroke-width]=\"element.options['stroke-width']\"\n [attr.id]=\"element.options['id']\"\n (mousemove)=\"showTooltipText($event, element.options['title']);\"\n (mouseout)=\"hideTooltip()\" >\n\n\n\n\n\n </path>\n\n<g *ngSwitchCase=\"'path-bar'\" >\n\n\n\n <path [attr.d]=\"element.options.d\"\n [attr.fill]=[element.options.fill]\n\n [attr.stroke]=\"element.options['stroke']\"\n [attr.stroke-width]=\"element.options['stroke-width']\"\n [attr.stroke-opacity]=\"element.options['stroke-opacity']\"\n [attr.fill-opacity]=\"element.options['fill-opacity']\"\n [attr.id]=\"element.options['id']\"\n (mousemove)=\"showTooltipText($event, element.options['title']);\" (mouseout)=\"hideTooltip()\" >\n\n\n\n\n <ng-container\n\n *ngIf=\"animateChart\"\n >\n\n <animate\n attributeName=\"fill\"\n [attr.from]=\"element.options['fill']\"\n to=\"transparent\"\n dur=\"1ms\"\n fill=\"freeze\" />\n <animate\n attributeName=\"stroke\"\n [attr.from]=\"element.options['fill']\"\n [attr.to]=\"element.options['fill']\"\n dur=\"1ms\"\n fill=\"freeze\" />\n <animate\n attributeName=\"stroke-width\"\n from=\"8\"\n to=\"8\"\n dur=\"1ms\"\n fill=\"freeze\" />\n <animate\n attributeName=\"stroke-dasharray\"\n from=\"1000\"\n to=\"1000\"\n dur=\"1ms\"\n fill=\"freeze\" />\n\n\n <animate\n attributeName=\"fill\"\n from=\"#FFFFFF\"\n [attr.to]=\"element.options['fill']\"\n begin=\"2s\"\n dur=\"3s\"\n fill=\"freeze\" />\n\n <animate\n attributeName=\"stroke-dashoffset\"\n from=\"1000\"\n to=\"0\"\n begin=\"1ms\"\n dur=\"3s\"\n fill=\"freeze\" />\n\n <animate\n attributeName=\"stroke-width\"\n from=\"8\"\n [attr.to]=\"element.options['stroke']\"\n begin=\"3s\"\n dur=\"1s\"\n fill=\"freeze\" />\n </ng-container>\n </path>\n\n\n\n\n</g>\n\n <text *ngSwitchCase=\"'text-on-arc'\"\n [attr.font-size]=\"element.options['font-size']\"\n\n >\n <textPath\n [attr.href]=\"element.options.href\"\n [attr.startOffset]=\"element.options.startOffset\"\n [attr.text-anchor]=\"element.options['text-anchor']\"\n >{{element.options['label']}}</textPath>\n <title>{{element.options['title']}}</title>\n\n </text>\n\n\n <line *ngSwitchCase=\"'line'\"\n [attr.x1]=\"element.options.x1\"\n [attr.y1]=\"element.options.y1\"\n [attr.x2]=\"element.options.x2\"\n [attr.y2]=\"element.options.y2\"\n [attr.stroke-width]=\"element.options.width\"\n\n [attr.stroke]=\"element.options['color']\" >\n <title>{{element.options['title']}}</title>\n </line>\n\n\n <text *ngSwitchCase=\"'text'\"\n [attr.x]=\"element.options.x\"\n [attr.y]=\"element.options.y\"\n [attr.stroke]=\"element.options.stroke\"\n [attr.stroke-width]=\"element.options['stroke-width']\"\n [attr.font-size]=\"element.options['font-size']\"\n [attr.text-anchor]=\"element.options['text-anchor']\"\n >{{element.options.content}}\n <title>{{element.options['content']}}</title>\n </text>\n\n </ng-container>\n\n\n\n </ng-container>\n\n\n </g>\n</svg>\n</ng-container>\n",
styles: [".app-tooltip{background:#fff8dc;border:1px solid #000;border-radius:5px;padding:5px;z-index:1002}.growAnimation{-moz-transition:transform 2s ease-in-out;-webkit-transition:transform 2s ease-in-out;-o-transition:transform 2s ease-in-out;transform:scale(1)}.growAnimation:active{transform:scale(.5)}"]
})
], AngularSunburstRadarChartComponent);
return AngularSunburstRadarChartComponent;
}());
var AngularSunburstRadarChartModule = /** @class */ (function () {
function AngularSunburstRadarChartModule() {
}
AngularSunburstRadarChartModule = __decorate([
NgModule({
declarations: [AngularSunburstRadarChartComponent],
imports: [
CommonModule
],
exports: [AngularSunburstRadarChartComponent]
})
], AngularSunburstRadarChartModule);
return AngularSunburstRadarChartModule;
}());
/*
* Public API Surface of angular-sunburst-radar-chart
*/
/**
* Generated bundle index. Do not edit.
*/
export { AngularSunburstRadarChartComponent, AngularSunburstRadarChartModule };
//# sourceMappingURL=angular-sunburst-radar-chart.js.map