mirror of
https://github.com/XCharts-Team/XCharts.git
synced 2026-05-19 23:10:06 +00:00
Merge branch 'master' into 3.0
This commit is contained in:
10196
Documentation~/en/api.md
10196
Documentation~/en/api.md
File diff suppressed because it is too large
Load Diff
@@ -2,6 +2,9 @@
|
||||
# 更新日志
|
||||
|
||||
[master](#master)
|
||||
[v3.12.0](#v3120)
|
||||
[v3.11.2](#v3112)
|
||||
[v3.11.1](#v3111)
|
||||
[v3.11.0](#v3110)
|
||||
[v3.10.2](#v3102)
|
||||
[v3.10.1](#v3101)
|
||||
@@ -69,6 +72,48 @@
|
||||
|
||||
## master
|
||||
|
||||
## v3.12.0
|
||||
|
||||
Version Highlights:
|
||||
|
||||
* Added `radiusGradient` parameter for `Ring` to set the gradient direction
|
||||
* Added support for `date` and `time` in `numericFormatter`
|
||||
* Improved `origin` parameter setting for `AreaStyle` to define the starting position of area filling
|
||||
* Adjusted and perfected the documentation
|
||||
* Other optimizations and fixes
|
||||
|
||||
Log Details:
|
||||
|
||||
* (2024.09.30) Released version `v3.12.0`
|
||||
* (2024.09.27) Improved the `5-minute tutorial`
|
||||
* (2024.09.24) Improved support for multiple Series in `Legend`'s `formatter` (#332)
|
||||
* (2024.09.22) Adjusted the display style of the `Documentation`
|
||||
* (2024.09.09) Added support for `date` and `time` in `numericFormatter`
|
||||
* (2024.09.03) Improved the setting of the `origin` parameter for `AreaStyle` to define the starting position of area filling
|
||||
* (2024.09.01) Added `radiusGradient` parameter for `Ring` to set the gradient direction
|
||||
* (2024.09.01) Optimized the position of the first Label when `Axis` is used as a time axis
|
||||
|
||||
|
||||
## v3.11.2
|
||||
|
||||
* (2024.08.01) Release `v3.11.2`
|
||||
* (2024.07.29) Fixed compatibility issue with `Tooltip` reporting error on wechat mini game platform (#326)
|
||||
* (2024.07.27) Adjust the default position of `AxisName` for `Axis`
|
||||
* (2024.07.22) Improved the behavior of `Pie`'s `Label` when `Tooltip` is triggered
|
||||
* (2024.07.21) Fix to `Tooltip` indicating inaccurate content when opening `DataZoom`
|
||||
* (2024.07.17) Fixed an issue where `Label` of `MarkLine` could flash during initialization
|
||||
* (2024.07.16) Optimized the default effect of `Tooltip` when `Axis` is `Time` timeline
|
||||
* (2024.07.15) Optimized segmentation when Axis is Time
|
||||
* (2024.07.14) Improved movement performance when `Axis` is `Time`
|
||||
* (2024.07.12) Optimized the initial display effect of `Label`
|
||||
* (2024.07.06) Fix to `Chart` background not adaptive when dynamically created (#323)
|
||||
|
||||
## v3.11.1
|
||||
|
||||
* (2024.07.01) Release `v3.11.1`
|
||||
* (2024.07.01) Fixed an issue where `Serie` has multiple abnormal colors
|
||||
* (2024.06.23) Fixed an issue where `labels` would pile up during initialization
|
||||
|
||||
## v3.11.0
|
||||
|
||||
Release Highlights:
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
BIN
Documentation~/en/img/tutorial01_axisdata.png
Normal file
BIN
Documentation~/en/img/tutorial01_axisdata.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
BIN
Documentation~/en/img/tutorial01_seriedata.png
Normal file
BIN
Documentation~/en/img/tutorial01_seriedata.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 26 KiB |
@@ -1,103 +1,143 @@
|
||||
---
|
||||
title: Introductory tutorial: Get started with XCharts 3.0 in 5 minutes
|
||||
title: Tutorial: Getting Started with XCharts 3.0 in 5 Minutes
|
||||
sidebar_position: 11
|
||||
slug: /tutorial01
|
||||
---
|
||||
|
||||
# Tutorial: Get started with XCharts 3.0 in 5 minutes
|
||||
# Tutorial: Getting Started with XCharts 3.0 in 5 Minutes
|
||||
|
||||
> Note: This tutorial is for XCharts 3.x version only
|
||||
|
||||
## What do I need to know before using XCharts
|
||||
> Note: This tutorial is only applicable to the XCharts 3.x version. For the 2.x version, please refer to [Tutorial: Mastering XCharts 2.0](https://github.com/XCharts-Team/XCharts/blob/2.0/Doc/Tutorial%3A5-Minute-Start-to-XCharts.md)
|
||||
|
||||
- Have used Unity, know the basic operation of Unity.
|
||||
- Understand UGUI and can use UGUI.
|
||||
- Understand MonoBehavior script usage in Unity, know how to hang scripts, manipulate scripts with code.
|
||||
## Prerequisites for XCharts
|
||||
|
||||
## Get and import XCharts
|
||||
XCharts is a Unity chart plugin, currently only available for use on the Unity platform.
|
||||
|
||||
XCharts can be imported into a project in any of the following ways:
|
||||
Before using XCharts, you need to:
|
||||
|
||||
- Source XCharts directly into the project
|
||||
- Have a basic understanding of how to use Unity.
|
||||
- Understand the basic usage of UGUI for making UI.
|
||||
- Know how to use Unity's MonoBehavior scripts, how to attach scripts, and how to manipulate scripts with code.
|
||||
|
||||
After downloading the XCharts source code, copy the XCharts directory directly to the Assets directory of the Unity project.
|
||||
If you are new to Unity, it is recommended to learn some basic Unity tutorials before using XCharts.
|
||||
|
||||
- Import XCharts through `Assets/Import Package`
|
||||
## Obtaining and Importing XCharts
|
||||
|
||||
After downloading the.unitypackage file for XCharts, open Unity and go to the menu bar Assets--> Import Package--> Select.unitypackage import to start using XCharts.
|
||||
XCharts is primarily maintained and released through Github. You can download the source code and Package from the [Github Homepage](https://github.com/XCharts-Team).
|
||||
|
||||
- Import XCharts through the Package Manager
|
||||
XCharts can be imported into your project in any of the following ways:
|
||||
|
||||
For Unity 2018.3 and later, XCharts can be imported through the Package Manager. After opening the Package Manager, run the `Add package form git URL...`, input XCharts dead simple URL: ` https://github.com/XCharts-Team/XCharts.git use XCharts after ` wait a moment.
|
||||
### Copying the XCharts Source Code Directly into the Project
|
||||
|
||||
You can also add the package directly to the manifest.json file: Open the manifest.json file in the Packages directory and add it under dependencies:
|
||||
After downloading the XCharts source code, simply copy the XCharts directory into the Assets directory of your Unity project. Once compiled, it is ready to use.
|
||||
|
||||
``` json
|
||||
"com.monitor1394.xcharts" : "https://github.com/XCharts-Team/XCharts.git",
|
||||
```
|
||||
### Importing XCharts through Import Package
|
||||
|
||||
To update XCharts, remove com.monitor1394.xcharts from the manifest.json file under lock (some versions of Unity may be packages-lock.json) and re-download and compile.
|
||||
After downloading the .unitypackage file of XCharts, open Unity, go to the menu bar Assets-->Import Package-->select the downloaded .unitypackage to import. After the import is complete and compiled, you can start using XCharts.
|
||||
|
||||
- Recommended daemon into XCharts (not required)
|
||||
### Importing XCharts through Package Manager
|
||||
|
||||
[XCharts Daemon](https://github.com/XCharts-Team/XCharts-Daemon) can ensure update compilation is normal, when the local open TextMeshPro or NewInputSystem would be very useful. After importing Xchart-daemon into a project, when updating XCharts, the Daemon will automatically refresh asmdef according to the status of local TMP, etc., to ensure normal compilation and facilitate the execution of automated processes such as CI-CD.
|
||||
For Unity versions above 2018.3, you can import XCharts through the Package Manager. Open the Package Manager, then use `Add package from git URL...`, enter the GitHub URL of XCharts: `https://github.com/XCharts-Team/XCharts.git`. After compiling, you can use XCharts.
|
||||
|
||||
## Add a simple chart
|
||||
For some Unity versions, you can also directly add the package to the `manifest.json` file: Open the `manifest.json` file under the `Packages` directory, and add the following under `dependencies`:
|
||||
|
||||
Right-click in `Hierarchy` view or menu bar `GameObject` drop down and select `XCharts->LineChart`, can quickly create a default line chart out:
|
||||
>"com.monitor1394.xcharts": "https://github.com/XCharts-Team/XCharts.git",
|
||||
|
||||
If you need to update `XCharts`, delete the relevant content of `com.monitor1394.xcharts` under the `lock` of the `manifest.json` file (some Unity versions may be the packages-lock.json file), and it will re-download and compile.
|
||||
|
||||
### Recommended Import of XCharts Daemon
|
||||
|
||||
The daemon [XCharts-Daemon](https://github.com/XCharts-Team/XCharts-Daemon) ensures that the compilation is normal when updating. It is very useful when TextMeshPro or NewInputSystem is turned on locally. After importing XCharts-Daemon into the project, the daemon will automatically refresh XCharts' asmdef according to the local situation of TMP when updating XCharts, ensuring that the compilation is normal without manual intervention, which is convenient for automated processes such as CI/CD.
|
||||
|
||||
The import method of XCharts-Daemon can refer to the previous import method of XCharts. It can be imported into the project through source code or Package. The GitHub URL of XCharts-Daemon: https://github.com/XCharts-Team/XCharts-Daemon.git
|
||||
|
||||
## Basic Usage of XCharts
|
||||
|
||||
After importing XCharts and compiling, the XCharts menu will appear in the Unity editor's menu bar, and you can start using XCharts.
|
||||
|
||||
>Note: The XCharts menu in the Unity menu bar indicates that XCharts is available.
|
||||
|
||||
### Adding a Simple Chart
|
||||
|
||||
In the `Hierarchy` view, right-click `UI->XCharts->LineChart` or select `LineChart` from the menu bar `XCharts` to quickly create a default line chart:
|
||||
|
||||

|
||||
|
||||
## Add multiple Seire
|
||||
If you need to create a chart under a certain node, you can select the node and right-click `UI->XCharts->LineChart` to create a chart under the node.
|
||||
|
||||
In the Inspector view, locate LineChart's panel, and with the `Add Serie` button, you can add a second Line line:
|
||||
### Modifying Chart Data
|
||||
|
||||
For the newly created chart, its data can be modified on the Inspector panel.
|
||||
|
||||
For X-axis data, you can add, delete, and modify by expanding: `XAxis->Data`:
|
||||
|
||||

|
||||
|
||||
For Serie data, you can add, delete, and modify by expanding: `Serie->Data`:
|
||||
|
||||

|
||||
|
||||
Serie supports multi-dimensional data, and generally, a line chart only uses two-dimensional data: the first dimension represents the ID of the X-axis category data, and the second dimension represents the corresponding value.
|
||||
|
||||
### Adding Multiple Series
|
||||
|
||||
In the `Inspector` view, find the `LineChart` panel, and click the `Add Serie` button to add a second `Line` line:
|
||||
|
||||

|
||||

|
||||
|
||||
## Add other components
|
||||
>Note: Series are added through the `Add Serie` button. Different types of Series can be added. [What kinds of Series does XCharts have?](https://xcharts-team.github.io/docs/configuration#serie-系列)
|
||||
|
||||
The default chart does not have a `Legend`, and a `Legend` Component can be added via the `Add Component` button:
|
||||
### Adding Other Main Components
|
||||
|
||||
By default, the chart does not have a `Legend`. If you need a `Legend` component, you can add it through the `Add Component` button:
|
||||
|
||||

|
||||
|
||||
## Add Serie components
|
||||
>Note: Main components are added through the `Add Component` button. [What main components does XCharts have?](https://xcharts-team.github.io/docs/configuration/#maincomponent-主组件)
|
||||
|
||||
Serie comes with only a few common components, and others are added as needed. For example, if you need to fill a line chart area with color, you can add a separate `AreaStyle` component to Serie:
|
||||
### Adding Serie Components
|
||||
|
||||
Serie only comes with a few common components, and other components need to be added when used. For example, if you need to fill the area color for the line chart, you can add an `AreaStyle` component to `Serie` separately:
|
||||
|
||||

|
||||

|
||||
|
||||
## Add the SerieData component
|
||||
>Note: Serie components are added through the button on the right side of Serie. [What components can be added to Serie in XCharts?](https://xcharts-team.github.io/docs/configuration/#iseriecomponent-可添加到serie的组件)
|
||||
|
||||
If you need to personalize the configuration of each data item, you can add a Component to each SerieData separately. For example, we give the second data of the line chart a separate display `Label`:
|
||||
### Adding SerieData Components
|
||||
|
||||
If you need to customize the configuration of each data item individually, you can add components to each `SerieData` separately. For example, we can display `Label` for the second data of the line chart individually:
|
||||
|
||||

|
||||

|
||||
|
||||
## More components and configuration parameters
|
||||
>Note: SerieData components are added through the button on the right side of SerieData after expanding. [What components can be added to SerieData in XCharts?](https://xcharts-team.github.io/docs/configuration/#iseriedatacomponent-可添加到seriedata的组件)
|
||||
|
||||
XCharts has been iteratively optimized and now has dozens of main and sub-components, each with a few to dozens of configurable parameters to support a variety of flexible and complex functions.
|
||||
### More Components and Configuration Parameters
|
||||
|
||||
Using XCharts for the first time, you can add various charts in the `Inspector` view, add or adjust the components in the chart, and the `Game` view gives real-time feedback on the effects of adjustments to familiarize yourself with the use of various components. Detailed parameter descriptions of each component can be found in the [XCharts Configuration](Configuration.md).
|
||||
XCharts has been continuously iterated and optimized, and now has dozens of main components and sub-components, each with several to dozens of configurable parameters to support a variety of functions.
|
||||
|
||||
## How to adjust parameters quickly
|
||||
When using XCharts for the first time, it is recommended to personally test the actual effects of each chart, each component. The `Inspector` view can directly add various charts, components, and adjust various configuration parameters, and the `Game` view will provide real-time feedback on the adjustments. A detailed description of each component's parameters can be found in the [XCharts Configuration Manual](configuration.md).
|
||||
|
||||
XCharts is configuration and data driven. Want what effect, only need to adjust the configuration parameters under the corresponding component can be, do not need to change the nodes under the `Hierarchy` view, because those nodes are generated by the `XCharts` internal according to the configuration and data, even if changed will be restored in the refresh.
|
||||
### How to Quickly Adjust Parameters
|
||||
|
||||
How to quickly locate the component corresponding to the effect you want to change requires a certain understanding of the component. For example, if we want to show an arrow at the end of the X-axis, how do we position it? First, position the X-axis to `XAxis0`; Second, locate the axis to `AxisLine`; Finally, check to see if there are any parameters in the AxisLine component that can achieve this effect, and check [XCharts configuration](Configuration.md) for uncertain parameters.
|
||||
XCharts is driven by data and parameters. To achieve the desired effect, simply adjust the configuration parameters under the corresponding component. Do not modify the nodes under the `Hierarchy` view, as those nodes are generated by XCharts internally based on configuration and data, and will be restored upon refresh.
|
||||
|
||||
`XCharts` provides a full range of parameter configuration from the global` Theme `, series` Serie `, and single data item `SerieData`. The priority in descending order is: `SerieData` -> `Serie` -> `Theme`. Take the color of `ItemStyle` for example:
|
||||
To quickly locate the component corresponding to the effect you want to change, you need to have a certain understanding of the components. For example, we want to display an arrow at the end of the X-axis line. How to locate it? The first step, the X-axis is located at `XAxis0`; the second step, the axis line is located at `AxisLine`; finally, check if there is such a parameter under the `AxisLine` component to achieve this effect. If you are not sure about the parameters, you can refer to the [XCharts Configuration Manual](configuration.md).
|
||||
|
||||
1. If the `ItemStyle` of `SerieData` has a color value other than `0000`, this color value is preferred.
|
||||
2. If the ItemStyle of `Serie` is configured with a color value other than `0000`, this color value takes precedence.
|
||||
3. Otherwise, the Color value is taken from the Color Palette of the Theme.
|
||||
`XCharts` provides comprehensive parameter configuration from the global `Theme`, series `Serie`, and individual data items `SerieData`. The priority order from high to low is: `SerieData`->`Serie`->`Theme`. Take the color of `ItemStyle` as
|
||||
an example:
|
||||
|
||||
Usually, `0000` indicates the theme default color, and 0 or null indicates the theme default.
|
||||
1. If the `ItemStyle` of `SerieData` has a color value other than `0000`, this color value is used first.
|
||||
2. If the `ItemStyle` of `Serie` has a color value other than `0000`, this color value is used.
|
||||
3. Otherwise, the color value is taken from the `Color Palette` of the theme `Theme`.
|
||||
|
||||
## Add line charts with code
|
||||
>Note: The color value is usually `0000` when using the default color of the theme; other parameters are `0` or null when using the default configuration of the theme; pay attention to transparency when setting colors.
|
||||
|
||||
Attach the `LineChart` script to the gameObject:
|
||||
### Adding a Line Chart with Code
|
||||
|
||||
Attach the `LineChart` script to `gameObject`:
|
||||
|
||||
```csharp
|
||||
var chart = gameObject.GetComponent<LineChart>();
|
||||
@@ -108,10 +148,10 @@ if (chart == null)
|
||||
}
|
||||
```
|
||||
|
||||
Resize:
|
||||
Adjust the size:
|
||||
|
||||
```csharp
|
||||
chart.SetSize(580, 300);//代码动态设置尺寸,或直接操作chart.rectTransform,或直接在Inspector上改
|
||||
chart.SetSize(580, 300);//Dynamically set the size with code, or directly operate chart.rectTransform, or directly change it in the Inspector
|
||||
```
|
||||
|
||||
Set the title:
|
||||
@@ -121,7 +161,7 @@ var title = chart.EnsureChartComponent<Title>();
|
||||
title.text = "Simple Line";
|
||||
```
|
||||
|
||||
Set whether prompt boxes and legends are displayed:
|
||||
Set whether to display the tooltip and legend:
|
||||
|
||||
```csharp
|
||||
var tooltip = chart.EnsureChartComponent<Tooltip>();
|
||||
@@ -131,7 +171,7 @@ var legend = chart.EnsureChartComponent<Legend>();
|
||||
legend.show = false;
|
||||
```
|
||||
|
||||
Set axes:
|
||||
Set the coordinate axis:
|
||||
|
||||
```csharp
|
||||
var xAxis = chart.EnsureChartComponent<XAxis>();
|
||||
@@ -143,14 +183,22 @@ var yAxis = chart.EnsureChartComponent<YAxis>();
|
||||
yAxis.type = Axis.AxisType.Value;
|
||||
```
|
||||
|
||||
Clear default data and add `Line` type `Serie` for receiving data:
|
||||
Clear all default data (including Series), add a `Line` type `Serie` to receive data:
|
||||
|
||||
```csharp
|
||||
chart.RemoveData();
|
||||
chart.AddSerie<Line>("line");
|
||||
```
|
||||
|
||||
Add 10 data:
|
||||
If the Serie is fixed, it is recommended to only clear the data, not to remove the Serie:
|
||||
|
||||
```csharp
|
||||
chart.ClearData();
|
||||
```
|
||||
|
||||
This way, you can set the configuration parameters of Serie in the UI in advance.
|
||||
|
||||
Add 10 data points:
|
||||
|
||||
```csharp
|
||||
for (int i = 0; i < 10; i++)
|
||||
@@ -160,59 +208,74 @@ for (int i = 0; i < 10; i++)
|
||||
}
|
||||
```
|
||||
|
||||
So a simple line chart comes out:
|
||||
Now, a simple line chart is ready:
|
||||
|
||||

|
||||
|
||||
If there are multiple series in a Chart, the data of Axis only needs to be added once, rather than repeated in multiple cycles. Remember: the number of data in Axis should be the same as the number in Serie.
|
||||
If there are multiple series in a Chart, the data of Axis only needs to be added once, and should not be repeated in multiple loops.
|
||||
|
||||
See `Examples`: `Example13_LineSimple.cs` for the complete code
|
||||
>Remember: The number of Axis data should be consistent with the number of Serie data.
|
||||
|
||||
You can also use code to control more parameters, there are more Examples under `Examples`, all the configurable parameters seen in the `Inspector` can be set by code. All parameters in [XCharts configuration](Configuration.md) can be controlled by code.
|
||||
For the complete code, please refer to `Examples`: `Example13_LineSimple.cs`
|
||||
|
||||
In addition, unless customized, it is recommended to call the `public` interface provided under `Chart`, especially in the data-related operations section. These interfaces do some associated processing inside, such as refreshing charts. Common interfaces are:
|
||||
You can also control more parameters with code. There are more examples in `Examples`. All parameters that can be configured in the `Inspector` can be set with code. All parameters in the [XCharts Configuration Manual](configuration.md) can be controlled by code.
|
||||
|
||||
1. `Chart.ClearData()` : Clear chart data (without removing Series)
|
||||
2. `Chart.RemoveData()` : Clear chart data (will remove all Serie)
|
||||
3. `chart.AddSerie()` : AddSerie
|
||||
4. `chart.AddXAxisData()` : Add X-axis data
|
||||
5. `chart.AddData()` : Adds Serie data
|
||||
6. `chart.UpdateData()` : Updates Serie data
|
||||
7. `chart.UpdateXAxisData()` : Updates the X-axis data
|
||||
8. `chart.UpdateDataName()` : Updates the Serie data name
|
||||
### Setting the Default Font
|
||||
|
||||
XCharts has an automatic refresh mechanism inside, but it only triggers under certain conditions. If you call the interface of the internal component, encounter the component did not refresh, and indeed can not find the reason, you can use the following two interfaces to force refresh:
|
||||
The default font used by XCharts is Unity's default font `Arial`, which may not display Chinese characters on the WebGL platform. When using XCharts in your project, it is recommended to set the font first:
|
||||
|
||||
1. `chart.RefreshAllComponent()` : refresh chart component, to initialize all of the components, often is not recommended.
|
||||
2. `chart.RefreshChart()` : refreshes the chart drawing, only the drawing part is refreshed, and the component text, position, etc., is not refreshed.
|
||||
3. Individual components can also refresh only themselves by `SetAllDirty()`.
|
||||
- Find the `XCharts/Resources/XCSetting.asset` resource and modify the `Font` inside and save.
|
||||
- Find the `XCharts/Resources/XCTheme-Default.asset` and `XCharts/Resources/XCTheme-Dark.asset` font configurations, and click the `Sync Font from Setting` and `Sync Font to Sub Theme` buttons to synchronize the font to the theme configuration files.
|
||||
|
||||
## Use TextMeshPro
|
||||
After the font is set, newly created charts will use the newly set font. For old charts, you can click the `Rebuild Chart Object` button to refresh.
|
||||
|
||||
XCharts supports TextMeshPro, but it is disabled by default and needs to be switched manually. It can be turned on and off in the following ways:
|
||||
>Note: It is recommended to set the font before using XCharts; when updating XCharts, pay attention to the potential restoration of the set font.
|
||||
|
||||
### Using TextMeshPro
|
||||
|
||||
XCharts supports TextMeshPro, but it is not enabled by default and needs to be switched on manually. It can be turned on and off in the following ways:
|
||||
|
||||

|
||||
|
||||
After opening, you need to set the global font used by TextMeshPro, or you can set it separately in the Theme:
|
||||
After turning it on, you need to set the global font to be used by TextMeshPro, and it can also be set individually in the Theme:
|
||||
|
||||

|
||||
|
||||
It is recommended to plan whether to use TextMeshPro at the beginning of the project and set the font. When switching TMP with many existing charts, some charts may not refresh automatically. You can manually click the `Rebuild Chart Object` button to rebuild the chart, which can be initialized normally.
|
||||
It is recommended to plan whether to use TextMeshPro at the beginning of the project and set the font accordingly. When switching to TMP in a project with many charts, some charts may not refresh automatically, and you can manually click the `Rebuild Chart Object` button to rebuild the chart, which will initialize normally.
|
||||
|
||||
When updating XCharts for TMP projects, you may encounter problems with missing TMP references and failing to compile. These problems can be solved in one of two ways:
|
||||
If you have enabled TMP in your project, you may encounter compilation failures due to lost TMP references when updating XCharts. This can be solved in the following two ways:
|
||||
|
||||
1. Find `XCharts.Runtime.asmdef` and `XCharts.Editor.asmdef` and manually add references to `TextMeshPro`
|
||||
2. Remove the `dUI_TextMeshPro` macro for Scripting Define Symbols in PlayerSetting
|
||||
1. Find `XCharts.Runtime.asmdef` and `XCharts.Editor.asmdef`, and manually add references to `TextMeshPro`.
|
||||
2. Remove the `dUI_TextMeshPro` macro from the `Scripting Define Symbols` in `PlayerSetting`.
|
||||
|
||||
Version `3.8.0` after adding daemon[XCharts - Daemon](https://github.com/XCharts-Team/XCharts-Daemon), will be XCharts-Daemon import project, When updating XCharts, the daemon automatically refreshes the asmdef based on the locally enabled TMP to ensure proper compilation.
|
||||
After the `3.8.0` version, the [XCharts-Daemon](https://github.com/XCharts-Team/XCharts-Daemon) daemon was added. After importing XCharts-Daemon into the project, the daemon will automatically refresh the asmdef based on the local situation of the enabled TMP when updating XCharts, ensuring normal compilation.
|
||||
|
||||
## Change chart parameters with code
|
||||
## XCharts Code Control
|
||||
|
||||
All parameters seen on Inspector can be modified with code, the key is to identify whether the parameters you want to change are on the component, on the Serie, or on the specific data item SerieData.
|
||||
All parameters seen in the `Inspector` can be modified with code. The key is to locate the parameter you want to change, whether it is on the component, the Serie, or the specific data item SerieData.
|
||||
|
||||
### Change the parameters on the main component
|
||||
In addition, unless customized, it is recommended to call the `public` interfaces provided under `Chart`, especially for data-related and list operations. These interfaces will do some associated processing internally, such as refreshing the chart. Common interfaces include:
|
||||
|
||||
You need to obtain the component first, and then modify the parameters in it:
|
||||
1. `chart.ClearData()`: Clear chart data (does not remove Series)
|
||||
2. `chart.RemoveData()`: Clear chart data (will remove all Series)
|
||||
3. `chart.AddSerie()`: Add Serie
|
||||
4. `chart.AddXAxisData()`: Add X-axis data
|
||||
5. `chart.AddData()`: Add Serie data
|
||||
6. `chart.UpdateData()`: Update Serie data
|
||||
7. `chart.UpdateXAxisData()`: Update X-axis data
|
||||
8. `chart.UpdateDataName()`: Update the name of Serie data
|
||||
|
||||
XCharts has an automatic refresh mechanism, but it is also triggered under certain conditions. If you have called the internal component interfaces and encountered components that have not been refreshed, and you cannot find the reason, you can use the following two interfaces to force a refresh:
|
||||
|
||||
1. `chart.RefreshAllComponent()`: Refresh chart components, which will re-initialize all components. It is not recommended to use it frequently.
|
||||
2. `chart.RefreshChart()`: Refresh chart rendering, which only refreshes the rendering part and will not refresh component text, position, etc.
|
||||
3. Each component can also refresh itself by calling `SetAllDirty()`.
|
||||
|
||||
>Note: Use APIs to manipulate data and various lists, not directly access the list for processing.
|
||||
|
||||
### Changing Parameters on Main Components
|
||||
|
||||
You need to obtain the component first, then modify its parameters:
|
||||
|
||||
```csharp
|
||||
var title = chart.EnsureChartComponent<Title>();
|
||||
@@ -225,11 +288,11 @@ xAxis.boundaryGap = true;
|
||||
xAxis.type = Axis.AxisType.Category;
|
||||
```
|
||||
|
||||
> Note: When the earlier version does not have the EnsureChartComponent() interface, GetOrAddChartComponent() is used.
|
||||
> Note: In older versions without the `EnsureChartComponent()` interface, use `GetOrAddChartComponent()`
|
||||
|
||||
### Change Serie parameters
|
||||
### Changing Serie Parameters
|
||||
|
||||
For newly added Serie:
|
||||
For newly added Series:
|
||||
|
||||
```csharp
|
||||
var serie = chart.AddSerie<Pie>();
|
||||
@@ -241,7 +304,7 @@ serie.animation.dataChangeEnable = true;
|
||||
serie.roundCap = true;
|
||||
```
|
||||
|
||||
For existing Serie:
|
||||
For existing Series:
|
||||
|
||||
```csharp
|
||||
var serie = chart.GetSerie<Pie>();
|
||||
@@ -253,7 +316,7 @@ serie.animation.dataChangeEnable = true;
|
||||
serie.roundCap = true;
|
||||
```
|
||||
|
||||
Add additional components to Serie:
|
||||
Adding additional components to Serie:
|
||||
|
||||
```csharp
|
||||
serie.EnsureComponent<AreaStyle>();
|
||||
@@ -262,14 +325,14 @@ var label = serie1.EnsureComponent<LabelStyle>();
|
||||
label.offset = new Vector3(0,20,0);
|
||||
```
|
||||
|
||||
### Change the parameter on the data item SerieData
|
||||
### Changing Parameters on Data Item SerieData
|
||||
|
||||
```csharp
|
||||
var serieData = chart.AddData(0, 20);
|
||||
//var serieData = serie.GetSerieData(0); //从已有数据中获取
|
||||
//var serieData = serie.GetSerieData(0); //To get from existing data
|
||||
serieData.radius = 10;
|
||||
|
||||
var itemStyle = serieData.EnsureComponent<ItemStyle>(); //给数据项添加ItemStyle组件
|
||||
var itemStyle = serieData.EnsureComponent<ItemStyle>(); //Add ItemStyle component to the data item
|
||||
itemStyle.color = Color.blue;
|
||||
|
||||
```
|
||||
```
|
||||
|
||||
10196
Documentation~/zh/api.md
10196
Documentation~/zh/api.md
File diff suppressed because it is too large
Load Diff
@@ -6,6 +6,9 @@ slug: /changelog
|
||||
# 更新日志
|
||||
|
||||
[master](#master)
|
||||
[v3.12.0](#v3120)
|
||||
[v3.11.2](#v3112)
|
||||
[v3.11.1](#v3111)
|
||||
[v3.11.0](#v3110)
|
||||
[v3.10.2](#v3102)
|
||||
[v3.10.1](#v3101)
|
||||
@@ -74,6 +77,47 @@ slug: /changelog
|
||||
|
||||
## master
|
||||
|
||||
## v3.12.0
|
||||
|
||||
版本要点:
|
||||
|
||||
* 增加`Ring`的`radiusGradient`参数设置渐变方向
|
||||
* 增加`numericFormatter`对`date`和`time`的支持
|
||||
* 完善`AreaStyle`的`origin`参数设置区域填充起始位置
|
||||
* 调整和完善文档
|
||||
* 其他优化和修复
|
||||
|
||||
日志详情:
|
||||
|
||||
* (2024.09.30) 发布`v3.12.0`版本
|
||||
* (2024.09.27) 完善`5分钟教程`
|
||||
* (2024.09.24) 完善`Legend`的`formatter`对多Serie的支持 (#332)
|
||||
* (2024.09.22) 调整`Documentation`文档显示样式
|
||||
* (2024.09.09) 增加`numericFormatter`对`date`和`time`的支持
|
||||
* (2024.09.03) 完善`AreaStyle`的`origin`参数设置区域填充起始位置
|
||||
* (2024.09.01) 增加`Ring`的`radiusGradient`参数设置渐变方向
|
||||
* (2024.09.01) 优化`Axis`为时间轴时首个Label的位置
|
||||
|
||||
## v3.11.2
|
||||
|
||||
* (2024.08.01) 发布`v3.11.2`版本
|
||||
* (2024.07.29) 修复`Tooltip`在微信小游戏平台上报错的兼容问题 (#326)
|
||||
* (2024.07.27) 调整`Axis`的`AxisName`的默认位置
|
||||
* (2024.07.22) 优化`Pie`的`Label`在`Tooltip`触发时的表现
|
||||
* (2024.07.21) 修复`Tooltip`在开启`DataZoom`时指示内容不准确的问题
|
||||
* (2024.07.17) 修复`MarkLine`的`Label`在初始化时可能会闪烁的问题
|
||||
* (2024.07.16) 优化`Axis`为`Time`时间轴时的`Tooltip`默认效果
|
||||
* (2024.07.15) 优化`Axis`为`Time`时间轴时的分割效果
|
||||
* (2024.07.14) 优化`Axis`为`Time`时间轴时的移动表现
|
||||
* (2024.07.12) 优化`Label`的初始化显示效果
|
||||
* (2024.07.06) 修复`Chart`在动态创建时背景没有自适应的问题 (#323)
|
||||
|
||||
## v3.11.1
|
||||
|
||||
* (2024.07.01) 发布`v3.11.1`版本
|
||||
* (2024.07.01) 修复`Serie`有多个时颜色异常的问题
|
||||
* (2024.06.23) 修复`Label`在初始化时会堆积的问题
|
||||
|
||||
## v3.11.0
|
||||
|
||||
版本要点:
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
BIN
Documentation~/zh/img/tutorial01_axisdata.png
Normal file
BIN
Documentation~/zh/img/tutorial01_axisdata.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
BIN
Documentation~/zh/img/tutorial01_seriedata.png
Normal file
BIN
Documentation~/zh/img/tutorial01_seriedata.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 26 KiB |
@@ -6,84 +6,122 @@ slug: /tutorial01
|
||||
|
||||
# 教程:5分钟上手 XCharts 3.0
|
||||
|
||||
> 注:本教程适用XCharts 3.x版本,2.x版本请看 [教程:5分钟上手XCharts 2.0](https://github.com/XCharts-Team/XCharts/blob/2.0/Doc/教程:5分钟上手XCharts.md)
|
||||
> Note:本教程仅适用XCharts 3.x版本,2.x版本请看 [教程:5分钟上手XCharts 2.0](https://github.com/XCharts-Team/XCharts/blob/2.0/Doc/教程:5分钟上手XCharts.md)
|
||||
|
||||
## 使用 XCharts 前需要掌握什么
|
||||
## XCharts的前提条件
|
||||
|
||||
- 会简单使用Unity
|
||||
- 了解UGUI,会使用UGUI
|
||||
- 了解Unity的MonoBehavior脚本用法,知道怎么挂脚本,用代码操作脚本
|
||||
XCharts是一个Unity图表插件,目前只能在Unity平台使用。
|
||||
|
||||
## 获取和导入 XCharts
|
||||
使用XCharts前,你需要:
|
||||
|
||||
XCharts可通过以下任意一种方式导入到项目:
|
||||
- 掌握Unity的基本用法。
|
||||
- 掌握UGUI制作UI的基本用法。
|
||||
- 了解Unity的MonoBehavior脚本用法,知道怎么挂脚本和用代码操作脚本。
|
||||
|
||||
- 直接将XCharts源码到项目
|
||||
如果你刚接触Unity,建议先学习Unity相关的基础教程再使用XCharts。
|
||||
|
||||
下载好XCharts源码后,直接将XCharts目录拷贝到Unity项目工程的Assets目录下。
|
||||
## XCharts的获取和导入
|
||||
|
||||
- 通过`Assets/Import Package`导入XCharts
|
||||
XCharts主要通过Github来维护更新和发布,可以到【Github主页】(https://github.com/XCharts-Team)进行下载获取源码和Pacakge;对于无Github访问条件的用户,可以访问[【国内镜像】](https://gitee.com/monitor1394/unity-ugui-XCharts)进行下载。国内镜像的版本更新可能会相对滞后。
|
||||
|
||||
下载好XCharts的.unitypackage文件后,打开Unity,菜单栏 Assets-->Import Package-->选中.unitypackage导入即可开始使用XCharts。
|
||||
XCharts可通过以下任意一种方式导入到你的项目:
|
||||
|
||||
- 通过`Package Manager`导入XCharts
|
||||
### 直接将XCharts源码拷贝到项目
|
||||
|
||||
对于Unity 2018.3以上版本,可通过 Package Manager来导入XCharts,打开Package Manager后,通过 `Add package form git URL...`,输入XCharts3.0的GitHub URL: `https://github.com/XCharts-Team/XCharts.git#3.0` 稍等片刻后即可使用XCharts。
|
||||
下载好XCharts源码后,直接将XCharts目录拷贝到Unity项目工程的Assets目录下。编译通过后即可使用。
|
||||
|
||||
也可以直接将package加入到`manifest.json`文件:打开`Packages`目录下的`manifest.json`文件,在`dependencies`下加入:
|
||||
### 通过Import Package导入XCharts
|
||||
|
||||
``` json
|
||||
"com.monitor1394.xcharts": "https://github.com/XCharts-Team/XCharts.git#3.0",
|
||||
```
|
||||
下载好XCharts的.unitypackage文件后,打开Unity,菜单栏 Assets-->Import Package-->选中下载好的.unitypackage进行导入。导入完成并通过编译后即可开始使用XCharts。
|
||||
|
||||
如需更新`XCharts`,删除`manifest.json`文件(部分Unity版本可能是packages-lock.json文件)的`lock`下的`com.monitor1394.xcharts`相关内容即会重新下载编译。
|
||||
### 通过Package Manager导入XCharts
|
||||
|
||||
- 建议先导入XCharts的守护程序(非必须)
|
||||
对于2018.3以上的Unity版本,可通过Package Manager来导入XCharts,打开Package Manager后,通过 `Add package form git URL...`,输入XCharts的GitHub URL: `https://github.com/XCharts-Team/XCharts.git` 编译通过后即可使用XCharts。
|
||||
|
||||
守护程序[XCharts-Daemon](https://github.com/XCharts-Team/XCharts-Daemon)可以确保更新时编译正常,当本地开启TextMeshPro或NewInputSystem时将会非常有用。将XCharts-Daemon导入项目后,在更新XCharts时守护程序会自动根据本地TMP等的开启情况刷新asmdef,确保编译正常,不用手动去解决,方便CI-CD等自动化流程执行。
|
||||
对于部分Unity版本,也可以直接将package加入到`manifest.json`文件:打开`Packages`目录下的`manifest.json`文件,在`dependencies`下加入:
|
||||
|
||||
## 添加一个简单图表
|
||||
>"com.monitor1394.xcharts": "https://github.com/XCharts-Team/XCharts.git",
|
||||
|
||||
在`Hierarchy`视图下右键`UI->XCharts->LineChart`或菜单栏`GameObject`下拉选择`XCharts->LineChart`,即可快速创建一个默认的折线图出来:
|
||||
如需更新`XCharts`,删除`manifest.json`文件(部分Unity版本可能是packages-lock.json文件)的`lock`下的`com.monitor1394.xcharts`相关内容即会重新下载编译。
|
||||
|
||||
### 建议导入XCharts的守护程序
|
||||
|
||||
守护程序[XCharts-Daemon](https://github.com/XCharts-Team/XCharts-Daemon)可以确保更新时编译正常,当本地开启TextMeshPro或NewInputSystem时将会非常有用。将XCharts-Daemon导入项目后,在更新XCharts时守护程序会自动根据本地TMP等的开启情况刷新XCharts的asmdef,确保编译正常,不用手动去解决,方便CI/CD等自动化流程执行。
|
||||
|
||||
XCharts-Daemon的导入方式可参考刚才的XCharts导入方式。可以通过源码或Package的方式导入项目,XCharts-Daemon的Github URL:https://github.com/XCharts-Team/XCharts-Daemon.git
|
||||
|
||||
## XCharts的基本使用
|
||||
|
||||
导入XCharts并编译通过后,Unity编辑器的菜单栏会显示XCharts,这时可以开始使用XCharts了。
|
||||
|
||||
>Note:Unity的菜单栏出现XCharts菜单时才表示XCharts可用。
|
||||
|
||||
### 添加一个简单图表
|
||||
|
||||
在`Hierarchy`视图下右键`UI->XCharts->LineChart`或菜单栏`XCharts`下拉选择`LineChart`,即可快速创建一个默认的折线图:
|
||||
|
||||

|
||||
|
||||
## 添加多个Seire
|
||||
如需在某个节点下创建图表,可以选中节点右键`UI->XCharts->LineChart`即可在节点下创建图表。
|
||||
|
||||
### 修改图表数据
|
||||
|
||||
刚创建的图表,它的数据可以在Inspector视图面板上进行修改。
|
||||
|
||||
对于X轴数据,可通过:`XAxis->Data`展开后进行增删和修改:
|
||||
|
||||

|
||||
|
||||
对于Serie数据,可通过:`Serie->Data`展开后进行增删和修改:
|
||||
|
||||

|
||||
|
||||
Serie支持多维数据,一般折线图只用到二维数据:第一维表示X轴类目数据的编号,第二维表示对应的数值。
|
||||
|
||||
### 添加多个Seire
|
||||
|
||||
在`Inspector`视图,找到`LineChart`的面板,通过`Add Serie`按钮,可以添加第二条`Line`折线:
|
||||
|
||||

|
||||

|
||||
|
||||
## 添加其他组件
|
||||
>Note:Serie通过`Add Serie`按钮添加。可添加不同类型的Serie。[XCharts有哪些Serie?](https://xcharts-team.github.io/docs/configuration#serie-系列)
|
||||
|
||||
### 添加其他主组件
|
||||
|
||||
默认图表没有`Legend`,需要`Legend`组件可通过`Add Component`按钮添加:
|
||||
|
||||

|
||||
|
||||
## 添加Serie组件
|
||||
>Note:主组件通过`Add Component`按钮添加。[XCharts有哪些主组件?](https://xcharts-team.github.io/docs/configuration/#maincomponent-主组件)
|
||||
|
||||
Serie只自带了几个常见的组件,其他组件按需额外添加。比如,需要给折线图区域填充颜色,可单独给`Serie`添加`AreaStyle`组件:
|
||||
### 添加Serie组件
|
||||
|
||||
Serie只自带了几个常见的组件,其他组件用到时需额外添加。比如,需要给折线图进行区域填充颜色,可单独给`Serie`添加`AreaStyle`组件:
|
||||
|
||||

|
||||

|
||||
|
||||
## 添加SerieData组件
|
||||
>Note:Serie组件通过Serie右边的按钮添加。[XCharts有哪些Serie组件?](https://xcharts-team.github.io/docs/configuration/#iseriecomponent-可添加到serie的组件)
|
||||
|
||||
如果需要个性化定制每个数据项的配置,可以单独给每个`SerieData`添加`Component`。比如我们给折线图的第二个数据单独显示`Label`:
|
||||
### 添加SerieData组件
|
||||
|
||||
如果需要个性化定制每个数据项的配置,可以单独给每个`SerieData`添加组件。比如我们给折线图的第二个数据单独显示`Label`:
|
||||
|
||||

|
||||

|
||||
|
||||
## 更多组件和配置参数
|
||||
>Note:SerieData组件通过展开SerieData后Component右边的按钮添加。[XCharts有哪些SerieData组件?](https://xcharts-team.github.io/docs/configuration/#iseriedatacomponent-可添加到seriedata的组件)
|
||||
|
||||
XCharts经过不断的迭代优化,目前已有多达几十种的主组件和子组件,每个组件有几个至几十个不等的可配置参数,以支持各种灵活而复杂的功能。
|
||||
### 更多组件和配置参数
|
||||
|
||||
首次使用XCharts,可在 `Inspector` 视图添加各种图表,给图表添加或调整里面组件,`Game` 视图会实时反馈调整后的效果,以熟悉各种组件的使用。各个组件的详细参数说明可查阅[XCharts配置项手册](configuration.md)。
|
||||
XCharts经过不断的迭代优化,目前已有多达几十种的主组件和子组件,每个组件有几个到几十个的可配置参数,用来支持多样化的功能。
|
||||
|
||||
## 如何快速调整参数
|
||||
首次使用XCharts,建议亲自去测试下各个图表各个组件的实际效果。`Inspector` 视图可以直接添加各种图表,各种组件以及调整各个配置参数,`Game` 视图会实时反馈调整后的效果。各个组件的详细参数说明可查阅[XCharts配置项手册](configuration.md)。
|
||||
|
||||
`XCharts`是配置和数据来驱动的。想要什么效果,只需要去调整对应组件下的配置参数就可以,不需要去改`Hierarchy`视图下的节点,因为那些节点是由`XCharts`内部根据配置和数据生成的,即使改了也会在刷新时还原回来。
|
||||
### 如何快速调整参数
|
||||
|
||||
XCharts是数据和参数驱动的。想要什么效果,只需要去调整对应组件下的配置参数就可以,不能去改`Hierarchy`视图下的节点,因为那些节点是由XCharts内部根据配置和数据生成的,即使改了也会在刷新时被还原掉。
|
||||
|
||||
如何快速定位你想要改的效果所对应的组件,这就需要对组件有一定的了解。比如我们想要让X轴的轴线末端显示箭头,如何定位?第一步,X轴定位到`XAxis0`;第二步,轴线定位到`AxisLine`;最后,再去看`AxisLine`组件下有没有这样的参数可以实现这个效果,对于不太确定的参数可以查阅[XCharts配置项手册](configuration.md)。
|
||||
|
||||
@@ -93,9 +131,9 @@ XCharts经过不断的迭代优化,目前已有多达几十种的主组件和
|
||||
2. 如果`Serie`的`ItemStyle`配置有非`0000`颜色值,则优先用这个颜色值。
|
||||
3. 否则颜色值取自主题`Theme`的`Color Palette`。
|
||||
|
||||
通常颜色值为0000时表示用主题默认颜色,配置为0或null时表示用主题默认配置。
|
||||
>Note:通常颜色值为0000时表示用主题默认颜色;其他参数为0或null时表示用主题默认配置;设置颜色时注意透明度。
|
||||
|
||||
## 用代码添加折线图
|
||||
### 用代码添加折线图
|
||||
|
||||
给`gameObject`挂上`LineChart`脚本:
|
||||
|
||||
@@ -143,13 +181,21 @@ var yAxis = chart.EnsureChartComponent<YAxis>();
|
||||
yAxis.type = Axis.AxisType.Value;
|
||||
```
|
||||
|
||||
清空默认数据,添加`Line`类型的`Serie`用于接收数据:
|
||||
清空所有默认数据(包含Serie),添加`Line`类型的`Serie`用于接收数据:
|
||||
|
||||
```csharp
|
||||
chart.RemoveData();
|
||||
chart.AddSerie<Line>("line");
|
||||
```
|
||||
|
||||
如果Serie是固定的,建议只是清空数据,不用把Serie也清掉:
|
||||
|
||||
```csharp
|
||||
chart.ClearData();
|
||||
```
|
||||
|
||||
这样可以提前在UI上设置好Serie的配置参数。
|
||||
|
||||
添加10个数据:
|
||||
|
||||
```csharp
|
||||
@@ -164,30 +210,26 @@ for (int i = 0; i < 10; i++)
|
||||
|
||||

|
||||
|
||||
如果一个Chart里面有多个系列时,则Axis的data只需要加一次,不要多个循环加重复了。记住:Axis的数据个数要和Serie的数据个数一致。
|
||||
如果一个Chart里面有多个系列时,则Axis的data只需要加一次,不要多个循环加重复了。
|
||||
|
||||
>记住:Axis的数据个数要和Serie的数据个数一致。
|
||||
|
||||
完整代码请查阅`Examples`:`Example13_LineSimple.cs`
|
||||
|
||||
你还可以用代码控制更多的参数,`Examples`下还有更多的其他例子,凡是`Inspector`上看到的可配置的参数,都可以通过代码来设置。[XCharts配置项手册](configuration.md)里面的所有参数都是可以通过代码控制的。
|
||||
|
||||
另外,除非定制,建议调用`Chart`下提供的`public`接口,特别是数据相关操作部分。这些接口内部会做一些关联处理,比如刷新图表等。常见的接口有:
|
||||
### 设置默认字体
|
||||
|
||||
1. `chart.ClearData()`:清空图表数据(不移除Series)
|
||||
2. `chart.RemoveData()`:清除图表数据(会移除所有Serie)
|
||||
3. `chart.AddSerie()`:添加Serie
|
||||
4. `chart.AddXAxisData()`:添加X轴数据
|
||||
5. `chart.AddData()`:添加Serie数据
|
||||
6. `chart.UpdateData()`:更新Serie数据
|
||||
7. `chart.UpdateXAxisData()`:更新X轴数据
|
||||
8. `chart.UpdateDataName()`:更新Serie数据的名字
|
||||
XCharts默认使用的是Unity默认字体`Arial`,在WebGL平台上可能无法显示中文。在将XCharts用在你的项目时,建议先设置好字体:
|
||||
|
||||
XCharts内部有自动刷新机制,但也是在一定条件才会触发。如果自己调用了内部组件的接口,碰到组件没有刷新,确实找不到原因的话,可以用以下两个接口强制刷新:
|
||||
- 找到`XCharts/Resources/XCSetting.asset`资源,修改里面的`Font`并保存。
|
||||
- 找到`XCharts/Resources/XCTheme-Default.asset`和`XCharts/Resources/XCTheme-Default.asset`两个字体配置,点击`Sync Font from Setting`和`Sync Font to Sub Theme`按钮将字体同步到主题配置文件上。
|
||||
|
||||
1. `chart.RefreshAllComponent()`:刷新图表组件,会重新初始化所有组件,不建议频繁待用。
|
||||
2. `chart.RefreshChart()`:刷新图表绘制,只刷新绘制部分,不会刷新组件文本,位置等部分。
|
||||
3. 各个组件也可以通过`SetAllDirty()`只刷新自己。
|
||||
字体设置好后,新创建的图表就会用新设置的字体了。对于旧图表,可以点击`Rebuild Chart Object`进行刷新。
|
||||
|
||||
## 使用TextMeshPro
|
||||
>Note:使用XCharts前建议先设置好字体;更新XCharts时注意设置的字体可能被还原的问题。
|
||||
|
||||
### 使用TextMeshPro
|
||||
|
||||
XCharts支持TextMeshPro,但默认是不开启的,需要自己手动切换。可通过以下方式开启和关闭:
|
||||
|
||||
@@ -206,10 +248,29 @@ XCharts支持TextMeshPro,但默认是不开启的,需要自己手动切换
|
||||
|
||||
`3.8.0`版本后增加[XCharts-Daemon](https://github.com/XCharts-Team/XCharts-Daemon)守护程序,将XCharts-Daemon导入项目后,在更新XCharts时守护程序会自动根据本地开启的TMP情况刷新asmdef,确保编译正常。
|
||||
|
||||
## 用代码改图表参数
|
||||
## XCharts的代码控制
|
||||
|
||||
`Inspector`上看到的所有参数都可以用代码来修改,关键是要定位好你要改的参数是在组件上、还是Serie上、还是在具体的数据项SerieData上。
|
||||
|
||||
另外,除非定制,建议调用`Chart`下提供的`public`接口,特别是数据相关和列表的操作。这些接口内部会做一些关联处理,比如刷新图表等。常见的接口有:
|
||||
|
||||
1. `chart.ClearData()`:清空图表数据(不移除Series)
|
||||
2. `chart.RemoveData()`:清除图表数据(会移除所有Serie)
|
||||
3. `chart.AddSerie()`:添加Serie
|
||||
4. `chart.AddXAxisData()`:添加X轴数据
|
||||
5. `chart.AddData()`:添加Serie数据
|
||||
6. `chart.UpdateData()`:更新Serie数据
|
||||
7. `chart.UpdateXAxisData()`:更新X轴数据
|
||||
8. `chart.UpdateDataName()`:更新Serie数据的名字
|
||||
|
||||
XCharts内部有自动刷新机制,但也是在一定条件才会触发。如果自己调用了内部组件的接口,碰到组件没有刷新,确实找不到原因的话,可以用以下两个接口强制刷新:
|
||||
|
||||
1. `chart.RefreshAllComponent()`:刷新图表组件,会重新初始化所有组件,不建议频繁待用。
|
||||
2. `chart.RefreshChart()`:刷新图表绘制,只刷新绘制部分,不会刷新组件文本,位置等部分。
|
||||
3. 各个组件也可以通过`SetAllDirty()`只刷新自己。
|
||||
|
||||
>Note:用API去操作数据和各种list,而不是直接访问list进行处理
|
||||
|
||||
### 改主组件上的参数
|
||||
|
||||
需要先获取组件,再修改里面的参数:
|
||||
|
||||
@@ -16,6 +16,7 @@ namespace XCharts.Editor
|
||||
PropertyField("m_RoundCap");
|
||||
PropertyField("m_Clockwise");
|
||||
PropertyField("m_AvoidLabelOverlap");
|
||||
PropertyField("m_RadiusGradient");
|
||||
|
||||
PropertyField("m_ItemStyle");
|
||||
PropertyField("m_Animation");
|
||||
|
||||
@@ -139,7 +139,7 @@ namespace XCharts
|
||||
}
|
||||
}
|
||||
|
||||
internal void UpdateAxisMinMaxValue(int axisIndex, Axis axis, bool updateChart = true)
|
||||
internal void UpdateAxisMinMaxValue(int axisIndex, Axis axis, bool cancelAnimation = false)
|
||||
{
|
||||
if (!axis.show)
|
||||
return;
|
||||
@@ -173,7 +173,7 @@ namespace XCharts
|
||||
{
|
||||
m_LastSplitNumber = axis.splitNumber;
|
||||
m_LastInterval = axis.interval;
|
||||
axis.UpdateMinMaxValue(tempMinValue, tempMaxValue, axis.context.needAnimation);
|
||||
axis.UpdateMinMaxValue(tempMinValue, tempMaxValue, !cancelAnimation && axis.context.needAnimation);
|
||||
axis.context.offset = 0;
|
||||
axis.context.lastCheckInverse = axis.inverse;
|
||||
UpdateAxisTickValueList(axis);
|
||||
@@ -191,14 +191,11 @@ namespace XCharts
|
||||
}
|
||||
}
|
||||
|
||||
if (updateChart)
|
||||
{
|
||||
UpdateAxisLabelText(axis);
|
||||
chart.RefreshChart();
|
||||
}
|
||||
UpdateAxisLabelText(axis);
|
||||
chart.RefreshChart();
|
||||
}
|
||||
|
||||
if (axis.context.needAnimation && (axis.context.minValue != axis.context.destMinValue || axis.context.maxValue != axis.context.destMaxValue))
|
||||
if (!cancelAnimation && axis.context.needAnimation && (axis.context.minValue != axis.context.destMinValue || axis.context.maxValue != axis.context.destMaxValue))
|
||||
{
|
||||
var duration = axis.animation.duration == 0
|
||||
? SeriesHelper.GetMinAnimationDuration(chart.series) / 1000f
|
||||
@@ -455,7 +452,7 @@ namespace XCharts
|
||||
|
||||
label = ChartHelper.AddChartLabel(s_DefaultAxisName, axisObj.transform, axis.axisName.labelStyle,
|
||||
chart.theme.axis, axis.axisName.name, autoColor, TextAnchor.MiddleCenter);
|
||||
label.SetActive(axis.axisName.labelStyle.show);
|
||||
label.SetActive(axis.axisName.labelStyle.show, true);
|
||||
label.SetPosition(axis.context.start + offset);
|
||||
break;
|
||||
|
||||
@@ -463,7 +460,7 @@ namespace XCharts
|
||||
|
||||
label = ChartHelper.AddChartLabel(s_DefaultAxisName, axisObj.transform, axis.axisName.labelStyle,
|
||||
chart.theme.axis, axis.axisName.name, autoColor, TextAnchor.MiddleCenter);
|
||||
label.SetActive(axis.axisName.labelStyle.show);
|
||||
label.SetActive(axis.axisName.labelStyle.show, true);
|
||||
label.SetPosition((axis.context.start + axis.context.end) / 2 + offset);
|
||||
break;
|
||||
|
||||
@@ -471,11 +468,12 @@ namespace XCharts
|
||||
|
||||
label = ChartHelper.AddChartLabel(s_DefaultAxisName, axisObj.transform, axis.axisName.labelStyle,
|
||||
chart.theme.axis, axis.axisName.name, autoColor, TextAnchor.MiddleCenter);
|
||||
label.SetActive(axis.axisName.labelStyle.show);
|
||||
label.SetActive(axis.axisName.labelStyle.show, true);
|
||||
label.SetPosition(axis.context.end + offset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
UpdateAxisMinMaxValue(axis.index, axis, true);
|
||||
}
|
||||
|
||||
protected void InitAxis(Axis relativedAxis, Orient orient,
|
||||
@@ -574,7 +572,7 @@ namespace XCharts
|
||||
|
||||
label = ChartHelper.AddChartLabel(s_DefaultAxisName, axisObj.transform, axis.axisName.labelStyle,
|
||||
chart.theme.axis, axis.axisName.name, autoColor, TextAnchor.MiddleRight);
|
||||
label.SetActive(axis.axisName.labelStyle.show);
|
||||
label.SetActive(axis.axisName.labelStyle.show, true);
|
||||
label.SetPosition(axis.position == Axis.AxisPosition.Top ?
|
||||
new Vector2(zeroPos.x - offset.x, axisStartY + relativedLength + offset.y + axis.offset) :
|
||||
new Vector2(zeroPos.x - offset.x, posY + offset.y));
|
||||
@@ -584,7 +582,7 @@ namespace XCharts
|
||||
|
||||
label = ChartHelper.AddChartLabel(s_DefaultAxisName, axisObj.transform, axis.axisName.labelStyle,
|
||||
chart.theme.axis, axis.axisName.name, autoColor, TextAnchor.MiddleCenter);
|
||||
label.SetActive(axis.axisName.labelStyle.show);
|
||||
label.SetActive(axis.axisName.labelStyle.show, true);
|
||||
label.SetPosition(axis.position == Axis.AxisPosition.Top ?
|
||||
new Vector2(axisStartX + axisLength / 2 + offset.x, axisStartY + relativedLength - offset.y + axis.offset) :
|
||||
new Vector2(axisStartX + axisLength / 2 + offset.x, posY + offset.y));
|
||||
@@ -594,7 +592,7 @@ namespace XCharts
|
||||
|
||||
label = ChartHelper.AddChartLabel(s_DefaultAxisName, axisObj.transform, axis.axisName.labelStyle,
|
||||
chart.theme.axis, axis.axisName.name, autoColor, TextAnchor.MiddleLeft);
|
||||
label.SetActive(axis.axisName.labelStyle.show);
|
||||
label.SetActive(axis.axisName.labelStyle.show, true);
|
||||
label.SetPosition(axis.position == Axis.AxisPosition.Top ?
|
||||
new Vector2(axisStartX + axisLength + offset.x, axisStartY + relativedLength + offset.y + axis.offset) :
|
||||
new Vector2(axisStartX + axisLength + offset.x, posY + offset.y));
|
||||
@@ -611,7 +609,7 @@ namespace XCharts
|
||||
|
||||
label = ChartHelper.AddChartLabel(s_DefaultAxisName, axisObj.transform, axis.axisName.labelStyle,
|
||||
chart.theme.axis, axis.axisName.name, autoColor, TextAnchor.MiddleCenter);
|
||||
label.SetActive(axis.axisName.labelStyle.show);
|
||||
label.SetActive(axis.axisName.labelStyle.show, true);
|
||||
label.SetPosition(axis.position == Axis.AxisPosition.Right ?
|
||||
new Vector2(axisStartX + relativedLength + offset.x + axis.offset, axisStartY - offset.y) :
|
||||
new Vector2(posX + offset.x, axisStartY - offset.y));
|
||||
@@ -621,7 +619,7 @@ namespace XCharts
|
||||
|
||||
label = ChartHelper.AddChartLabel(s_DefaultAxisName, axisObj.transform, axis.axisName.labelStyle,
|
||||
chart.theme.axis, axis.axisName.name, autoColor, TextAnchor.MiddleCenter);
|
||||
label.SetActive(axis.axisName.labelStyle.show);
|
||||
label.SetActive(axis.axisName.labelStyle.show, true);
|
||||
label.SetPosition(axis.position == Axis.AxisPosition.Right ?
|
||||
new Vector2(axisStartX + relativedLength - offset.x + axis.offset, axisStartY + axisLength / 2 + offset.y) :
|
||||
new Vector2(posX + offset.x, axisStartY + axisLength / 2 + offset.y));
|
||||
@@ -631,7 +629,7 @@ namespace XCharts
|
||||
//LabelStyle.Position
|
||||
label = ChartHelper.AddChartLabel(s_DefaultAxisName, axisObj.transform, axis.axisName.labelStyle,
|
||||
chart.theme.axis, axis.axisName.name, autoColor, TextAnchor.MiddleCenter);
|
||||
label.SetActive(axis.axisName.labelStyle.show);
|
||||
label.SetActive(axis.axisName.labelStyle.show, true);
|
||||
label.SetPosition(axis.position == Axis.AxisPosition.Right ?
|
||||
new Vector2(axisStartX + relativedLength + offset.x + axis.offset, axisStartY + axisLength + offset.y) :
|
||||
new Vector2(posX + offset.x, axisStartY + axisLength + offset.y));
|
||||
@@ -639,6 +637,7 @@ namespace XCharts
|
||||
}
|
||||
}
|
||||
}
|
||||
UpdateAxisMinMaxValue(axis.index, axis, true);
|
||||
}
|
||||
|
||||
internal static Vector3 GetLabelPosition(int i, Orient orient, Axis axis, Axis relativedAxis, AxisTheme theme,
|
||||
@@ -720,12 +719,6 @@ namespace XCharts
|
||||
if (AxisHelper.NeedShowSplit(axis))
|
||||
{
|
||||
var size = AxisHelper.GetScaleNumber(axis, axisLength, dataZoom);
|
||||
if (axis.IsTime())
|
||||
{
|
||||
size += 1;
|
||||
if (!ChartHelper.IsEquals(axis.GetLastLabelValue(), axis.context.maxValue))
|
||||
size += 1;
|
||||
}
|
||||
var tickWidth = axis.axisTick.GetWidth(theme.tickWidth);
|
||||
var tickColor = axis.axisTick.GetColor(theme.tickColor);
|
||||
var current = orient == Orient.Horizonal ? startX : startY;
|
||||
|
||||
@@ -124,7 +124,7 @@ namespace XCharts.Runtime
|
||||
label.text.SetAlignment(textStyle.GetAlignment(TextAnchor.MiddleCenter));
|
||||
label.SetText(labelName);
|
||||
label.SetPosition(GetLabelPosition(polar, axis, angleAxis.context.startAngle, totalWidth));
|
||||
label.SetActive(true);
|
||||
label.SetActive(true, true);
|
||||
label.SetTextActive(true);
|
||||
|
||||
axis.context.labelObjectList.Add(label);
|
||||
|
||||
@@ -28,6 +28,7 @@ namespace XCharts.Runtime
|
||||
splitLine.show = false;
|
||||
splitLine.lineStyle.type = LineStyle.Type.None;
|
||||
axisLabel.textLimit.enable = true;
|
||||
axisName.labelStyle.offset = new Vector3(5, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace XCharts.Runtime
|
||||
{
|
||||
@@ -25,6 +26,7 @@ namespace XCharts.Runtime
|
||||
splitLine.lineStyle.type = LineStyle.Type.None;
|
||||
axisLabel.textLimit.enable = false;
|
||||
axisTick.showStartTick = true;
|
||||
axisName.labelStyle.offset = new Vector3(0, 22, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -50,7 +50,7 @@ namespace XCharts.Runtime
|
||||
var borderColor = component.borderStyle.GetRuntimeBorderColor();
|
||||
var cornerRadius = component.borderStyle.GetRuntimeCornerRadius();
|
||||
UGL.DrawRoundRectangleWithBorder(vh, chart.chartRect, backgroundColor, backgroundColor, cornerRadius,
|
||||
borderWidth, borderColor);
|
||||
borderWidth, borderColor, 0, 1f);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -209,10 +209,29 @@ namespace XCharts.Runtime
|
||||
set { if (PropertyUtil.SetClass(ref m_ItemMarker, value)) SetVerticesDirty(); }
|
||||
}
|
||||
/// <summary>
|
||||
/// Standard numeric format strings.
|
||||
/// ||标准数字格式字符串。用于将数值格式化显示为字符串。
|
||||
/// 使用Axx的形式:A是格式说明符的单字符,支持C货币、D十进制、E指数、F定点数、G常规、N数字、P百分比、R往返、X十六进制的。xx是精度说明,从0-99。
|
||||
/// 参考:https://docs.microsoft.com/zh-cn/dotnet/standard/base-types/standard-numeric-format-strings
|
||||
/// Standard number and date format string. Used to format a Double value or a DateTime date as a string.
|
||||
/// numericFormatter is used as an argument to either `Double.ToString ()` or `DateTime.ToString()`. <br />
|
||||
/// The number format uses the Axx format: A is a single-character format specifier that supports C currency,
|
||||
/// D decimal, E exponent, F fixed-point number, G regular, N digit, P percentage, R round trip, and X hexadecimal.
|
||||
/// xx is precision specification, from 0-99. E.g. F1, E2<br />
|
||||
/// Date format: Starts with `date`, which is used to format DateTime. Common date formats are:
|
||||
/// yyyy year, MM month, dd day, HH hour, mm minute, ss second, fff millisecond. For example: date:yyyy-MM-dd HH:mm:ss<br />
|
||||
/// Time format: Starts with `time`, which is used to format TimeSpan. Common time formats are:
|
||||
/// d day, HH hour, mm minute, ss second, fffffff fractional part.
|
||||
/// Only the version of Unity2018 or later can support formatting, and the characters inside should be escaped.
|
||||
/// For example: time:HH\:mm\:ss<br />
|
||||
/// number format reference: https://docs.microsoft.com/en-us/dotnet/standard/base-types/standard-numeric-format-strings<br/>
|
||||
/// date format reference: https://docs.microsoft.com/en-us/dotnet/standard/base-types/standard-numeric-format-strings<br/>
|
||||
/// Note: The date and time formats are only supported by 'v3.12.0' or later.<br/>
|
||||
/// ||标准数字和日期格式字符串。用于将Double数值或DateTime日期格式化显示为字符串。numericFormatter用来作为Double.ToString()或DateTime.ToString()的参数。<br/>
|
||||
/// 数字格式使用Axx的形式:A是格式说明符的单字符,支持C货币、D十进制、E指数、F定点数、G常规、N数字、P百分比、R往返、X十六进制的。xx是精度说明,从0-99。如:F1, E2<br/>
|
||||
/// 日期格式:以`date`开头,用来格式化DateTime,常见格式有:yyyy年,MM月,dd日,HH时,mm分,ss秒,fff毫秒。如:date:yyyy-MM-dd HH:mm:ss<br/>
|
||||
/// 时间格式:以`time`开头,用来格式化TimeSpan,常见格式有:d日,HH时,mm分,ss秒,fffffff小数部分。
|
||||
/// 需要Unity2018以上版本才支持格式化,并且里面的字符要转义。如:time:d\.HH\:mm\:ss<br/>
|
||||
/// 数值格式化参考:https://docs.microsoft.com/zh-cn/dotnet/standard/base-types/standard-numeric-format-strings <br/>
|
||||
/// 日期格式化参考:https://learn.microsoft.com/zh-cn/dotnet/standard/base-types/standard-date-and-time-format-strings <br/>
|
||||
/// 时间格式化参考:https://learn.microsoft.com/zh-cn/dotnet/standard/base-types/standard-timespan-format-strings <br/>
|
||||
/// 注意:date和time格式需要`v3.12.0`以上版本才支持。
|
||||
/// </summary>
|
||||
public string numericFormatter
|
||||
{
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace XCharts.Runtime
|
||||
var labelPos = chart.chartPosition + item.location.GetPosition(chart.chartWidth, chart.chartHeight);
|
||||
var label = ChartHelper.AddChartLabel(s_CommentObjectName + i, commentObj.transform, labelStyle, chart.theme.common,
|
||||
GetContent(item), Color.clear, TextAnchor.MiddleCenter);
|
||||
label.SetActive(comment.show && item.show);
|
||||
label.SetActive(comment.show && item.show, true);
|
||||
label.SetPosition(labelPos);
|
||||
label.text.SetLocalPosition(labelStyle.offset);
|
||||
}
|
||||
|
||||
@@ -184,16 +184,29 @@ namespace XCharts.Runtime
|
||||
set { if (PropertyUtil.SetClass(ref m_Formatter, value)) SetComponentDirty(); }
|
||||
}
|
||||
/// <summary>
|
||||
/// Standard number and date format string. Used to format a Double value or a DateTime date as a string. numericFormatter is used as an argument to either `Double.ToString ()` or `DateTime.ToString()`. <br />
|
||||
/// The number format uses the Axx format: A is a single-character format specifier that supports C currency, D decimal, E exponent, F fixed-point number, G regular, N digit, P percentage, R round trip, and X hexadecimal. xx is precision specification, from 0-99. E.g. F1, E2<br />
|
||||
/// Date format Common date formats are: yyyy year, MM month, dd day, HH hour, mm minute, ss second, fff millisecond. For example: yyyy-MM-dd HH:mm:ss<br />
|
||||
/// Standard number and date format string. Used to format a Double value or a DateTime date as a string.
|
||||
/// numericFormatter is used as an argument to either `Double.ToString ()` or `DateTime.ToString()`. <br />
|
||||
/// The number format uses the Axx format: A is a single-character format specifier that supports C currency,
|
||||
/// D decimal, E exponent, F fixed-point number, G regular, N digit, P percentage, R round trip, and X hexadecimal.
|
||||
/// xx is precision specification, from 0-99. E.g. F1, E2<br />
|
||||
/// Date format: Starts with `date`, which is used to format DateTime. Common date formats are:
|
||||
/// yyyy year, MM month, dd day, HH hour, mm minute, ss second, fff millisecond. For example: date:yyyy-MM-dd HH:mm:ss<br />
|
||||
/// Time format: Starts with `time`, which is used to format TimeSpan. Common time formats are:
|
||||
/// d day, HH hour, mm minute, ss second, fffffff fractional part.
|
||||
/// Only the version of Unity2018 or later can support formatting, and the characters inside should be escaped.
|
||||
/// For example: time:HH\:mm\:ss<br />
|
||||
/// number format reference: https://docs.microsoft.com/en-us/dotnet/standard/base-types/standard-numeric-format-strings<br/>
|
||||
/// date format reference: https://docs.microsoft.com/en-us/dotnet/standard/base-types/standard-numeric-format-strings<br/>
|
||||
/// Note: The date and time formats are only supported by 'v3.12.0' or later.<br/>
|
||||
/// ||标准数字和日期格式字符串。用于将Double数值或DateTime日期格式化显示为字符串。numericFormatter用来作为Double.ToString()或DateTime.ToString()的参数。<br/>
|
||||
/// 数字格式使用Axx的形式:A是格式说明符的单字符,支持C货币、D十进制、E指数、F定点数、G常规、N数字、P百分比、R往返、X十六进制的。xx是精度说明,从0-99。如:F1, E2<br/>
|
||||
/// 日期格式常见的格式:yyyy年,MM月,dd日,HH时,mm分,ss秒,fff毫秒。如:yyyy-MM-dd HH:mm:ss<br/>
|
||||
/// 日期格式:以`date`开头,用来格式化DateTime,常见格式有:yyyy年,MM月,dd日,HH时,mm分,ss秒,fff毫秒。如:date:yyyy-MM-dd HH:mm:ss<br/>
|
||||
/// 时间格式:以`time`开头,用来格式化TimeSpan,常见格式有:d日,HH时,mm分,ss秒,fffffff小数部分。
|
||||
/// 需要Unity2018以上版本才支持格式化,并且里面的字符要转义。如:time:d\.HH\:mm\:ss<br/>
|
||||
/// 数值格式化参考:https://docs.microsoft.com/zh-cn/dotnet/standard/base-types/standard-numeric-format-strings <br/>
|
||||
/// 日期格式化参考:https://learn.microsoft.com/zh-cn/dotnet/standard/base-types/standard-date-and-time-format-strings
|
||||
/// 日期格式化参考:https://learn.microsoft.com/zh-cn/dotnet/standard/base-types/standard-date-and-time-format-strings <br/>
|
||||
/// 时间格式化参考:https://learn.microsoft.com/zh-cn/dotnet/standard/base-types/standard-timespan-format-strings <br/>
|
||||
/// 注意:date和time格式需要`v3.12.0`以上版本才支持。
|
||||
/// </summary>
|
||||
public string numericFormatter
|
||||
{
|
||||
@@ -405,7 +418,7 @@ namespace XCharts.Runtime
|
||||
public virtual string GetFormatterContent(int labelIndex, double value, double minValue, double maxValue, bool isLog = false)
|
||||
{
|
||||
var newNumericFormatter = numericFormatter;
|
||||
if (value == 0)
|
||||
if (value == 0 && !DateTimeUtil.IsDateOrTimeRegex(newNumericFormatter))
|
||||
{
|
||||
newNumericFormatter = "f0";
|
||||
}
|
||||
@@ -444,6 +457,8 @@ namespace XCharts.Runtime
|
||||
}
|
||||
}
|
||||
|
||||
private static bool isDateFormatter = false;
|
||||
private static string newFormatter = null;
|
||||
public string GetFormatterDateTime(int labelIndex, double value, double minValue, double maxValue)
|
||||
{
|
||||
var timestamp = (int)value;
|
||||
@@ -457,7 +472,17 @@ namespace XCharts.Runtime
|
||||
{
|
||||
try
|
||||
{
|
||||
dateString = dateTime.ToString(numericFormatter);
|
||||
if(DateTimeUtil.IsDateOrTimeRegex(numericFormatter, ref isDateFormatter, ref newFormatter))
|
||||
{
|
||||
if(isDateFormatter)
|
||||
dateString = ChartCached.NumberToDateStr(timestamp, newFormatter);
|
||||
else
|
||||
dateString = ChartCached.NumberToTimeStr(timestamp, newFormatter);
|
||||
}
|
||||
else
|
||||
{
|
||||
dateString = dateTime.ToString(numericFormatter);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
@@ -87,11 +87,14 @@ namespace XCharts.Runtime
|
||||
ChartHelper.HideAllObject(legendObject);
|
||||
if (!legend.show) return;
|
||||
var textLimitInitFlag = false;
|
||||
var isAnySerieColorByData = SeriesHelper.IsAnyColorByDataSerie(chart.series);
|
||||
for (int i = 0; i < datas.Count; i++)
|
||||
{
|
||||
if (!SeriesHelper.IsLegalLegendName(datas[i])) continue;
|
||||
string legendName = datas[i];
|
||||
var legendContent = GetFormatterContent(legend, i, datas[i]);
|
||||
var serieIndex = isAnySerieColorByData ? 0 : i;
|
||||
var dataIndex = isAnySerieColorByData ? i : 0;
|
||||
var legendContent = GetFormatterContent(legend, dataIndex, datas[i], serieIndex);
|
||||
if (legend.textLimit.enable)
|
||||
legendContent = legend.textLimit.GetLimitContent(legendContent);
|
||||
var readIndex = chart.m_LegendRealShowName.IndexOf(datas[i]);
|
||||
@@ -158,7 +161,7 @@ namespace XCharts.Runtime
|
||||
legend.refreshComponent();
|
||||
}
|
||||
|
||||
private string GetFormatterContent(Legend legend, int dataIndex, string category)
|
||||
private string GetFormatterContent(Legend legend, int dataIndex, string category, int serieIndex)
|
||||
{
|
||||
#pragma warning disable 0618
|
||||
if (string.IsNullOrEmpty(legend.formatter) && string.IsNullOrEmpty(legend.labelStyle.formatter))
|
||||
@@ -168,7 +171,7 @@ namespace XCharts.Runtime
|
||||
var formatter = string.IsNullOrEmpty(legend.labelStyle.formatter) ? legend.formatter : legend.labelStyle.formatter;
|
||||
var content = formatter.Replace("{name}", category);
|
||||
content = content.Replace("{value}", category);
|
||||
var serie = chart.GetSerie(0);
|
||||
var serie = chart.GetSerie(serieIndex);
|
||||
FormatterHelper.ReplaceContent(ref content, dataIndex, legend.labelStyle.numericFormatter, serie, chart, category);
|
||||
return content;
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ namespace XCharts.Runtime
|
||||
|
||||
var label = ChartHelper.AddChartLabel("content", btnObj.transform, legend.labelStyle, theme.legend,
|
||||
content, contentColor, TextAnchor.MiddleLeft);
|
||||
label.SetActive(true);
|
||||
label.SetActive(true, true);
|
||||
|
||||
var item = new LegendItem();
|
||||
item.index = i;
|
||||
|
||||
@@ -45,7 +45,7 @@ namespace XCharts.Runtime
|
||||
var label = ChartHelper.AddChartLabel("label", m_MarkLineLabelRoot.transform, markArea.label, chart.theme.axis,
|
||||
component.text, Color.clear, TextAnchor.MiddleCenter);
|
||||
UpdateRuntimeData(component);
|
||||
label.SetActive(markArea.label.show);
|
||||
label.SetActive(markArea.label.show, true);
|
||||
label.SetPosition(component.runtimeLabelPosition);
|
||||
label.SetText(component.text);
|
||||
markArea.runtimeLabel = label;
|
||||
|
||||
@@ -86,7 +86,7 @@ namespace XCharts.Runtime
|
||||
content, Color.clear, TextAnchor.MiddleCenter);
|
||||
var pos = MarkLineHelper.GetLabelPosition(data);
|
||||
label.SetIconActive(false);
|
||||
label.SetActive(data.label.show && data.runtimeInGrid);
|
||||
label.SetActive(false, true);
|
||||
label.SetPosition(pos);
|
||||
data.runtimeLabel = label;
|
||||
};
|
||||
|
||||
@@ -53,7 +53,7 @@ namespace XCharts.Runtime
|
||||
|
||||
var label = ChartHelper.AddChartLabel(objName, radarObject.transform, radar.axisName.labelStyle,
|
||||
chart.theme.common, radar.GetFormatterIndicatorContent(i), Color.clear, TextAnchor.MiddleCenter);
|
||||
label.SetActive(radar.axisName.show && radar.indicator && radar.axisName.labelStyle.show);
|
||||
label.SetActive(radar.axisName.show && radar.indicator && radar.axisName.labelStyle.show, true);
|
||||
AxisHelper.AdjustCircleLabelPos(label, pos, radar.context.center, txtHig, radar.axisName.labelStyle.offset);
|
||||
}
|
||||
chart.RefreshBasePainter();
|
||||
|
||||
@@ -293,16 +293,29 @@ namespace XCharts.Runtime
|
||||
/// </summary>
|
||||
public string itemFormatter { get { return m_ItemFormatter; } set { m_ItemFormatter = value; } }
|
||||
/// <summary>
|
||||
/// Standard number and date format string. Used to format a Double value or a DateTime date as a string. numericFormatter is used as an argument to either `Double.ToString ()` or `DateTime.ToString()`. <br />
|
||||
/// The number format uses the Axx format: A is a single-character format specifier that supports C currency, D decimal, E exponent, F fixed-point number, G regular, N digit, P percentage, R round trip, and X hexadecimal. xx is precision specification, from 0-99. E.g. F1, E2<br />
|
||||
/// Date format Common date formats are: yyyy year, MM month, dd day, HH hour, mm minute, ss second, fff millisecond. For example: yyyy-MM-dd HH:mm:ss<br />
|
||||
/// Standard number and date format string. Used to format a Double value or a DateTime date as a string.
|
||||
/// numericFormatter is used as an argument to either `Double.ToString ()` or `DateTime.ToString()`. <br />
|
||||
/// The number format uses the Axx format: A is a single-character format specifier that supports C currency,
|
||||
/// D decimal, E exponent, F fixed-point number, G regular, N digit, P percentage, R round trip, and X hexadecimal.
|
||||
/// xx is precision specification, from 0-99. E.g. F1, E2<br />
|
||||
/// Date format: Starts with `date`, which is used to format DateTime. Common date formats are:
|
||||
/// yyyy year, MM month, dd day, HH hour, mm minute, ss second, fff millisecond. For example: date:yyyy-MM-dd HH:mm:ss<br />
|
||||
/// Time format: Starts with `time`, which is used to format TimeSpan. Common time formats are:
|
||||
/// d day, HH hour, mm minute, ss second, fffffff fractional part.
|
||||
/// Only the version of Unity2018 or later can support formatting, and the characters inside should be escaped.
|
||||
/// For example: time:HH\:mm\:ss<br />
|
||||
/// number format reference: https://docs.microsoft.com/en-us/dotnet/standard/base-types/standard-numeric-format-strings<br/>
|
||||
/// date format reference: https://docs.microsoft.com/en-us/dotnet/standard/base-types/standard-numeric-format-strings<br/>
|
||||
/// Note: The date and time formats are only supported by 'v3.12.0' or later.<br/>
|
||||
/// ||标准数字和日期格式字符串。用于将Double数值或DateTime日期格式化显示为字符串。numericFormatter用来作为Double.ToString()或DateTime.ToString()的参数。<br/>
|
||||
/// 数字格式使用Axx的形式:A是格式说明符的单字符,支持C货币、D十进制、E指数、F定点数、G常规、N数字、P百分比、R往返、X十六进制的。xx是精度说明,从0-99。如:F1, E2<br/>
|
||||
/// 日期格式常见的格式:yyyy年,MM月,dd日,HH时,mm分,ss秒,fff毫秒。如:yyyy-MM-dd HH:mm:ss<br/>
|
||||
/// 日期格式:以`date`开头,用来格式化DateTime,常见格式有:yyyy年,MM月,dd日,HH时,mm分,ss秒,fff毫秒。如:date:yyyy-MM-dd HH:mm:ss<br/>
|
||||
/// 时间格式:以`time`开头,用来格式化TimeSpan,常见格式有:d日,HH时,mm分,ss秒,fffffff小数部分。
|
||||
/// 需要Unity2018以上版本才支持格式化,并且里面的字符要转义。如:time:d\.HH\:mm\:ss<br/>
|
||||
/// 数值格式化参考:https://docs.microsoft.com/zh-cn/dotnet/standard/base-types/standard-numeric-format-strings <br/>
|
||||
/// 日期格式化参考:https://learn.microsoft.com/zh-cn/dotnet/standard/base-types/standard-date-and-time-format-strings
|
||||
/// 日期格式化参考:https://learn.microsoft.com/zh-cn/dotnet/standard/base-types/standard-date-and-time-format-strings <br/>
|
||||
/// 时间格式化参考:https://learn.microsoft.com/zh-cn/dotnet/standard/base-types/standard-timespan-format-strings <br/>
|
||||
/// 注意:date和time格式需要`v3.12.0`以上版本才支持。
|
||||
/// </summary>
|
||||
public string numericFormatter
|
||||
{
|
||||
|
||||
@@ -255,7 +255,7 @@ namespace XCharts.Runtime
|
||||
{
|
||||
if (label == null) return;
|
||||
if (double.IsNaN(axis.context.pointerValue)) return;
|
||||
label.SetActive(true);
|
||||
label.SetActive(true, true);
|
||||
label.SetTextActive(true);
|
||||
label.SetPosition(axis.context.pointerLabelPosition + axis.indicatorLabel.offset);
|
||||
|
||||
@@ -359,7 +359,7 @@ namespace XCharts.Runtime
|
||||
serie.context.pointerEnter = true;
|
||||
serie.context.pointerAxisDataIndexs.Add(index);
|
||||
serie.context.pointerItemDataIndex = index;
|
||||
yAxis.context.axisTooltipValue = yAxis.context.pointerValue;
|
||||
yAxis.context.axisTooltipValue = index;
|
||||
}
|
||||
}
|
||||
else if (yAxis.IsTime())
|
||||
@@ -571,11 +571,13 @@ namespace XCharts.Runtime
|
||||
var isTriggerByAxis = false;
|
||||
var isTriggerByItem = tooltip.context.trigger == Tooltip.Trigger.Item;
|
||||
var dataIndex = -1;
|
||||
var timestamp = -1;
|
||||
double axisRange = 0;
|
||||
tooltip.context.data.param.Clear();
|
||||
tooltip.context.pointer = GetTooltipPointerPos();
|
||||
if (m_PointerContainer is GridCoord)
|
||||
{
|
||||
GetAxisCategory(m_PointerContainer.index, ref dataIndex, ref category);
|
||||
GetAxisCategory(m_PointerContainer.index, ref dataIndex, ref category, ref timestamp, ref axisRange);
|
||||
if (tooltip.context.trigger == Tooltip.Trigger.Axis)
|
||||
{
|
||||
isTriggerByAxis = true;
|
||||
@@ -585,7 +587,9 @@ namespace XCharts.Runtime
|
||||
tooltip.context.data.title = series[0].serieName;
|
||||
}
|
||||
else
|
||||
{
|
||||
tooltip.context.data.title = category;
|
||||
}
|
||||
}
|
||||
else if (tooltip.context.trigger == Tooltip.Trigger.Item)
|
||||
{
|
||||
@@ -604,6 +608,15 @@ namespace XCharts.Runtime
|
||||
serie.context.isTriggerByAxis = isTriggerByAxis;
|
||||
if (isTriggerByAxis && dataIndex >= 0 && serie.context.pointerItemDataIndex < 0)
|
||||
serie.context.pointerItemDataIndex = dataIndex;
|
||||
if (timestamp >= 0)
|
||||
{
|
||||
showCategory = false;
|
||||
var serieData = serie.GetSerieData(serie.context.pointerItemDataIndex);
|
||||
if (serieData != null)
|
||||
{
|
||||
tooltip.context.data.title = DateTimeUtil.GetDefaultDateTimeString((int)serieData.GetData(0), axisRange);
|
||||
}
|
||||
}
|
||||
serie.handler.UpdateTooltipSerieParams(dataIndex, showCategory, category,
|
||||
tooltip.marker, tooltip.itemFormatter, tooltip.numericFormatter,
|
||||
tooltip.ignoreDataDefaultContent,
|
||||
@@ -626,20 +639,28 @@ namespace XCharts.Runtime
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool GetAxisCategory(int gridIndex, ref int dataIndex, ref string category)
|
||||
private bool GetAxisCategory(int gridIndex, ref int dataIndex, ref string category, ref int timestamp, ref double axisRange)
|
||||
{
|
||||
foreach (var component in chart.components)
|
||||
{
|
||||
if (component is Axis)
|
||||
{
|
||||
var axis = component as Axis;
|
||||
if (axis.gridIndex == gridIndex && axis.IsCategory())
|
||||
if (axis.gridIndex == gridIndex)
|
||||
{
|
||||
dataIndex = double.IsNaN(axis.context.pointerValue)
|
||||
? axis.context.dataZoomStartIndex
|
||||
: axis.context.dataZoomStartIndex + (int)axis.context.axisTooltipValue;
|
||||
category = axis.GetData(dataIndex);
|
||||
return true;
|
||||
if (axis.IsCategory())
|
||||
{
|
||||
dataIndex = double.IsNaN(axis.context.pointerValue)
|
||||
? axis.context.dataZoomStartIndex
|
||||
: (int)axis.context.axisTooltipValue;
|
||||
category = axis.GetData(dataIndex);
|
||||
return true;
|
||||
}
|
||||
else if (axis.IsTime())
|
||||
{
|
||||
timestamp = (int)axis.context.pointerValue;
|
||||
axisRange = axis.context.minMaxRange;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,6 +175,7 @@ namespace XCharts.Runtime
|
||||
m_ChartWidth = m_GraphWidth;
|
||||
m_ChartHeight = m_GraphHeight;
|
||||
rectTransform.sizeDelta = new Vector2(m_ChartWidth, m_ChartHeight);
|
||||
UpdateSize();
|
||||
}
|
||||
ChartHelper.HideAllObject(transform);
|
||||
m_ChartInited = true;
|
||||
|
||||
@@ -56,7 +56,7 @@ namespace XCharts.Runtime
|
||||
protected override void Awake()
|
||||
{
|
||||
raycastTarget = false;
|
||||
SetActive(true);
|
||||
m_Active = ChartHelper.IsActiveByScale(gameObject);
|
||||
}
|
||||
|
||||
public void SetTextPadding(TextPadding padding)
|
||||
@@ -200,10 +200,13 @@ namespace XCharts.Runtime
|
||||
return m_Active;
|
||||
}
|
||||
|
||||
public void SetActive(bool flag)
|
||||
public void SetActive(bool flag, bool force = false)
|
||||
{
|
||||
m_Active = flag;
|
||||
ChartHelper.SetActive(gameObject, flag);
|
||||
if (m_Active == flag && !force) return;
|
||||
if (ChartHelper.SetActive(gameObject, flag))
|
||||
{
|
||||
m_Active = flag;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetTextActive(bool flag)
|
||||
@@ -247,7 +250,7 @@ namespace XCharts.Runtime
|
||||
AdjustIconPos();
|
||||
if (m_HideIconIfTextEmpty && isIconActive)
|
||||
{
|
||||
ChartHelper.SetActive(m_IconImage.gameObject, !string.IsNullOrEmpty(text));
|
||||
SetIconActive(!string.IsNullOrEmpty(text));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -67,7 +67,7 @@ namespace XCharts.Runtime
|
||||
{
|
||||
var label = ChartHelper.AddChartLabel(name, parent, labelStyle, theme.common,
|
||||
"", color, TextAnchor.MiddleCenter);
|
||||
label.SetActive(labelStyle.show);
|
||||
label.SetActive(labelStyle.show, true);
|
||||
return label.gameObject;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace XCharts.Runtime
|
||||
private const string NUMERIC_FORMATTER_X = "X";
|
||||
private const string NUMERIC_FORMATTER_x = "x";
|
||||
private static readonly string s_DefaultAxis = "axis_";
|
||||
private static CultureInfo ci = new CultureInfo("en-us"); // "en-us", "zh-cn", "ar-iq", "de-de"
|
||||
private static CultureInfo ci = GetDefaultCultureInfo(); // "en-us", "zh-cn", "ar-iq", "de-de"
|
||||
private static Dictionary<Color, string> s_ColorToStr = new Dictionary<Color, string>(100);
|
||||
private static Dictionary<int, string> s_SerieLabelName = new Dictionary<int, string>(1000);
|
||||
private static Dictionary<Color, string> s_ColorDotStr = new Dictionary<Color, string>(100);
|
||||
@@ -23,6 +23,20 @@ namespace XCharts.Runtime
|
||||
private static Dictionary<double, Dictionary<string, string>> s_NumberToStr = new Dictionary<double, Dictionary<string, string>>();
|
||||
private static Dictionary<int, Dictionary<string, string>> s_PrecisionToStr = new Dictionary<int, Dictionary<string, string>>();
|
||||
private static Dictionary<string, Dictionary<int, string>> s_StringIntDict = new Dictionary<string, Dictionary<int, string>>();
|
||||
private static Dictionary<double, DateTime> s_TimestampToDateTimeDict = new Dictionary<double, DateTime>();
|
||||
private static Dictionary<double, TimeSpan> s_NumberToTimeSpanDict = new Dictionary<double, TimeSpan>();
|
||||
|
||||
private static CultureInfo GetDefaultCultureInfo()
|
||||
{
|
||||
try
|
||||
{
|
||||
return new CultureInfo("en-us");
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return CultureInfo.InvariantCulture;
|
||||
}
|
||||
}
|
||||
|
||||
public static string FloatToStr(double value, string numericFormatter = "F", int precision = 0)
|
||||
{
|
||||
@@ -52,10 +66,19 @@ namespace XCharts.Runtime
|
||||
}
|
||||
if (!s_NumberToStr[value].ContainsKey(formatter))
|
||||
{
|
||||
bool isDateFormatter = false;
|
||||
string newFormatter = null;
|
||||
if (string.IsNullOrEmpty(formatter))
|
||||
{
|
||||
s_NumberToStr[value][formatter] = value.ToString();
|
||||
}
|
||||
else if (DateTimeUtil.IsDateOrTimeRegex(formatter,ref isDateFormatter, ref newFormatter))
|
||||
{
|
||||
if(isDateFormatter)
|
||||
s_NumberToStr[value][formatter] = NumberToDateStr(value, newFormatter);
|
||||
else
|
||||
s_NumberToStr[value][formatter] = NumberToTimeStr(value, newFormatter);
|
||||
}
|
||||
else if (formatter.StartsWith(NUMERIC_FORMATTER_D) ||
|
||||
formatter.StartsWith(NUMERIC_FORMATTER_d) ||
|
||||
formatter.StartsWith(NUMERIC_FORMATTER_X) ||
|
||||
@@ -77,6 +100,56 @@ namespace XCharts.Runtime
|
||||
return NumberToStr(value, numericFormatter);
|
||||
}
|
||||
|
||||
public static string NumberToDateStr(double timestamp, string formatter)
|
||||
{
|
||||
var dt = NumberToDateTime(timestamp);
|
||||
try
|
||||
{
|
||||
return dt.ToString(formatter, ci);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
XLog.LogError("Not support DateTime format: " + formatter);
|
||||
return timestamp.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
public static string NumberToTimeStr(double timestamp, string formatter)
|
||||
{
|
||||
try
|
||||
{
|
||||
var ts = NumberToTimeSpan(timestamp);
|
||||
#if UNITY_2018_3_OR_NEWER
|
||||
return ts.ToString(formatter, ci);
|
||||
#else
|
||||
return ts.ToString();
|
||||
#endif
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
XLog.LogError("Not support TimeSpan format: " + formatter);
|
||||
return timestamp.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
public static DateTime NumberToDateTime(double timestamp)
|
||||
{
|
||||
if (!s_TimestampToDateTimeDict.ContainsKey(timestamp))
|
||||
{
|
||||
s_TimestampToDateTimeDict[timestamp] = DateTimeUtil.GetDateTime(timestamp);
|
||||
}
|
||||
return s_TimestampToDateTimeDict[timestamp];
|
||||
}
|
||||
|
||||
public static TimeSpan NumberToTimeSpan(double timestamp)
|
||||
{
|
||||
if(!s_NumberToTimeSpanDict.ContainsKey(timestamp))
|
||||
{
|
||||
s_NumberToTimeSpanDict[timestamp] = TimeSpan.FromSeconds(timestamp);
|
||||
}
|
||||
return s_NumberToTimeSpanDict[timestamp];
|
||||
}
|
||||
|
||||
public static string ColorToStr(Color color)
|
||||
{
|
||||
if (s_ColorToStr.ContainsKey(color))
|
||||
|
||||
@@ -41,22 +41,39 @@ namespace XCharts.Runtime
|
||||
return s_Builder.ToString();
|
||||
}
|
||||
|
||||
public static void SetActive(GameObject gameObject, bool active)
|
||||
public static bool IsActiveByScale(GameObject gameObject)
|
||||
{
|
||||
if (gameObject == null) return;
|
||||
SetActive(gameObject.transform, active);
|
||||
if (gameObject == null) return false;
|
||||
return IsActiveByScale(gameObject.transform);
|
||||
}
|
||||
|
||||
public static void SetActive(Image image, bool active)
|
||||
public static bool IsActiveByScale(Image image)
|
||||
{
|
||||
if (image == null) return;
|
||||
SetActive(image.gameObject, active);
|
||||
if (image == null) return false;
|
||||
return IsActiveByScale(image.gameObject);
|
||||
}
|
||||
|
||||
public static void SetActive(Text text, bool active)
|
||||
public static bool IsActiveByScale(Transform transform)
|
||||
{
|
||||
if (text == null) return;
|
||||
SetActive(text.gameObject, active);
|
||||
return transform.localScale != Vector3.zero;
|
||||
}
|
||||
|
||||
public static bool SetActive(GameObject gameObject, bool active)
|
||||
{
|
||||
if (gameObject == null) return false;
|
||||
return SetActive(gameObject.transform, active);
|
||||
}
|
||||
|
||||
public static bool SetActive(Image image, bool active)
|
||||
{
|
||||
if (image == null) return false;
|
||||
return SetActive(image.gameObject, active);
|
||||
}
|
||||
|
||||
public static bool SetActive(Text text, bool active)
|
||||
{
|
||||
if (text == null) return false;
|
||||
return SetActive(text.gameObject, active);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -64,12 +81,14 @@ namespace XCharts.Runtime
|
||||
/// </summary>
|
||||
/// <param name="transform"></param>
|
||||
/// <param name="active"></param>
|
||||
public static void SetActive(Transform transform, bool active)
|
||||
public static bool SetActive(Transform transform, bool active)
|
||||
{
|
||||
if (transform == null) return;
|
||||
if (transform == null) return false;
|
||||
if (active) transform.localScale = Vector3.one;
|
||||
else transform.localScale = Vector3.zero;
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void HideAllObject(GameObject obj, string match = null)
|
||||
{
|
||||
if (obj == null) return;
|
||||
@@ -460,7 +479,7 @@ namespace XCharts.Runtime
|
||||
label.color = (!labelStyle.background.autoColor || autoColor == Color.clear) ?
|
||||
labelStyle.background.color : autoColor;
|
||||
label.sprite = labelStyle.background.sprite;
|
||||
if(label.type != labelStyle.background.type)
|
||||
if (label.type != labelStyle.background.type)
|
||||
label.type = labelStyle.background.type;
|
||||
}
|
||||
else
|
||||
@@ -536,7 +555,7 @@ namespace XCharts.Runtime
|
||||
{
|
||||
var label = ChartHelper.AddChartLabel(name, parent, labelStyle, theme.tooltip,
|
||||
"", Color.clear, alignment);
|
||||
label.SetActive(tooltip.show && labelStyle.show);
|
||||
label.SetActive(tooltip.show && labelStyle.show, true);
|
||||
return label;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,8 +21,8 @@ namespace XCharts.Runtime
|
||||
[ExecuteInEditMode]
|
||||
public static class XChartsMgr
|
||||
{
|
||||
public static readonly string version = "3.11.0";
|
||||
public static readonly int versionDate = 20240616;
|
||||
public static readonly string version = "3.12.0";
|
||||
public static readonly int versionDate = 20240930;
|
||||
public static string fullVersion { get { return version + "-" + versionDate; } }
|
||||
|
||||
internal static List<BaseChart> chartList = new List<BaseChart>();
|
||||
|
||||
@@ -35,12 +35,27 @@ namespace XCharts.Runtime
|
||||
return;
|
||||
}
|
||||
var gridXY = (isY ? grid.context.x : grid.context.y);
|
||||
var min = gridXY;
|
||||
var max = gridXY + (isY ? grid.context.width : grid.context.height);
|
||||
var start = 0f;
|
||||
switch(serie.areaStyle.origin)
|
||||
{
|
||||
case AreaStyle.AreaOrigin.Start:
|
||||
start = min;
|
||||
break;
|
||||
case AreaStyle.AreaOrigin.End:
|
||||
start = max;
|
||||
break;
|
||||
default:
|
||||
start = gridXY + relativedAxis.context.offset;
|
||||
break;
|
||||
}
|
||||
if (lastStackSerie == null)
|
||||
{
|
||||
DrawSerieLineNormalArea(vh, serie, isY,
|
||||
gridXY + relativedAxis.context.offset,
|
||||
gridXY,
|
||||
gridXY + (isY ? grid.context.width : grid.context.height),
|
||||
start,
|
||||
min,
|
||||
max,
|
||||
areaColor,
|
||||
areaToColor,
|
||||
visualMap,
|
||||
@@ -52,9 +67,9 @@ namespace XCharts.Runtime
|
||||
else
|
||||
{
|
||||
DrawSerieLineStackArea(vh, serie, lastStackSerie, isY,
|
||||
gridXY + relativedAxis.context.offset,
|
||||
gridXY,
|
||||
gridXY + (isY ? grid.context.width : grid.context.height),
|
||||
start,
|
||||
min,
|
||||
max,
|
||||
areaColor,
|
||||
areaToColor,
|
||||
visualMap,
|
||||
|
||||
@@ -470,7 +470,7 @@ namespace XCharts.Runtime
|
||||
var rad = Mathf.Deg2Rad * serieData.context.halfAngle;
|
||||
var lineLength1 = ChartHelper.GetActualValue(labelLine.lineLength1, serie.context.outsideRadius);
|
||||
var lineLength2 = ChartHelper.GetActualValue(labelLine.lineLength2, serie.context.outsideRadius);
|
||||
var radius = lineLength1 + serie.context.outsideRadius - serieData.context.outsideRadius;
|
||||
var radius = lineLength1;
|
||||
var pos1 = startPosition;
|
||||
var pos2 = pos1 + new Vector3(Mathf.Sin(rad) * radius, Mathf.Cos(rad) * radius);
|
||||
var pos5 = labelLine.lineType == LabelLine.LineType.HorizontalLine
|
||||
|
||||
@@ -9,7 +9,20 @@ namespace XCharts.Runtime
|
||||
[SerieDataExtraField()]
|
||||
public class Ring : Serie
|
||||
{
|
||||
[SerializeField][Since("v3.12.0")] private bool m_RadiusGradient = false;
|
||||
|
||||
/// <summary>
|
||||
/// Whether to use gradient color in pie chart.
|
||||
/// || 是否开启半径方向的渐变效果。
|
||||
/// </summary>
|
||||
public bool radiusGradient
|
||||
{
|
||||
get { return m_RadiusGradient; }
|
||||
set { if (PropertyUtil.SetStruct(ref m_RadiusGradient, value)) { SetVerticesDirty(); } }
|
||||
}
|
||||
|
||||
public override SerieColorBy defaultColorBy { get { return SerieColorBy.Data; } }
|
||||
|
||||
public static Serie AddDefaultSerie(BaseChart chart, string serieName)
|
||||
{
|
||||
var serie = chart.AddSerie<Ring>(serieName);
|
||||
|
||||
@@ -162,7 +162,7 @@ namespace XCharts.Runtime
|
||||
DrawBackground(vh, serie, serieData, j, insideRadius, outsideRadius);
|
||||
UGL.DrawDoughnut(vh, serie.context.center, insideRadius, outsideRadius, itemColor, itemToColor,
|
||||
Color.clear, startDegree, toDegree, borderWidth, borderColor, 0, chart.settings.cicleSmoothness,
|
||||
roundCap, serie.clockwise);
|
||||
roundCap, serie.clockwise, serie.radiusGradient);
|
||||
DrawCenter(vh, serie, serieData, insideRadius, j == data.Count - 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -155,6 +155,7 @@ namespace XCharts.Runtime
|
||||
{
|
||||
Color32 color1, toColor1;
|
||||
bool needInteract = false;
|
||||
serie.context.colorIndex = chart.GetLegendRealShowNameIndex(serie.legendName);
|
||||
foreach (var serieData in serie.data)
|
||||
{
|
||||
var state = SerieHelper.GetSerieState(serie, serieData, true);
|
||||
@@ -367,7 +368,7 @@ namespace XCharts.Runtime
|
||||
var textName = string.Format("{0}_{1}_{2}_{3}", s_SerieLabelObjectName, serie.index, serieData.index, i);
|
||||
var label = ChartHelper.AddChartLabel(textName, serieLabelRoot.transform, serieLabel, chart.theme.common,
|
||||
"", dataAutoColor, TextAnchor.MiddleCenter);
|
||||
label.SetActive(serieLabel.show);
|
||||
label.SetActive(false, true);
|
||||
serieData.context.dataLabels.Add(label);
|
||||
}
|
||||
}
|
||||
@@ -376,7 +377,7 @@ namespace XCharts.Runtime
|
||||
var textName = ChartCached.GetSerieLabelName(s_SerieLabelObjectName, serie.index, serieData.index);
|
||||
var label = ChartHelper.AddChartLabel(textName, serieLabelRoot.transform, serieLabel, chart.theme.common,
|
||||
"", dataAutoColor, TextAnchor.MiddleCenter);
|
||||
label.SetActive(serieLabel.show);
|
||||
label.SetActive(false, true);
|
||||
serieData.labelObject = label;
|
||||
}
|
||||
|
||||
@@ -440,7 +441,7 @@ namespace XCharts.Runtime
|
||||
var label = ChartHelper.AddChartLabel("title_" + 0, serieTitleRoot.transform, titleStyle, chart.theme.common,
|
||||
content, color, TextAnchor.MiddleCenter);
|
||||
serie.context.titleObject = label;
|
||||
label.SetActive(titleStyle.show);
|
||||
label.SetActive(titleStyle.show, true);
|
||||
var labelPosition = GetSerieDataTitlePosition(null, titleStyle);
|
||||
var offset = titleStyle.GetOffset(serie.context.insideRadius);
|
||||
label.SetPosition(labelPosition + offset);
|
||||
@@ -467,7 +468,7 @@ namespace XCharts.Runtime
|
||||
var label = ChartHelper.AddChartLabel("title_" + i, serieTitleRoot.transform, titleStyle, chart.theme.common,
|
||||
content, color, TextAnchor.MiddleCenter);
|
||||
serieData.titleObject = label;
|
||||
label.SetActive(titleStyle.show);
|
||||
label.SetActive(titleStyle.show, true);
|
||||
var labelPosition = GetSerieDataTitlePosition(serieData, titleStyle);
|
||||
var offset = titleStyle.GetOffset(serie.context.insideRadius);
|
||||
label.SetPosition(labelPosition + offset);
|
||||
@@ -484,6 +485,8 @@ namespace XCharts.Runtime
|
||||
var dataAddDuration = serie.animation.GetAdditionDuration();
|
||||
var unscaledTime = serie.animation.unscaledTime;
|
||||
var needCheck = serie.context.dataIndexs.Count > 0;
|
||||
var allLabelZeroPosition = true;
|
||||
var anyLabelActive = false;
|
||||
foreach (var serieData in serie.data)
|
||||
{
|
||||
if (serieData.labelObject == null && serieData.context.dataLabels.Count <= 0)
|
||||
@@ -518,7 +521,16 @@ namespace XCharts.Runtime
|
||||
SerieLabelHelper.GetFormatterContent(serie, serieData, value, total,
|
||||
currLabel, color, chart);
|
||||
var offset = GetSerieDataLabelOffset(serieData, currLabel);
|
||||
labelObject.SetActive(currLabel.show && !isIgnore && !serie.IsMinShowLabelValue(value));
|
||||
var active = currLabel.show && !isIgnore && !serie.IsMinShowLabelValue(value);
|
||||
if (active)
|
||||
{
|
||||
anyLabelActive = true;
|
||||
if (!ChartHelper.IsZeroVector(serieData.context.dataPoints[i]))
|
||||
{
|
||||
allLabelZeroPosition = false;
|
||||
}
|
||||
}
|
||||
labelObject.SetActive(active);
|
||||
labelObject.SetText(content);
|
||||
labelObject.SetPosition(serieData.context.dataPoints[i] + offset);
|
||||
labelObject.UpdateIcon(currLabel.icon);
|
||||
@@ -539,10 +551,19 @@ namespace XCharts.Runtime
|
||||
ChartCached.NumberToStr(value, currLabel.numericFormatter) :
|
||||
SerieLabelHelper.GetFormatterContent(serie, serieData, value, total,
|
||||
currLabel, color, chart);
|
||||
serieData.SetLabelActive(currLabel.show && !isIgnore && !serie.IsMinShowLabelValue(value));
|
||||
var labelPos = UpdateLabelPosition(serieData, currLabel);
|
||||
var active = currLabel.show && !isIgnore && !serie.IsMinShowLabelValue(value);
|
||||
if (active)
|
||||
{
|
||||
anyLabelActive = true;
|
||||
if (!ChartHelper.IsZeroVector(labelPos))
|
||||
{
|
||||
allLabelZeroPosition = false;
|
||||
}
|
||||
}
|
||||
serieData.SetLabelActive(active);
|
||||
serieData.labelObject.UpdateIcon(currLabel.icon);
|
||||
serieData.labelObject.SetText(content);
|
||||
UpdateLabelPosition(serieData, currLabel);
|
||||
if (currLabel.textStyle.autoColor)
|
||||
{
|
||||
var dataAutoColor = GetSerieDataAutoColor(serieData);
|
||||
@@ -556,6 +577,13 @@ namespace XCharts.Runtime
|
||||
serieData.SetLabelActive(false);
|
||||
}
|
||||
}
|
||||
if (anyLabelActive && allLabelZeroPosition)
|
||||
{
|
||||
foreach (var serieData in serie.data)
|
||||
{
|
||||
serieData.SetLabelActive(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void RefreshEndLabelInternal()
|
||||
@@ -579,7 +607,7 @@ namespace XCharts.Runtime
|
||||
m_EndLabel.isAnimationEnd = serie.animation.IsFinish();
|
||||
}
|
||||
|
||||
protected void UpdateLabelPosition(SerieData serieData, LabelStyle currLabel)
|
||||
protected Vector3 UpdateLabelPosition(SerieData serieData, LabelStyle currLabel)
|
||||
{
|
||||
var labelPosition = GetSerieDataLabelPosition(serieData, currLabel);
|
||||
var offset = GetSerieDataLabelOffset(serieData, currLabel);
|
||||
@@ -591,6 +619,7 @@ namespace XCharts.Runtime
|
||||
else
|
||||
serieData.labelObject.SetRotate(-serieData.context.angle + currLabel.rotate);
|
||||
}
|
||||
return labelPosition;
|
||||
}
|
||||
|
||||
public virtual Vector3 GetSerieDataLabelPosition(SerieData serieData, LabelStyle label)
|
||||
|
||||
@@ -132,6 +132,21 @@ namespace XCharts.Runtime
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// check if series has any serie which is color by data.
|
||||
/// || 是否有任何一个系列是按数据颜色的。
|
||||
/// </summary>
|
||||
/// <param name="series"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsAnyColorByDataSerie(List<Serie> series)
|
||||
{
|
||||
foreach (var serie in series)
|
||||
{
|
||||
if (serie.defaultColorBy == SerieColorBy.Data) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获得上一个同堆叠且显示的serie。
|
||||
/// </summary>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.RegularExpressions;
|
||||
using UnityEngine;
|
||||
|
||||
namespace XCharts.Runtime
|
||||
@@ -7,10 +8,11 @@ namespace XCharts.Runtime
|
||||
public static class DateTimeUtil
|
||||
{
|
||||
#if UNITY_2018_3_OR_NEWER
|
||||
private static readonly DateTime k_DateTime1970 = TimeZoneInfo.ConvertTimeFromUtc(new DateTime(1970, 1, 1), TimeZoneInfo.Local);
|
||||
private static readonly DateTime k_LocalDateTime1970 = TimeZoneInfo.ConvertTimeFromUtc(new DateTime(1970, 1, 1), TimeZoneInfo.Local);
|
||||
#else
|
||||
private static readonly DateTime k_DateTime1970 = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1));
|
||||
private static readonly DateTime k_LocalDateTime1970 = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1));
|
||||
#endif
|
||||
private static readonly DateTime k_DateTime1970 = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
|
||||
public static readonly int ONE_SECOND = 1;
|
||||
public static readonly int ONE_MINUTE = ONE_SECOND * 60;
|
||||
public static readonly int ONE_HOUR = ONE_MINUTE * 60;
|
||||
@@ -26,22 +28,54 @@ namespace XCharts.Runtime
|
||||
//private static string s_MinuteDateFormatter = "mm:ss";
|
||||
private static string s_SecondDateFormatter = "HH:mm:ss";
|
||||
//private static string s_FullDateFormatter = "yyyy-MM-dd HH:mm:ss";
|
||||
private static Regex s_DateOrTimeRegex = new Regex(@"^(date|time)\s*[:\s]+(.*)", RegexOptions.IgnoreCase);
|
||||
|
||||
public static bool IsDateOrTimeRegex(string regex)
|
||||
{
|
||||
return regex.StartsWith("date") || regex.StartsWith("time");
|
||||
}
|
||||
|
||||
public static bool IsDateOrTimeRegex(string regex, ref bool date, ref string formatter)
|
||||
{
|
||||
if(IsDateOrTimeRegex(regex))
|
||||
{
|
||||
if(regex == "date" || regex == "time")
|
||||
{
|
||||
date = regex == "date";
|
||||
formatter = "";
|
||||
return true;
|
||||
}
|
||||
var mc = s_DateOrTimeRegex.Matches(regex);
|
||||
date = mc[0].Groups[1].Value == "date";
|
||||
formatter = mc[0].Groups[2].Value;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static int GetTimestamp()
|
||||
{
|
||||
return (int)(DateTime.Now - k_DateTime1970).TotalSeconds;
|
||||
return (int)(DateTime.Now - k_LocalDateTime1970).TotalSeconds;
|
||||
}
|
||||
|
||||
public static int GetTimestamp(DateTime time)
|
||||
public static int GetTimestamp(DateTime time, bool local = false)
|
||||
{
|
||||
return (int)(time - k_DateTime1970).TotalSeconds;
|
||||
if (local)
|
||||
{
|
||||
return (int)(time - k_LocalDateTime1970).TotalSeconds;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (int)(time - k_DateTime1970).TotalSeconds;
|
||||
}
|
||||
}
|
||||
|
||||
public static int GetTimestamp(string dateTime)
|
||||
public static int GetTimestamp(string dateTime, bool local = false)
|
||||
{
|
||||
try
|
||||
{
|
||||
return GetTimestamp(DateTime.Parse(dateTime));
|
||||
|
||||
return GetTimestamp(DateTime.Parse(dateTime), local);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -49,9 +83,24 @@ namespace XCharts.Runtime
|
||||
}
|
||||
}
|
||||
|
||||
public static DateTime GetDateTime(int timestamp)
|
||||
public static DateTime GetDateTime(double timestamp, bool local = true)
|
||||
{
|
||||
return k_DateTime1970.AddSeconds(timestamp);
|
||||
return local ? k_LocalDateTime1970.AddSeconds(timestamp) : k_DateTime1970.AddSeconds(timestamp);
|
||||
}
|
||||
|
||||
public static string GetDefaultDateTimeString(int timestamp, double range = 0)
|
||||
{
|
||||
var dateString = String.Empty;
|
||||
var dateTime = GetDateTime(timestamp);
|
||||
if (range <= 0 || range >= DateTimeUtil.ONE_DAY)
|
||||
{
|
||||
dateString = dateTime.ToString("yyyy-MM-dd");
|
||||
}
|
||||
else
|
||||
{
|
||||
dateString = dateTime.ToString(s_SecondDateFormatter);
|
||||
}
|
||||
return dateString;
|
||||
}
|
||||
|
||||
internal static string GetDateTimeFormatString(DateTime dateTime, double range)
|
||||
@@ -97,17 +146,20 @@ namespace XCharts.Runtime
|
||||
/// <param name="splitNumber"></param>
|
||||
internal static float UpdateTimeAxisDateTimeList(List<double> list, int minTimestamp, int maxTimestamp, int splitNumber)
|
||||
{
|
||||
var firstValue = list.Count > 0 ? list[0] : 0;
|
||||
var secondValue = list.Count > 1 ? list[1] : 0;
|
||||
list.Clear();
|
||||
var range = maxTimestamp - minTimestamp;
|
||||
if (range <= 0) return 0;
|
||||
if (splitNumber <= 0) splitNumber = 1;
|
||||
var dtMin = DateTimeUtil.GetDateTime(minTimestamp);
|
||||
var dtMax = DateTimeUtil.GetDateTime(maxTimestamp);
|
||||
int tick = 0;
|
||||
if (range >= ONE_YEAR * MIN_TIME_SPLIT_NUMBER)
|
||||
{
|
||||
var num = Math.Max(range / (splitNumber * ONE_YEAR), 1);
|
||||
var dtStart = new DateTime(dtMin.Year + 1, 1, 1);
|
||||
var num = splitNumber <= 0 ? GetSplitNumber(range, ONE_YEAR) : Math.Max(range / (splitNumber * ONE_YEAR), 1);
|
||||
var dtStart = (firstValue == 0 || secondValue == 0 || (minTimestamp > firstValue && minTimestamp > secondValue))
|
||||
? (new DateTime(dtMin.Year, dtMin.Month, 1).AddMonths(1))
|
||||
: (minTimestamp > firstValue ? DateTimeUtil.GetDateTime(secondValue) : DateTimeUtil.GetDateTime(firstValue));
|
||||
tick = num * 365 * 24 * 3600;
|
||||
while (dtStart.Ticks < dtMax.Ticks)
|
||||
{
|
||||
@@ -117,8 +169,10 @@ namespace XCharts.Runtime
|
||||
}
|
||||
else if (range >= ONE_MONTH * MIN_TIME_SPLIT_NUMBER)
|
||||
{
|
||||
var num = Math.Max(range / (splitNumber * ONE_MONTH), 1);
|
||||
var dtStart = new DateTime(dtMin.Year, dtMin.Month, 1).AddMonths(1);
|
||||
var num = splitNumber <= 0 ? GetSplitNumber(range, ONE_MONTH) : Math.Max(range / (splitNumber * ONE_MONTH), 1);
|
||||
var dtStart = (firstValue == 0 || secondValue == 0 || (minTimestamp > firstValue && minTimestamp > secondValue))
|
||||
? (new DateTime(dtMin.Year, dtMin.Month, 1).AddMonths(1))
|
||||
: (minTimestamp > firstValue ? DateTimeUtil.GetDateTime(secondValue) : DateTimeUtil.GetDateTime(firstValue));
|
||||
tick = num * 30 * 24 * 3600;
|
||||
while (dtStart.Ticks < dtMax.Ticks)
|
||||
{
|
||||
@@ -129,30 +183,44 @@ namespace XCharts.Runtime
|
||||
else if (range >= ONE_DAY * MIN_TIME_SPLIT_NUMBER)
|
||||
{
|
||||
tick = GetTickSecond(range, splitNumber, ONE_DAY);
|
||||
var startTimestamp = (minTimestamp - minTimestamp % tick) + tick;
|
||||
var let = minTimestamp % tick;
|
||||
var startTimestamp = let == 0 ? minTimestamp : (minTimestamp - let) + tick;
|
||||
AddTickTimestamp(list, startTimestamp, maxTimestamp, tick);
|
||||
}
|
||||
else if (range >= ONE_HOUR * MIN_TIME_SPLIT_NUMBER)
|
||||
{
|
||||
tick = GetTickSecond(range, splitNumber, ONE_HOUR);
|
||||
var startTimestamp = (minTimestamp - minTimestamp % tick) + tick;
|
||||
var let = minTimestamp % tick;
|
||||
var startTimestamp = let == 0 ? minTimestamp : (minTimestamp - let) + tick;
|
||||
AddTickTimestamp(list, startTimestamp, maxTimestamp, tick);
|
||||
}
|
||||
else if (range >= ONE_MINUTE * MIN_TIME_SPLIT_NUMBER)
|
||||
{
|
||||
tick = GetTickSecond(range, splitNumber, ONE_MINUTE);
|
||||
var startTimestamp = (minTimestamp - minTimestamp % tick) + tick;
|
||||
var let = minTimestamp % tick;
|
||||
var startTimestamp = let == 0 ? minTimestamp : (minTimestamp - let) + tick;
|
||||
AddTickTimestamp(list, startTimestamp, maxTimestamp, tick);
|
||||
}
|
||||
else
|
||||
{
|
||||
tick = GetTickSecond(range, splitNumber, ONE_SECOND);
|
||||
var startTimestamp = (minTimestamp - minTimestamp % tick) + tick;
|
||||
var let = minTimestamp % tick;
|
||||
var startTimestamp = let == 0 ? minTimestamp : (minTimestamp - let) + tick;
|
||||
AddTickTimestamp(list, startTimestamp, maxTimestamp, tick);
|
||||
}
|
||||
return tick;
|
||||
}
|
||||
|
||||
private static int GetSplitNumber(int range, int tickSecond)
|
||||
{
|
||||
var num = 1;
|
||||
while (range / (num * tickSecond) > 8)
|
||||
{
|
||||
num++;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
private static int GetTickSecond(int range, int splitNumber, int tickSecond)
|
||||
{
|
||||
var num = 0;
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
"displayName": "XCharts",
|
||||
"author": "monitor1394",
|
||||
"license": "MIT",
|
||||
"version": "3.11.0",
|
||||
"date": "20240616",
|
||||
"checkdate": "20240616",
|
||||
"version": "3.12.0",
|
||||
"date": "20240930",
|
||||
"checkdate": "20240930",
|
||||
"unity": "2018.3",
|
||||
"description": "A charting and data visualization library for Unity. Support line chart, bar chart, pie chart, radar chart, scatter chart, heatmap chart, ring chart, candlestick chart, polar chart and parallel coordinates.",
|
||||
"keywords": [
|
||||
|
||||
Reference in New Issue
Block a user