VChart icon indicating copy to clipboard operation
VChart copied to clipboard

[Feature] 饼图在无数据时支持展示占位圆

Open kkxxkk2019 opened this issue 2 years ago • 5 comments

参考 echarts 的如下配置:

kkxxkk2019 avatar Oct 09 '23 10:10 kkxxkk2019

hello,我正在尝试实现这个feature,但是似乎遇到了一点问题。

  // VChart\packages\vchart\src\data\transforms\pie.ts
  if (data.length === 0 && showEmptyCircle) {
    data[0] = {};
    appendArcInfo(data[0], startAngle, endAngle);
  }

bad_pie

我使用的spec是VChart\packages\vchart\__tests__\runtime\browser\test-page\pie.ts,只对data项作了修改(将values设为空数组),不确定为什么默认情况下绘制的圆仅有3/4,想冒昧问一下。

FunctionEurus avatar Jun 07 '24 07:06 FunctionEurus

@FunctionEurus

Hi, 同学的实现思路没有问题, 应该添加一个占位的数据, 用于绘制一个圆形的图元. transforms\pie的功能是对原始数据进行数据转换操作, 并不适合添加或删减数据.

可以参考packages/vchart/src/series/pie/pie.ts中的逻辑, 为pie添加一个占位圆.

VChart的图表, 都是基于series设计的, 在pie.series中, 有initData、initMark、initMarkStyle三个方法.

  1. 在初始化数据时, 可以添加一个空白的占位数据
  2. 在初始化图元时, 可以添加一个emptyMark, 即一个饼图同时有pieMark和emptyMark.
  3. 在初始化图元样式时, 当数据项为0, 可以为emptyMark设置样式.

我在这完成了一部分代码 临时MR , 同学可以参考并实现这个feature.

youngwinds avatar Jun 07 '24 09:06 youngwinds

非常感谢您的回复!我尝试在上述pr的基础上实现emptyCircleStyle接口时仍然遇到了一些问题,并且囿于我本身的能力以及对VChart源码的理解有限,尝试完成该feature还是有些操之过急,但我依然希望提出我的思路并得到斧正。

我的接口设计如下:

  • pieChart.pie.showEmptyCircle
  • pieChart.pie.emptyCircleStyle

在绘制过程中,我发现只有this._pieMark可以获取完整的style spec,initMarkStyleWithSpec在处理this._emptyArcMark时所接收到的spec是空对象(undefined则是initMarkStyleWithSpec的第三个参数key)。

problem

我期望当数据为空且showEmptyCircletrue时,能够通过initMarkStyleWithSpec方法为emptyMark设置自定义样式。但由于spec接收到的是空对象,导致样式没有正确应用。虽然以下实现可以绕开这个问题实现自定义占位圆样式,但我认为这不应该是正确的方法。

initMarkStyleWithSpec(mark?: IMark, spec?: any, key?: string): void {
    super.initMarkStyleWithSpec(mark, spec, key);
    if (mark.name === this._pieMarkName) {
      // radius 配置需要额外处理比例值
      const pieSpec = this.getSpec()[mark.name];
      if (pieSpec) {
        for (const state in pieSpec.state || {}) {
          this.setMarkStyle(mark, this.generateRadiusStyle(pieSpec.state[state]), state, AttributeLevel.User_Mark);
        }
      }
    }
    // 我的实现
    if (this.getRawData().latestData.length === 0 && mark.name === 'emptyMark' && this._showEmptyCircle) {
      super.initMarkStyleWithSpec(mark, { style: this._spec.pie.emptyCircleStyle }, key);
    }
  }

如果可以,我希望能够获得以下方面的帮助:

  • 确认initMarkStyleWithSpec方法中的spec接收空对象的原因。
  • 确定如何正确传递emptyCircleStyle配置到emptyMark
  • 任何关于理解VChart源码结构和流程的建议。

如有需要,完整的修改请见此处,再次感谢您的时间。

FunctionEurus avatar Jun 08 '24 11:06 FunctionEurus

一、首先, 需要了解VChart的图表组成: chart、component、region、series. https://visactor.io/vchart/guide/tutorial_docs/Chart_Concepts/Understanding_VChart VChart的设计约束: 1个chart对应多个series

二、spec init的逻辑 Step1: 调用renderSync, 在beforeRender中, 有一个spec的转换逻辑, 代码位置在这: packages/vchart/src/core/vchart.ts:657 img_v3_02bo_32326bb3-d55d-44e5-87b8-409c62e9048g

需要重点阅读 this._chartSpecTransformer.transformSpec, 由Factory.createChartSpecTransformer创建. img_v3_02bo_4320fe50-c8b3-4f5a-a84e-4af2c0b222cg

Step2: 在pie chart的实现中, 调用了registerPieChart向Factory注册了饼图, 包含了transformer的实现, 代码位置在:packages/vchart/src/chart/pie/pie.ts img_v3_02bo_8a7e5d02-5a61-401a-a460-f04b3b60501g

Step3: 执行transformSpec: 将一个图表spec 拆成 多个series的spec

packages/vchart/src/chart/polar/polar-transformer.ts img_v3_02bo_ae2f22e0-92b0-411a-8cdd-4cfa09ad340g

img_v3_02bo_82db8323-615a-4cff-a8ca-8d7f95f7dcag

img_v3_02bo_e20f9350-3e76-4d96-9c57-15eca264113g

img_v3_02bo_693fa1d3-a1ac-404c-9992-67fb74222ebg

Step4: pie series中, 使用series spec. img_v3_02bo_d8c449b5-36ff-4e12-ada6-4652317c48eg

三: 接口设计与补齐类型 接口的确定要谨慎, 因为要避免breakChange, 所以只能增加, 不能修改或删除, 需要对功能进行抽象, 考虑是否可以成为一个所有图表都需要的足够通用功能.

饼图这次如果实现了 showEmptyCircle、emptyCircleStyle, 在未来可能会出现这些情况: 饼图不想要占位圆, 想要占位的文本 或 icon. 除了饼图之外, 其他图表, 也想在没有数据的场景, 拥有类似能力

因此可以针对这个场景, 把功能做的更加的“抽象”和“通用”, 因此该feature的实现, 需要考虑到未来的快速扩展.

建议把showEmptyCircle、emptyCircleStyle的命名更改为 “placeholder” 或者 “emptyPlaceholder”, 结构可以由你自行设计.

youngwinds avatar Jun 11 '24 04:06 youngwinds

@FunctionEurus 确认initMarkStyleWithSpec方法中的spec接收空对象的原因。 答: 这个方法不应使用, 接收到的空对象, 纯粹是因为漏了初始化.

确定如何正确传递emptyCircleStyle配置到emptyMark。 答: initSpec的过程中, 执行transformSpec即可. 将chart spec转换为series spec.

任何关于理解VChart源码结构和流程的建议。 答: 简单写了一下 初始化spec的流程, 你可以参考一下.

youngwinds avatar Jun 11 '24 04:06 youngwinds

released in 1.12.0

xile611 avatar Aug 20 '24 05:08 xile611