@amcharts/amcharts5
Version:
amCharts 5
653 lines • 20.1 kB
JavaScript
import { Theme } from "../core/Theme";
import { MultiDisposer } from "../core/util/Disposer";
import { p100, percent } from "../core/util/Percent";
import * as $array from "../core/util/Array";
/**
* A configurable theme that dynamically adapts chart settings for best fit
* in available space.
*
* @see {@link https://www.amcharts.com/docs/v5/concepts/responsive/} for more info
*/
export class ResponsiveTheme extends Theme {
constructor(root, isReal) {
super(root, isReal);
/**
* Currently added rules.
*/
this.responsiveRules = [];
this._dp = new MultiDisposer([
this._root._rootContainer.onPrivate("width", (_width) => {
if (this._isUsed()) {
this._maybeApplyRules();
}
}),
this._root._rootContainer.onPrivate("height", (_height) => {
if (this._isUsed()) {
this._maybeApplyRules();
}
})
]);
}
// Breakpoint functions (for use in `relevant` clause of the responsive rules)
static widthXXS(width, _height) {
return width <= ResponsiveTheme.XXS;
}
static widthXS(width, _height) {
return width <= ResponsiveTheme.XS;
}
static widthS(width, _height) {
return width <= ResponsiveTheme.S;
}
static widthM(width, _height) {
return width <= ResponsiveTheme.M;
}
static widthL(width, _height) {
return width <= ResponsiveTheme.L;
}
static widthXL(width, _height) {
return width <= ResponsiveTheme.XL;
}
static widthXXL(width, _height) {
return width <= ResponsiveTheme.XXL;
}
static heightXXS(_width, height) {
return height <= ResponsiveTheme.XXS;
}
static heightXS(_width, height) {
return height <= ResponsiveTheme.XS;
}
static heightS(_width, height) {
return height <= ResponsiveTheme.S;
}
static heightM(_width, height) {
return height <= ResponsiveTheme.M;
}
static heightL(_width, height) {
return height <= ResponsiveTheme.L;
}
static heightXL(_width, height) {
return height <= ResponsiveTheme.XL;
}
static heightXXL(_width, height) {
return height <= ResponsiveTheme.XXL;
}
static isXXS(width, height) {
return (width <= ResponsiveTheme.XXS) && (height <= ResponsiveTheme.XXS);
}
static isXS(width, height) {
return (width <= ResponsiveTheme.XS) && (height <= ResponsiveTheme.XS);
}
static isS(width, height) {
return (width <= ResponsiveTheme.S) && (height <= ResponsiveTheme.S);
}
static isM(width, height) {
return (width <= ResponsiveTheme.M) && (height <= ResponsiveTheme.M);
}
static isL(width, height) {
return (width <= ResponsiveTheme.L) && (height <= ResponsiveTheme.L);
}
static isXL(width, height) {
return (width <= ResponsiveTheme.XL) && (height <= ResponsiveTheme.XL);
}
static isXXL(width, height) {
return (width <= ResponsiveTheme.XXL) && (height <= ResponsiveTheme.XXL);
}
static maybeXXS(width, height) {
return (width <= ResponsiveTheme.XXS) || (height <= ResponsiveTheme.XXS);
}
static maybeXS(width, height) {
return (width <= ResponsiveTheme.XS) || (height <= ResponsiveTheme.XS);
}
static maybeS(width, height) {
return (width <= ResponsiveTheme.S) || (height <= ResponsiveTheme.S);
}
static maybeM(width, height) {
return (width <= ResponsiveTheme.M) || (height <= ResponsiveTheme.M);
}
static maybeL(width, height) {
return (width <= ResponsiveTheme.L) || (height <= ResponsiveTheme.L);
}
static maybeXL(width, height) {
return (width <= ResponsiveTheme.XL) || (height <= ResponsiveTheme.XL);
}
static maybeXXL(width, height) {
return (width <= ResponsiveTheme.XXL) || (height <= ResponsiveTheme.XXL);
}
/**
* Instantiates the theme without adding default respomsive rules.
*/
static newEmpty(root) {
return (new this(root, true));
}
/**
* Adds a responsive rule as well as retuns it.
*
* @see {@link https://www.amcharts.com/docs/v5/concepts/responsive/} for more info
* @param rule Responsive rule
* @return Responsive rule
*/
addRule(rule) {
if (rule.name && !rule.template) {
rule.template = this.rule(rule.name, rule.tags);
}
this.responsiveRules.push(rule);
this._maybeApplyRule(rule);
return rule;
}
/**
* Removes the responsive rule.
*
* @param rule Responsive rule
*/
removeRule(rule) {
$array.remove(this.responsiveRules, rule);
}
dispose() {
if (this._dp) {
this._dp.dispose();
}
}
_isUsed() {
return this._root._rootContainer.get("themes").indexOf(this) !== -1;
}
_maybeApplyRules() {
$array.each(this.responsiveRules, (rule) => {
this._maybeUnapplyRule(rule);
});
$array.each(this.responsiveRules, (rule) => {
this._maybeApplyRule(rule);
});
}
_maybeApplyRule(rule) {
if (rule.applied)
return;
const w = this._root._rootContainer.getPrivate("width");
const h = this._root._rootContainer.getPrivate("height");
const relevant = rule.relevant.call(rule, w, h);
if (relevant) {
rule.applied = true;
if (rule.template && rule.settings) {
rule.template.setAll(rule.settings);
}
if (rule.applying) {
rule.applying.call(rule);
}
}
}
_maybeUnapplyRule(rule) {
if (!rule.applied)
return;
const w = this._root._rootContainer.getPrivate("width");
const h = this._root._rootContainer.getPrivate("height");
const relevant = rule.relevant.call(rule, w, h);
if (!relevant) {
rule.applied = false;
if (rule.template) {
rule.template.removeAll();
}
if (rule.removing) {
rule.removing.call(rule);
}
}
}
/**
* Adds default rules for various chart types and most standard scenarios.
*/
setupDefaultRules() {
super.setupDefaultRules();
const addRule = (rule) => this.addRule(rule);
/**
* ========================================================================
* Universal
* ========================================================================
*/
addRule({
name: "Chart",
relevant: ResponsiveTheme.widthXXS,
settings: {
paddingLeft: 0,
paddingRight: 0
}
});
addRule({
name: "Chart",
relevant: ResponsiveTheme.heightXXS,
settings: {
paddingTop: 0,
paddingBottom: 0
}
});
addRule({
name: "Bullet",
relevant: ResponsiveTheme.isXS,
settings: {
forceHidden: true
}
});
addRule({
name: "Legend",
relevant: ResponsiveTheme.isXS,
settings: {
forceHidden: true
}
});
addRule({
name: "HeatLegend",
tags: ["vertical"],
relevant: ResponsiveTheme.widthXS,
settings: {
forceHidden: true
}
});
addRule({
name: "HeatLegend",
tags: ["horizontal"],
relevant: ResponsiveTheme.heightXS,
settings: {
forceHidden: true
}
});
addRule({
name: "Label",
tags: ["heatlegend", "start"],
relevant: ResponsiveTheme.maybeXS,
settings: {
forceHidden: true
}
});
addRule({
name: "Label",
tags: ["heatlegend", "end"],
relevant: ResponsiveTheme.maybeXS,
settings: {
forceHidden: true
}
});
addRule({
name: "Button",
tags: ["resize"],
relevant: ResponsiveTheme.maybeXS,
settings: {
forceHidden: true
}
});
/**
* ========================================================================
* XY
* ========================================================================
*/
addRule({
name: "AxisRendererX",
relevant: ResponsiveTheme.heightXS,
settings: {
inside: true
}
});
addRule({
name: "AxisRendererY",
relevant: ResponsiveTheme.widthXS,
settings: {
inside: true
}
});
addRule({
name: "AxisRendererXLabel",
relevant: ResponsiveTheme.heightXS,
settings: {
minPosition: 0.1,
maxPosition: 0.9
}
});
addRule({
name: "AxisLabel",
tags: ["y"],
relevant: ResponsiveTheme.widthXS,
settings: {
centerY: p100,
maxPosition: 0.9
}
});
addRule({
name: "AxisLabel",
tags: ["x"],
relevant: ResponsiveTheme.heightXXS,
settings: {
forceHidden: true
}
});
addRule({
name: "AxisLabel",
tags: ["x", "minor"],
relevant: ResponsiveTheme.widthXXL,
settings: {
forceHidden: true
}
});
addRule({
name: "AxisLabel",
tags: ["y"],
relevant: ResponsiveTheme.widthXXS,
settings: {
forceHidden: true
}
});
addRule({
name: "AxisLabel",
tags: ["y", "minor"],
relevant: ResponsiveTheme.heightXXL,
settings: {
forceHidden: true
}
});
addRule({
name: "AxisTick",
tags: ["x"],
relevant: ResponsiveTheme.heightXS,
settings: {
inside: true,
minPosition: 0.1,
maxPosition: 0.9
}
});
addRule({
name: "AxisTick",
tags: ["y"],
relevant: ResponsiveTheme.widthXXS,
settings: {
inside: true,
minPosition: 0.1,
maxPosition: 0.9
}
});
addRule({
name: "Grid",
relevant: ResponsiveTheme.maybeXXS,
settings: {
forceHidden: true
}
});
/**
* ========================================================================
* Radar
* ========================================================================
*/
addRule({
name: "RadialLabel",
tags: ["radial"],
relevant: ResponsiveTheme.maybeXS,
settings: {
forceHidden: true
}
});
addRule({
name: "RadialLabel",
tags: ["circular"],
relevant: ResponsiveTheme.maybeS,
settings: {
inside: true
}
});
addRule({
name: "AxisTick",
relevant: ResponsiveTheme.maybeS,
settings: {
inside: true
}
});
addRule({
name: "RadialLabel",
tags: ["circular"],
relevant: ResponsiveTheme.maybeXS,
settings: {
forceHidden: true
}
});
addRule({
name: "AxisTick",
tags: ["circular"],
relevant: ResponsiveTheme.maybeXS,
settings: {
inside: true
}
});
/**
* ========================================================================
* Pie
* ========================================================================
*/
addRule({
name: "PieChart",
relevant: ResponsiveTheme.maybeXS,
settings: {
radius: percent(99)
}
});
addRule({
name: "PieChart",
relevant: ResponsiveTheme.widthM,
settings: {
radius: percent(99)
}
});
addRule({
name: "RadialLabel",
tags: ["pie"],
relevant: ResponsiveTheme.maybeXS,
settings: {
forceHidden: true
}
});
addRule({
name: "RadialLabel",
tags: ["pie"],
relevant: ResponsiveTheme.widthM,
settings: {
forceHidden: true
}
});
addRule({
name: "Tick",
tags: ["pie"],
relevant: ResponsiveTheme.maybeXS,
settings: {
forceHidden: true
}
});
addRule({
name: "Tick",
tags: ["pie"],
relevant: ResponsiveTheme.widthM,
settings: {
forceHidden: true
}
});
/**
* ========================================================================
* Funnel
* ========================================================================
*/
addRule({
name: "FunnelSeries",
relevant: ResponsiveTheme.widthM,
settings: {
alignLabels: false
}
});
addRule({
name: "Label",
tags: ["funnel", "vertical"],
relevant: ResponsiveTheme.widthL,
settings: {
forceHidden: true
}
});
addRule({
name: "Tick",
tags: ["funnel", "vertical"],
relevant: ResponsiveTheme.widthL,
settings: {
forceHidden: true
}
});
addRule({
name: "Label",
tags: ["funnel", "horizontal"],
relevant: ResponsiveTheme.heightS,
settings: {
forceHidden: true
}
});
addRule({
name: "Tick",
tags: ["funnel", "horizontal"],
relevant: ResponsiveTheme.heightS,
settings: {
forceHidden: true
}
});
/**
* ========================================================================
* Pyramid
* ========================================================================
*/
addRule({
name: "PyramidSeries",
relevant: ResponsiveTheme.widthM,
settings: {
alignLabels: false
}
});
addRule({
name: "Label",
tags: ["pyramid", "vertical"],
relevant: ResponsiveTheme.widthL,
settings: {
forceHidden: true
}
});
addRule({
name: "Tick",
tags: ["pyramid", "vertical"],
relevant: ResponsiveTheme.widthL,
settings: {
forceHidden: true
}
});
addRule({
name: "Label",
tags: ["pyramid", "horizontal"],
relevant: ResponsiveTheme.heightS,
settings: {
forceHidden: true
}
});
addRule({
name: "Tick",
tags: ["pyramid", "horizontal"],
relevant: ResponsiveTheme.heightS,
settings: {
forceHidden: true
}
});
/**
* ========================================================================
* Pictorial
* ========================================================================
*/
addRule({
name: "PictorialStackedSeries",
relevant: ResponsiveTheme.widthM,
settings: {
alignLabels: false
}
});
addRule({
name: "Label",
tags: ["pictorial", "vertical"],
relevant: ResponsiveTheme.widthL,
settings: {
forceHidden: true
}
});
addRule({
name: "Tick",
tags: ["pictorial", "vertical"],
relevant: ResponsiveTheme.widthL,
settings: {
forceHidden: true
}
});
addRule({
name: "Label",
tags: ["pictorial", "horizontal"],
relevant: ResponsiveTheme.heightS,
settings: {
forceHidden: true
}
});
addRule({
name: "Tick",
tags: ["pictorial", "horizontal"],
relevant: ResponsiveTheme.heightS,
settings: {
forceHidden: true
}
});
/**
* ========================================================================
* Map
* ========================================================================
*/
// Nothing to do here
/**
* ========================================================================
* Flow (Sankey+Chord)
* ========================================================================
*/
addRule({
name: "Label",
tags: ["flow", "horizontal"],
relevant: ResponsiveTheme.widthS,
settings: {
forceHidden: true
}
});
addRule({
name: "Label",
tags: ["flow", "vertical"],
relevant: ResponsiveTheme.heightS,
settings: {
forceHidden: true
}
});
addRule({
name: "Chord",
relevant: ResponsiveTheme.maybeXS,
settings: {
radius: percent(99)
}
});
/**
* ========================================================================
* Hierarchy (Treemap, Partition, Sunburst, Pack, ForceDirected)
* ========================================================================
*/
addRule({
name: "Label",
tags: ["hierarchy", "node"],
relevant: ResponsiveTheme.maybeXS,
settings: {
forceHidden: true
}
});
}
}
// Named pixel breakpoints
ResponsiveTheme.XXS = 100;
ResponsiveTheme.XS = 200;
ResponsiveTheme.S = 300;
ResponsiveTheme.M = 400;
ResponsiveTheme.L = 600;
ResponsiveTheme.XL = 800;
ResponsiveTheme.XXL = 1000;
//# sourceMappingURL=ResponsiveTheme.js.map