@carbon/charts
Version:
Carbon charting components
302 lines • 12.5 kB
JavaScript
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
// Internal Imports
import { Component } from '../component';
import { DOMUtils } from '../../services';
import { Events, ColorClassNameTypes } from '../../interfaces';
import { Tools } from '../../tools';
// D3 Imports
import { hierarchy as d3Hierarchy, treemap as d3Treemap } from 'd3-hierarchy';
import { sum } from 'd3-array';
import { hsl, color } from 'd3-color';
import { select } from 'd3-selection';
// Carbon colors
import { colors } from '@carbon/colors';
var findColorShade = function (hex) {
if (!hex) {
return null;
}
for (var _i = 0, _a = Object.keys(colors); _i < _a.length; _i++) {
var colorName = _a[_i];
var colorShades = colors[colorName];
for (var _b = 0, _c = Object.keys(colorShades); _b < _c.length; _b++) {
var colorShadeLevel = _c[_b];
var colorShade = colorShades[colorShadeLevel];
if (colorShade === hex) {
return colorShadeLevel;
}
}
}
return null;
};
var textFillColor = function () {
var correspondingLeaf = select(this.parentNode).select('rect.leaf');
var correspondingLeafFill = getComputedStyle(correspondingLeaf.node(), null).getPropertyValue('fill');
var cl = color(correspondingLeafFill);
var colorShade;
if (cl) {
colorShade = findColorShade(cl ? cl.hex() : null);
}
if (colorShade === null || colorShade === undefined) {
var lightness = hsl(cl).l;
colorShade = Math.abs(lightness * 100 - 100);
}
return colorShade > 50 ? 'white' : 'black';
};
var uidCounter = 0;
var Treemap = /** @class */ (function (_super) {
__extends(Treemap, _super);
function Treemap() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.type = 'treemap';
_this.handleLegendOnHover = function (event) {
var hoveredElement = event.detail.hoveredElement;
_this.parent
.selectAll("g[data-name='leaf']")
.transition(_this.services.transitions.getTransition('legend-hover-treemap'))
.attr('opacity', function (d) {
return d.parent.data.name === hoveredElement.datum()['name'] ? 1 : 0.3;
});
};
_this.handleLegendMouseOut = function (event) {
_this.parent
.selectAll("g[data-name='leaf']")
.transition(_this.services.transitions.getTransition('legend-mouseout-treemap'))
.attr('opacity', 1);
};
return _this;
}
Treemap.prototype.init = function () {
var events = this.services.events;
// Highlight correct circle on legend item hovers
events.addEventListener(Events.Legend.ITEM_HOVER, this.handleLegendOnHover);
// Un-highlight circles on legend item mouseouts
events.addEventListener(Events.Legend.ITEM_MOUSEOUT, this.handleLegendMouseOut);
};
Treemap.prototype.render = function (animate) {
var _this = this;
if (animate === void 0) { animate = true; }
var svg = this.getContainerSVG();
var allData = this.model.getData();
var displayData = this.model.getDisplayData();
var options = this.model.getOptions();
var windowLocation = Tools.getProperty(window, 'location');
var _a = DOMUtils.getSVGElementSize(this.parent, {
useAttrs: true,
}), width = _a.width, height = _a.height;
var hierarchy = d3Hierarchy({
name: options.title || 'Treemap',
children: displayData,
})
.sum(function (d) { return d.value; })
.sort(function (a, b) { return b.value - a.value; });
var total = sum(allData, function (d) {
return sum(d.children, function (child) { return child.value; });
});
var root = d3Treemap()
.size([width, height])
.paddingInner(1)
.paddingOuter(0)
.round(true)(hierarchy);
var transitions = this.services.transitions;
var leafGroups = svg
.selectAll("g[data-name='leaf']")
.data(root.leaves(), function (leaf) { return leaf.data.name; });
// Remove leaf groups that need to be removed
leafGroups.exit().attr('opacity', 0).remove();
// Add the leaf groups that need to be introduced
var enteringLeafGroups = leafGroups
.enter()
.append('g')
.attr('data-name', 'leaf')
.attr('data-uid', function () { return uidCounter++; });
var allLeafGroups = enteringLeafGroups.merge(leafGroups);
allLeafGroups
.attr('data-name', 'leaf')
.transition(transitions.getTransition('treemap-group-update', animate))
.attr('transform', function (d) { return "translate(" + d.x0 + "," + d.y0 + ")"; });
var rects = allLeafGroups.selectAll('rect.leaf').data(function (d) { return [d]; });
rects.exit().attr('width', 0).attr('height', 0).remove();
var enteringRects = rects
.enter()
.append('rect')
.classed('leaf', true);
enteringRects
.merge(rects)
.attr('width', 0)
.attr('height', 0)
.attr('id', function () {
var uid = select(this.parentNode).attr('data-uid');
return options.style.prefix + "-leaf-" + uid;
})
.attr('class', function (d) {
while (d.depth > 1)
d = d.parent;
return _this.model.getColorClassName({
classNameTypes: [ColorClassNameTypes.FILL],
dataGroupName: d.data.name,
originalClassName: 'leaf',
});
})
.transition(this.services.transitions.getTransition('treemap-leaf-update-enter', animate))
.attr('width', function (d) { return d.x1 - d.x0; })
.attr('height', function (d) { return d.y1 - d.y0; })
.style('fill', function (d) {
while (d.depth > 1)
d = d.parent;
return _this.model.getFillColor(d.data.name);
});
// Update all clip paths
allLeafGroups
.selectAll('clipPath')
.data(function (d) {
if (d.data.showLabel !== true) {
return [];
}
return [1];
}, function (d) { return d; })
.join(function (enter) {
enter
.append('clipPath')
.attr('id', function () {
var uid = select(this.parentNode).attr('data-uid');
return options.style.prefix + "-clip-" + uid;
})
.append('use')
.attr('xlink:href', function () {
var uid = select(this.parentNode.parentNode).attr('data-uid');
var leafID = options.style.prefix + "-leaf-" + uid;
return new URL("#" + leafID, windowLocation) + '';
});
}, function (update) { return null; }, function (exit) { return exit.remove(); });
// Update all titles
allLeafGroups
.selectAll('text')
.data(function (d) {
if (d.data.showLabel !== true) {
return [];
}
var parent = d;
while (parent.depth > 1)
parent = parent.parent;
var color = hsl(_this.model.getFillColor(parent.data.name));
return [
{
text: d.data.name,
color: color.l < 0.5 ? 'white' : 'black',
},
];
}, function (d) { return d; })
.join(function (enter) {
var addedText = enter
.append('text')
.text(function (d) { return d.text; })
.style('fill', textFillColor)
.attr('x', 7)
.attr('y', 18);
if (windowLocation) {
addedText.attr('clip-path', function () {
var uid = select(this.parentNode).attr('data-uid');
var clipPathID = options.style.prefix + "-clip-" + uid;
return "url(" + (new URL("#" + clipPathID, windowLocation) + '') + ")";
});
}
}, function (update) {
return update.text(function (d) { return d.text; }).style('fill', textFillColor);
}, function (exit) { return exit.remove(); });
// Add event listeners to elements drawn
this.addEventListeners();
};
Treemap.prototype.addEventListeners = function () {
var self = this;
this.parent
.selectAll('rect.leaf')
.on('mouseover', function (datum) {
var hoveredElement = select(this);
var fillColor = getComputedStyle(this, null).getPropertyValue('fill');
var parent = datum;
while (parent.depth > 1)
parent = parent.parent;
hoveredElement
.transition(self.services.transitions.getTransition('graph_element_mouseover_fill_update'))
.style('fill', function (d) {
var customColor = self.model.getFillColor(d.parent.data.name);
if (customColor) {
fillColor = customColor;
}
return color(fillColor).darker(0.7).toString();
});
// Show tooltip
self.services.events.dispatchEvent(Events.Tooltip.SHOW, {
hoveredElement: hoveredElement,
items: [
{
color: fillColor,
label: parent.data.name,
bold: true,
},
{
label: datum.data.name,
value: datum.data.value,
},
],
});
// Dispatch mouse event
self.services.events.dispatchEvent(Events.Treemap.LEAF_MOUSEOVER, {
element: hoveredElement,
datum: datum,
});
})
.on('mousemove', function (datum) {
var hoveredElement = select(this);
// Dispatch mouse event
self.services.events.dispatchEvent(Events.Treemap.LEAF_MOUSEMOVE, {
element: hoveredElement,
datum: datum,
});
self.services.events.dispatchEvent(Events.Tooltip.MOVE);
})
.on('click', function (datum) {
// Dispatch mouse event
self.services.events.dispatchEvent(Events.Treemap.LEAF_CLICK, {
element: select(this),
datum: datum,
});
})
.on('mouseout', function (datum) {
var hoveredElement = select(this);
hoveredElement.classed('hovered', false);
var parent = datum;
while (parent.depth > 1)
parent = parent.parent;
hoveredElement
.transition(self.services.transitions.getTransition('graph_element_mouseout_fill_update'))
.style('fill', function (d) {
return self.model.getFillColor(d.parent.data.name);
});
// Dispatch mouse event
self.services.events.dispatchEvent(Events.Treemap.LEAF_MOUSEOUT, {
element: hoveredElement,
datum: datum,
});
// Hide tooltip
self.services.events.dispatchEvent(Events.Tooltip.HIDE, {
hoveredElement: hoveredElement,
});
});
};
return Treemap;
}(Component));
export { Treemap };
//# sourceMappingURL=../../../src/components/graphs/treemap.js.map