Joint JS를 사용하는 경우 그래픽 최적화

만약 나의 Voximplant Kit 장면이 매우 간결하지만 원소가 너무 많고 느려진다면 나는 어떻게 해야 합니까?이것은 우리 개발자가 자문자답한 문제이며 최적화를 실현할 생각을 제시했다.
다음에 저는 대형 장면을 어떻게 초고속으로 만드는지 최적화하고 저희 개발진이 이 기능을 만들 때 어떤 문제에 부딪혔는지 알려 드리겠습니다.

왜 최적화해야 하는가


우리 중 많은 사람들이 페이지의 대량 요소로 인한 성능 문제에 익숙하다.이게 무슨 뜻이죠?우리의 예에서 Voximplant 패키지 장면의 요소가 많을수록, 우리가 그것들을 캔버스에 드래그할 때, 그것들은 캔버스의 요소의 렌더링 속도와 캔버스 자체의 축소와 렌더링 속도에 대한 영향이 크다.
브라우저에서 요소에 적용할 변경 사항을 알리려면 will-change CSS property를 사용하십시오.이것은 페이지 응답성에 부정적인 영향을 미치는 작업을 시작하지 않도록 최적화를 미리 설정할 수 있음을 의미한다.
그러나 Voximplant 패키지에서 사용된 JointJS library 에서는 전체 캔버스가 아닌 드래그 및 축소 캔버스와 관련된 변환이 SVG 요소의 하위 그룹에 적용됩니다.우리는 계산을 카드로 옮기지 못했다.브라우저는 이 속성을 무시하고 이동할 때마다 모든 그룹 요소를 다시 그려서 지연을 초래합니다.
<svg ... > <!-- Canvas -->
  <g transform="matrix(1,0,0,1,224,444)"> <!-- Group of elements inside svg -->
    <rect>
    <rect>

구현


Google 개발자들은 SVG 요소를 한div 요소에 포장하면 모든 변환을div 요소에 먼저 적용할 수 있고 필요할 때만 모든 변환을 캔버스가 있는 SVG 요소에 적용할 수 있다고 결정했습니다.변환이div에 적용되기 시작하면 다음을 추적하기 위해 will-change:transform을 사용해야 합니다.
<div> <!-- div-wrapper to which we apply optimization and transformation -->
  <svg> <!-- Canvas -->
    <g> <!-- Group of elements inside svg -->
      <rect>
      <rect>
