Performance optimization configuration
Performance Optimization Configuration
ECharts, as a powerful data visualization library, may encounter performance bottlenecks when handling large-scale data or complex charts. Reasonable configurations can significantly improve rendering efficiency and interactive experience.
Data-Level Optimization
Data sampling is a core optimization technique for big data scenarios. When data points exceed tens of thousands, it is recommended to enable dataSampling
:
series: [{
type: 'line',
data: largeDataSet,
sampling: 'lttb', // Largest-Triangle-Three-Buckets algorithm
progressive: 1e6, // Progressive rendering threshold
progressiveThreshold: 500
}]
Chunked loading is suitable for ultra-large datasets (>10MB):
function fetchData(page) {
return fetch(`/api/data?page=${page}&size=10000`).then(res => res.json());
}
let currentPage = 0;
chart.showLoading();
fetchData(currentPage++).then(initData => {
chart.hideLoading();
const option = {
dataset: { source: initData },
series: [{ type: 'scatter' }]
};
chart.setOption(option);
// Scroll to load more data
window.addEventListener('scroll', async () => {
if (shouldLoadMore()) {
const moreData = await fetchData(currentPage++);
chart.appendData({
seriesIndex: 0,
data: moreData
});
}
});
});
Rendering Configuration Optimization
Animation strategy should be dynamically adjusted based on data volume:
animationDuration: dataLength > 1000 ? 0 : 1000,
animationEasing: 'elasticOut',
animationThreshold: 1500 // Disable animation if data points exceed 1500
Hybrid rendering combines the advantages of Canvas and SVG:
const option = {
renderer: 'canvas', // Use Canvas for large datasets
useDirtyRect: true, // Enable dirty rectangle rendering
series: [{
type: 'pie',
renderAsImage: true // Pre-render static charts as images
}]
};
Visual Element Simplification
Visual mapping as an alternative to traditional legends:
visualMap: {
type: 'continuous',
dimension: 2,
seriesIndex: 0,
min: 0,
max: 100,
inRange: {
color: ['#313695', '#4575b4', '#74add1', '#abd9e9', '#e0f3f8']
},
calculable: true
}
Label display strategy optimization:
label: {
show: true,
position: 'top',
formatter: params => {
return params.dataIndex % 5 === 0 ? params.value : '';
},
fontSize: dataLength > 500 ? 0 : 12
}
Interaction Performance Improvement
Debouncing high-frequency events:
let resizeTimer;
window.addEventListener('resize', () => {
clearTimeout(resizeTimer);
resizeTimer = setTimeout(() => {
chart.resize();
}, 200);
});
Area selection optimization:
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow',
shadowStyle: {
color: 'rgba(150,150,150,0.1)'
}
},
confine: true // Restrict to chart area
}
Memory Management Techniques
Timely cleanup of unused instances:
// When unmounting the component
beforeUnmount() {
this.chart.dispose();
this.chart = null;
window.removeEventListener('resize', this.handleResize);
}
Shared datasets to reduce memory usage:
const commonSource = [...];
const option = {
dataset: [{
id: 'sharedData',
source: commonSource
}],
series: [{
type: 'line',
datasetId: 'sharedData'
},{
type: 'bar',
datasetId: 'sharedData'
}]
};
Advanced Optimization Techniques
WebWorker for compute-intensive tasks:
// worker.js
self.onmessage = function(e) {
const result = heavyCompute(e.data);
postMessage(result);
};
// Main thread
const worker = new Worker('worker.js');
worker.postMessage(largeData);
worker.onmessage = function(e) {
chart.setOption({ dataset: { source: e.data } });
};
GPU acceleration configuration:
const option = {
series: [{
type: 'heatmap',
progressive: true,
itemStyle: {
opacity: 0.8
},
emphasis: {
itemStyle: {
opacity: 1
}
}
}],
graphic: {
elements: [{
type: 'image',
style: {
image: '/texture.png',
width: 400,
height: 400
},
blend: 'lighter' // Enable blending mode
}]
}
};
Mobile-Specific Optimization
Gesture interaction adaptation:
chart.on('touchstart', {
throttle: 300,
throttleType: 'fixRate'
}, e => {
// Handle touch events
});
Responsive degradation strategy:
function getOptimizedOption() {
const isMobile = window.innerWidth < 768;
return {
animation: !isMobile,
tooltip: {
show: isMobile ? false : true,
trigger: isMobile ? 'none' : 'axis'
},
series: [{
type: 'line',
symbolSize: isMobile ? 2 : 4
}]
};
}
Server-Side Rendering Solutions
Pre-generating static content:
const echarts = require('echarts');
const { createCanvas } = require('canvas');
const canvas = createCanvas(800, 600);
const chart = echarts.init(canvas);
chart.setOption(/* ... */);
// Output as Base64
const imgData = canvas.toDataURL('image/png');
res.send(`<img src="${imgData}">`);
Incremental rendering protocol:
// Server-side
app.get('/chart-update', (req, res) => {
const lastVersion = req.query.v;
const deltaData = getDeltaData(lastVersion);
res.json({
version: currentVersion,
data: deltaData
});
});
// Client-side
function pollUpdates() {
fetch(`/chart-update?v=${currentVersion}`)
.then(res => res.json())
.then(updateChart);
}
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn