VisActor / VChart

VChart, more than just a cross-platform charting library, but also an expressive data storyteller.
https://www.visactor.io/vchart
MIT License
760 stars 42 forks source link

[Performance] optimize performance of scatter- chart width datazoom #2781

Open xile611 opened 3 weeks ago

xile611 commented 3 weeks ago

const IMAGEX_URL_PREFIX = 'https://p-file.bytedance.net/tos-cn-i-owbsiqhmhc';
const TooltipID = 'scatter-chart-tooltip-link';

const spec = {
  type: 'common',
  data: [
    {
      id: 'data',
      values: scatterData
    }
  ],
  animationAppear: false,
  animationEnter: false,
  animationUpdate: false,
  animationDisappear: false,
  background: '#fff',
  series: [
    {
      type: 'scatter',
      xField: 'x',
      yField: 'y',
      seriesField: 'cluster_id',
      point: {
        style: {
          lineWidth: 1,
          stroke: '#fff'
        },
        state: {
          selected: {
            globalZIndex: 10,
            size: 14,
            lineWidth: 1,
            stroke: 'red',
            zIndex: 10
          }
        }
      }
    }
  ],
  brush: {
    visible: true,
    brushType: 'rect',
    inBrush: {
      colorAlpha: 1
    },
    outOfBrush: {
      colorAlpha: 0.2
    },
    // 开启后默认关联所有axis/dataZoom
    zoomAfterBrush: true,
    delayTime: 50
  },
  dataZoom: [
    {
      orient: 'left',
      start: 0,
      end: 1,
      // zoomLock: true,
      filterMode: 'axis',
      backgroundChart: {
        line: { style: { visible: false } },
        area: { style: { visible: false } }
      }
    },
    {
      orient: 'bottom',
      start: 0,
      end: 1,
      // zoomLock: true,
      filterMode: 'axis',
      backgroundChart: {
        line: { style: { visible: false } },
        area: { style: { visible: false } }
      }
    }
  ],
  crosshair: {
    trigger: ['hover', 'click'],
    yField: {
      visible: true,
      line: { visible: true, type: 'line' },
      label: {
        visible: true // label 默认关闭
      }
    },
    xField: {
      visible: true,
      line: { visible: true, type: 'line' },
      label: {
        visible: true // label 默认关闭
      }
    }
  },

  axes: [
    {
      orient: 'left',
      type: 'linear',
      range: {
        min: Math.min(...scatterData.map(d => +d.y)),
        max: Math.max(...scatterData.map(d => +d.y))
      },
      title: {
        visible: true,
        text: 'Y'
      },
      domainLine: {
        visible: true
      }
    },
    {
      orient: 'bottom',
      type: 'linear',
      title: {
        visible: true,
        text: 'X'
      },
      domainLine: {
        visible: true
      }
    }
  ],
  legends: {
    visible: true,
    orient: 'right',
    allowAllCanceled: true,
    item: {
      focus: true // enable focus
    }
  },

  tooltip: {
    activeType: 'mark',
    mark: {
      title: {
        visible: false
      },
      content: [
        {
          key: 'uid',
          value: (datum: any) => datum?.uid
        },
        {
          key: 'cluster_id',
          value: (datum: any) => datum?.cluster_id
        }
      ]
    },
    trigger: ['hover', 'click'],
    lockAfterClick: true,
    enterable: true,
    renderMode: 'html',
    style: {
      panel: {
        backgroundColor: 'rgba(255, 255, 255, 0.95)',
        shadow: {
          blur: 10,
          color: 'rgba(0, 0, 0, 0.1)',
          y: 4,
          x: 0,
          spread: 0
        }
      }
    },

    updateElement(tooltipElement: any, _: any, params: any) {
      if (params.changePositionOnly) {
        return;
      }
      const TooltipElement = document.getElementById(TooltipID);
      const uid = params?.datum?.uid ?? params?.dimensionInfo?.[0]?.data?.[0]?.datum?.uid;

      if (TooltipElement) {
        TooltipElement.innerHTML = `<a target="_blank" style="display: flex; align-items: center" href="https://holmes.bytedance.net/aweme-debug/user/detail?appId=1128&uid=${uid}">前往抖音Debug查看<img style="width: 14px; height: 14px"
      src='${IMAGEX_URL_PREFIX}/right.png' /></a>`;
      } else {
        const p = document.createElement('p');
        p.id = TooltipID;
        p.innerHTML = `<a target="_blank" style="display: flex; align-items: center" href="https://holmes.bytedance.net/aweme-debug/user/detail?appId=1128&uid=${uid}">前往抖音Debug查看<img style="width: 14px; height: 14px"
      src='${IMAGEX_URL_PREFIX}/right.png' /></a>`;
        p.style.marginTop = '6px';
        p.style.fontSize = '14px';
        p.style.color = '#165DFF';
        p.style.display = 'flex';
        p.style.alignItems = 'center';
        p.style.cursor = 'pointer';

        tooltipElement.appendChild(p);
      }
    }
  }
};

大数据散点图,现在在 datazoom、brush交互下存在如下问题:

  1. DataZoom axis 过滤模式下,可以给视窗外的点设置visible: false,优化VRedner图形渲染性能(待确定现在没有设置visible: false,VRender渲染性能是否有问题);
  2. DataZoom filter 过滤模式下,当关联轴为linear 的时候需要优化轴刻度效果,不走完成新计算的流程
  3. DataZoom 更新现在会触发Brush 的状态初始化流程,存在较大的性能消耗

img_v3_02bi_0c9c567d-88c8-46f4-8914-c6f0b76b9c5g

  1. DataZoom backgroundChart绘制和属性计算,性能消耗非常大,可以从VRender-component计算层面以及vrender层面看看有没有通过配置降低性能消耗的办法
image
xile611 commented 3 weeks ago

其他相关优化:

xile611 commented 3 weeks ago

DataZoom 相关bugfix:

xile611 commented 3 weeks ago

Brush 相关issue:

webiamcome commented 3 weeks ago

再加一个 DataZoom 相关: 缩略轴大数据量场景下,如何支持标签布局(自动省略、自动旋转)且拖动不卡顿? #2535