Apache ECharts 5.3.0 功能

Apache ECharts 5.3.0 在動畫表現力、渲染效能和伺服器端渲染方面進行了重大改進。它還新增了社群期待已久的功能,例如多軸刻度的自動對齊、工具提示值格式化和地圖投影。

關鍵影格動畫

以前,ECharts 動畫主要集中在建立、更新和移除元素的過渡動畫,這些動畫通常只有開始狀態和結束狀態。為了表達更複雜的動畫,我們在 5.3.0 中為自訂系列和圖形元件引入了新的關鍵影格動畫。

這是一個透過關鍵影格動畫實現的簡單呼吸動畫效果

option = {
  graphic: {
    type: 'circle',
    shape: { r: 100 },
    left: 'center',
    top: 'center',
    keyframeAnimation: [
      {
        duration: 3000,
        loop: true,
        keyframes: [
          {
            percent: 0.5,
            easing: 'sinusoidalInOut',
            scaleX: 0.1,
            scaleY: 0.1
          },
          {
            percent: 1,
            easing: 'sinusoidalInOut',
            scaleX: 1,
            scaleY: 1
          }
        ]
      }
    ]
  }
};
即時

在關鍵影格動畫中,您可以設定動畫持續時間、延遲、緩和效果、是否循環、每個關鍵影格的位置、緩和效果和圖形屬性。您還可以同時為每個元素設定多個具有不同設定的關鍵影格動畫。彈性的設定使我們能夠實現非常複雜的動畫效果,以下是幾個可以應用關鍵影格動畫的場景。

自訂載入動畫

ECharts 預設具有內建載入動畫,可以透過呼叫 showLoading 來顯示。社群中經常會詢問更多載入動畫效果。現在有了關鍵影格動畫,我們可以將 graphic 元件與關鍵影格動畫結合使用,以實現任何我們想要的載入動畫效果。

這是一個文字筆劃動畫的範例。

option = {
  graphic: {
    elements: [
      {
        type: 'text',
        left: 'center',
        top: 'center',
        style: {
          text: 'Apache ECharts',
          fontSize: 40,
          fontWeight: 'bold',
          lineDash: [0, 200],
          lineDashOffset: 0,
          fill: 'transparent',
          stroke: '#000',
          lineWidth: 1
        },
        keyframeAnimation: {
          duration: 3000,
          loop: true,
          keyframes: [
            {
              percent: 0.7,
              style: {
                fill: 'transparent',
                lineDashOffset: 200,
                lineDash: [200, 0]
              }
            },
            {
              // Stop for a while.
              percent: 0.8,
              style: {
                fill: 'transparent'
              }
            },
            {
              percent: 1,
              style: {
                fill: 'black'
              }
            }
          ]
        }
      }
    ]
  }
};
即時

或動畫列。

const columns = [];
for (let i = 0; i < 7; i++) {
  columns.push({
    type: 'rect',
    x: i * 20,
    shape: {
      x: 0,
      y: -40,
      width: 10,
      height: 80
    },
    style: {
      fill: '#5470c6'
    },
    keyframeAnimation: {
      duration: 1000,
      delay: i * 200,
      loop: true,
      keyframes: [
        {
          percent: 0.5,
          scaleY: 0.1,
          easing: 'cubicIn'
        },
        {
          percent: 1,
          scaleY: 1,
          easing: 'cubicOut'
        }
      ]
    }
  });
}
option = {
  graphic: {
    elements: [
      {
        type: 'group',
        left: 'center',
        top: 'center',
        children: columns
      }
    ]
  }
};
即時

擴展圖表中更豐富的動畫效果

具有動畫效果的散佈圖一直是 ECharts 的一個特色。開發人員可以使用 effectScatter 系列來實現具有漣漪效果的動態散佈圖,這使圖表更有趣,也用於突出顯示使用者。與載入動畫一樣,開發人員經常要求更多的動畫效果。現在,我們可以在 custom 系列中使用關鍵影格動畫來實現更複雜的效果。

例如,以下範例使用跳躍效果和漣漪動畫為自訂系列在 SVG 地圖上繪製的圖釘製作動畫。

