rumble-charts
Version:
Truly declarative React charts components
120 lines (117 loc) • 6.32 kB
JavaScript
import { __assign } from './external/tslib/tslib.es6.js';
import React, { useState, useEffect } from 'react';
import { scaleLinear } from 'd3-scale';
import cloud from 'd3-cloud';
import { colorFunc, defaultSchemeName } from './helpers/colorFunc.js';
import 'd3-shape';
import 'd3-ease';
import { isUndefined } from './helpers/isUndefined.js';
import { value } from './helpers/value.js';
/**
* Renders cloud of tags/keywords. Uses [d3-cloud](https://www.npmjs.com/package/d3-cloud) for calculations.
* Please notice, `series` data points should have `label` attribute. See example below.
*/
function Cloud(props) {
var _a;
var className = props.className, layerWidth = props.layerWidth, layerHeight = props.layerHeight, _b = props.colors, colors = _b === void 0 ? defaultSchemeName : _b;
var _c = useState({
labels: [],
series: []
}), state = _c[0], setState = _c[1];
useEffect(function () {
var layerWidth = props.layerWidth, layerHeight = props.layerHeight, series = props.series, minY = props.minY, maxY = props.maxY, canvas = props.canvas, _a = props.font, font = _a === void 0 ? 'serif' : _a, _b = props.minFontSize, minFontSize = _b === void 0 ? 10 : _b, _c = props.maxFontSize, maxFontSize = _c === void 0 ? 100 : _c, _d = props.timeInterval, timeInterval = _d === void 0 ? 15 : _d, _e = props.fontStyle, fontStyle = _e === void 0 ? 'normal' : _e, _f = props.fontWeight, fontWeight = _f === void 0 ? 'normal' : _f, rotate = props.rotate, _g = props.spiral, spiral = _g === void 0 ? 'archimedean' : _g, _h = props.padding, padding = _h === void 0 ? 1 : _h, random = props.random;
var scale = scaleLinear()
.range([minFontSize, maxFontSize])
.domain([minY, maxY]);
var words = (series === null || series === void 0 ? void 0 : series.reduce(function (words, _a, seriesIndex) {
var data = _a.data;
data.forEach(function (point, pointIndex) {
words.push(__assign(__assign({}, point), { text: point.label, size: point.y, seriesIndex: seriesIndex, pointIndex: pointIndex }));
});
return words;
}, [])) || [];
var cl = cloud()
.size([layerWidth, layerHeight])
.words(words)
.font(font)
.fontStyle(fontStyle)
.fontWeight(fontWeight)
.spiral(spiral)
.padding(padding)
.timeInterval(timeInterval)
.fontSize(function (p) { return scale(p.size); });
if (!isUndefined(rotate)) {
cl.rotate(rotate);
}
if (random) {
cl.random(random);
}
if (canvas) {
cl.canvas(canvas);
}
cl.on('end', function (cloudLabels) {
var labels = cloudLabels.reduce(function (labels, label) {
labels[label.seriesIndex] = labels[label.seriesIndex] || [];
labels[label.seriesIndex][label.pointIndex] = label;
return labels;
}, []);
setState({ series: series, labels: labels });
});
cl.start();
}, [
setState, layerWidth, layerHeight,
props.series, props.minY, props.maxY, props.canvas, props.timeInterval,
props.font, props.minFontSize, props.maxFontSize, props.fontStyle, props.fontWeight,
props.rotate, props.spiral, props.padding, props.random
]);
var color = colorFunc(colors);
return React.createElement("g", { className: className, style: props.style, opacity: props.opacity, transform: 'translate(' + (layerWidth / 2) + ',' + (layerHeight / 2) + ')' }, (_a = state.series) === null || _a === void 0 ? void 0 : _a.map(function (series, seriesIndex) {
if ('seriesVisible' in props) {
var seriesVisible = value(props.seriesVisible, { seriesIndex: seriesIndex, series: series, props: props });
if (!seriesVisible) {
return;
}
}
var seriesAttributes = value(props.seriesAttributes, {
seriesIndex: seriesIndex,
series: series,
props: props
});
var seriesStyle = value(props.seriesStyle, { seriesIndex: seriesIndex, series: series, props: props });
return React.createElement("g", __assign({ key: seriesIndex, className: className && (className + '-series ' + className + '-series-' + seriesIndex), style: seriesStyle, opacity: series.opacity }, seriesAttributes), series.data.map(function (point, pointIndex) {
var _a, _b;
var label = (_b = (_a = state.labels) === null || _a === void 0 ? void 0 : _a[seriesIndex]) === null || _b === void 0 ? void 0 : _b[pointIndex];
if (!label) {
return;
}
if ('labelVisible' in props) {
var labelVisible = value(props.labelVisible, {
seriesIndex: seriesIndex,
pointIndex: pointIndex,
point: point,
label: label,
series: series,
props: props
});
if (!labelVisible) {
return;
}
}
var labelAttributes = value(props.labelAttributes, {
seriesIndex: seriesIndex,
pointIndex: pointIndex,
point: point,
label: label,
series: series,
props: props
});
var labelStyle = value([point.style, series.style, props.labelStyle], { seriesIndex: seriesIndex, pointIndex: pointIndex, point: point, label: label, series: series, props: props });
return React.createElement("g", { key: pointIndex, className: className && (className + '-label ' + className + '-label-' + +pointIndex), style: {
fontSize: label.size + 'px',
fontFamily: label.font
} },
React.createElement("text", __assign({ transform: 'translate(' + label.x + ',' + label.y + '),rotate(' + label.rotate + ')', fill: point.color || series.color || color(seriesIndex), fillOpacity: point.opacity, textAnchor: 'middle', style: labelStyle }, labelAttributes), label.text));
}));
}));
}
export { Cloud };