init()

in src/Wlinebar/index.tsx [242:528]


  init(chart: Chart, config: WlinebarConfig, data: ChartData) {
    const rawLineData: DataAdapterData[] = [];
    this.rawLineData = rawLineData;
    const rawBarData: DataAdapterData[] = [];
    this.rawBarData = rawBarData;
    (data || []).forEach((d: DataAdapterData) => {
      if (d.type === 'line') {
        rawLineData.push(d);
      } else if (d.type === 'bar') {
        rawBarData.push(d);
      }
    });

    const lineData = highchartsDataToG2Data(rawLineData, config as DataAdapterConfig, {
      // type: 'lineType',
    });
    const barData = highchartsDataToG2Data(rawBarData, config as DataAdapterConfig, {
      // type: 'barType',
    });

    const defs: Record<string, Types.ScaleOption> = {
      x: propertyAssign(
        propertyMap.axis,
        {
          type: 'cat',
          // fix 更新数据时x轴无法清除数据
          // sync: 'x',
          tickCount: null
        },
        config.xAxis,
      ),
      type: {
        type: 'cat',
      },
    };

    if (Array.isArray(config.yAxis)) {
      config.yAxis.forEach((axis, yIndex) => {
        defs[`y${yIndex}`] = propertyAssign(
          propertyMap.axis,
          {
            type: 'linear',
            tickCount: 5,
            nice: true,
          },
          axis,
        );
      });
    } else {
      defs.y = propertyAssign(
        propertyMap.axis,
        {
          type: 'linear',
          tickCount: 5,
          // 单轴时,必须同步度量,否则会两个度量叠加在一起
          sync: true,
          nice: true,
        },
        config.yAxis,
      );
    }

    autoTimeScale(defs, this.rawData, this.language || this.context.language);

    chart.scale(defs);

    // 设置X轴
    rectXAxis(this, chart, config);

    if (Array.isArray(config.yAxis)) {
      config.yAxis.forEach((axis, yIndex) => {
        const axisColor =
          // getDataIndexColor(config.lineColors, rawLineData, yIndex) ||
          // getDataIndexColor(config.barColors, rawBarData, yIndex) ||
          themes['widgets-axis-line'];
        const yAxisConfig: Types.AxisCfg = {
          line: {
            style: {
              stroke: axisColor,
            },
          },
        };
        if (yIndex !== 0) {
          yAxisConfig.grid = null;
          // 因为是多个view组成的图表,所以这里需要移动位置
          yAxisConfig.position = 'right';
        }

        rectYAxis(this, chart, { ...config, yAxis: axis }, `y${yIndex}`, yAxisConfig);
      });
    } else {
      // 设置单个Y轴
      rectYAxis(this, chart, config as { yAxis: (Types.ScaleOption & YAxisConfig) | false });
    }

    // 设置图例
    // const legendStyle = {
    //   ...legendHtmlContainer,
    //   display: 'inline-block',
    //   position: 'relative',
    // };
    // // const legendItemStyle = {
    // //   ...legendHtmlListItem,
    // // };
    // if (config.legend !== false) {
    //   const { position, align } = config.legend || {};
    //
    //   // if (position === 'top') {
    //   //   legendStyle.top = themes['widgets-font-size-1'];
    //   // }
    //
    //   if (align === 'right') {
    //     legendStyle.marginLeft = themes['widgets-font-size-1'];
    //   } else if (align === 'left') {
    //     legendStyle.marginRight = themes['widgets-font-size-1'];
    //   } else if (align === 'center') {
    //     legendStyle.marginRight = themes['widgets-font-size-1'];
    //   } else {
    //     // 默认放到左边
    //     legendStyle.marginRight = themes['widgets-font-size-1'];
    //   }
    //
    //   if (position === 'bottom') {
    //     legendStyle.top = '100%';
    //     legendStyle.transform = 'translate(0, -100%)';
    //     legendStyle.overflow = 'visible';
    //     legendStyle.verticalAlign = 'top';
    //
    //     // legendItemStyle.marginBottom = 0;
    //     // legendItemStyle.marginTop = themes['widgets-font-size-1'];
    //   }
    // }

    // tooltip
    rectTooltip(this, chart, config, {}, null, {
      showCrosshairs: false,
      showMarkers: false,
    });

    // 正式开始绘图,创建两个不同的view
    const barView = chart.createView({
      padding: config.padding === 'auto' ? 'auto' : 0,
    });
    barView.data(barData);
    this.barView = barView;

    // Tooltip 背景区域
    activeRegionWithTheme(barView);

    const lineView = chart.createView({
      padding: config.padding === 'auto' ? 'auto' : 0,
    });
    lineView.data(lineData);
    this.lineView = lineView;
    // 关闭一个View的X轴,避免重叠字体变粗
    // 用于解决缩放后线视图位移的问题
    lineView.axis('x', {
      top: false,
      line: null,
      subTickLine: null,
      tickLine: null,
      grid: null,
      animate: false,
      label: {
        style: {
          fill: "rgba(0,0,0,0)"
        }
      }
    });

    if (Array.isArray(config.yAxis)) {
      config.yAxis.forEach((asix, yIndex) => {
        if (getDataIndexColor(config.barColors, rawBarData, yIndex)) {
          drawBar(barView, config, `y${yIndex}`, 'type');
        }
        if (getDataIndexColor(config.lineColors, rawLineData, yIndex)) {
          drawLine(lineView, config, `y${yIndex}`, 'type');
        }
      });
    } else {
      // 单Y轴时同时关闭一个View的Y轴,避免重叠字体变粗
      lineView.axis('y', false);

      drawBar(barView, config, 'y', 'type');
      drawLine(lineView, config, 'y', 'type');
    }

    // 绘制辅助线,辅助背景区域
    viewGuide(config, lineView, rawLineData, barView, rawBarData);

    legendFilter(this, barView, 'rawBarData');
    legendFilter(this, lineView, 'rawLineData');

    rectLegend(
      this,
      chart,
      config,
      {
        items: getLegendItems(rawLineData, rawBarData, lineView.geometries[0], barView.geometries[0], config),
      },
      'multiple',
    );

    rectZoom(chart, config, getText('reset', this.language || this.context.language, this.context.locale));

    // 判断是否要加padding
    chart.on('beforepaint', () => {
      chart.views.forEach((view: any) => {
        if (view?.geometries?.length === 0) {
          return;
        }
        // 柱图还是线图
        const chartType = view?.geometries?.[0]?.shapeType === 'interval' ? 'bar' : 'line';
        // y轴刻度最大值
        const yAxisKey =
          'y' in view?.geometries?.[0]?.scales ? 'y' : 'y0' in view?.geometries?.[0]?.scales ? 'y0' : 'y1';
        const axisMax = view?.geometries?.[0]?.scales?.[yAxisKey]?.max;
        // y轴高度
        const height = view?.coordinateBBox?.height;

        // 是否显示label,且label在top
        const showLabel =
          config?.[`${chartType}Label`] === true ||
          (typeof config?.[`${chartType}Label`] === 'object' &&
            config?.[`${chartType}Label`]?.visible !== false &&
            (config?.[`${chartType}Label`]?.position === undefined ||
              config?.[`${chartType}Label`]?.position === 'top'));

        // 是否隐藏legend,或legend不在top
        const hideLegend =
          config?.legend === false ||
          (typeof config?.legend === 'object' &&
            (config?.legend?.visible === false || (config?.legend?.position && config?.legend?.position !== 'top')));

        if (!config?.appendPadding && showLabel && hideLegend) {
          const valueMap: Record<string, number> = {};
          (view?.filteredData || []).forEach((d: any) => {
            if (chartType === 'bar') {
              const xValue = `${d.x}-${config?.stack ? '' : d.dodge || ''}`;
              if (!(xValue in valueMap)) {
                valueMap[xValue] = 0;
              }
              // 区间柱状图
              if (Array.isArray(d?.[yAxisKey])) {
                valueMap[xValue] += d?.[yAxisKey] || 0;
              } else {
                // 堆叠、分组堆叠、普通柱图
                valueMap[xValue] += d?.[yAxisKey] || 0;
              }
            } else {
              valueMap[d.x] = d?.[yAxisKey] || 0;
            }
          });

          const maxY = Math.max(...Object.values(valueMap));

          // 判断最高的柱子距离顶部的间距是否过小
          const dis = (1 - maxY / axisMax) * height;
          if (dis < 20) {
            chart.appendPadding = [20, 0, 0, 0];
          } else {
            chart.appendPadding = undefined;
          }
        }
      });
    });

    // chart.on('afterrender', () => {
    //   // chart.getLegendAttributes()
    //   // console.log('getLegendAttributes', barView.geometries[0].getAttribute('shape'));
    //   // console.log('getLegendAttributes', lineView.geometries[0].getAttribute('shape'));
    //   lineView.geometries.forEach((geom) => {
    //     const shapeAttr = geom.getAttribute('shape');
    //
    //     const shape = getMappingValue(shapeAttr, '机房3', 'point');
    //     let marker = geom.getShapeMarker(shape, {
    //       color: 'red',
    //       isInPolar: false,
    //     });
    //
    //     console.log(marker);
    //   })
    //   // console.log(getLegendItems(rawLineData, rawBarData, lineView.geometries[0], barView.geometries[0], config));
    //
    //   // console.log(chart.getController('legend'));
    // })
  }