fetch(
  'https://fastly.jsdelivr.net/gh/apache/echarts-website@asf-site/examples/data/asset/geo/Map_of_Iceland.svg'
)
  .then(response => response.text())
  .then(svg => {
    echarts.registerMap('iceland_svg', { svg: svg });
    option = {
      geo: {
        map: 'iceland_svg',
        left: 0,
        right: 0
      },
      series: {
        type: 'custom',
        coordinateSystem: 'geo',
        geoIndex: 0,
        zlevel: 1,
        data: [
          [488, 459, 100],
          [770, 757, 30],
          [1180, 743, 80],
          [894, 1188, 61],
          [1372, 477, 70],
          [1378, 935, 81]
        ],
        renderItem(params, api) {
          const coord = api.coord([
            api.value(0, params.dataIndex),
            api.value(1, params.dataIndex)
          ]);

          const circles = [];
          for (let i = 0; i < 5; i++) {
            circles.push({
              type: 'circle',
              shape: {
                cx: 0,
                cy: 0,
                r: 30
              },
              style: {
                stroke: 'red',
                fill: 'none',
                lineWidth: 2
              },
              // Ripple animation
              keyframeAnimation: {
                duration: 4000,
                loop: true,
                delay: (-i / 4) * 4000,
                keyframes: [
                  {
                    percent: 0,
                    scaleX: 0,
                    scaleY: 0,
                    style: {
                      opacity: 1
                    }
                  },
                  {
                    percent: 1,
                    scaleX: 1,
                    scaleY: 0.4,
                    style: {
                      opacity: 0
                    }
                  }
                ]
              }
            });
          }
          return {
            type: 'group',
            x: coord[0],
            y: coord[1],
            children: [
              ...circles,
              {
                type: 'path',
                shape: {
                  d:
                    'M16 0c-5.523 0-10 4.477-10 10 0 10 10 22 10 22s10-12 10-22c0-5.523-4.477-10-10-10zM16 16c-3.314 0-6-2.686-6-6s2.686-6 6-6 6 2.686 6 6-2.686 6-6 6z',
                  x: -10,
                  y: -35,
                  width: 20,
                  height: 40
                },
                style: {
                  fill: 'red'
                },
                // Jump animation.
                keyframeAnimation: {
                  duration: 1000,
                  loop: true,
                  delay: Math.random() * 1000,
                  keyframes: [
                    {
                      y: -10,
                      percent: 0.5,
                      easing: 'cubicOut'
                    },
                    {
                      y: 0,
                      percent: 1,
                      easing: 'bounceOut'
                    }
                  ]
                }
              }
            ]
          };
        }
      }
    };

    myChart.setOption(option);
  });
即時

載入 Lottie 動畫

為了充分利用新關鍵影格動畫的功能,ECharts 團隊的 Yi Shen 編寫了一個 Lottie 動畫解析程式庫,該程式庫可以將 Lottie 動畫檔案解析為 ECharts 圖形格式以進行渲染。結合 Lottie 的表達能力,我們可以為我們的專案引入更多令人驚嘆的動畫。

圖形元件轉場動畫

我們在 5.0 中為自訂系列中返回的元素提供了更彈性的轉場動畫設定。transitionenterFromleaveTo 設定項目允許您設定每個元素的哪些屬性將具有轉場動畫,以及在建立和移除圖形時如何為它們設定動畫。這是一個範例。

function renderItem() {
  //...
  return {
    //...
    x: 100,
    // 'style', 'x', 'y' will be animated
    transition: ['style', 'x', 'y'],
    enterFrom: {
      style: {
        // Fade in
        opacity: 0
      },
      // Fly in from the left
      x: 0
    },
    leaveTo: {
      // Fade out
      opacity: 0
    },
    // Fly out to the right
    x: 200
  };
}

在 5.3.0 中,我們將這些轉場動畫的設定擴展到圖形元件,並進行了額外的增強。

如果您不想寫出每個要製作動畫的屬性,您現在可以直接設定 transition: 'all' 來為所有屬性製作動畫。

我們還新增了 enterAnimationupdateAnimationleaveAnimation,分別用於設定每個圖形的進入、更新和退出動畫的 durationdelayeasing。漸層顏色現在也支援動畫。

