/
githubmirror
/
echarts
Обзор
Документация
Войти
/
githubmirror
/
echarts
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
test/scatter-jitter.html
897 строк
31 KB
plainheart
test(scatter)L fix test case
19 дек 2025, 08:25
Не верифицирован
19 дек 2025, 08:25
5592113
Код
Авторство
О чём код?
<!DOCTYPE html> <!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1" /> <script src="lib/simpleRequire.js"></script> <script src="lib/config.js"></script> <script src="lib/jquery.min.js"></script> <script src="lib/facePrint.js"></script> <script src="lib/testHelper.js"></script> <!-- <script src="ut/lib/canteen.js"></script> --> <link rel="stylesheet" href="lib/reset.css" /> </head> <body> <style> </style> <div id="main0"></div> <div id="main0-no-overlap"></div> <div id="main0-no-overlap2"></div> <div id="main1"></div> <div id="main2"></div> <div id="main2-no-overlap"></div> <div id="main2-symbolSize"></div> <div id="main2-no-overlap-special-case"></div> <div id="main3"></div> <div id="main3-no-overlap"></div> <div id="main3-boundary-test"></div> <div id="main3-boundary-test-no-overlap"></div> <div id="main4"></div> <div id="main5"></div> <script> require([ 'echarts', // 'map/js/china', // './data/nutrients.json' ], function (echarts) { var option; const data = []; for (let i = 0; i < 300; ++i) { data.push([ 'a' + (Math.floor(Math.random() * 4) + 1), Math.random() * 100, ]) } option = { xAxis: { type: 'category', data: ['a1', 'a2', 'a3', 'a4'], jitter: 150, jitterOverlap: true }, yAxis: {}, series: { type: 'scatter', data, itemStyle: { color: params => { return 'rgba(100, 100, 255, ' + (params.dataIndex / 300 * 0.9 + 0.1) + ')'; } } } }; var chart = testHelper.create(echarts, 'main0', { title: [ 'Jittering with Cartesian Category Axis', '**jitterOverlap: true** (default)' ], option: option // height: 300, // buttons: [{text: 'btn-txt', onclick: function () {}}], // recordCanvas: true, }); }); </script> <script> require([ 'echarts', // 'map/js/china', // './data/nutrients.json' ], function (echarts) { var option; const data = []; for (let i = 0; i < 300; ++i) { data.push([ 'a' + (Math.floor(Math.random() * 4) + 1), Math.random() * 100, ]) } option = { xAxis: { type: 'category', data: ['a1', 'a2', 'a3', 'a4'], jitter: 150, jitterOverlap: false }, yAxis: {}, series: { type: 'scatter', data, itemStyle: { color: params => { return 'rgba(100, 100, 255, ' + (params.dataIndex / 300 * 0.9 + 0.1) + ')'; } } } }; var chart = testHelper.create(echarts, 'main0-no-overlap', { title: [ 'Jittering with Cartesian Category Axis', '**jitterOverlap: false**' ], option: option // height: 300, // buttons: [{text: 'btn-txt', onclick: function () {}}], // recordCanvas: true, }); }); </script> <script> require([ 'echarts', // 'map/js/china', // './data/nutrients.json' ], function (echarts) { var option; const data = []; for (let i = 0; i < 500; ++i) { data.push([ Math.random() * 100, 'a' + (Math.floor(Math.random() * 4) + 1), ]) } option = { yAxis: { type: 'category', data: ['a1', 'a2', 'a3', 'a4'], jitter: 50, jitterOverlap: false }, xAxis: {}, series: { type: 'scatter', data } }; var chart = testHelper.create(echarts, 'main0-no-overlap2', { title: [ 'Jittering with Cartesian Category Axis', '**jitterOverlap: false**', 'When too crowded to avoid overlap, there may be overlap' ], option: option // height: 300, // buttons: [{text: 'btn-txt', onclick: function () {}}], // recordCanvas: true, }); }); </script> <script> require([ 'echarts', // 'map/js/china', // './data/nutrients.json' ], function (echarts) { var option; const data = []; for (let i = 0; i < 200; ++i) { data.push([ Math.floor(Math.random() * 4), Math.random() * 100, ]); } option = { tooltip: { show: true, formatter: params => { return params.value[0] + ', ' + params.value[1]; } }, xAxis: { min: 0, jitter: 20 }, yAxis: {}, series: { type: 'scatter', data } }; var chart = testHelper.create(echarts, 'main1', { title: [ 'Jittering is NOT allowed with Value Axis' ], option: option // height: 300, // buttons: [{text: 'btn-txt', onclick: function () {}}], // recordCanvas: true, }); }); </script> <script> require([ 'echarts' ], function (echarts) { var data1 = []; var data2 = []; for (var clutter = 0; clutter < 10; ++clutter) { var cnt = Math.round(Math.random() * 20); var base = Math.random() * 20 * 20; for (var i = 0; i < cnt; ++i) { data1.push((Math.random() * base).toFixed(3)); data2.push((Math.random() * base).toFixed(3)); } } var option = { tooltip: { }, legend: { data: ['scatter'] }, singleAxis: { bottom: '15%', jitter: 200, jitterOverlap: true }, series: [{ type: 'scatter', coordinateSystem: 'singleAxis', symbolSize: 20, data: data1 }, { type: 'scatter', coordinateSystem: 'singleAxis', symbolSize: 20, data: data2 }] }; var chart = testHelper.create(echarts, 'main2', { title: [ 'Jittering with SingleAxis in Category', '**jitterOverlap: true** (default)' ], option: option // height: 300, // buttons: [{text: 'btn-txt', onclick: function () {}}], // recordCanvas true, }); }); </script> <script> require([ 'echarts' ], function (echarts) { var data1 = []; var data2 = []; for (var clutter = 0; clutter < 10; ++clutter) { var cnt = Math.round(Math.random() * 10) + 5; var base = Math.random() * 20 * 20 + 100; for (var i = 0; i < cnt; ++i) { data1.push((Math.random() * base).toFixed(3)); data2.push((Math.random() * base).toFixed(3)); } } var option = { tooltip: { }, legend: { data: ['scatter'] }, singleAxis: { bottom: '15%', jitter: 400, jitterOverlap: false, max: 500 }, series: [{ type: 'scatter', coordinateSystem: 'singleAxis', symbolSize: dataItem => Math.random() * 20 + 10, data: data1 }, { type: 'scatter', coordinateSystem: 'singleAxis', symbolSize: dataItem => Math.random() * 10 + 10, data: data2 }, { type: 'scatter', coordinateSystem: 'singleAxis', symbolSize: dataItem => Math.random() * 10 + 5, data: data2 }] }; var chart = testHelper.create(echarts, 'main2-symbolSize', { title: [ 'Jittering with SingleAxis in Category, **dynamic symbolSize**', '**jitterOverlap: false**' ], option: option, height: 500, // buttons: [{text: 'btn-txt', onclick: function () {}}], // recordCanvas: true, }); }); </script> <script> require([ 'echarts' ], function (echarts) { const data1 = [ 11.2, 10.7, 11.4, 11.8, 11.5, 10, 10.3, 11.1, 11.2, 11.8, 10.7, 11, 11.1, 11.7, 10.5, 10.9, 11.2, 10.4, 11.6, 10.1, 11.1, 11.8, 11.3, 10.8, 10.5, 10.5, 10.8, 10.3, 10.6, 10.2 ]; option = { animation: false, singleAxis: { bottom: '15%', jitter: 500, jitterOverlap: false, max: 15 }, tooltip: { show: true }, series: [{ type: 'scatter', coordinateSystem: 'singleAxis', symbolSize: v => 30, itemStyle: { color: params => { const index = params.dataIndex; return 'rgba(100, 100, 255, ' + (index / data1.length * 0.9 + 0.1) + ')'; } }, data: data1 }] } var chart = testHelper.create(echarts, 'main2-no-overlap-special-case', { title: [ 'There should be no overlap', '**jitterOverlap: false**' ], option: option, height: 600, // buttons: [{text: 'btn-txt', onclick: function () {}}], // recordCanvas: true, }); }); </script> <script> require([ 'echarts' ], function (echarts) { var main = document.getElementById('main2-no-overlap'); if (!main) { return; } var chart = echarts.init(main); var data1 = []; var data2 = []; for (var clutter = 0; clutter < 10; ++clutter) { var cnt = Math.round(Math.random() * 20); var base = Math.random() * 20 * 20; for (var i = 0; i < cnt; ++i) { data1.push((Math.random() * base).toFixed(3)); data2.push((Math.random() * base).toFixed(3)); } } var option = { tooltip: { }, legend: { data: ['scatter'] }, singleAxis: { bottom: '15%', jitter: 200, jitterOverlap: false }, series: [{ type: 'scatter', coordinateSystem: 'singleAxis', symbolSize: 20, data: data1 }, { type: 'scatter', coordinateSystem: 'singleAxis', symbolSize: 20, data: data2 }] }; var chart = testHelper.create(echarts, 'main2-no-overlap', { title: [ 'Jittering with SingleAxis in Category', '**jitterOverlap: false**' ], option: option // height: 300, // buttons: [{text: 'btn-txt', onclick: function () {}}], // recordCanvas: true, }); }); </script> <script> require([ 'echarts' ], function (echarts) { var data1 = []; for (var clutter = 0; clutter < 50; ++clutter) { data1.push([ 'a' + (Math.floor(Math.random() * 4) + 1), Math.random() * 100 ]); } var option = { tooltip: { trigger: 'axis' }, legend: { data: ['scatter'] }, singleAxis: { bottom: '15%', jitter: 500, jitterOverlap: true, type: 'category', data: ['a1', 'a2', 'a3', 'a4'], // orient: 'vertical' }, series: [{ name: 'scatter', type: 'scatter', coordinateSystem: 'singleAxis', symbolSize: 30, data: data1, itemStyle: { color: params => { const x = parseInt(params.value[0].slice(1)); return 'rgba(' + (x * 255 / 4) + ', 100, 255, ' + (x / 4 * 0.9 + 0.1) + ')'; } } }] }; var chart = testHelper.create(echarts, 'main3', { title: [ 'Jittering with SingleAxis in Category', '**jitterOverlap: true** (default)' ], option: option // height: 300, // buttons: [{text: 'btn-txt', onclick: function () {}}], // recordCanvas: true, }); }); </script> <script> require([ 'echarts' ], function (echarts) { var data1 = []; for (var clutter = 0; clutter < 50; ++clutter) { data1.push([ 'a' + (Math.floor(Math.random() * 4) + 1), Math.random() * 100 ]); } var option = { tooltip: { trigger: 'axis' }, legend: { data: ['scatter'] }, singleAxis: { bottom: '15%', jitter: 150, jitterOverlap: false, type: 'category', data: ['a1', 'a2', 'a3', 'a4'], // orient: 'vertical' }, series: [{ name: 'scatter', type: 'scatter', coordinateSystem: 'singleAxis', // symbolSize: 20, data: data1 }] }; var chart = testHelper.create(echarts, 'main3-no-overlap', { title: [ 'Jittering with SingleAxis in Category', '**jitterOverlap: false**' ], option: option // height: 300, // buttons: [{text: 'btn-txt', onclick: function () {}}], // recordCanvas: true, }); }); </script> <script> require([ 'echarts', // 'map/js/china', // './data/nutrients.json' ], function (echarts) { var option; const data = []; for (let i = 0; i < 300; ++i) { data.push([ 'a' + (Math.floor(Math.random() * 4) + 1), Math.random() * 100, ]) } option = { xAxis: { type: 'category', data: ['a1', 'a2', 'a3', 'a4'], jitter: 500, jitterOverlap: true }, yAxis: {}, series: { type: 'scatter', data, symbolSize: 30, itemStyle: { color: params => { const x = parseInt(params.value[0].slice(1)); return 'rgba(' + (x * 255 / 4) + ', 100, 255, ' + (x / 4 * 0.9 + 0.1) + ')'; } } } }; var chart = testHelper.create(echarts, 'main3-boundary-test', { title: [ 'Jittering should be clamped to category bounds', '**jitterOverlap: true**' ], option: option }); }); </script> <script> require([ 'echarts', // 'map/js/china', // './data/nutrients.json' ], function (echarts) { var option; const data = []; for (let i = 0; i < 300; ++i) { data.push([ 'a' + (Math.floor(Math.random() * 4) + 1), Math.random() * 100, ]) } option = { xAxis: { type: 'category', data: ['a1', 'a2', 'a3', 'a4'], jitter: 500, jitterOverlap: false }, yAxis: {}, series: { type: 'scatter', data, symbolSize: 30, itemStyle: { color: params => { const x = parseInt(params.value[0].slice(1)); return 'rgba(' + (x * 255 / 4) + ', 100, 255, ' + (x / 4 * 0.9 + 0.1) + ')'; } } } }; var chart = testHelper.create(echarts, 'main3-boundary-test-no-overlap', { title: [ 'Jittering should be clamped to category bounds', '**jitterOverlap: false**' ], option: option }); }); </script> <script> require([ 'echarts' ], function (echarts) { function genData(len, offset) { let arr = new Float32Array(len * 2); let off = 0; for (let i = 0; i < len; i++) { let x = +Math.random() * 10; let y = +Math.sin(x) - x * (len % 2 ? 0.1 : -0.1) * Math.random() + (offset || 0) / 10; arr[off++] = x; arr[off++] = y; } return arr; } const data1 = genData(5e5); const data2 = genData(5e5, 10); var option = { title: { text: echarts.format.addCommas(data1.length / 2 + data2.length / 2) + ' Points' }, tooltip: {}, xAxis: {}, yAxis: {}, dataZoom: [ { type: 'inside' }, { type: 'slider' } ], animation: true, series: [ { name: 'A', type: 'scatter', data: data1, dimensions: ['x', 'y'], symbolSize: 3, itemStyle: { opacity: 0.4 }, large: true }, { name: 'B', type: 'scatter', data: data2, dimensions: ['x', 'y'], symbolSize: 3, itemStyle: { opacity: 0.4 }, large: true } ] }; // NOTE: Please manually test this case, as the chart may get stuck and cause the VRT to fail. var chart = testHelper.create(echarts, 'main4', { title: [ 'Large Dataset **without** Jittering', 'The chart **SHOULD NOT** get stuck and render as expected', 'Notice: **DO NOT** use SVG renderer for this test case' ], buttons: [ { text: 'Click to load chart', onclick: function () { const elapsedTimeTip = document.createElement('div'); elapsedTimeTip.style.position = 'absolute'; elapsedTimeTip.style.top = '0'; elapsedTimeTip.style.left = '0'; elapsedTimeTip.style.backgroundColor = 'rgba(0,0,0,0.7)'; elapsedTimeTip.style.color = '#fff'; elapsedTimeTip.style.padding = '4px 8px'; elapsedTimeTip.style.zIndex = '9999'; elapsedTimeTip.innerText = 'Rendering...'; chart.getDom().appendChild(elapsedTimeTip); if (chart.getZr().painter.type === 'svg') { elapsedTimeTip.innerText = 'SVG renderer detected! Please switch to Canvas renderer to test large dataset rendering performance.'; return; } const onFinished = () => { const elapsed = performance.now() - startTime; elapsedTimeTip.innerText = `Rendered in ${elapsed.toFixed(2)} ms`; chart.off('finished', onFinished); } chart.on('finished', onFinished); const startTime = performance.now(); chart.setOption(option); // NOTICE: Remove this logic to see the stuck behavior requestIdleCallback((deadline) => { if (deadline.didTimeout) { // Show tip and stop rendering to prevent getting stuck elapsedTimeTip.innerText = 'Rendering is taking longer than expected! Stopping to prevent getting stuck.'; chart.clear(); } }, { timeout: 5000 } ); } } ] }); }); </script> <script> require([ 'echarts' ], async function (echarts) { function genData(len, offset) { let arr = new Float32Array(len * 2); let off = 0; for (let i = 0; i < len; i++) { let x = +Math.random() * 10; let y = +Math.sin(x) - x * (len % 2 ? 0.1 : -0.1) * Math.random() + (offset || 0) / 10; arr[off++] = x; arr[off++] = y; } return arr; } const data1 = genData(5e5); const data2 = genData(5e5, 10); var option = { title: { text: echarts.format.addCommas(data1.length / 2 + data2.length / 2) + ' Points' }, tooltip: {}, xAxis: { jitter: 1.5, type: 'category', data: Array.from({ length: 5 }, (_, idx) => idx) }, yAxis: {}, dataZoom: [ { type: 'inside' }, { type: 'slider' } ], animation: false, series: [ { name: 'A', type: 'scatter', data: data1, dimensions: ['x', 'y'], symbolSize: 3, itemStyle: { opacity: 0.4 }, large: true }, { name: 'B', type: 'scatter', data: data2, dimensions: ['x', 'y'], symbolSize: 3, itemStyle: { opacity: 0.4 }, large: true } ] }; var chart = testHelper.create(echarts, 'main5', { title: [ 'Large Dataset **with** Jittering', 'The chart **SHOULD NOT** throw errors' ], option: option }); }); </script> </body> </html>