Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(dimension): auto padding #5046

Merged
merged 1 commit into from
May 19, 2023
Merged

feat(dimension): auto padding #5046

merged 1 commit into from
May 19, 2023

Conversation

pearmini
Copy link
Member

@pearmini pearmini commented May 17, 2023

Auto Padding

支持 autoPadding,相关链接:

目前所有 static 案例都设置了 autoPadding,保证除去复合视图(分面等)正确计算。

未来工作

  • GUI title 的锚点有问题,修复之后需要重新更新截图。
  • GUI 需要使用缓存的 label bbox 去优化性能。
  • 复合视图的 autoPadding 计算较为麻烦,这个 PR 不去优化,后续可以考虑优化。

开始使用

None AutoPadding
image image
export function alphabetIntervalAutoPadding(): G2Spec {
  return {
    type: 'interval',
    padding: 'auto',
    transform: [{ type: 'sortX', by: 'y', reverse: true }],
    data: {
      type: 'fetch',
      value: 'data/alphabet.csv',
    },
    encode: {
      x: 'letter',
      y: 'frequency',
      color: 'steelblue',
    },
    axis: {
      y: { labelFormatter: (d) => d + '0000' },
      x: { labelFormatter: (d) => d + '0000' },
    },
    viewStyle: {
      viewFill: '#4e79a7',
      plotFill: '#f28e2c',
      mainFill: '#e15759',
      contentFill: '#76b7b2',
    },
  };
}

策略

  • 首先计算 paddingLeft 和 paddingRight,让竖直的轴水平方向完整绘制。
  • 通过 paddingLeft 和 paddingRight 计算得到水平轴的长度,如果 label 满足下面两个条件之一:旋转 90 度垂直展示。
    • 超出图表区域
    • 和相邻 label 重叠。
  • 轴本身对仍然重叠的文本使用 labelTransform.hide 处理,对于竖直来说是上下重叠,对于水平轴是左右重叠。

计算得到的 padding 都不会超过图表区域的 1/3。

性能

之前担心性能问题不做 autoPadding,但是目前可以和没有设置 autoPadding 保持一致。之前担心性能问题是因为:label 的宽高会求两次 bbox,但是目前计算 autoPadding 把 bbox 存储为 indexBBox 变量,GUI 拿到这个 indexBBox 可以直接获得对应的 bbox 而不用重新计算。这样可以保证 label 的 bbox 只被计算一次。

案例

不同位置

None AutoPadding
image image
export function alphabetIntervalAutoPaddingPosition(): G2Spec {
  return {
    type: 'interval',
    padding: 'auto',
    transform: [{ type: 'sortX', by: 'y', reverse: true }],
    data: {
      type: 'fetch',
      value: 'data/alphabet.csv',
    },
    encode: {
      x: 'letter',
      y: 'frequency',
      color: 'steelblue',
    },
    axis: {
      y: { labelFormatter: (d) => d + '0000', position: 'right' },
      x: { labelFormatter: (d) => d + '0000', position: 'top' },
    },
    viewStyle: {
      viewFill: '#4e79a7',
      plotFill: '#f28e2c',
      mainFill: '#e15759',
      contentFill: '#76b7b2',
    },
  };
}

自定义 Label

None AutoPadding
image image
export function alphabetIntervalAutoPaddingCustom(): G2Spec {
  return {
    type: 'interval',
    padding: 'auto',
    transform: [{ type: 'sortX', by: 'y', reverse: true }],
    data: {
      type: 'fetch',
      value: 'data/alphabet.csv',
    },
    encode: {
      x: 'letter',
      y: 'frequency',
      color: 'steelblue',
    },
    axis: {
      y: {
        labelFormatter: (d) => {
          const width = 60;
          const height = 15;
          const rect = new Rect({
            style: { x: -width, y: -height / 2, height, width, fill: 'red' },
          });
          const text = new Text({
            style: {
              x: width / 2,
              text: d + '',
              fontSize: 12,
              textBaseline: 'top',
              textAlign: 'center',
            },
          });
          rect.appendChild(text);
          return rect;
        },
      },
      x: {
        labelFormatter: (d) => {
          const width = 60;
          const height = 15;
          const rect = new Rect({
            style: { x: 0, y: 0, height, width, fill: 'red' },
          });
          const text = new Text({
            style: {
              x: width / 2,
              text: d + '',
              fontSize: 12,
              textBaseline: 'top',
              textAlign: 'center',
            },
          });
          rect.appendChild(text);
          return rect;
        },
      },
    },
    viewStyle: {
      viewFill: '#4e79a7',
      plotFill: '#f28e2c',
      mainFill: '#e15759',
      contentFill: '#76b7b2',
    },
  };
}

没有 Title

None AutoPadding
image image
export function alphabetIntervalAutoPaddingNoTitle(): G2Spec {
  return {
    type: 'interval',
    padding: 'auto',
    transform: [{ type: 'sortX', by: 'y', reverse: true }],
    data: {
      type: 'fetch',
      value: 'data/alphabet.csv',
    },
    encode: {
      x: 'letter',
      y: 'frequency',
      color: 'steelblue',
    },
    axis: {
      y: { title: false },
      x: { title: false },
    },
    viewStyle: {
      viewFill: '#4e79a7',
      plotFill: '#f28e2c',
      mainFill: '#e15759',
      contentFill: '#76b7b2',
    },
  };
}

设置属性