新的 SVG 渲染器

在 5.3.0 中,我們重構了 SVG 渲染器,使其效能提高了 2 倍到 10 倍,在某些特殊場景中甚至提高了數十倍。

之前,我們直接從渲染佇列將 SVG 渲染器更新到 DOM,但由於 zrender 的圖形屬性與 DOM 不是一對一的,我們必須在中間實作非常複雜的差異邏輯,這很容易出錯,並且在某些情況下無法提供最佳效能。在此版本中,我們首先將完整的渲染重建到 VDOM,然後將 VDOM 補丁到 DOM 以完成渲染。完整的渲染避免了複雜差異邏輯造成的潛在錯誤,並且 VDOM 與 DOM 之間的一對一對應關係確保在打補丁時更新次數最少,從而大幅提高了效能。

這個範例讓您對效能的提升有直觀的印象。在 SVG 模式下拖曳圖表時,新版本比以前的版本流暢得多。

5.2.2 (之前) 5.3.0 (之後)
before after

除了效能的提升之外,我們還可以透過渲染的 VDOM 做更多的事情,例如伺服器端渲染,這將在下面說明。

零相依性的伺服器端渲染

在先前的版本中,ECharts 也可以實作伺服器端渲染,但它必須依賴 node-canvas,或者如果您使用 SVG 模式模擬 DOM 環境,則依賴 JSDOM。這些相依性不僅帶來額外的尺寸和使用要求,還會影響效能。

這個新的 SVG 渲染器允許我們從中間渲染的 VDOM 中取得字串,帶來完全零相依性的伺服器端渲染,並輸出整合 CSS 動畫的更精細的 SVG 字串。

const echarts = require('echarts');

// In SSR mode the first parameter does not need to be passed in as a DOM object
const chart = echarts.init(null, null, {
  renderer: 'svg', // must use SVG mode
  ssr: true, // enable SSR
  width: 400, // need to specify height and width
  height: 300
});

// setOption as normal
chart.setOption({
  xAxis: {
    type: 'category',
    data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
  },
  yAxis: {
    type: 'value'
  },
  series: [
    {
      data: [120, 200, 150, 80, 70, 110, 130],
      type: 'bar'
    }
  ]
});

// Output string
const svgStr = chart.renderToSVGString();

自訂地圖投影

地圖一直是 ECharts 中使用非常廣泛的元件。通常,地圖元件使用 GeoJSON 格式化的數據,並儲存緯度和經度。然後,ECharts 會計算適當的顯示區域,並將緯度和經度線性對應到該區域。這是投影地圖最簡單的方法。但是,簡單的線性投影不適用於複雜的地圖場景,例如使用 Albers 投影來解決線性投影中的失真問題,或者將太平洋放在世界地圖的中心等。

因此,在 5.3.0 中,我們引入了擴展地圖投影。它透過 projectunproject 方法告訴 ECharts 如何投影坐標,以及如何從投影的坐標計算緯度和經度。以下是使用墨卡托投影的簡單範例。

series = {
  type: 'map',
  projection: {
    project: point => [
      (point[0] / 180) * Math.PI,
      -Math.log(Math.tan((Math.PI / 2 + (point[1] / 180) * Math.PI) / 2))
    ],
    unproject: point => [
      (point[0] * 180) / Math.PI,
      ((2 * 180) / Math.PI) * Math.atan(Math.exp(point[1])) - 90
    ]
  }
};

除了實作我們自己的投影公式之外,我們還可以使用第三方程式庫(例如 d3-geo)提供的投影實作。

const projection = d3.geoConicEqualArea();
// ...
series = {
  type: 'map',
  projection: {
    project: point => projection(point),
    unproject: point => projection.invert(point)
  }
};

結合 5.2 中新增的全新全域轉場動畫功能,我們可以為不同投影效果之間的轉場製作動畫:!

map-projection-animation

除了地圖投影之外,我們在此版本中對地圖進行了以下兩項增強。

  • 為 GeoJSON 數據提供 'LineString''MultiLineString' 支援。
  • 將預設標籤位置的計算從邊界框的中心變更為最大區域的質心,以獲得更準確的結果。

