Revert "chore: [charts]rename chart-core packages to huicharts-core (#2002)" (#2018)

This reverts commit b03de5c569.
This commit is contained in:
ajaxzheng 2024-08-31 11:46:41 +08:00 committed by GitHub
parent b03de5c569
commit 77969c4b1c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
364 changed files with 14998 additions and 525 deletions

View File

@ -10,10 +10,10 @@ export default {
TinyBoxplot: ChartBoxplot
},
data() {
const sourceData0 = this.makeData()
const sourceData1 = this.makeData()
const sourceData2 = this.makeData()
return {
sourceData0: makeData(),
sourceData1: makeData(),
sourceData2: makeData(),
options: {
padding: [50, 30, 55, 20],
xAxis: {

View File

@ -4,6 +4,4 @@ title: Chart 图表
# Chart 图表
**【预告】**: Chart 图表组件预计从 `@opentiny/vue@3.22.0` 版本中移除,后续从 `@opentiny/vue-huicharts` 单独引入。
Chart 图表组件基于 `hui-charts` 封装,集成自适应、性能提升、数据状态、无障碍能力、刻度优化等特性。
<div>基于 hui-charts 封装,一个纯 Javascript 的图表库。</div>

View File

@ -4,6 +4,4 @@ title: Chart 图表
# Chart 图表
**【预告】**: Chart 图表组件预计从 `@opentiny/vue@3.22.0` 版本中移除,后续从 `@opentiny/vue-huicharts` 单独引入。
Chart 图表组件基于 `hui-charts` 封装,集成自适应、性能提升、数据状态、无障碍能力、刻度优化等特性。
<div>基于 hui-charts 封装,一个纯 Javascript 的图表库。</div>

View File

@ -4,6 +4,4 @@ title: Chart 图表
# Chart 图表
**【预告】**: Chart 图表组件预计从 `@opentiny/vue@3.22.0` 版本中移除,后续从 `@opentiny/vue-huicharts` 单独引入。
Chart 图表组件基于 `hui-charts` 封装,集成自适应、性能提升、数据状态、无障碍能力、刻度优化等特性。
<div>基于 hui-charts 封装,一个纯 Javascript 的图表库。</div>

View File

@ -4,6 +4,4 @@ title: Chart 图表
# Chart 图表
**【预告】**: Chart 图表组件预计从 `@opentiny/vue@3.22.0` 版本中移除,后续从 `@opentiny/vue-huicharts` 单独引入。
Chart 图表组件基于 `hui-charts` 封装,集成自适应、性能提升、数据状态、无障碍能力、刻度优化等特性。
<div>基于 hui-charts 封装,一个纯 Javascript 的图表库。</div>

View File

@ -4,6 +4,4 @@ title: Chart 图表
# Chart 图表
**【预告】**: Chart 图表组件预计从 `@opentiny/vue@3.22.0` 版本中移除,后续从 `@opentiny/vue-huicharts` 单独引入。
Chart 图表组件基于 `hui-charts` 封装,集成自适应、性能提升、数据状态、无障碍能力、刻度优化等特性。
<div>基于 hui-charts 封装,一个纯 Javascript 的图表库。</div>

View File

@ -4,6 +4,4 @@ title: Chart 图表
# Chart 图表
**【预告】**: Chart 图表组件预计从 `@opentiny/vue@3.22.0` 版本中移除,后续从 `@opentiny/vue-huicharts` 单独引入。
Chart 图表组件基于 `hui-charts` 封装,集成自适应、性能提升、数据状态、无障碍能力、刻度优化等特性。
<div>基于 hui-charts 封装,一个纯 Javascript 的图表库。</div>

View File

@ -4,6 +4,4 @@ title: Chart 图表
# Chart 图表
**【预告】**: Chart 图表组件预计从 `@opentiny/vue@3.22.0` 版本中移除,后续从 `@opentiny/vue-huicharts` 单独引入。
Chart 图表组件基于 `hui-charts` 封装,集成自适应、性能提升、数据状态、无障碍能力、刻度优化等特性。
<div>基于 hui-charts 封装,一个纯 Javascript 的图表库。</div>

View File

@ -4,6 +4,4 @@ title: Chart 图表
# Chart 图表
**【预告】**: Chart 图表组件预计从 `@opentiny/vue@3.22.0` 版本中移除,后续从 `@opentiny/vue-huicharts` 单独引入。
Chart 图表组件基于 `hui-charts` 封装,集成自适应、性能提升、数据状态、无障碍能力、刻度优化等特性。
<div>基于 hui-charts 封装,一个纯 Javascript 的图表库。</div>

View File

@ -4,6 +4,4 @@ title: Chart 图表
# Chart 图表
**【预告】**: Chart 图表组件预计从 `@opentiny/vue@3.22.0` 版本中移除,后续从 `@opentiny/vue-huicharts` 单独引入。
Chart 图表组件基于 `hui-charts` 封装,集成自适应、性能提升、数据状态、无障碍能力、刻度优化等特性。
<div>基于 hui-charts 封装,一个纯 Javascript 的图表库。</div>

View File

@ -4,6 +4,4 @@ title: Chart 图表
# Chart 图表
**【预告】**: Chart 图表组件预计从 `@opentiny/vue@3.22.0` 版本中移除,后续从 `@opentiny/vue-huicharts` 单独引入。
Chart 图表组件基于 `hui-charts` 封装,集成自适应、性能提升、数据状态、无障碍能力、刻度优化等特性。
<div>基于 hui-charts 封装,一个纯 Javascript 的图表库。</div>

View File

@ -4,6 +4,4 @@ title: Chart 图表
# Chart 图表
**【预告】**: Chart 图表组件预计从 `@opentiny/vue@3.22.0` 版本中移除,后续从 `@opentiny/vue-huicharts` 单独引入。
Chart 图表组件基于 `hui-charts` 封装,集成自适应、性能提升、数据状态、无障碍能力、刻度优化等特性。
<div>基于 hui-charts 封装,一个纯 Javascript 的图表库。</div>

View File

@ -4,6 +4,4 @@ title: Chart 图表
# Chart 图表
**【预告】**: Chart 图表组件预计从 `@opentiny/vue@3.22.0` 版本中移除,后续从 `@opentiny/vue-huicharts` 单独引入。
Chart 图表组件基于 `hui-charts` 封装,集成自适应、性能提升、数据状态、无障碍能力、刻度优化等特性。
<div>基于 hui-charts 封装,一个纯 Javascript 的图表库。</div>

View File

@ -4,6 +4,4 @@ title: Chart 图表
# Chart 图表
**【预告】**: Chart 图表组件预计从 `@opentiny/vue@3.22.0` 版本中移除,后续从 `@opentiny/vue-huicharts` 单独引入。
Chart 图表组件基于 `hui-charts` 封装,集成自适应、性能提升、数据状态、无障碍能力、刻度优化等特性。
<div>基于 hui-charts 封装,一个纯 Javascript 的图表库。</div>

View File

@ -4,6 +4,4 @@ title: Chart 图表
# Chart 图表
**【预告】**: Chart 图表组件预计从 `@opentiny/vue@3.22.0` 版本中移除,后续从 `@opentiny/vue-huicharts` 单独引入。
Chart 图表组件基于 `hui-charts` 封装,集成自适应、性能提升、数据状态、无障碍能力、刻度优化等特性。
<div>基于 hui-charts 封装,一个纯 Javascript 的图表库。</div>

View File

@ -4,6 +4,4 @@ title: Chart 图表
# Chart 图表
**【预告】**: Chart 图表组件预计从 `@opentiny/vue@3.22.0` 版本中移除,后续从 `@opentiny/vue-huicharts` 单独引入。
Chart 图表组件基于 `hui-charts` 封装,集成自适应、性能提升、数据状态、无障碍能力、刻度优化等特性。
<div>基于 hui-charts 封装,一个纯 Javascript 的图表库。</div>

View File

@ -4,6 +4,4 @@ title: Chart 图表
# Chart 图表
**【预告】**: Chart 图表组件预计从 `@opentiny/vue@3.22.0` 版本中移除,后续从 `@opentiny/vue-huicharts` 单独引入。
Chart 图表组件基于 `hui-charts` 封装,集成自适应、性能提升、数据状态、无障碍能力、刻度优化等特性。
<div>基于 hui-charts 封装,一个纯 Javascript 的图表库。</div>

View File

@ -4,6 +4,4 @@ title: Chart 图表
# Chart 图表
**【预告】**: Chart 图表组件预计从 `@opentiny/vue@3.22.0` 版本中移除,后续从 `@opentiny/vue-huicharts` 单独引入。
Chart 图表组件基于 `hui-charts` 封装,集成自适应、性能提升、数据状态、无障碍能力、刻度优化等特性。
<div>基于 hui-charts 封装,一个纯 Javascript 的图表库。</div>

View File

@ -4,6 +4,4 @@ title: Chart 图表
# Chart 图表
**【预告】**: Chart 图表组件预计从 `@opentiny/vue@3.22.0` 版本中移除,后续从 `@opentiny/vue-huicharts` 单独引入。
Chart 图表组件基于 `hui-charts` 封装,集成自适应、性能提升、数据状态、无障碍能力、刻度优化等特性。
<div>基于 hui-charts 封装,一个纯 Javascript 的图表库。</div>

View File

@ -4,6 +4,4 @@ title: Chart 图表
# Chart 图表
**【预告】**: Chart 图表组件预计从 `@opentiny/vue@3.22.0` 版本中移除,后续从 `@opentiny/vue-huicharts` 单独引入。
Chart 图表组件基于 `hui-charts` 封装,集成自适应、性能提升、数据状态、无障碍能力、刻度优化等特性。
<div>基于 hui-charts 封装,一个纯 Javascript 的图表库。</div>

View File

@ -4,6 +4,4 @@ title: Chart 图表
# Chart 图表
**【预告】**: Chart 图表组件预计从 `@opentiny/vue@3.22.0` 版本中移除,后续从 `@opentiny/vue-huicharts` 单独引入。
Chart 图表组件基于 `hui-charts` 封装,集成自适应、性能提升、数据状态、无障碍能力、刻度优化等特性。
<div>基于 hui-charts 封装,一个纯 Javascript 的图表库。</div>

View File

@ -4,6 +4,4 @@ title: Chart 图表
# Chart 图表
**【预告】**: Chart 图表组件预计从 `@opentiny/vue@3.22.0` 版本中移除,后续从 `@opentiny/vue-huicharts` 单独引入。
Chart 图表组件基于 `hui-charts` 封装,集成自适应、性能提升、数据状态、无障碍能力、刻度优化等特性。
<div>基于 hui-charts 封装,一个纯 Javascript 的图表库。</div>

View File

@ -4,6 +4,4 @@ title: Chart 图表
# Chart 图表
**【预告】**: Chart 图表组件预计从 `@opentiny/vue@3.22.0` 版本中移除,后续从 `@opentiny/vue-huicharts` 单独引入。
Chart 图表组件基于 `hui-charts` 封装,集成自适应、性能提升、数据状态、无障碍能力、刻度优化等特性。
<div>基于 hui-charts 封装,一个纯 Javascript 的图表库。</div>

View File

@ -4,6 +4,4 @@ title: Chart 图表
# Chart 图表
**【预告】**: Chart 图表组件预计从 `@opentiny/vue@3.22.0` 版本中移除,后续从 `@opentiny/vue-huicharts` 单独引入。
Chart 图表组件基于 `hui-charts` 封装,集成自适应、性能提升、数据状态、无障碍能力、刻度优化等特性。
<div>基于 hui-charts 封装,一个纯 Javascript 的图表库。</div>

View File

@ -4,6 +4,4 @@ title: Chart 图表
# Chart 图表
**【预告】**: Chart 图表组件预计从 `@opentiny/vue@3.22.0` 版本中移除,后续从 `@opentiny/vue-huicharts` 单独引入。
Chart 图表组件基于 `hui-charts` 封装,集成自适应、性能提升、数据状态、无障碍能力、刻度优化等特性。
<div>基于 hui-charts 封装,一个纯 Javascript 的图表库。</div>

View File

@ -4,6 +4,4 @@ title: Chart 图表
# Chart 图表
**【预告】**: Chart 图表组件预计从 `@opentiny/vue@3.22.0` 版本中移除,后续从 `@opentiny/vue-huicharts` 单独引入。
Chart 图表组件基于 `hui-charts` 封装,集成自适应、性能提升、数据状态、无障碍能力、刻度优化等特性。
<div>基于 hui-charts 封装,一个纯 Javascript 的图表库。</div>

View File

@ -4,6 +4,4 @@ title: Chart 图表
# Chart 图表
**【预告】**: Chart 图表组件预计从 `@opentiny/vue@3.22.0` 版本中移除,后续从 `@opentiny/vue-huicharts` 单独引入。
Chart 图表组件基于 `hui-charts` 封装,集成自适应、性能提升、数据状态、无障碍能力、刻度优化等特性。
<div>基于 hui-charts 封装,一个纯 Javascript 的图表库。</div>

View File

@ -4,6 +4,4 @@ title: Chart 图表
# Chart 图表
**【预告】**: Chart 图表组件预计从 `@opentiny/vue@3.22.0` 版本中移除,后续从 `@opentiny/vue-huicharts` 单独引入。
Chart 图表组件基于 `hui-charts` 封装,集成自适应、性能提升、数据状态、无障碍能力、刻度优化等特性。
<div>基于 hui-charts 封装,一个纯 Javascript 的图表库。</div>

View File

@ -4,6 +4,4 @@ title: Chart 图表
# Chart 图表
**【预告】**: Chart 图表组件预计从 `@opentiny/vue@3.22.0` 版本中移除,后续从 `@opentiny/vue-huicharts` 单独引入。
Chart 图表组件基于 `hui-charts` 封装,集成自适应、性能提升、数据状态、无障碍能力、刻度优化等特性。
<div>基于 hui-charts 封装,一个纯 Javascript 的图表库。</div>

View File

@ -4,6 +4,4 @@ title: Chart 图表
# Chart 图表
**【预告】**: Chart 图表组件预计从 `@opentiny/vue@3.22.0` 版本中移除,后续从 `@opentiny/vue-huicharts` 单独引入。
Chart 图表组件基于 `hui-charts` 封装,集成自适应、性能提升、数据状态、无障碍能力、刻度优化等特性。
<div>基于 hui-charts 封装,一个纯 Javascript 的图表库。</div>

View File

@ -4,6 +4,4 @@ title: Chart 图表
# Chart 图表
**【预告】**: Chart 图表组件预计从 `@opentiny/vue@3.22.0` 版本中移除,后续从 `@opentiny/vue-huicharts` 单独引入。
Chart 图表组件基于 `hui-charts` 封装,集成自适应、性能提升、数据状态、无障碍能力、刻度优化等特性。
<div>基于 hui-charts 封装,一个纯 Javascript 的图表库。</div>

View File

@ -4,6 +4,4 @@ title: Chart 图表
# Chart 图表
**【预告】**: Chart 图表组件预计从 `@opentiny/vue@3.22.0` 版本中移除,后续从 `@opentiny/vue-huicharts` 单独引入。
Chart 图表组件基于 `hui-charts` 封装,集成自适应、性能提升、数据状态、无障碍能力、刻度优化等特性。
<div>基于 hui-charts 封装,一个纯 Javascript 的图表库。</div>

View File

@ -4,6 +4,4 @@ title: Chart 图表
# Chart 图表
**【预告】**: Chart 图表组件预计从 `@opentiny/vue@3.22.0` 版本中移除,后续从 `@opentiny/vue-huicharts` 单独引入。
Chart 图表组件基于 `hui-charts` 封装,集成自适应、性能提升、数据状态、无障碍能力、刻度优化等特性。
<div>基于 hui-charts 封装,一个纯 Javascript 的图表库。</div>

View File

@ -4,6 +4,4 @@ title: Chart 图表
# Chart 图表
**【预告】**: Chart 图表组件预计从 `@opentiny/vue@3.22.0` 版本中移除,后续从 `@opentiny/vue-huicharts` 单独引入。
Chart 图表组件基于 `hui-charts` 封装,集成自适应、性能提升、数据状态、无障碍能力、刻度优化等特性。
<div>基于 hui-charts 封装,一个纯 Javascript 的图表库。</div>

View File

@ -4,6 +4,4 @@ title: Chart 图表
# Chart 图表
**【预告】**: Chart 图表组件预计从 `@opentiny/vue@3.22.0` 版本中移除,后续从 `@opentiny/vue-huicharts` 单独引入。
Chart 图表组件基于 `hui-charts` 封装,集成自适应、性能提升、数据状态、无障碍能力、刻度优化等特性。
<div>基于 hui-charts 封装,一个纯 Javascript 的图表库。</div>

View File

@ -4,6 +4,4 @@ title: Chart 图表
# Chart 图表
**【预告】**: Chart 图表组件预计从 `@opentiny/vue@3.22.0` 版本中移除,后续从 `@opentiny/vue-huicharts` 单独引入。
Chart 图表组件基于 `hui-charts` 封装,集成自适应、性能提升、数据状态、无障碍能力、刻度优化等特性。
<div>基于 hui-charts 封装,一个纯 Javascript 的图表库。</div>

View File

@ -4,6 +4,4 @@ title: Chart 图表
# Chart 图表
**【预告】**: Chart 图表组件预计从 `@opentiny/vue@3.22.0` 版本中移除,后续从 `@opentiny/vue-huicharts` 单独引入。
Chart 图表组件基于 `hui-charts` 封装,集成自适应、性能提升、数据状态、无障碍能力、刻度优化等特性。
<div>基于 hui-charts 封装,一个纯 Javascript 的图表库。</div>

View File

@ -4,6 +4,4 @@ title: Chart 图表
# Chart 图表
**【预告】**: Chart 图表组件预计从 `@opentiny/vue@3.22.0` 版本中移除,后续从 `@opentiny/vue-huicharts` 单独引入。
Chart 图表组件基于 `hui-charts` 封装,集成自适应、性能提升、数据状态、无障碍能力、刻度优化等特性。
<div>基于 hui-charts 封装,一个纯 Javascript 的图表库。</div>

View File

@ -4,6 +4,4 @@ title: Chart 图表
# Chart 图表
**【预告】**: Chart 图表组件预计从 `@opentiny/vue@3.22.0` 版本中移除,后续从 `@opentiny/vue-huicharts` 单独引入。
Chart 图表组件基于 `hui-charts` 封装,集成自适应、性能提升、数据状态、无障碍能力、刻度优化等特性。
<div>基于 hui-charts 封装,一个纯 Javascript 的图表库。</div>

View File

@ -4,6 +4,4 @@ title: Chart 图表
# Chart 图表
**【预告】**: Chart 图表组件预计从 `@opentiny/vue@3.22.0` 版本中移除,后续从 `@opentiny/vue-huicharts` 单独引入。
Chart 图表组件基于 `hui-charts` 封装,集成自适应、性能提升、数据状态、无障碍能力、刻度优化等特性。
<div>基于 hui-charts 封装,一个纯 Javascript 的图表库。</div>

View File

@ -4,6 +4,4 @@ title: Chart 图表
# Chart 图表
**【预告】**: Chart 图表组件预计从 `@opentiny/vue@3.22.0` 版本中移除,后续从 `@opentiny/vue-huicharts` 单独引入。
Chart 图表组件基于 `hui-charts` 封装,集成自适应、性能提升、数据状态、无障碍能力、刻度优化等特性。
<div>基于 hui-charts 封装,一个纯 Javascript 的图表库。</div>

View File

@ -4,6 +4,4 @@ title: Chart 图表
# Chart 图表
**【预告】**: Chart 图表组件预计从 `@opentiny/vue@3.22.0` 版本中移除,后续从 `@opentiny/vue-huicharts` 单独引入。
Chart 图表组件基于 `hui-charts` 封装,集成自适应、性能提升、数据状态、无障碍能力、刻度优化等特性。
<div>基于 hui-charts 封装,一个纯 Javascript 的图表库。</div>

View File

@ -4,6 +4,4 @@ title: Chart 图表
# Chart 图表
**【预告】**: Chart 图表组件预计从 `@opentiny/vue@3.22.0` 版本中移除,后续从 `@opentiny/vue-huicharts` 单独引入。
Chart 图表组件基于 `hui-charts` 封装,集成自适应、性能提升、数据状态、无障碍能力、刻度优化等特性。
<div>基于 hui-charts 封装,一个纯 Javascript 的图表库。</div>

View File

@ -4,6 +4,4 @@ title: Chart 图表
# Chart 图表
**【预告】**: Chart 图表组件预计从 `@opentiny/vue@3.22.0` 版本中移除,后续从 `@opentiny/vue-huicharts` 单独引入。
Chart 图表组件基于 `hui-charts` 封装,集成自适应、性能提升、数据状态、无障碍能力、刻度优化等特性。
<div>基于 hui-charts 封装,一个纯 Javascript 的图表库。</div>

View File

@ -4,6 +4,4 @@ title: Chart 图表
# Chart 图表
**【预告】**: Chart 图表组件预计从 `@opentiny/vue@3.22.0` 版本中移除,后续从 `@opentiny/vue-huicharts` 单独引入。
Chart 图表组件基于 `hui-charts` 封装,集成自适应、性能提升、数据状态、无障碍能力、刻度优化等特性。
<div>基于 hui-charts 封装,一个纯 Javascript 的图表库。</div>

View File

@ -4,6 +4,4 @@ title: Chart 图表
# Chart 图表
**【预告】**: Chart 图表组件预计从 `@opentiny/vue@3.22.0` 版本中移除,后续从 `@opentiny/vue-huicharts` 单独引入。
Chart 图表组件基于 `hui-charts` 封装,集成自适应、性能提升、数据状态、无障碍能力、刻度优化等特性。
<div>基于 hui-charts 封装,一个纯 Javascript 的图表库。</div>

View File

@ -4,6 +4,4 @@ title: Chart 图表
# Chart 图表
**【预告】**: Chart 图表组件预计从 `@opentiny/vue@3.22.0` 版本中移除,后续从 `@opentiny/vue-huicharts` 单独引入。
Chart 图表组件基于 `hui-charts` 封装,集成自适应、性能提升、数据状态、无障碍能力、刻度优化等特性。
<div>基于 hui-charts 封装,一个纯 Javascript 的图表库。</div>

View File

@ -4,6 +4,4 @@ title: Chart 图表
# Chart 图表
**【预告】**: Chart 图表组件预计从 `@opentiny/vue@3.22.0` 版本中移除,后续从 `@opentiny/vue-huicharts` 单独引入。
Chart 图表组件基于 `hui-charts` 封装,集成自适应、性能提升、数据状态、无障碍能力、刻度优化等特性。
<div>基于 hui-charts 封装,一个纯 Javascript 的图表库。</div>

View File

@ -4,6 +4,4 @@ title: Chart 图表
# Chart 图表
**【预告】**: Chart 图表组件预计从 `@opentiny/vue@3.22.0` 版本中移除,后续从 `@opentiny/vue-huicharts` 单独引入。
Chart 图表组件基于 `hui-charts` 封装,集成自适应、性能提升、数据状态、无障碍能力、刻度优化等特性。
<div>基于 hui-charts 封装,一个纯 Javascript 的图表库。</div>

View File

@ -4,6 +4,4 @@ title: Chart 图表
# Chart 图表
**【预告】**: Chart 图表组件预计从 `@opentiny/vue@3.22.0` 版本中移除,后续从 `@opentiny/vue-huicharts` 单独引入。
Chart 图表组件基于 `hui-charts` 封装,集成自适应、性能提升、数据状态、无障碍能力、刻度优化等特性。
<div>基于 hui-charts 封装,一个纯 Javascript 的图表库。</div>

View File

@ -4,6 +4,4 @@ title: Chart 图表
# Chart 图表
**【预告】**: Chart 图表组件预计从 `@opentiny/vue@3.22.0` 版本中移除,后续从 `@opentiny/vue-huicharts` 单独引入。
Chart 图表组件基于 `hui-charts` 封装,集成自适应、性能提升、数据状态、无障碍能力、刻度优化等特性。
<div>基于 hui-charts 封装,一个纯 Javascript 的图表库。</div>

View File

@ -4,6 +4,4 @@ title: Chart 图表
# Chart 图表
**【预告】**: Chart 图表组件预计从 `@opentiny/vue@3.22.0` 版本中移除,后续从 `@opentiny/vue-huicharts` 单独引入。
Chart 图表组件基于 `hui-charts` 封装,集成自适应、性能提升、数据状态、无障碍能力、刻度优化等特性。
<div>基于 hui-charts 封装,一个纯 Javascript 的图表库。</div>

View File

@ -4,6 +4,4 @@ title: Chart 图表
# Chart 图表
**【预告】**: Chart 图表组件预计从 `@opentiny/vue@3.22.0` 版本中移除,后续从 `@opentiny/vue-huicharts` 单独引入。
Chart 图表组件基于 `hui-charts` 封装,集成自适应、性能提升、数据状态、无障碍能力、刻度优化等特性。
<div>基于 hui-charts 封装,一个纯 Javascript 的图表库。</div>

View File

@ -4,6 +4,4 @@ title: Chart 图表
# Chart 图表
**【预告】**: Chart 图表组件预计从 `@opentiny/vue@3.22.0` 版本中移除,后续从 `@opentiny/vue-huicharts` 单独引入。
Chart 图表组件基于 `hui-charts` 封装,集成自适应、性能提升、数据状态、无障碍能力、刻度优化等特性。
<div>基于 hui-charts 封装,一个纯 Javascript 的图表库。</div>

View File

@ -80,15 +80,9 @@
"type": "component",
"exclude": false,
"mode": [
"mobile-first",
"pc"
]
},
"AnchorMobileFirst": {
"path": "vue/src/anchor/src/mobile-first.vue",
"type": "template",
"exclude": false
},
"AnchorPc": {
"path": "vue/src/anchor/src/pc.vue",
"type": "template",
@ -1470,11 +1464,6 @@
"type": "template",
"exclude": false
},
"Hooks": {
"path": "vue-hooks/index.ts",
"type": "module",
"exclude": false
},
"Hrapprover": {
"path": "vue/src/hrapprover/index.ts",
"type": "component",

View File

@ -1,5 +1,5 @@
{
"name": "@opentiny/vue-huicharts-amap",
"name": "@opentiny/vue-autonavi-map",
"version": "3.18.0",
"description": "",
"main": "lib/index.js",
@ -15,7 +15,7 @@
"//postversion": "pnpm build"
},
"dependencies": {
"@opentiny/vue-huicharts-core": "workspace:~",
"@opentiny/vue-chart-core": "workspace:~",
"@opentiny/vue-common": "workspace:~"
},
"license": "MIT"

View File

@ -6,7 +6,7 @@
</template>
<script>
import Core from '@opentiny/vue-huicharts-core'
import Core from '@opentiny/vue-chart-core'
import registerAmap from './amap'
import { $prefix } from '@opentiny/vue-common'

View File

@ -1,5 +1,5 @@
{
"name": "@opentiny/vue-huicharts-bmap",
"name": "@opentiny/vue-baidu-map",
"version": "3.18.0",
"description": "",
"main": "lib/index.js",
@ -15,7 +15,7 @@
"//postversion": "pnpm build"
},
"dependencies": {
"@opentiny/vue-huicharts-core": "workspace:~",
"@opentiny/vue-chart-core": "workspace:~",
"@opentiny/vue-common": "workspace:~"
},
"license": "MIT"

View File

@ -7,7 +7,7 @@
<script>
import 'echarts/extension/bmap/bmap'
import Core from '@opentiny/vue-huicharts-core'
import Core from '@opentiny/vue-chart-core'
import { $prefix } from '@opentiny/vue-common'
export default {

View File

@ -1,5 +1,5 @@
{
"name": "@opentiny/vue-huicharts-bar",
"name": "@opentiny/vue-chart-bar",
"version": "3.18.0",
"description": "",
"main": "lib/index.js",
@ -12,7 +12,7 @@
"//postversion": "pnpm build"
},
"dependencies": {
"@opentiny/vue-huicharts-core": "workspace:~",
"@opentiny/vue-chart-core": "workspace:~",
"@opentiny/vue-common": "workspace:~"
},
"license": "MIT"

View File

@ -7,7 +7,7 @@
<script>
import { histogram } from './histogram'
import Core from '@opentiny/vue-huicharts-core'
import Core from '@opentiny/vue-chart-core'
import { $prefix } from '@opentiny/vue-common'
export default {

View File

@ -1,13 +1,4 @@
import {
getFormatted,
cloneDeep,
getStackMap,
get,
set,
isNull,
getRows,
getTooltip
} from '@opentiny/vue-huicharts-core'
import { getFormatted, cloneDeep, getStackMap, get, set, isNull, getRows, getTooltip } from '@opentiny/vue-chart-core'
const VALUE_AXIS_OPACITY = 0.5

View File

@ -1,5 +1,5 @@
{
"name": "@opentiny/vue-huicharts-boxplot",
"name": "@opentiny/vue-chart-boxplot",
"version": "3.18.0",
"description": "",
"main": "lib/index.js",
@ -12,7 +12,7 @@
"//postversion": "pnpm build"
},
"dependencies": {
"@opentiny/vue-huicharts-core": "workspace:~",
"@opentiny/vue-chart-core": "workspace:~",
"@opentiny/vue-common": "workspace:~"
},
"license": "MIT"

View File

@ -1,4 +1,4 @@
import { getFormatted, itemPoint, itemLabel, itemContent, htmlHandler } from '@opentiny/vue-huicharts-core'
import { getFormatted, itemPoint, itemLabel, itemContent, htmlHandler } from '@opentiny/vue-chart-core'
const getXAxis = (args) => {
const { columns, xAxisName, axisVisible, xAxisType } = args

View File

@ -6,7 +6,7 @@
</template>
<script>
import Core from '@opentiny/vue-huicharts-core'
import Core from '@opentiny/vue-chart-core'
import { prepareBoxplotData } from 'echarts/extension/dataTool'
import { boxplot } from './boxplot'
import { $prefix } from '@opentiny/vue-common'

View File

@ -1,5 +1,5 @@
{
"name": "@opentiny/vue-huicharts-candle",
"name": "@opentiny/vue-chart-candle",
"version": "3.18.0",
"description": "",
"main": "lib/index.js",
@ -12,7 +12,7 @@
"//postversion": "pnpm build"
},
"dependencies": {
"@opentiny/vue-huicharts-core": "workspace:~",
"@opentiny/vue-chart-core": "workspace:~",
"@opentiny/vue-locale": "workspace:~",
"@opentiny/vue-common": "workspace:~"
},

View File

@ -16,7 +16,7 @@
* dataType string 可选值: KMB, normal, percent
*/
import { getFormatted, itemPoint, itemLabel, itemContent } from '@opentiny/vue-huicharts-core'
import { getFormatted, itemPoint, itemLabel, itemContent } from '@opentiny/vue-chart-core'
const isNull = (x) => x === null || x === undefined
let defaultKName = ''

View File

@ -6,7 +6,7 @@
</template>
<script>
import Core from '@opentiny/vue-huicharts-core'
import Core from '@opentiny/vue-chart-core'
import { t } from '@opentiny/vue-locale'
import { candle } from './candle'
import { $prefix } from '@opentiny/vue-common'

View File

@ -0,0 +1,63 @@
/* eslint-disable new-cap */
/* eslint-disable no-unused-expressions */
import core from './core'
import Register from './register'
import Theme from './feature/token'
import { isFunction } from './util/type'
import axistip from './feature/axistip'
import { mergeExtend } from './util/merge'
import readScreen from './feature/readScreen'
import mediaScreen from './feature/mediaScreen'
// 图表核心对象,通过 Register 全量引入图表给 HuiCharts 渲染,打包容量较大
export default class HuiCharts extends core {
constructor() {
super()
// 图表名称
this.chartName
}
// 传入简化后的icharts-option
setSimpleOption(chartName, iChartOption, plugins = {}, isInit = true) {
if (isInit) {
Theme.setDefaultTheme(iChartOption.theme)
this.mediaScreenObserver && this.mediaScreenObserver.setInitOption(iChartOption)
}
if (iChartOption.readScreen) {
readScreen(this.dom, iChartOption.readScreen)
}
if (isFunction(chartName)) {
this.redirectSelfChart(chartName, iChartOption, plugins)
return
}
this.plugins = plugins
this.chartName = chartName
this.iChartOption = iChartOption
const ChartClass = this.getChartClass(chartName)
this.ichartsIns = new ChartClass(iChartOption, this.echartsIns, this.plugins)
this.eChartOption = this.ichartsIns.getOption()
this.iChartOption.axistip && axistip(this.dom, this.echartsIns, this.eChartOption)
mergeExtend(this.iChartOption, this.eChartOption)
}
// 获取图表类
getChartClass(name) {
return Register.getRegisteredComp(name)
}
// 开启响应式布局(类媒体查询效果)
mediaScreen(dom, screenOption) {
this.mediaScreenObserver = new mediaScreen(dom, screenOption, (option) => {
this.setSimpleOption(this.chartName, option, this.plugins, false)
this.render()
})
}
// 图表刷新,包括刷新配置和数据
refresh(iChartOption) {
this.iChartOption = iChartOption
this.setSimpleOption(this.chartName, iChartOption, this.plugins)
this.render()
this.mediaScreenObserver && this.mediaScreenObserver.refresh()
}
}

View File

@ -0,0 +1,147 @@
import BaseChart from '../BaseChart'
import * as echarts from 'echarts/lib/echarts'
// 常规的调用方法
// integrateChart.init(chartRef.current);
// integrateChart.setSimpleOption(AutonaviMapChart, option, {});
// integrateChart.render();
let amapPromise = null
export default class AutonaviMapChart extends BaseChart {
constructor() {
super()
// 图表echarts实例
this.echartsIns = null
// 图表icharts实例
this.ichartsIns = null
// 图表echarts配置项
this.eChartOption = null
// 图表icharts配置项
this.iChartOption = null
// 图表渲染容器
this.dom = null
// 图表配置项
this.option = null
}
getAmap(option) {
if (!amapPromise) {
const key = option.key
const url = option.url
const version = option.version || option.ver || option.v
amapPromise = new Promise((resolve) => {
const cbName = 'amap' + Date.now()
let script = document.createElement('script')
window[cbName] = resolve
let src = `${url}?v=${version}&key=${key}`
if (option.plugin) {
src += `&plugin=${option.plugin}`
}
script.src = `${src}&callback=${cbName}`
script.onload = () => resolve()
document.body.appendChild(script)
})
}
return amapPromise
}
// 初始化图表渲染容器
init(dom) {
this.uninstall()
this.dom = dom
this.echartsIns = echarts.init(this.dom)
}
// 初始化图表渲染配置
setSimpleOption(chartName, option) {
this.option = option
this.getAmap(this.option).then(() => {
this.echartsIns.setOption(this.option)
this.setResizeObserver()
})
}
// 图表渲染回调
render() {
this.initDom() // 渲染dom
this.renderCallBack && this.renderCallBack(this)
}
// 图表渲染完成时回调
onRenderReady(callback) {
this.renderCallBack = callback
}
// 渲染dom
initDom() {}
// 监听容器变化
setResizeObserver() {
if (this.resizeObserver) {
this.resizeObserver.disconnect()
this.resizeObserver = null
}
this.resizeObserver = new ResizeObserver((entries) => {
this.resizeDom()
})
this.resizeObserver.observe(this.dom)
}
resizeDom() {
this.echartsIns && this.echartsIns.resize && this.echartsIns.resize()
}
// 图表刷新,刷新配置项
refresh(option) {
this.iChartOption = option
this.setSimpleOption('AutonaviMapChart', this.iChartOption)
this.resizeDom()
}
// 图表刷新,仅刷新数据
refreshData(data) {
this.iChartOption.series[0].data = data
this.refresh(this.iChartOption)
}
// 刷新图表自适应宽度
setResize() {
this.resizeDom()
}
// 销毁图表
uninstall() {
if (this.resizeObserver) {
this.resizeObserver.disconnect()
this.resizeObserver = null
}
// 销毁ECharts实例
if (this.echartsIns && !this.echartsIns.isDisposed()) {
this.echartsIns.dispose()
}
this.echartsIns = null
this.dom = null
}
// 获取到ECharts实例
getEchartsInstance() {
return this.echartsIns
}
// 获取到ECharts配置项
getEchartsOption() {
return this.echartsIns.getOption()
}
// 获取 ECharts 高德地图组件
getAmapComponent() {
return this.echartsIns.getModel().getComponent('amap')
}
// 获取高德地图实例
getAmapInstance() {
return this.getAmapComponent().getAMap()
}
}

View File

@ -0,0 +1,138 @@
import BaseChart from '../BaseChart'
import * as echarts from 'echarts'
import 'echarts/extension/bmap/bmap'
export default class BaiduMapChart extends BaseChart {
constructor() {
super()
// 图表echarts实例
this.echartsIns = null
// 图表渲染容器
this.dom = null
// 图表配置项
this.option = null
// 图表所需数据
this.data = null
// 图表容器的宽高变化监听器
this.resizeObserver = null
}
// 初始化图表渲染容器
init(dom) {
this.uninstall()
this.dom = dom
}
// 初始化图表渲染配置
setSimpleOption(chartName, option) {
this.option = option
}
// 判断某个script是否存在
isScriptExist(src) {
let scripts = document.getElementsByTagName('script')
for (let i = 0; i < scripts.length; i++) {
if (scripts[i].src && scripts[i].src === src) {
return true
}
}
return false
}
loadMap({ key, version, url }) {
return new Promise((resolve) => {
let cbName = 'bmap' + Date.now()
let script = document.createElement('script')
let ver = version || '2.0'
window[cbName] = resolve
script.src = [`${url}?v=${ver}`, `ak=${key}`, `callback=${cbName}`].join('&')
document.body.appendChild(script)
})
}
// 加载百度api并渲染图表
render() {
let url = this.option.url
let ver = this.option.v || '2.0'
let key = this.option.key
let src = [`${url}?${ver}`, `ak=${key}`].join('&')
let bmap = this.option.bmap
let scriptExists = this.isScriptExist(src)
// 判断是否重复加载script
if (scriptExists) {
this.renderInit()
} else {
this.loadMap({ key, version: ver, url }).then(() => {
this.renderInit()
})
}
}
// 渲染图表
renderInit() {
this.echartsIns = echarts.init(this.dom)
// 渲染
this.setOption(this.option)
this.setResizeObserver()
// 图表渲染完成时回调
this.renderCallBack && this.renderCallBack(this.echartsIns)
}
// 第一次渲染: 调用echarts原生的setOption
setOption(option) {
this.echartsIns.setOption(option)
}
// 图表渲染完成时回调
onRenderReady(callback) {
this.renderCallBack = callback
}
// 监听容器变化
setResizeObserver() {
this.resizeObserver = new ResizeObserver((entries) => {
this.resizeDom()
})
this.resizeObserver.observe(this.dom)
}
resizeDom() {
this.echartsIns && this.echartsIns.resize && this.echartsIns.resize()
}
// 图表刷新,包括刷新配置和数据
refresh(iChartOption) {
this.iChartOption = iChartOption
this.setSimpleOption(this.chartName, iChartOption)
this.render()
}
// 图表刷新,仅刷新数据
refreshData(data) {
this.iChartOption.series[0].data = data
this.refresh(this.iChartOption)
}
// 刷新图表自适应宽度
setResize() {
this.resizeDom()
}
// 销毁图表
uninstall() {
// 卸载window resize监听功能
window.removeEventListener('resize', this.throttleResize)
// 卸载container容器变化监听
if (this.resizeObserver) {
this.resizeObserver.disconnect()
this.resizeObserver = null
}
// 销毁ECharts实例
if (this.echartsIns && !this.echartsIns.isDisposed()) {
this.echartsIns.dispose()
}
this.echartsIns = null
this.dom = null
}
}

View File

@ -0,0 +1,29 @@
import Theme from '../../feature/token'
import proxy from '../../util/proxy'
function getChartToken() {
const {
itemStyle: { borderWidth, borderColor, borderRadius, color },
label: { color: colorLabel, fontSize },
barWidth
} = Theme.config.BarChart
const {
colorState: { colorError }
} = Theme.config
return {
borderWidth,
borderColor,
borderRadius,
color,
labelColor: colorLabel,
fontSize,
barWidth,
colorError
}
}
const chartToken = proxy(getChartToken)
export default chartToken

View File

@ -0,0 +1,84 @@
import defendXSS from '../../util/defendXSS'
import chartToken from './chartToken'
/**
* ,
*/
export function setStack(baseOption, iChartOption, legendData, seriesData) {
const type = iChartOption.type
if (type && type === 'stack') {
// 添加堆叠图空白缝隙
baseOption.series.forEach((item) => {
item.itemStyle.borderWidth = chartToken.borderWidth
item.itemStyle.borderColor = chartToken.borderColor
})
// 柱子圆角,上层数值为空时,圆角递进到下层
const direction = iChartOption.direction
iChartOption.data.forEach((item, i) => {
for (let j = legendData.length - 1; j >= 0; j--) {
const name = legendData[j]
if (item[name]) {
seriesData[name][i] = {
value: seriesData[name][i],
itemStyle: {
borderRadius:
direction === 'horizontal'
? [0, chartToken.borderRadius, chartToken.borderRadius, 0]
: [chartToken.borderRadius, chartToken.borderRadius, 0, 0]
}
}
break
}
}
})
}
}
/**
* y轴的label都转为正数
* tooltip
*/
export function setDoubleSides(baseOption, iChartOption) {
const type = iChartOption.type
if (type && type === 'double-sides') {
const yAxis = baseOption.yAxis
yAxis.forEach((item) => {
item.axisLabel.formatter = (value) => {
return Math.abs(value)
}
})
if (!baseOption.tooltip.formatter) {
baseOption.tooltip.formatter = (params, ticket, callback) => {
let html = ''
params.forEach((item, index) => {
if (index === 0) {
html += `<div style="margin-bottom:4px;">${defendXSS(item.name)}</div>`
}
html += `<div>
<span style="display:inline-block;width:10px;height:10px;border-radius:5px;background-color:${defendXSS(
item.color
)};"></span>
<span style="margin-left:5px;color:#000000">
<span style="display:inline-block; margin-right:8px;min-width:48px;">${defendXSS(
item.seriesName
)}</span>
<span style="font-weight:bold">${defendXSS(item.value ? Math.abs(item.value) : '-')}</span>
</span>
</div>`
})
return html
}
}
}
}
/**
*
*/
export function setDirection(baseOption, direction) {
if (direction && direction === 'horizontal') {
const temp = baseOption.xAxis
baseOption.xAxis = baseOption.yAxis
baseOption.yAxis = temp
}
}

View File

@ -0,0 +1,619 @@
import merge from '../../util/merge'
import defendXSS from '../../util/defendXSS'
import { getColor } from '../../util/color'
import cloneDeep from '../../util/cloneDeep'
import { isArray, isNumber } from '../../util/type'
import { getMarkLineDefault } from '../../option/config/mark'
import chartToken from './chartToken'
export const seriesInit = () => {
return {
label: {
show: false,
color: chartToken.labelColor,
fontSize: chartToken.fontSize
},
// 数据
data: [],
// 柱形
type: 'bar',
// 柱条宽度
barWidth: chartToken.barWidth,
// 柱间距离
barGap: '60%',
// 阈值线
markLine: null,
// 峰值标志
markPoint: null,
// 柱形的每个样式配置项
itemStyle: {
borderRadius: [chartToken.borderRadius, chartToken.borderRadius, 0, 0]
}
}
}
function handleWaterFall(type, seriesUnit) {
if (type && type === 'water-fall') {
// 调整堆叠柱子圆角
seriesUnit.itemStyle.borderRadius = [
chartToken.borderRadius,
chartToken.borderRadius,
chartToken.borderRadius,
chartToken.borderRadius
]
// 瀑布图最有有一个总体数据
seriesUnit.data.push(
seriesUnit.data.reduce(function (prev, curr) {
const n = Number(curr) || 0
return prev + n
}, 0)
)
}
}
function handleRange(type, seriesUnit) {
if (type && type === 'range') {
// 调整堆叠柱子圆角
seriesUnit.itemStyle.borderRadius = [
chartToken.borderRadius,
chartToken.borderRadius,
chartToken.borderRadius,
chartToken.borderRadius
]
}
}
/**
* echarts所需要的series
* @param {} seriesData
* @param {} legendData
* @param {} isArea
* @param {线} isSmooth
* @param {线} isStep
* @param {线} markLine
* @param {} markPoint
* @param {} colors
* @returns
*/
export function setSeries(seriesData, legendData, iChartOption) {
// 柱状图类型
const type = iChartOption.type
// 柱状图方向
const direction = iChartOption.direction
// 覆盖用户传入的itemStyle
const seriesInit_ = handleItemStyle(direction, iChartOption.itemStyle)
// 拼装series
const series = []
legendData.forEach((legend, index) => {
const seriesUnit = cloneDeep(seriesInit_)
// 数值显示
handleLabel(seriesUnit, iChartOption, index)
// 聚焦效果
handleFocus(seriesUnit, iChartOption)
// 数据 / 数据名称
seriesUnit.name = legend
// 如果设置了 barMinHeight那么就把数据里面的0设置成null
if (iChartOption.itemStyle && iChartOption.itemStyle.barMinHeight) {
seriesUnit.data = seriesData[legend].map((item) => {
return item === 0 ? undefined : item
})
} else {
seriesUnit.data = seriesData[legend]
}
// 阈值线
handleMarkLine(seriesUnit, iChartOption, direction)
// 堆叠图
handleStack(type, seriesUnit, index, legendData, iChartOption)
// 双向图
handleBothSides(type, seriesUnit, direction, index, legendData)
// 数据均为正数的双向图
handleDoubleSides(type, seriesUnit, index, legendData)
// 瀑布图
handleWaterFall(type, seriesUnit)
// 区间图
handleRange(type, seriesUnit)
// 包含图
handleContain(type, seriesUnit)
series.push(seriesUnit)
})
// 配置多个series的y轴index
handleYaxis(series, iChartOption.yAxis)
return series
}
function handleItemStyle(direction, itemStyle) {
const seriesInit_ = cloneDeep(seriesInit())
if (direction && direction === 'horizontal') {
seriesInit_.itemStyle.borderRadius = [0, chartToken.borderRadius, chartToken.borderRadius, 0]
}
if (itemStyle?.barMinHeight) {
seriesInit_.barMinHeight = itemStyle.barMinHeight
}
if (itemStyle?.barWidth) {
seriesInit_.barWidth = itemStyle.barWidth
}
if (itemStyle?.barGap) {
seriesInit_.barGap = itemStyle.barGap
}
if (itemStyle?.color) {
seriesInit_.itemStyle.color = itemStyle.color
}
merge(seriesInit_.itemStyle, itemStyle)
return seriesInit_
}
function handleLabel(seriesUnit, iChartOption, index) {
const label = iChartOption.label
let labelOption
if (label && isArray(label)) {
labelOption = label[index]
} else {
labelOption = label
}
if (labelOption && labelOption.show) {
merge(seriesUnit.label, labelOption)
seriesUnit.label.show = true
seriesUnit.label.offset = labelOption.offset || [0, 0]
seriesUnit.label.position = labelOption.position || 'inside'
seriesUnit.label.formatter = labelOption.formatter
}
}
function handleMarkLine(seriesUnit, iChartOption, direction) {
const name = seriesUnit.name
const markLine = iChartOption.markLine
const isTopMarkLine = markLine && markLine.top && !(markLine.topUse && !markLine.topUse.includes(name))
const isBottomMarkLine = markLine && markLine.bottom && !(markLine.bottomUse && !markLine.bottomUse.includes(name))
if (isTopMarkLine || isBottomMarkLine) {
seriesUnit.markLine = cloneDeep(getMarkLineDefault())
merge(seriesUnit.markLine, markLine)
seriesUnit.markLine.lineStyle.color = markLine.color || chartToken.colorError
}
if (isTopMarkLine) {
if (direction && direction === 'horizontal') {
seriesUnit.markLine.data.push({ xAxis: markLine.top })
} else {
seriesUnit.markLine.data.push({ yAxis: markLine.top })
}
}
if (isBottomMarkLine) {
if (direction && direction === 'horizontal') {
seriesUnit.markLine.data.push({ xAxis: markLine.bottom })
} else {
seriesUnit.markLine.data.push({ yAxis: markLine.bottom })
}
}
}
function handleFocus(seriesUnit, iChartOption) {
if (iChartOption.focus) {
seriesUnit.emphasis = {
focus: 'series',
blurScope: 'global'
}
}
}
function handleStack(type, seriesUnit, index, legendData, iChartOption) {
if (type && type === 'stack') {
const stack = iChartOption.stack
if (stack) {
for (const name in stack) {
if (Object.hasOwnProperty.call(stack, name)) {
const stackArray = stack[name]
const seriesName = seriesUnit.name
const stackIndex = stackArray.indexOf(seriesName)
if (stackIndex !== -1) {
seriesUnit.stack = name
if (stackIndex + 1 < stackArray.length) {
delete seriesUnit.itemStyle.borderRadius
}
}
break
}
}
} else {
seriesUnit.stack = 'stack'
if (index !== legendData.length - 1) {
delete seriesUnit.itemStyle.borderRadius
}
}
}
}
function handleBothSides(type, seriesUnit, direction, index, legendData) {
if (type && (type === 'both-sides' || type === 'double-sides')) {
seriesUnit.stack = 'stack'
// 调整堆叠柱子圆角
if (direction && direction === 'horizontal') {
if (index === 0) {
seriesUnit.itemStyle.borderRadius = [0, chartToken.borderRadius, chartToken.borderRadius, 0]
}
if (index === legendData.length - 1) {
seriesUnit.itemStyle.borderRadius = [chartToken.borderRadius, 0, 0, chartToken.borderRadius]
}
} else {
if (index === 0) {
seriesUnit.itemStyle.borderRadius = [chartToken.borderRadius, chartToken.borderRadius, 0, 0]
}
if (index === legendData.length - 1) {
seriesUnit.itemStyle.borderRadius = [0, 0, chartToken.borderRadius, chartToken.borderRadius]
}
}
}
}
function handleDoubleSides(type, seriesUnit, index, legendData) {
if (type && type === 'double-sides') {
if (index === legendData.length - 1) {
seriesUnit.data = seriesUnit.data.map((item) => {
if (isNumber(item)) {
return -1 * item
} else {
return item
}
})
}
}
}
function handleContain(type, seriesUnit) {
if (type && type === 'contain') {
seriesUnit.barGap = '-100%'
}
}
function handleColorStops(percent, originColor, markLineColor) {
const colorStops = [
{
offset: 0,
color: markLineColor || chartToken.colorError
},
{
offset: percent,
color: markLineColor || chartToken.colorError
},
{
offset: percent + 0.001,
color: originColor
},
{
offset: 1,
color: originColor
}
]
return colorStops
}
function handleTopObj(d, direction, percent, originColor, markLineColor) {
const topObj = {
value: d,
itemStyle: {
color: {
type: 'linear',
x: direction === 'horizontal' ? 1 : 0,
y: direction === 'horizontal' ? 0 : 0,
x2: direction === 'horizontal' ? 0 : 0,
y2: direction === 'horizontal' ? 0 : 1,
colorStops: handleColorStops(percent, originColor, markLineColor)
}
}
}
return topObj
}
function handleBottomObj(d, direction, percent, originColor, markLineColor) {
const bottomObj = {
value: d,
itemStyle: {
color: {
type: 'linear',
x: direction === 'horizontal' ? 0 : 0,
y: direction === 'horizontal' ? 0 : 1,
x2: direction === 'horizontal' ? 1 : 0,
y2: direction === 'horizontal' ? 0 : 0,
colorStops: handleColorStops(percent, originColor, markLineColor)
}
}
}
return bottomObj
}
const colorStopsOrigin = [
{ offset: 0, color: chartToken.colorError },
{ offset: 1, color: chartToken.colorError }
]
function handleColorStopsTop(originColor, bottomPercent) {
const colorStops = [
{ offset: 0, color: originColor },
{ offset: bottomPercent, color: originColor },
{ offset: bottomPercent + 0.0001, color: chartToken.colorError },
{ offset: 1, color: chartToken.colorError }
]
return colorStops
}
function handleColorStopsBottom(originColor, topPercent) {
const colorStops = [
{ offset: 0, color: chartToken.colorError },
{ offset: topPercent, color: chartToken.colorError },
{ offset: topPercent + 0.0001, color: originColor },
{ offset: 1, color: originColor }
]
return colorStops
}
function handleColorStopsOther(originColor, topPercent, bottomPercent) {
const colorStops = [
{ offset: 0, color: chartToken.colorError },
{ offset: topPercent, color: chartToken.colorError },
{ offset: topPercent + 0.0001, color: originColor },
{ offset: bottomPercent, color: originColor },
{ offset: bottomPercent + 0.0001, color: chartToken.colorError },
{ offset: 1, color: chartToken.colorError }
]
return colorStops
}
function handleResObj(d, direction, colorStops) {
const resObj = {
value: d,
itemStyle: {
color: {
type: 'linear',
x: direction === 'horizontal' ? 1 : 0,
y: direction === 'horizontal' ? 0 : 0,
x2: direction === 'horizontal' ? 0 : 0,
y2: direction === 'horizontal' ? 0 : 1,
colorStops
}
}
}
return resObj
}
function handleSeries(iChartOption, baseOption, exclude, colors, direction) {
// 顶部阈值
let top = iChartOption.markLine.top
// 底部阈值
let bottom = iChartOption.markLine.bottom
const usefullSeries = baseOption.series.filter((item) => {
return !exclude.includes(item.name)
})
usefullSeries.forEach((item, index) => {
if (!exclude.includes(item.name)) {
const barData = item.data
const placeHolderData = baseOption.series[index * 2].data
item.data = barData.map((d, i) => {
const pd = placeHolderData[i]
if (top === undefined) {
top = pd + d + 1
}
if (bottom === undefined) {
bottom = pd - 1
}
const originColor = getColor(colors, index)
let topPercent = 0
let bottomPercent = 1
topPercent = (d + pd - top) / d
topPercent < 0 && (topPercent = 0)
topPercent > 1 && (topPercent = 1)
bottomPercent = (d + pd - bottom) / d
bottomPercent < 0 && (bottomPercent = 0)
bottomPercent > 1 && (bottomPercent = 1)
let colorStops = []
if (topPercent === 1 || bottomPercent === 0) {
// 纯红
colorStops = colorStopsOrigin
} else if (topPercent === 0 && bottomPercent === 1) {
// 原色
return d
} else if (topPercent === 0) {
colorStops = handleColorStopsTop(originColor, bottomPercent)
} else if (bottomPercent === 1) {
colorStops = handleColorStopsBottom(originColor, topPercent)
} else {
colorStops = handleColorStopsOther(originColor, topPercent, bottomPercent)
}
const resObj = handleResObj(d, direction, colorStops)
return resObj
})
}
})
}
// 针对阈值线以上显示红色区域的需求,图表需要进行特殊处理
export function setMarkLine(baseOption, iChartOption) {
const type = iChartOption.type
const colors = baseOption.color
const direction = iChartOption.direction
const exclude = ['Placeholder']
if (iChartOption.markLine && type !== 'water-fall' && type !== 'range') {
// 顶部阈值
const top = iChartOption.markLine.top
const topUse = iChartOption.markLine.topUse
// 底部阈值
const bottom = iChartOption.markLine.bottom
const bottomUse = iChartOption.markLine.bottomUse
// 用户自定义阈值线颜色
const markLineColor = iChartOption.markLine.color
const usefullSeries = baseOption.series.filter((item) => {
return !exclude.includes(item.name)
})
usefullSeries.forEach((item, index) => {
if (!exclude.includes(item.name)) {
const barData = item.data
item.data = barData.map((d) => {
const originColor = getColor(colors, index)
// 如果该柱形高度超过阈值,侧改变其颜色
if (top && d >= 0 && top >= 0 && d > top) {
if (topUse && !topUse.includes(item.name)) {
return d
}
const percent = (d - top) / (d - 0)
const topObj = handleTopObj(d, direction, percent, originColor, markLineColor)
return topObj
// 如果该柱形高度低于阈值,侧改变其颜色
} else if (bottom && d <= 0 && bottom <= 0 && d < bottom) {
if (bottomUse && !bottomUse.includes(item.name)) {
return d
}
const percent = (bottom - d) / (0 - d)
const bottomObj = handleBottomObj(d, direction, percent, originColor, markLineColor)
return bottomObj
} else {
return d
}
})
}
})
}
//
if (iChartOption.markLine && type === 'range') {
handleSeries(iChartOption, baseOption, exclude, colors, direction)
}
}
function placeFun(index, placeholderData) {
const a = {
name: 'Placeholder',
type: 'bar',
stack: `stack${index}`,
itemStyle: {
borderColor: chartToken.borderColor,
color: chartToken.color
},
emphasis: {
itemStyle: {
borderColor: chartToken.borderColor,
color: chartToken.color
}
},
data: placeholderData
}
return a
}
// 针对区间图表需求,图表需要进行特殊处理
export function setRange(baseOption, iChartOption) {
const type = iChartOption.type
if (type && type === 'range') {
const tempArray = []
baseOption.series.forEach((item, index) => {
const barData = item.data
const barRealData = []
const placeholderData = []
const placeholder = placeFun(index, placeholderData)
barData.forEach((d) => {
placeholderData.push(d[0])
barRealData.push(d[1] - d[0])
})
item.stack = `stack${index}`
item.data = barRealData
tempArray.push(placeholder)
tempArray.push(item)
})
baseOption.series = tempArray
}
}
// 针对瀑布图表需求,图表需要进行特殊处理
export function setWaterFall(baseOption, iChartOption) {
const type = iChartOption.type
const totalName = iChartOption.totalName || 'Total'
const totalPosition = iChartOption.totalPosition || 'end'
if (type && type === 'water-fall') {
const tempArray = []
baseOption.series.forEach((item, index) => {
const barData = item.data
const placeholderData = [0]
const placeholder = placeFun(index, placeholderData)
if (totalPosition === 'end') {
barData.forEach((d, i) => {
if (i < barData.length - 1) {
placeholderData.push((Number(d) || 0) + placeholderData[i])
}
})
placeholderData[placeholderData.length - 1] = 0
} else {
barData.unshift(barData.pop())
placeholderData[0] = barData[0]
barData.forEach((d, i) => {
if (i > 0) {
placeholderData.push(placeholderData[i - 1] - (Number(d) || 0))
}
})
placeholderData[0] = 0
}
item.stack = `stack${index}`
tempArray.push(placeholder)
tempArray.push(item)
})
if (totalPosition === 'end') {
baseOption.xAxis[0].data.push(totalName)
} else {
baseOption.xAxis[0].data.unshift(totalName)
}
baseOption.series = tempArray
}
}
/**
* seriesPlaceHolder series
* tooltip series
* tooltip.formatter
*/
export function setLimitFormatter(baseOption, iChartOption, seriesData) {
const type = iChartOption.type
const toolTipFormatter = baseOption.tooltip.formatter
const exclude = ['Placeholder']
const colors = baseOption.color
baseOption.tooltip.formatter = (params, ticket, callback) => {
const newParams = params.filter((item) => {
return !exclude.includes(item.seriesName)
})
if (toolTipFormatter) {
return toolTipFormatter(newParams, ticket, callback)
}
let htmlString = ''
newParams.forEach((item, index) => {
if (index === 0) {
htmlString += `<div style="margin-bottom:4px;">${defendXSS(item.name)}</div>`
}
const itemColor = typeof item.color === 'string' ? item.color : getColor(colors, index)
htmlString += `
<div>
<span style="display:inline-block;width:10px;height:10px;border-radius:5px;background-color:${defendXSS(
itemColor
)};">
</span>
<span style="margin-left:5px;">
<span style="display:inline-block;margin-right:8px;min-width:60px;">${defendXSS(
item.seriesName
)}</span>
<span style="font-weight:bold">
${defendXSS(
type === 'range'
? `${`${`[${params[index * 2].value}`}-${params[index * 2].value + item.value}`}]`
: item.value || seriesData[item.seriesName][item.dataIndex]
)}
</span>
</span>
</div>
`
})
return htmlString
}
}
function handleYaxis(series, yAxis) {
if (Array.isArray(yAxis)) {
yAxis.forEach((y, index) => {
series.forEach((s, indexs) => {
if (y.dataName && y.dataName.includes(s.name)) {
series[indexs].yAxisIndex = index
}
})
})
}
}

View File

@ -0,0 +1,37 @@
import min from '../../util/sort/min'
import max from '../../util/sort/max'
import { getColor } from '../../util/color'
import chartToken from './chartToken'
export function setVisualMap(legendData, seriesData, markLine, colors) {
const visualMap = []
if (markLine) {
const topValue = markLine.top
const bottomValue = markLine.bottom
legendData.forEach((legendName, index) => {
const data = seriesData[legendName]
const minData = min(data)
const maxData = max(data)
const bottom = bottomValue || minData - 1
const top = topValue || maxData + 1
// 根据数据大小映射颜色
visualMap.push({
show: false,
type: 'piecewise',
dimension: 1,
seriesIndex: index,
pieces: [
{
gt: bottom,
lt: top,
color: getColor(colors, index)
}
],
outOfRange: {
color: chartToken.colorError
}
})
})
}
return visualMap
}

View File

@ -0,0 +1,110 @@
import LineChart from '../LineChart'
import init from '../../option/init'
import { event } from '../../util/event'
import cloneDeep from '../../util/cloneDeep'
import BaseOption from '../../option/base'
import { mergeVisualMap, mergeSeries } from '../../util/merge'
import RectCoordSys from '../../option/RectSys'
import { setStack, setDirection, setDoubleSides } from './handleOptipn'
import { xkey, xdata, ldata, ydata } from '../../option/RectSys'
import { setSeries, setRange, setMarkLine, setWaterFall, setLimitFormatter } from './handleSeries'
class BarChart {
constructor(iChartOption, chartInstance) {
this.baseOption = {}
this.baseOption = cloneDeep(BaseOption)
this.chartInstance = chartInstance
// 组装 iChartOption, 补全默认值
this.iChartOption = init(iChartOption)
// 根据 iChartOption 组装 baseOption
this.updateOption()
}
updateOption() {
const iChartOption = this.iChartOption
// 装载除series之外的其他配置
RectCoordSys(this.baseOption, this.iChartOption, 'BarChart')
// x轴key值
const xAxisKey = xkey(iChartOption)
// x轴数据
const xAxisData = xdata(iChartOption.data, xAxisKey)
// 图例数据
const legendData = ldata(iChartOption.data, xAxisKey)
// 连线的数据
const seriesData = ydata(iChartOption.data, legendData)
// 赋值数据
this.baseOption.legend.data = iChartOption.legend.data || legendData
this.baseOption.xAxis.forEach((item) => {
item.data = xAxisData
})
this.baseOption.series = setSeries(seriesData, legendData, iChartOption)
// 给堆叠图的柱子中间加上空白缝隙,并覆盖图例的点击事件
setStack(this.baseOption, iChartOption, legendData, seriesData)
// 针对数据均为正数的双向柱状图进行一些特殊处理
setDoubleSides(this.baseOption, iChartOption)
// 针对瀑布图表需求,图表需要进行特殊处理
setWaterFall(this.baseOption, iChartOption)
// 针对区间图表需求,图表需要进行特殊处理
setRange(this.baseOption, iChartOption)
// 针对阈值线变色,图表需要进行特殊处理
setMarkLine(this.baseOption, iChartOption)
// 设置柱状图的方向
setDirection(this.baseOption, iChartOption.direction)
// 对 tooltip.formatter 进行二次封装
setLimitFormatter(this.baseOption, iChartOption, seriesData)
// 配置图表事件
if (iChartOption.event) {
event(this.chartInstance, iChartOption.event)
}
// 是否关闭hover态的效果默认为false
if (iChartOption.silent) {
this.baseOption.tooltip = {}
}
// 合并用户自定义series
mergeSeries(iChartOption, this.baseOption)
// 合并用户自定义visualMap
mergeVisualMap(iChartOption, this.baseOption)
}
// 根据渲染出的结果二次计算option
updateOptionAgain(YAxiMax, YAxiMin) {
const baseOption = this.baseOption
const iChartOption = this.iChartOption
const lineDataName = iChartOption.lineDataName
// 折柱混合
if (lineDataName && lineDataName.length > 0) {
const lineChartBaseOpt = new LineChart(iChartOption, {}, this.chartInstance)
const lineBaseOption = lineChartBaseOpt.getOption()
const lineSeries = lineBaseOption.series
const barSeries = baseOption.series
lineDataName.forEach((lineName) => {
let bar = null
let line = null
for (let i = 0; i < lineSeries.length; i++) {
if (lineSeries[i].name === lineName) {
line = lineSeries[i]
break
}
}
for (let i = 0; i < barSeries.length; i++) {
if (barSeries[i].name === lineName) {
bar = barSeries[i]
break
}
}
for (const key in line) {
bar[key] = line[key]
}
})
}
}
getOption() {
return this.baseOption
}
setOption() {}
}
export default BarChart

View File

@ -0,0 +1,113 @@
import { insertStateDom, removeStateDom } from '../../util/init/insert'
export default class BaseChart {
// 图表渲染容器
dom
// 图表渲染配置
option
constructor() {
// 必须实现 init 方法,初始化图表渲染容器
if (this.init === undefined) {
throw new Error('This chart has not overwrite "init" callback!')
}
// 必须实现 setSimpleOption 方法,初始化图表渲染配置
if (this.setSimpleOption === undefined) {
throw new Error('This chart has not overwrite "setSimpleOption" callback!')
}
// 必须实现 render 方法,调用时开始渲染图表
if (this.render === undefined) {
throw new Error('This chart has not overwrite "render" callback!')
}
// 必须实现 onRenderReady 方法
if (this.onRenderReady === undefined) {
throw new Error('This chart has not overwrite "onRenderReady" callback!')
}
// 必须实现 refresh 方法传入新的option刷新图表
if (this.refresh === undefined) {
throw new Error('This chart has not overwrite "refresh" callback!')
}
// 必须实现 refreshData 方法传入新的data刷新图表
if (this.refreshData === undefined) {
throw new Error('This chart has not overwrite "refreshData" callback!')
}
// 必须实现 setResize 方法,该方法一般手动调用,实现图表自适应宽度
if (this.setResize === undefined) {
throw new Error('This chart has not overwrite "setResize" callback!')
}
// 必须实现 uninstall 方法,清空图表容器,卸载所有监听事件
if (this.uninstall === undefined) {
throw new Error('This chart has not overwrite "uninstall" callback!')
}
}
// 加载状态
showLoading(option) {
insertStateDom(this.dom, 'loading', option)
}
hideLoading() {
removeStateDom(this.dom, 'loading')
}
closeLoading() {
removeStateDom(this.dom, 'loading')
}
// 错误状态
showError(option) {
insertStateDom(this.dom, 'error', option)
}
closeError() {
removeStateDom(this.dom, 'error')
}
// 空数据状态
showEmpty(option) {
insertStateDom(this.dom, 'empty', option)
}
closeEmpty() {
removeStateDom(this.dom, 'empty')
}
// 阶段空数据状态
showStageEmpty(option) {
insertStateDom(this.dom, 'stage_empty', option)
}
closeStageEmpty() {
removeStateDom(this.dom, 'stage_empty')
}
// 自定义数据状态
showState(option) {
insertStateDom(this.dom, 'custom', option)
}
closeState() {
removeStateDom(this.dom, 'custom')
}
// 传入自定义DOM
showCustomDom(callback) {
if (this.dom.getElementsByClassName('huicharts-custom-dom').length > 0) return
if (getComputedStyle(this.dom).position === ('static' || '')) {
this.dom.style.position = 'relative'
}
let customContainer = document.createElement('div')
customContainer.className = 'huicharts-custom-dom'
customContainer.setAttribute(
'style',
'position:absolute;width:100%;height:100%;top:0px;left:0px;display:flex;justify-content:center;align-items:center'
)
this.dom.appendChild(customContainer)
callback(customContainer)
}
// 删除自定义DOM
closeCustomDom() {
let customContainer = this.dom.getElementsByClassName('huicharts-custom-dom')
this.dom.removeChild(customContainer[0])
}
}

View File

@ -0,0 +1,16 @@
import Theme from '../../feature/token'
import proxy from '../../util/proxy'
function getChartToken() {
const {
itemStyle: { color: colorBgPrimary }
} = Theme.config.BoxplotChart
return {
itemColor: colorBgPrimary
}
}
const chartToken = proxy(getChartToken)
export default chartToken

View File

@ -0,0 +1,52 @@
import defendXSS from '../../util/defendXSS'
/**
*
*/
export function setDirection(baseOption, direction) {
if (direction && direction === 'horizontal') {
const temp = baseOption.xAxis
baseOption.xAxis = baseOption.yAxis
baseOption.yAxis = temp
}
}
function tooltipFormatter(params) {
const { data, color, seriesType } = params
const labels = ['下限', '下四分位数', '中位数', '上四分位数', '上限']
let htmlString = ''
if (seriesType === 'boxplot') {
const arr = []
labels.forEach((item, index) => {
htmlString = `<div>
<span style="display:inline-block;width:10px;height:10px;
margin-right:4px;border-radius:5px;border-style: solid;border-width:1px;
border-color:${defendXSS(color)};background-color:${defendXSS(color)};"></span>
<span style="display:inline-block;width:90px">${defendXSS(item)}:</span><span>${defendXSS(
data[index + 1]
)}</span>
</div>`
arr.push(htmlString)
})
htmlString = arr.join('<br/>')
} else {
htmlString = `<div>
<span style="display:inline-block;width:10px;height:10px;
margin-right:4px;border-radius:5px;border-style: solid;border-width:1px;
border-color:${defendXSS(color)};background-color:${defendXSS(color)};"></span>
<span style="display:inline-block;width:90px">:</span><span>${defendXSS(
data[1]
)}</span>
</div>`
}
return htmlString
}
/**
*
*/
export function setTooltip(baseOpt) {
if (!baseOpt.tooltip.formatter) {
baseOpt.tooltip.formatter = tooltipFormatter
}
}

View File

@ -0,0 +1,50 @@
import cloneDeep from '../../util/cloneDeep'
import chartToken from './chartToken'
const datasetInit = [
{
source: []
},
{
transform: {
type: 'boxplot'
}
},
{
fromDatasetIndex: 1,
fromTransformResult: 1
}
]
const seriesInit = [
{
name: 'boxplot',
type: 'boxplot',
datasetIndex: 1,
itemStyle: {
color: ''
}
},
{
name: 'outlier',
type: 'scatter',
datasetIndex: 2
}
]
/**
* echarts所需要的dataset
* @param {} data
* @returns
*/
export function setDataset(data) {
const dataset = cloneDeep(datasetInit)
dataset[0].source = data
return dataset
}
export function setSeries() {
const series = cloneDeep(seriesInit)
series[0].itemStyle.color = chartToken.itemColor
return series
}

View File

@ -0,0 +1,52 @@
import init from '../../option/init'
import { event } from '../../util/event'
import { setDataset, setSeries } from './handleSeries'
import { setDirection, setTooltip } from './handleOption'
import RectCoordSys from '../../option/RectSys'
import chartToken from './chartToken'
const CHART_NAME = 'BoxplotChart'
export default class BoxplotChart {
constructor(iChartOption, chartInstance) {
this.baseOption = {}
this.iChartOption = {}
this.iChartOption = init(iChartOption)
this.updateOption(chartInstance)
}
updateOption(chartInstance) {
const iChartOption = this.iChartOption
// 装载除series之外的其他配置
RectCoordSys(this.baseOption, this.iChartOption, CHART_NAME)
// 箱形图data必须设为undefined
this.baseOption.xAxis[0].data = undefined
// 提示框trigger设为item
this.baseOption.tooltip.trigger = 'item'
// 配置默认dataset
if (iChartOption.data && !iChartOption.dataset) {
this.baseOption.dataset = setDataset(iChartOption.data)
this.baseOption.series = setSeries()
}
// 自定义dataset和series
if (iChartOption.dataset && iChartOption.series) {
this.baseOption.dataset = iChartOption.dataset
this.baseOption.series = iChartOption.series
this.baseOption.series.forEach((item) => {
item.itemStyle = {}
item.itemStyle.color = chartToken.itemColor
})
}
// 横向
setDirection(this.baseOption, iChartOption.direction)
// 提示框
setTooltip(this.baseOption)
// 配置图表事件
if (iChartOption.event) {
event(chartInstance, iChartOption.event)
}
}
getOption() {
return this.baseOption
}
}

View File

@ -0,0 +1,19 @@
import Theme from '../../feature/token'
import proxy from '../../util/proxy'
function getChartToken() {
const {
emphasis: {
label: { color: colorLabel }
}
} = Theme.config.BubbleChart
return {
emphasisLabelColor: colorLabel,
labelColor: colorLabel
}
}
const chartToken = proxy(getChartToken)
export default chartToken

View File

@ -0,0 +1,22 @@
/**
* legend-data
*/
export function getLegendData(data) {
return Object.keys(data)
}
/**
* x轴的坐标数据
*/
export function getXAxisData(data) {
const xAxisData = []
const dataValues = Object.values(data)
dataValues.forEach((item) => {
item.forEach((val) => {
if (!xAxisData.includes(val[0])) {
xAxisData.push(val[0])
}
})
})
return xAxisData
}

View File

@ -0,0 +1,53 @@
import { changeRgbaOpacity } from '../../util/color'
import defendXSS from '../../util/defendXSS'
function tooltipFormatter(params) {
const seriesName = params.seriesName
const color = params.color
const data = params.data
const [x, y, radius, name] = data
let htmlString = `<div style="margin-bottom:4px;">
${defendXSS(seriesName)}
</div>`
htmlString += `<div style="margin-bottom:4px;">
<span style="display:inline-block;width:10px;height:10px;
margin-right:8px;border-radius:5px;border-style: solid;border-width:1px;
border-color:${defendXSS(changeRgbaOpacity(color, 1))};background-color:${defendXSS(
color
)};"></span>
<span>${defendXSS(name)}</span>
</div>`
htmlString += `
<div>
<span style="display:inline-block;margin-right:8px;min-width:60px;">x维度</span>
<span>${defendXSS(x)}</span>
</div>
`
htmlString += `
<div>
<span style="display:inline-block;margin-right:8px;min-width:60px;">y维度</span>
<span>${defendXSS(y)}</span>
</div>
`
htmlString += `
<div>
<span style="display:inline-block;margin-right:8px;min-width:60px;"></span>
<span>${defendXSS(radius)}</span>
</div>
`
return htmlString
}
/**
*
*/
export function setTooltip(baseOpt, iChartOption) {
baseOpt.tooltip.trigger = 'item'
if (iChartOption.trigger === 'axis') {
baseOpt.tooltip.trigger = 'axis'
baseOpt.tooltip.axisPointer.type = 'shadow'
}
if (!baseOpt.tooltip.formatter) {
baseOpt.tooltip.formatter = tooltipFormatter
}
}

View File

@ -0,0 +1,72 @@
import { getColor, codeToRGB } from '../../util/color'
import cloneDeep from '../../util/cloneDeep'
import { getMarkLineDefault } from '../../option/config/mark'
import chartToken from './chartToken'
import merge from '../../util/merge'
export const seriesInit = {
// 数据
data: [],
// 气泡图
type: 'scatter',
// 鼠标hover时显示label并且其他legend变成灰色
emphasis: {
label: {
show: true,
color: '#ffffff',
fontSize: 14,
formatter(param) {
return param.data[3]
},
position: 'top'
}
},
// 气泡样式
itemStyle: {}
}
export function setSeries({ legendData, data, markLine, color, iChartOption }) {
// 更改hover时显示的label颜色
seriesInit.emphasis.label.color = chartToken.emphasisLabelColor
const series = []
legendData.forEach((legend, index) => {
const seriesUnit = cloneDeep(seriesInit)
const itemBorderColor = getColor(color, index)
// 设置图元透明度
const itemColor = codeToRGB(itemBorderColor, iChartOption.symbolOpacity || 0.2)
// 阈值线
if (markLine) {
seriesUnit.markLine = cloneDeep(getMarkLineDefault())
if (markLine.y) {
seriesUnit.markLine.data.push({ yAxis: markLine.y })
}
if (markLine.x) {
seriesUnit.markLine.data.push({ xAxis: markLine.x })
}
}
// 数据 / 数据名称
seriesUnit.name = legend
seriesUnit.data = data[legend]
seriesUnit.itemStyle = {
color: itemColor,
borderColor: itemBorderColor,
borderWidth: 1
}
series.push(seriesUnit)
})
return series
}
// 添加seires属性
export function handleSeriesExtra(baseOpt, iChartOption) {
const { symbol, symbolRotate, symbolOffset, cursor, label, itemStyle, emphasis } = iChartOption
baseOpt.series.forEach((item) => {
item.symbol = symbol
item.symbolRotate = symbolRotate
item.symbolOffset = symbolOffset
item.cursor = cursor
item.label = label
merge(item.itemStyle, itemStyle)
merge(item.emphasis, emphasis)
})
}

View File

@ -0,0 +1,45 @@
import * as echarts from 'echarts'
import chartToken from './chartToken'
/**
* 线
*/
export function handleTrendLine(option, iChartOption, plugins) {
const ecStat = plugins.ecStat
if (iChartOption.trendLineConfig) {
if (ecStat) {
echarts.registerTransform(ecStat.transform.regression)
// 集合数据
option.dataset.push({
transform: {
type: 'ecStat:regression',
config: iChartOption.trendLineConfig
}
})
// 趋势线
option.series.push({
name: 'trendline',
type: 'line',
smooth: true,
datasetIndex: 1,
symbolSize: 0.1,
symbol: 'circle',
label: {
show: true,
fontSize: 14,
color: chartToken.labelColor
},
labelLayout: {
dx: -20
},
encode: {
label: 2,
tooltip: 1
},
silent: true
})
} else {
throw new Error('您必须安装echarts-stat才可以使用趋势线功能')
}
}
}

View File

@ -0,0 +1,39 @@
import min from '../../util/sort/min'
import max from '../../util/sort/max'
export function setVisualMap(baseOption, iChartOption, legendData) {
const visualMap = []
const bubbleSize = iChartOption.bubbleSize || [10, 70]
const radius = baseOption.dataset[0].source.map((item) => {
return item[2]
})
const minValue = min(radius)
const maxValue = max(radius)
const seriesIndex = new Array(legendData.length).fill(0).map((item, index) => {
return index
})
visualMap.push({
show: false,
dimension: 2,
min: minValue,
max: maxValue,
seriesIndex,
inRange: {
symbolSize: bubbleSize
}
})
return visualMap
}
// 设置数据集
export function setDataset(baseOption, iChartOption) {
let source = []
Object.keys(iChartOption.data).forEach((key) => {
source = source.concat(iChartOption.data[key])
})
return [
{
source
}
]
}

View File

@ -0,0 +1,86 @@
import init from '../../option/init'
import BaseOption from '../../option/base'
import cloneDeep from '../../util/cloneDeep'
import { getLegendData, getXAxisData } from './handleData'
import { setSeries, handleSeriesExtra } from './handleSeries'
import { setTooltip } from './handleOptipn'
import { handleTrendLine } from './handleTrendLine'
import { setDataset, setVisualMap } from './handleVisualMap'
import RectCoordSys from '../../option/RectSys'
import { event } from '../../util/event'
import { mergeSeries, mergeVisualMap } from '../../util/merge'
class BubbleChart {
constructor(iChartOption, chartInstance, plugins) {
this.baseOption = {}
this.baseOption = cloneDeep(BaseOption)
this.iChartOption = {}
this.chartInstance = chartInstance
// 组装 iChartOption, 补全默认值
this.iChartOption = init(iChartOption)
// 根据 iChartOption 组装 baseOption
this.updateOption(plugins)
}
updateOption(plugins) {
const iChartOption = this.iChartOption
// 装载除series之外的其他配置
RectCoordSys(this.baseOption, this.iChartOption, 'BubbleChart')
// 增加气泡图的默认悬浮提示框
setTooltip(this.baseOption, iChartOption)
// 组装基础数据
const legendData = getLegendData(iChartOption.data)
// 设置x轴类型是目录型还是数值型
const { xAxisType } = iChartOption
if (
legendData &&
legendData[0] &&
iChartOption.data[legendData[0]] &&
iChartOption.data[legendData[0]][0] &&
iChartOption.data[legendData[0]][0][0] &&
typeof iChartOption.data[legendData[0]][0][0] === 'string'
) {
this.baseOption.xAxis.forEach((item) => {
item.type = xAxisType || 'category'
item.data = getXAxisData(iChartOption.data)
})
} else {
this.baseOption.xAxis.forEach((item) => {
item.type = xAxisType || 'value'
})
}
// 赋值数据
this.baseOption.legend.data = this.baseOption.legend.data || legendData
this.baseOption.series = setSeries({
legendData,
data: iChartOption.data,
markLine: iChartOption.markLine,
color: this.baseOption.color,
iChartOption
})
// 添加dataset
this.baseOption.dataset = setDataset(this.baseOption, iChartOption)
// 设置VisualMap通过数值映射气泡大小
this.baseOption.visualMap = setVisualMap(this.baseOption, iChartOption, legendData)
// 针对趋势线的需求,图表需要进行特殊处理
handleTrendLine(this.baseOption, iChartOption, plugins)
// 添加seires属性
handleSeriesExtra(this.baseOption, iChartOption)
// 配置图表事件
if (iChartOption.event) {
event(this.chartInstance, iChartOption.event)
}
// 合并用户自定义series
mergeSeries(iChartOption, this.baseOption)
// 合并用户自定义visualMap
mergeVisualMap(iChartOption, this.baseOption)
}
getOption() {
return this.baseOption
}
setOption() {}
}
export default BubbleChart

View File

@ -0,0 +1,33 @@
// 显示volume需要的grid
const VOLUMEGRID = [
{
left: '5%',
right: '5%',
height: '50%',
top: '2%',
containLabel: false
},
{
left: '5%',
right: '5%',
top: '63%',
height: '25%',
containLabel: false
}
]
const BASICSERIES = [
{
name: '日K',
type: 'candlestick',
data: undefined,
itemStyle: {
color: undefined,
color0: undefined,
borderColor: undefined,
borderColor0: undefined
}
}
]
export { BASICSERIES, VOLUMEGRID }

View File

@ -0,0 +1,21 @@
import Theme from '../../feature/token'
import proxy from '../../util/proxy'
function getChartToken() {
const {
axisPointer: {
label: { color: colorTextSecondary }
}
} = Theme.config.CandlestickChart
const { colorState } = Theme.config
return {
axisPointerLabelColor: colorTextSecondary,
colorState
}
}
const chartToken = proxy(getChartToken)
export default chartToken

View File

@ -0,0 +1,119 @@
import { isArray } from '../../util/type'
import cloneDeep from '../../util/cloneDeep'
import { VOLUMEGRID } from './BaseOption'
import merge from '../../util/merge'
import chartToken from './chartToken'
import { xkey } from '../../option/RectSys'
function handleData(iChartOpt) {
const { data } = iChartOpt
const xAxisDataName = xkey(iChartOpt)
if (data && data.length !== 0) {
const time = []
const total = []
data.forEach((item) => {
time.push(item[xAxisDataName])
const totalItem = [item.open, item.close, item.lowest, item.highest]
if (item.volume) {
totalItem.push(item.volume)
}
total.push(totalItem)
})
return {
time,
total
}
}
return null
}
function handleAxis(baseOpt, data, volume) {
const { xAxis } = baseOpt
if (isArray(xAxis)) {
const len = xAxis.length
if (volume && len === 1) {
const secXaxis = cloneDeep(xAxis[0])
xAxis.push(secXaxis)
}
xAxis.forEach((x, xIndex) => {
x.data = data.time
x.boundaryGap = false
x.axisLine.onZero = false
if (xIndex === 1) {
x.axisLabel.show = false
x.axisTick.show = false
x.gridIndex = 1
}
})
} else {
xAxis.data = data.time
xAxis.boundaryGap = false
xAxis.axisLine.onZero = false
}
const { yAxis } = baseOpt
const lenY = yAxis.length
if (volume && lenY === 1) {
const secYaxis = cloneDeep(yAxis[0])
yAxis.push(secYaxis)
}
yAxis.forEach((y, yIndex) => {
y.scale = true
if (yIndex === 1) {
y.axisLabel.show = false
y.splitLine.show = false
y.gridIndex = 1
}
})
}
function handleDataZoom(baseOpt, iChartOpt) {
const { dataZoom } = iChartOpt
baseOpt.dataZoom[0].show = true
baseOpt.dataZoom[0].xAxisIndex = [0, 1]
baseOpt.dataZoom[0].bottom = '6%'
if (dataZoom) {
merge(baseOpt.dataZoom[0], dataZoom)
}
}
function handleLegend(baseOpt, iChartOpt) {
const { legend } = iChartOpt
if (legend) {
merge(baseOpt.legend, legend)
}
}
function handleTooltip(baseOpt, iChartOpt) {
const inerTooltip = { ...baseOpt.tooltip }
delete inerTooltip.axisPointer
inerTooltip.axisPointer = { type: 'cross' }
baseOpt.tooltip = inerTooltip
if (iChartOpt.tooltip) {
merge(baseOpt.tooltip, iChartOpt.tooltip)
}
}
function handleGrid(baseOpt, iChartOpt) {
const { volume, grid } = iChartOpt
// 用户没有自定义grid,并且需要去显示volume,使用默认值
if (!grid && volume) {
baseOpt.grid = cloneDeep(VOLUMEGRID)
}
}
function handleAxisPointer(baseOpt) {
const axisPointer = {
link: [
{
xAxisIndex: 'all'
}
],
label: {
color: chartToken.axisPointerLabelColor
}
}
baseOpt.axisPointer = axisPointer
}
export { handleData, handleAxis, handleDataZoom, handleLegend, handleTooltip, handleGrid, handleAxisPointer }

View File

@ -0,0 +1,110 @@
import cloneDeep from '../../util/cloneDeep'
import { BASICSERIES } from './BaseOption'
import LineChart from '../LineChart'
import BarChart from '../BarChart'
import { xkey } from '../../option/RectSys'
import chartToken from './chartToken'
function handleSeries(baseOpt, iChartOpt, data, chartInstance) {
const { upColor, downColor } = iChartOpt
const { colorState } = chartToken
const upStateColor = upColor || colorState.colorError
const downStateColor = downColor || colorState.colorSuccess
const baseSeries = cloneDeep(BASICSERIES)
baseSeries[0].data = data.total
baseSeries[0].itemStyle.color = upStateColor
baseSeries[0].itemStyle.color0 = downStateColor
baseSeries[0].itemStyle.borderColor = upStateColor
baseSeries[0].itemStyle.borderColor0 = downStateColor
baseOpt.series = baseSeries
handleMaAndVolSeries(baseOpt, iChartOpt, data, { upStateColor, downStateColor }, chartInstance)
}
// 用于计算相关的平均值
function calculateMA(dayCount, data) {
const result = []
for (let i = 0, len = data.length; i < len; i++) {
if (i < dayCount) {
result.push('')
continue
}
let sum = 0
for (let j = 0; j < dayCount; j++) {
sum += +data[i - j][1]
}
result.push(Number((sum / dayCount).toFixed(2)))
}
return result
}
function getLineChartData(data, total, ma, xAxisKey) {
const maData = {}
ma.forEach((item) => {
const data = calculateMA(item, total)
maData[`MA${item}`] = data
})
const lineData = data.map((obj, index) => {
const newObj = {
[xAxisKey]: obj[xAxisKey]
}
for (const i in maData) {
newObj[i] = maData[i][index]
}
return newObj
})
return lineData
}
function getBarChartData(data, xAxisKey) {
const barData = data.map((obj) => {
const newObj = {
[xAxisKey]: obj[xAxisKey],
volume: obj.volume
}
return newObj
})
return barData
}
function handleMaSeries(baseOpt, iChartOpt, data, total, inerMa, xAxisKey, chartInstance) {
const lineChartData = getLineChartData(data, total, inerMa, xAxisKey)
const newIchartOption = { ...iChartOpt, data: lineChartData }
const lineChart = new LineChart(newIchartOption, {}, chartInstance)
const lineBaseOption = lineChart.getOption()
const lineSeries = lineBaseOption.series
for (let i = 0; i < lineSeries.length; i++) {
baseOpt.series.push(lineSeries[i])
}
}
function handleVol(baseOpt, iChartOpt, data, xAxisKey, { upStateColor, downStateColor }, total, chartInstance) {
const barChartData = getBarChartData(data, xAxisKey)
const newIchartOption = { ...iChartOpt, data: barChartData }
const barChart = new BarChart(newIchartOption, {}, chartInstance)
// 获取生成的相应的barchart配置
const barBaseOption = barChart.getOption()
const barSeries = barBaseOption.series[0]
barSeries.itemStyle.color = (params) => {
const { dataIndex } = params
const curTimeData = total[dataIndex]
return curTimeData[0] > curTimeData[1] ? downStateColor : upStateColor
}
barSeries.xAxisIndex = 1
barSeries.yAxisIndex = 1
baseOpt.series.push(barSeries)
}
function handleMaAndVolSeries(baseOpt, iChartOpt, inerData, { upStateColor, downStateColor }, chartInstance) {
const { MA, volume, data } = iChartOpt
const { total } = inerData
const xAxisKey = xkey(iChartOpt)
if (MA && MA.length !== 0) {
handleMaSeries(baseOpt, iChartOpt, data, total, MA, xAxisKey, chartInstance)
}
if (volume) {
handleVol(baseOpt, iChartOpt, data, xAxisKey, { upStateColor, downStateColor }, total, chartInstance)
}
}
export { handleSeries, handleMaSeries }

View File

@ -0,0 +1,55 @@
import init from '../../option/init'
import { event } from '../../util/event'
import RectCoordSys from '../../option/RectSys'
import {
handleData,
handleAxis,
handleDataZoom,
handleTooltip,
handleLegend,
handleGrid,
handleAxisPointer
} from './hanleOption'
import { handleSeries } from './hanleSeries'
import { mergeSeries } from '../../util/merge'
class CandlestickChart {
constructor(iChartOption, chartInstance) {
this.baseOption = {}
this.iChartOption = {}
this.chartInstance = chartInstance
// 组装 iChartOption, 补全默认值
this.iChartOption = init(iChartOption)
// 根据 iChartOption 组装 baseOption
this.updateOption()
}
updateOption() {
const iChartOption = this.iChartOption
const volume = this.iChartOption.volume
const data = handleData(iChartOption)
if (!data) return
handleSeries(this.baseOption, iChartOption, data, this.chartInstance)
RectCoordSys(this.baseOption, iChartOption)
// 装载除series之外的其他配置
handleGrid(this.baseOption, iChartOption)
// 平均线和成交量,在这部分对ma和vol的图表进行处理
handleAxis(this.baseOption, data, volume)
handleTooltip(this.baseOption, iChartOption)
handleDataZoom(this.baseOption, iChartOption)
handleLegend(this.baseOption, iChartOption)
handleAxisPointer(this.baseOption)
event(this.chartInstance, iChartOption.event)
mergeSeries(iChartOption, this.baseOption)
}
getOption() {
return this.baseOption
}
setOption(option) {
this.baseOption = option
}
}
export default CandlestickChart

View File

@ -0,0 +1,18 @@
import Theme from '../../feature/token'
import proxy from '../../util/proxy'
function getChartToken() {
const {
itemStyle: { borderColor: colorBorder },
label: { color: colorLabel }
} = Theme.config.FunnelChart
return {
labelColor: colorLabel,
borderColor: colorBorder
}
}
const chartToken = proxy(getChartToken)
export default chartToken

View File

@ -0,0 +1,37 @@
import cloneDeep from '../../util/cloneDeep'
// 设置legend顺序
export function setLegend(baseOption) {
let dataUnit = cloneDeep(baseOption.series[0].data)
let data = []
let sort = []
if (dataUnit !== undefined) {
data = dataUnit
sort = baseOption.series[0].sort
}
let legendData = sortData(sort, data)
return legendData
}
function sortData(sort, data) {
let legendName = []
// 升序
if (sort === 'ascending') {
const sortedData = [...data].sort((a, b) => {
return a.value - b.value
})
sortedData.forEach((item) => {
legendName.push(item.name)
})
}
// 降序
else {
const sortedData = [...data].sort((a, b) => {
return b.value - a.value
})
sortedData.forEach((item) => {
legendName.push(item.name)
})
}
return legendName
}

View File

@ -0,0 +1,141 @@
import cloneDeep from '../../util/cloneDeep'
import chartToken from './chartToken'
export const seriesInit = {
type: 'funnel',
width: '80%',
min: 0,
max: 100,
minSize: '0%',
maxSize: '100%',
left: 'center',
top: 60,
bottom: 60,
funnelAlign: 'center',
orient: 'vertical',
sort: 'descending',
gap: 10,
itemStyle: {
borderColor: '',
borderWidth: 1
},
label: {},
data: []
}
const SIZE_NAME = ['width', 'height', 'min', 'max', 'minSize', 'maxSize']
const POSITION_NAME = ['left', 'right', 'top', 'bottom', 'funnelAlign', 'orient']
/**
* echarts所需要的series
* @param {} iChartOption
* @returns
*/
export function setSeries(iChartOption) {
const { data, sort, size, position, gap } = iChartOption
let series = []
const selfSeries = iChartOption.series
// 处理series里多个数据的优先级配置方法
if (selfSeries !== undefined && selfSeries.length !== 0) {
selfSeries.forEach((seriesItem) => {
const seriesUnit = seriesItem
// 处理size的优先级
for (let index = 0; index < SIZE_NAME.length; index++) {
const name = SIZE_NAME[index]
if (seriesUnit[name] === undefined) {
if (iChartOption.size && iChartOption.size[name]) {
// 下面说明一级属性的赋值给series
seriesUnit[name] = iChartOption.size[name]
} else {
// series的不存在size把初始化的赋值给series
seriesUnit[name] = seriesInit[name]
}
}
}
// 处理position的优先级
for (let index = 0; index < POSITION_NAME.length; index++) {
const name = POSITION_NAME[index]
if (seriesUnit[name] === undefined) {
if (iChartOption.position && iChartOption.position[name]) {
// 下面说明一级属性的赋值给series
seriesUnit[name] = iChartOption.position[name]
} else {
// series的不存在position把初始化的赋值给series
seriesUnit[name] = seriesInit[name]
}
}
}
// 处理label
const defaultLabel = {
show: true,
color: chartToken.labelColor
}
seriesUnit.label = Object.assign(defaultLabel, seriesUnit.label)
// 处理gap、sort的优先级
const config = ['gap', 'sort']
for (let index = 0; index < config.length; index++) {
const name = config[index]
if (seriesUnit[name] === undefined) {
if (iChartOption && iChartOption[name]) {
// 把一级属性值赋给series
seriesUnit[name] = iChartOption[name]
} else {
// 把初始化的赋值给series
seriesUnit[name] = seriesInit[name]
}
}
}
// 处理图形边框颜色
const defaultItemStyle = {
borderColor: chartToken.borderColor,
borderWidth: 1
}
seriesUnit.itemStyle = Object.assign(defaultItemStyle, seriesUnit.itemStyle)
})
series = selfSeries
} else {
// 处理单个数据的默认配置
const seriesUnit = cloneDeep(seriesInit)
data && (seriesUnit.data = data)
// 配置项变成一级属性处理sort和gap
sort && (seriesUnit.sort = sort)
gap && (seriesUnit.gap = gap)
// 配置漏斗图的label
setLabel(seriesUnit, iChartOption)
// 处理漏斗图的size和position
setSize(size, seriesUnit)
setPosition(position, seriesUnit)
// 处理图形边框颜色
seriesUnit.itemStyle.borderColor = chartToken.borderColor
series.push(seriesUnit)
}
return series
}
// 处理漏斗图的大小
function setSize(size, seriesUnit) {
for (let index = 0; index < SIZE_NAME.length; index++) {
const name = SIZE_NAME[index]
if (size !== undefined && size[name] !== undefined) {
seriesUnit[name] = size[name]
}
}
}
// 处理漏斗图的位置
function setPosition(position, seriesUnit) {
for (let index = 0; index < POSITION_NAME.length; index++) {
const name = POSITION_NAME[index]
if (position !== undefined && position[name] !== undefined) {
seriesUnit[name] = position[name]
}
}
}
// 设置label的属性主要是formatter
function setLabel(seriesUnit, iChartOption) {
seriesUnit.label.color = chartToken.labelColor
seriesUnit.label.position = 'inside'
seriesUnit.label.show = true
Object.assign(seriesUnit.label, iChartOption.label)
}

View File

@ -0,0 +1,37 @@
import init from '../../option/init'
import { event } from '../../util/event'
import { setLegend } from './handleLegend.js'
import { setSeries } from './handleSeries.js'
import PolarCoordSys from '../../option/PolarSys'
const CHART_NAME = 'FunnelChart'
export default class FunnelChart {
constructor(iChartOption, chartInstance) {
this.baseOption = {}
this.iChartOption = {}
// 组装 iChartOption, 补全默认值
this.iChartOption = init(iChartOption)
// 根据 iChartOption 组装 baseOption
this.updateOption(chartInstance)
}
updateOption(chartInstance) {
const iChartOption = this.iChartOption
// 装载除series之外的其他配置
PolarCoordSys(this.baseOption, iChartOption, CHART_NAME)
// 组装series
this.baseOption.series = setSeries(iChartOption)
// 组装legend.data
// eslint-disable-next-line no-unused-expressions
this.baseOption.legend.data ? this.baseOption.legend.data : setLegend(this.baseOption)
// 配置图表事件
if (iChartOption.event) {
event(chartInstance, iChartOption.event)
}
}
getOption() {
return this.baseOption
}
}

View File

@ -0,0 +1,11 @@
import BaseOption from '../../option/base'
BaseOption.series = []
BaseOption.tooltip = {
show: true,
trigger: 'item',
formatter: '{b}: {c} ({d}%)'
}
BaseOption.legend = {}
export default BaseOption

View File

@ -0,0 +1,31 @@
import Theme from '../../feature/token'
import proxy from '../../util/proxy'
function getChartToken() {
const {
axisLine: {
lineStyle: { color: colorAxisLine }
},
splitLine: {
lineStyle: { color: colorAxisSplitLine }
},
axisLabel: { color: colorTextSecondary },
detail: {
rich: { color: colorTextPrimary }
}
} = Theme.config.GaugeChart
const { colorState } = Theme.config
return {
marklineColor: colorState.colorError,
axisLineColor: colorAxisLine,
splitLineColor: colorAxisSplitLine,
axisLabelColor: colorTextSecondary,
detailRichColor: colorTextPrimary
}
}
const chartToken = proxy(getChartToken)
export default chartToken

View File

@ -0,0 +1,9 @@
import tooltip from '../../option/config/tooltip'
/**
*
*/
export function handleTooltip(iChartOpt, chartName) {
const basicTip = tooltip(iChartOpt, chartName)
return basicTip
}

Some files were not shown because too many files have changed in this diff Show More