The theme module of VChart is a powerful and flexible chart style configuration system. It allows users to customize the visual appearance of charts in a unified and reusable way. Users can easily define comprehensive style configurations for the entire chart or specific chart types, including colors, fonts, layouts, component styles, etc. By using predefined themes, users can quickly achieve a consistent design style without having to repeatedly configure styles for each chart, greatly simplifying the chart development process and ensuring visual consistency and professionalism across different scenarios. In simple terms, the theme of VChart is like a "design template" for charts, allowing users to quickly create beautiful and professional data visualization charts by simply selecting or customizing a theme.
package/vchart/scr/util/theme: A folder of utility classes related to themes, including tools for theme merging, parsing, preprocessing (color palettes, token semantics), and converting string themes to objects.
package/vchart/scr/core/vchart.ts: Defines the core class VChart, including a series of hooks throughout the chart lifecycle such as theme initialization, registration, updating, switching, and destruction. VChart is a specific chart instance responsible for application and rendering, closely related to theme configuration and updates.
package/vchart/src/theme: This folder contains special concepts related to themes: color palettes (color-theme), tokenMap, theme manager class (theme-manager), and other data structures.
Core Classes and Their Relationships
VChart: Responsible for specific rendering, instantiation, and lifecycle management of charts
ThemeManager: Responsible for global registration, management, and switching of themes
ThemeManager is exposed as a static class of VChart, allowing users to manage themes using commands like
VChart.ThemeManager.registerTheme('myTheme', { ... }); or VChart.ThemeManager.setCurrentTheme('myTheme');
However, essentially, ThemeManager is still an independent class, but it provides a more convenient way to access it through this method. This design pattern of exposing static properties achieves the decoupling of theme management and chart rendering.
Theme Configuration Parsing Logic
VChart provides two ways to configure chart themes:
Through chart spec configuration
By registering themes through ThemeManager
Theme Configuration Retrieval and Priority Comparison (core/vchart.ts)
Both configurations can be set up with a ITheme type theme object, but what is the priority of these two configurations? This priority issue is handled in the updateCurrentTheme method:
Note: Strictly speaking, there are three sources of themes:
currentTheme: The global default theme registered through ThemeManager
optionTheme: The theme passed in the options of the VChart constructor
specTheme: The theme specified in the chart specification (spec)
Their priority from low to high is:
currentTheme < optionTheme < specTheme
In src/core/vchart.ts, the following properties are used to obtain the theme content configured by the user:
_spec.theme: The theme specified by the user in the chart spec object configuration
_currentThemeName: The current global theme name registered through VChart.ThemeManager.registerTheme
Brief Analysis of Theme Merging Logic (util/theme/merge-theme.ts)
function transformThemeToMerge(theme?: Maybe<ITheme>): Maybe<ITheme> {
if (!theme) {
return theme;
}
// 将色板转化为标准形式
const colorScheme = transformColorSchemeToMerge(theme.colorScheme);
return Object.assign({}, theme, {
colorScheme,
token: theme.token ?? {},
series: Object.assign({}, theme.series)
} as Partial<ITheme>);
}
/** 将色板转化为标准形式 */
export function transformColorSchemeToMerge(colorScheme?: Maybe<IThemeColorScheme>): Maybe<IThemeColorScheme> {
if (colorScheme) {
colorScheme = Object.keys(colorScheme).reduce<IThemeColorScheme>((scheme, key) => {
const value = colorScheme[key];
scheme[key] = transformColorSchemeToStandardStruct(value);
return scheme;
}, {} as IThemeColorScheme);
}
return colorScheme;
}
transformThemeToMerge generally serves to standardize and normalize the theme object, addressing the following:
Colors are always in array form
Always have token and series attributes
This ensures that regardless of the theme configuration provided by the user, it can be transformed into a structurally complete, consistent, and predictable theme object, providing a standardized data structure for subsequent theme merging and application.
processThemeByChartType is a key function in the VChart theme system that implements chart type personalization. It achieves the ability to provide customized styles for different chart types while maintaining global theme consistency through conditional merging and mergeTheme.
Parsing and Processing of String Themes and Object Themes
When configuring themes, users can easily and conveniently pass in string themes (usually themes exported from third-party theme packages), for example:
import vScreenVolcanoBlue from '@visactor/vchart-theme/public/vScreenVolcanoBlue.json';
import VChart from '@visactor/vchart';
VChart.ThemeManager.registerTheme('vScreenVolcanoBlue', vScreenVolcanoBlue);
VChart.ThemeManager.setCurrentTheme('vScreenVolcanoBlue');
You can also pass in a custom theme with detailed configuration, for example:
The core of handling both in the source code is to determine the type in _updateCurrentTheme and convert it through getThemeObject(), uniformly processing it into an object theme for parsing. This is a simple logic, yet it provides flexibility and convenience for VChart's configuration.
Ultimately, after layers of priority comparison, merging of table types (processThemeByChartType), and theme merging processing logic, the currentTheme attribute mounted on the VChart object is finally obtained.
Preprocessing of Theme Configuration
When the theme configuration is merged, it enters the preprocessing stage. Theme preprocessing is a key step in the VChart theme system, converting abstract theme descriptions into specific style configurations, providing developers with intuitive configuration capabilities.
Mainly accomplishes the following tasks:
Semantic color conversion
Convert color semantics like { color: 'brand.primary' } into specific color values
Token replacement
Convert token semantics like { fontSize: 'size.m' } into specific font sizes