多軸的刻度對齊

多軸的刻度對齊是社群中長期存在的需求,我們可以在社群中看到許多關於如何在 ECharts 中實作軸對齊的文章,這通常很麻煩且有限。

在 5.3.0 中,我們最終引入了在 'value''log' 軸上對齊刻度的功能。您可以在需要對齊的軸中設定 alignTicks: true。然後,軸將根據第一個軸的刻度調整自己的刻度,從而實現自動對齊。

option = {
  tooltip: {
    trigger: 'axis'
  },
  legend: {},
  xAxis: [
    {
      type: 'category',
      data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
      axisPointer: {
        type: 'shadow'
      }
    }
  ],
  yAxis: [
    {
      type: 'value',
      name: 'Precipitation',
      alignTicks: true,
      axisLabel: {
        formatter: '{value} ml'
      }
    },
    {
      type: 'value',
      name: 'Temperature',
      axisLabel: {
        formatter: '{value} °C'
      }
    }
  ],
  series: [
    {
      name: 'Evaporation',
      type: 'bar',
      // prettier-ignore
      data: [2.0, 4.9, 7.0, 23.2, 25.6, 76.7, 135.6, 162.2, 32.6, 20.0, 6.4, 3.3]
    },
    {
      name: 'Precipitation',
      type: 'bar',
      // prettier-ignore
      data: [2.6, 5.9, 9.0, 26.4, 28.7, 70.7, 175.6, 182.2, 48.7, 18.8, 6.0, 2.3]
    },
    {
      name: 'Temperature',
      type: 'line',
      yAxisIndex: 1,
      data: [2.0, 2.2, 3.3, 4.5, 6.3, 10.2, 20.3, 23.4, 23.0, 16.5, 12.0, 6.2]
    }
  ]
};
即時

停用強調和選取狀態

ECharts 中的 emphasis 狀態會在滑鼠懸停在元素上方時向使用者提供回饋,但在具有大量元素的圖表中,醒目顯示動畫可能會導致效能問題。特別是,由 tooltiplegend 元件連結觸發的醒目顯示可能會同時醒目顯示多個元素。

因此,在此版本中,我們新增了 emphasis.disabled 設定。如果您不需要醒目顯示回饋,並且您關心互動性,您可以使用此選項停用 emphasis 狀態。

對於 select 狀態,我們也新增了 select.disabled。此選項可用於設定某些數據為不可選取。

支援選取整個系列

在 5.3.0 版本中,我們支援將 selectedMode 設定為 'series',以啟用選擇整個系列中的所有數據。

工具提示中數值的格式化

當使用者懸停在數據項目上時,工具提示可用於顯示有關該數據項目的更詳細資訊。ECharts 還提供了一個 formatter 回呼函數,讓開發人員可以更彈性地自訂工具提示的內容。

然而,我們發現大多數時候,開發人員只需要格式化工具提示中的數值部分,例如固定精度、加上 $ 前綴等等。以前,為了格式化數字,開發人員必須使用 formatter 重寫工具提示的整個內容。尤其是在 5.0 之後,ECharts 的提示框變得更加複雜和美觀,因此重寫它們變得既耗時又難以達到預設效果。

因此,在這個版本中,我們為工具提示新增了一個 valueFormatter 設定,用於格式化數值部分。

如同軸對齊範例,我們可以在工具提示的數值部分加上 °C 和 ml 後綴。