그러나 여기서 우리는 또 다른 도전에 직면해 있다. 의지 변화의 사용은 하나의 부가층의 창설을 시작할 것이다.이 속성을 사용하는 요소의 폭과 높이가 클수록 이 층을 저장해야 하는RAM이 많아집니다.우리는 SVG의 규모를 10배로 줄여서 이 문제를 해결했다.예를 들어 캔버스의 비율이 200%일 때 윌 체인지 층은 300MB의 램이 필요하다.축소하면 약 3메가바이트가 필요하다.
이를 위해 우리는 zoom=0.1을 사용하고 transformToCenterViewport 방법으로 SVG 화포를 수축할 것이다.그런 다음 div 요소에 동일한 변환을 적용합니다.
if (isPerfMode) {
  this.el.classList.add('perf-mode');
  // Change scaling before enabling the performance mode
  const prevScale = this._viewportMatrix.a;
  const point = this.getViewPortCenter();
  const zoom = 0.1;
  // Shrink the original svg so that will-change uses less RAM
  this.transformToCenterViewport(point, zoom, true, false, true);
  this.initScale = this._viewportMatrix.a;
  this.createMatrix();
  this.isPerfMode = true;
  // Apply transformations to the wrapper-element
  this.startPerformance();
  this.transformToCenterViewport(point, prevScale, false, false, true);
}
최적화 모드를 사용하면 SVG를 축소하고 캔버스는 매우 작아져 사용하기 어렵다.이 문제를 해결하기 위해 div 요소에 직접 역배율을 적용합니다.
public startPerformance(force = false) {
  ...
  this.isPerformance = true;
  // Get the size of the area with blocks and the indent from the left corner of the viewport
  const { x, y, width, height } = this.layers.getBBox();
  const initScale = this.initScale;
  // Width and height for the wrapper and the x- and y-axis offsets for the area with blocks
  const wrapW = Math.floor(width * initScale) + 2;
  const wrapH = Math.floor(height * initScale) + 2;
  const layerX = -x * initScale;
  const layerY = -y * initScale;
  // this.wrapMatrix - div-element matrix containing the canvas
  this.wrapMatrix.e = +(this._viewportMatrix.e + x * this._viewportMatrix.a);
  this.wrapMatrix.f = +(this._viewportMatrix.f + y * this._viewportMatrix.d);
  this.svgWrapper.style.width = wrapW + 'px';
  this.svgWrapper.style.height = wrapH + 'px';
  this.svgWrapper.style.transform = this.wrapMatrix.toString();
  this.svgWrapper.style.willChange = 'transform';
  this.layers.style.transform = `matrix(${initScale},0,0,${initScale},${layerX} ,${layerY} )`;
}
우리는 속도 문제를 해결했지만, 여기서 끝나지 않았다. 화포를 축소할 때, 이미지의 디테일이 사라지기 시작했다.그래서 확대할 때 희미해진다.우리는 re-rastering composited layers on scale change에 관한 문장의 도움으로 해결 방안을 찾았다.
축소 (스크롤 이벤트) 를 중지한 후 윌 change 속성 0. 1초를 삭제한 다음 다시 설정합니다.그러면 브라우저가 레이어를 래스터 검색을 다시 수행하고 누락된 이미지 세부 정보를 반환합니다.
// Add a 3d transformation so that the layer is not deleted
this.svgWrapper.style.transform = this.wrapMatrix.toString() + ' translateZ(0)';
this.transformFrameId = requestAnimationFrame(() => {
  // Set the will-change property to apply in the next frame
  this.svgWrapper.style.willChange = '';
  this.transformFrameId = requestAnimationFrame(() => {
    this.svgWrapper.style.willChange = 'transform';
    this.svgWrapper.style.transform = this.wrapMatrix.toString();
  });
});
우리가 해야 할 마지막 일은 항상 이동하는 블록을 다른 블록의 꼭대기에 표시하는 것이다.JointJS에서는 toFronttoBack 방법(HTML의 z-index과 유사)이 Z축을 따라 블록과 링크를 이동합니다.그러나 요소를 정렬하고 블록과 링크를 다시 그려서 지연시켜야 한다.
우리의 개발자는 다음과 같은 건의를 제기했다. mousedown 이벤트에서 우리가 상호작용하는 블록은 SVG 요소 트리의 끝(z 인덱스가 가장 높은 요소는 끝에 있음)에 잠시 두었다가 mouseup 이벤트에서 이전의 위치로 되돌아간다.

작업 원리


모든 크롬 기반 브라우저(Chrome, Opera, Edge, Yandex 브라우저 등)와 Safari 브라우저에서 최적화 모드를 테스트할 수 있습니다.장면에 50개 이상의 블록이 포함된 경우 최적화 모드가 자동으로 활성화됩니다.오른쪽 위에 있는 편집기 설정으로 전환하여 활성화하거나 비활성화할 수 있습니다.

최적화 모드를 사용 또는 사용 안 함으로 설정하면 장면 윈도우 맨 위에 알림이 표시됩니다.

다음 GIF를 보고 최적화 모드를 켜고 끄는 장면의 차이를 봅니다.하지만 직접 시도하는 것이 항상 재미있기 때문에 Voxim Plant Kit 장면으로 이동하거나 계정이 없으면to the registration page
최적화 종료 시 캔버스와 해당 요소를 사용하면 많거나 적게 보일 수 있습니다(피쳐가 다른 컴퓨터는 다른 결과를 표시할 수 있습니다).

우리는 최적화를 실현했다. 봐라!

이것이 바로 우리가 캔버스의 이동과 축소를 더욱 매끄럽고 빠르게 하고 링크가 있는 블록의 드래그 속도를 높이는 방법이다.
나는 네가 이 문장을 좋아하길 바란다.우리는 계속 제품을 개선할 것이기 때문에 제가 당신과 더 많은 업데이트와 기교를 공유할 준비를 하세요!:)

좋은 웹페이지 즐겨찾기