None AutoPadding
image image
export function alphabetIntervalAutoPaddingStyle(): G2Spec {
  return {
    type: 'interval',
    padding: 'auto',
    transform: [{ type: 'sortX', by: 'y', reverse: true }],
    data: {
      type: 'fetch',
      value: 'data/alphabet.csv',
    },
    encode: {
      x: 'letter',
      y: 'frequency',
      color: 'steelblue',
    },
    axis: {
      y: {
        labelFormatter: (d) => d + '0000',
        style: {
          labelFontSize: (_, i) => 10 + i,
          labelFill: 'steelblue',
        },
      },
      x: { labelFormatter: (d) => d + '0000', style: { labelFontSize: 20 } },
    },
    viewStyle: {
      viewFill: '#4e79a7',
      plotFill: '#f28e2c',
      mainFill: '#e15759',
      contentFill: '#76b7b2',
    },
  };
}

多轴图

None AutoPadding
image image
export function weatherLineMultiAxesAutoPadding(): G2Spec {
  return {
    type: 'view',
    data: weather,
    padding: 'auto',
    style: {
      viewFill: '#4e79a7',
      plotFill: '#f28e2c',
      mainFill: '#e15759',
      contentFill: '#76b7b2',
    },
    children: [
      {
        type: 'line',
        encode: {
          x: 'Month',
          y: 'Temperature',
          color: '#EE6666',
          shape: 'smooth',
        },
        scale: {
          y: { independent: true, domainMax: 30 },
        },
        axis: {
          y: {
            title: 'Temperature (°C)',
            labelFormatter: (d) => d + '00000',
            grid: false,
            style: {
              titleFill: '#EE6666',
            },
          },
        },
      },
      {
        type: 'interval',
        encode: {
          x: 'Month',
          y: 'Evaporation',
          color: '#5470C6',
        },
        scale: {
          y: { independent: true, domainMax: 200 },
        },
        style: {
          fillOpacity: 0.8,
        },
        axis: {
          y: {
            title: 'Temperature (°C)',
            labelFormatter: (d) => d + '00000',
            grid: null,
            style: {
              titleFill: '#5470C6',
            },
          },
        },
      },
      {
        type: 'line',
        encode: {
          x: 'Month',
          y: 'Precipitation',
          color: '#91CC75',
        },
        scale: {
          y: { independent: true },
        },
        style: {
          lineWidth: 2,
          lineDash: [2, 2],
        },
        axis: {
          y: {
            position: 'right',
            title: 'Precipitation (ml)',
            grid: false,
            labelFormatter: (d) => d + '00000',
            style: {
              titleFill: '#91CC75',
            },
          },
        },
      },
    ],
  };
}

超出图表区域

None AutoPadding
image image
export function browserLineAreaTrendingAutoPadding(): G2Spec {
  return {
    type: 'view',
    data: browser,
    padding: 'auto',
    style: {
      viewFill: '#4e79a7',
      plotFill: '#f28e2c',
      mainFill: '#e15759',
      contentFill: '#76b7b2',
    },
    children: [
      {
        type: 'line',
        encode: {
          x: 'name',
          y: 'value',
          shape: 'hv',
        },
        scale: {
          y: { domain: [0, 50] },
        },
        style: {
          opacity: 0.5,
        },
      },
      {
        type: 'area',
        encode: {
          x: 'name',
          y: 'value',
          shape: 'hv',
        },
        scale: {
          y: { domain: [0, 50] },
        },
        style: {
          opacity: 0.5,
        },
      },
    ],
  };
}

Flex 图

None AutoPadding
image image
export function gdpIntervalFlex(): G2Spec {
  return {
    type: 'interval',
    width: 1000,
    paddingBottom: 100,
    data: {
      type: 'fetch',
      value: 'data/gdp.csv',
    },
    transform: [{ type: 'flexX', field: 'gdp' }],
    legend: { color: false },
    encode: {
      x: 'country',
      y: 'value',
      color: 'country',
    },
    axis: {
      x: {
        style: { labelTransform: 'rotate(90)' },
      },
    },
  };
}

超过最大的区域范围

对于超出的,还是截断处理。

None AutoPadding
image image
function appendZero(count) {
  return Array.from({ length: count }, () => 0).join('');
}

export function alphabetIntervalAutoPaddingMaxRatio(): G2Spec {
  return {
    type: 'interval',
    padding: 'auto',
    margin: 50,
    inset: 10,
    transform: [{ type: 'sortX', by: 'y', reverse: true }],
    data: {
      type: 'fetch',
      value: 'data/alphabet.csv',
    },
    encode: {
      x: 'letter',
      y: 'frequency',
      color: 'steelblue',
    },
    axis: {
      y: [
        { labelFormatter: (d) => d + appendZero(40) },
        { labelFormatter: (d) => appendZero(40) + d, position: 'right' },
      ],
      x: [
        { labelFormatter: (d) => appendZero(40) + d },
        { labelFormatter: (d) => d + appendZero(40), position: 'top' },
      ],
    },
    viewStyle: {
      viewFill: '#4e79a7',
      plotFill: '#f28e2c',
      mainFill: '#e15759',
      contentFill: '#76b7b2',
    },
  };
}

更多案例看新增的测试。

@pearmini pearmini force-pushed the feat/auto-padding branch 6 times, most recently from dab534e to dbfa198 Compare May 18, 2023 05:46
@pearmini pearmini changed the title [WIP] feat(dimension): auto padding feat(dimension): auto padding May 18, 2023
src/runtime/component.ts Show resolved Hide resolved
@hustcc hustcc self-requested a review May 18, 2023 11:59
@hustcc hustcc merged commit 914d445 into v5 May 19, 2023
3 checks passed
@hustcc hustcc deleted the feat/auto-padding branch May 19, 2023 01:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

【v5】数据项过大或过长时,轴显示不全
2 participants