option = {
  tooltip: {
    trigger: 'axis'
  },
  legend: {},
  xAxis: [
    {
      type: 'category',
      data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
      axisPointer: {
        type: 'shadow'
      }
    }
  ],
  yAxis: [
    {
      type: 'value',
      name: 'Precipitation',
      alignTicks: true,
      axisLabel: {
        formatter: '{value} ml'
      }
    },
    {
      type: 'value',
      name: 'Temperature',
      axisLabel: {
        formatter: '{value} °C'
      }
    }
  ],
  series: [
    {
      name: 'Evaporation',
      type: 'bar',
      tooltip: {
        valueFormatter: value => value + ' ml'
      },
      // prettier-ignore
      data: [2.0, 4.9, 7.0, 23.2, 25.6, 76.7, 135.6, 162.2, 32.6, 20.0, 6.4, 3.3]
    },
    {
      name: 'Precipitation',
      type: 'bar',
      tooltip: {
        valueFormatter: value => value + ' ml'
      },
      // prettier-ignore
      data: [2.6, 5.9, 9.0, 26.4, 28.7, 70.7, 175.6, 182.2, 48.7, 18.8, 6.0, 2.3]
    },
    {
      name: 'Temperature',
      type: 'line',
      yAxisIndex: 1,
      tooltip: {
        valueFormatter: value => value + ' °C'
      },
      data: [2.0, 2.2, 3.3, 4.5, 6.3, 10.2, 20.3, 23.4, 23.0, 16.5, 12.0, 6.2]
    }
  ]
};
即時

每個系列都可以根據自己的數值格式配置自己的 valueFormatter

更靈活的扇形角半徑

在 5.0 版本中,我們為扇形新增了圓角設定,這可以使圓餅圖和旭日圖更加有趣。之前,我們僅支援分別設定內半徑和外半徑,這次我們更進一步,支援為扇形的四個角配置不同的角半徑,以帶來更靈活的顯示效果。

option = {
  tooltip: {
    trigger: 'item'
  },
  legend: {
    top: '5%',
    left: 'center'
  },
  series: [
    {
      name: 'Access From',
      type: 'pie',
      radius: ['30%', '70%'],
      roseType: 'angle',
      itemStyle: {
        borderRadius: [20, 5, 5, 10],
        borderColor: '#fff',
        borderWidth: 2
      },
      label: {
        show: false
      },
      data: [
        { value: 800, name: 'Search Engine' },
        { value: 735, name: 'Direct' },
        { value: 580, name: 'Email' },
        { value: 484, name: 'Union Ads' },
        { value: 400, name: 'Video Ads' }
      ]
    }
  ]
};
即時

圓餅圖的複雜標籤優化

圓餅圖一直是 ECharts 中標籤顯示最複雜的圖表之一。長期以來,我們一直在優化圓餅圖標籤的佈局和顯示。

這次,我們對使用文字換行、背景顏色、富文本和其他複雜佈局的圓餅圖標籤進行了深入的優化。在自適應寬度、容器溢位、引導線計算方面,都比以前有更好的效果。

5.2.2 (之前) 5.3.0 (之後)
before after
before after

長條圖大型模式優化

在數據量大的情況下(> 2k),我們支援透過開啟large模式來加速長條圖的渲染並提高互動效能。但先前,在large模式下的長條圖佈局很簡單,並且不支援堆疊多個系列後的佈局。在 5.3.0 版本中,我們優化了large模式的佈局,使其與正常模式一致。我們可以透過開啟large來在更多場景中優化長條圖的效能。

此外,優化後的長條圖佈局也修復了在對數軸等非線性軸上堆疊錯誤的錯誤。

重大變更

registerMapgetMap 方法需要在地圖圖表匯入後才能使用

為了減少最小捆綁包的大小,我們從核心模組中刪除了地圖數據管理方法 getMapregisterMap

如果您僅匯入必要的圖表和組件,則需要確保已匯入 GeoComponentMapChart,然後才能使用 registerMap 註冊地圖數據。

import * as echarts from 'echarts/core';
import { MapChart } from 'echarts/charts';

echarts.use([MapChart]);

// You must import the MapChart with the `use` method before you can register the map with registerMap
echarts.registerMap('world', worldJSON);

如果您使用 import * as echarts from 'echarts' 匯入整個套件,則此變更不會對您產生任何影響。

移除折線圖中預設的粗體強調效果

我們在 5.0 版本中為折線圖引入了預設的粗體強調效果,但社群的回饋是這種效果在許多情況下看起來並不好。因此,在這個版本中,我們將此效果從預設開啟改為預設關閉。您可以透過以下方式啟用它:

series = {
  type: 'line',
  //...
  emphasis: {
    lineStyle: {
      width: 'bolder'
    }
  }
};

完整更新日誌

檢視更新日誌

貢獻者 在 GitHub 上編輯此頁面

Ovilia Oviliapissang pissangplainheart plainheart