blob: 6d136e6e9e76b210febaffe7eb363ad34416facd [file] [log] [blame]
/*
title: Aggregate Morphing Between Scatter Clustering
category: custom
titleCN: 聚合分割形变(散点图聚类)
difficulty: 10
*/
var CLUSTER_COLORS = [
'#cc5664',
'#9bd6ec',
'#ea946e',
'#8acaaa',
'#f1ec64',
'#ee8686',
'#a48dc1',
'#5da6bc',
'#b9dcae'
];
var ANIMATION_DURATION_UPDATE = 1500;
var RAW_DATA = [
[1425139200000, 34, 0.13, 2, 'MD', 'ZD', 'P0'],
[1425225600000, 28, 0.71, 1.5, 'MB', 'ZD', 'P1'],
[1425312000000, 23, 0.9, 2.8, 'MA', 'ZC', 'P2'],
[1425398400000, 21, 0.58, 6, 'MB', 'ZC', 'P3'],
[1425484800000, 14, 0.1, 1.6, 'MC', 'ZA', 'P4'],
[1425571200000, 21, 0.6, 7.7, 'MC', 'ZA', 'P5'],
[1425657600000, 23, 0.31, 2.6, 'MC', 'ZC', 'P6'],
[1425744000000, 34, 0.74, 2.4, 'MD', 'ZE', 'P7'],
[1425830400000, 14, 0.59, 2.3, 'MB', 'ZD', 'P8'],
[1425916800000, 18, 0.85, 5.1, 'MB', 'ZB', 'P9'],
[1426003200000, 36, 0.96, 1.2, 'MC', 'ZC', 'P10'],
[1426089600000, 18, 0.28, 2.5, 'MA', 'ZC', 'P11'],
[1426176000000, 20, 0.62, 6, 'MB', 'ZD', 'P12'],
[1426262400000, 32, 0.79, 1.7, 'MB', 'ZA', 'P13'],
[1426348800000, 17, 0.58, 4.4, 'MD', 'ZB', 'P14'],
[1426435200000, 23, 0.77, 3, 'MB', 'ZA', 'P15'],
[1426521600000, 39, 0.87, 4.6, 'MC', 'ZA', 'P16'],
[1426608000000, 15, 0.7, 6, 'MB', 'ZC', 'P17'],
[1426694400000, 21, 0.94, 2.7, 'MB', 'ZD', 'P18'],
[1426780800000, 28, 0.48, 4.5, 'MC', 'ZC', 'P19'],
[1426867200000, 31, 0.49, 9.8, 'MA', 'ZC', 'P20'],
[1426953600000, 27, 0.87, 7.7, 'MB', 'ZB', 'P21'],
[1427040000000, 27, 0.82, 5.5, 'MC', 'ZB', 'P22'],
[1427126400000, 11, 0.53, 2.7, 'MD', 'ZC', 'P23'],
[1427212800000, 13, 0.7, 7.6, 'MB', 'ZD', 'P24'],
[1427299200000, 39, 0.99, 4.8, 'MB', 'ZD', 'P25'],
[1427385600000, 32, 0.91, 2.1, 'MB', 'ZE', 'P26'],
[1427472000000, 20, 0.97, 5, 'MB', 'ZA', 'P27'],
[1427558400000, 36, 0.01, 8.9, 'MB', 'ZD', 'P28'],
[1427644800000, 22, 0.08, 9.2, 'MB', 'ZE', 'P29'],
[1427731200000, 21, 0.36, 3.1, 'MD', 'ZC', 'P30'],
[1427817600000, 11, 0.15, 5.8, 'MD', 'ZB', 'P31'],
[1427904000000, 39, 0.02, 1.4, 'MC', 'ZD', 'P32'],
[1427990400000, 20, 0.86, 8.7, 'MB', 'ZD', 'P33'],
[1428076800000, 23, 0.24, 7.2, 'MD', 'ZB', 'P34'],
[1428163200000, 12, 0.06, 2, 'MD', 'ZB', 'P35'],
[1428249600000, 36, 0.42, 8.2, 'MA', 'ZB', 'P36'],
[1428336000000, 17, 0.48, 7.5, 'MB', 'ZC', 'P37'],
[1428422400000, 19, 0.12, 6.6, 'MB', 'ZB', 'P38'],
[1428508800000, 39, 0.58, 3.1, 'MC', 'ZE', 'P39'],
[1428595200000, 10, 0.18, 6.6, 'MC', 'ZD', 'P40'],
[1428681600000, 22, 0.28, 2.1, 'MB', 'ZE', 'P41'],
[1428768000000, 27, 0.33, 1.9, 'MC', 'ZB', 'P42'],
[1428854400000, 37, 0.46, 9.4, 'MD', 'ZE', 'P43'],
[1428940800000, 18, 0.96, 5.5, 'MB', 'ZA', 'P44'],
[1429027200000, 11, 0.61, 8.2, 'MD', 'ZC', 'P45'],
[1429113600000, 15, 0.88, 4.6, 'MD', 'ZA', 'P46'],
[1429200000000, 38, 0.89, 7.2, 'MD', 'ZC', 'P47'],
[1429286400000, 20, 0.39, 5.4, 'MB', 'ZB', 'P48'],
[1429372800000, 30, 0.71, 5.5, 'MA', 'ZA', 'P49']
];
var RAW_DATA_DIMENSIONS = [
'DATE',
'COUNT',
'PRICE',
'WEIGHT',
'M_TAG',
'Z_TAG',
'ID'
];
$.when(
$.getScript(
'https://fastly.jsdelivr.net/npm/echarts-stat@1.2.0/dist/ecStat.min.js'
),
$.getScript(
'https://fastly.jsdelivr.net/npm/echarts-simple-transform@1.0.0/dist/ecSimpleTransform.min.js'
)
).done(function () {
init();
var currentIsClustered = false;
setRawScatterOption();
setInterval(function () {
if (currentIsClustered) {
currentIsClustered = false;
setRawScatterOption();
} else {
currentIsClustered = true;
setClusteredScatterOption();
}
}, 3000);
});
function init() {
echarts.registerTransform(ecSimpleTransform.aggregate);
echarts.registerTransform(ecStat.transform.clustering);
var baseOption = {
dataset: [
{
id: 'raw_dataset',
dimensions: RAW_DATA_DIMENSIONS,
source: RAW_DATA
},
{
id: 'raw_clustered_dataset',
fromDatasetId: 'raw_dataset',
transform: {
type: 'ecStat:clustering',
print: true,
config: {
clusterCount: 4,
dimensions: ['COUNT', 'PRICE'],
outputClusterIndexDimension: {
index: RAW_DATA_DIMENSIONS.length,
name: 'CLUSTER_IDX'
},
outputCentroidDimensions: [
{
index: RAW_DATA_DIMENSIONS.length + 1,
name: 'CLUSTER_CENTER_COUNT'
},
{
index: RAW_DATA_DIMENSIONS.length + 2,
name: 'CLUSTER_CENTER_PRICE'
}
]
}
}
},
{
id: 'raw_cluster_centers_dataset',
fromDatasetId: 'raw_clustered_dataset',
transform: {
type: 'ecSimpleTransform:aggregate',
print: true,
config: {
resultDimensions: [
{ from: 'COUNT', method: 'count' },
{ from: 'CLUSTER_CENTER_COUNT', method: 'first' },
{ from: 'CLUSTER_CENTER_PRICE', method: 'first' },
{ from: 'CLUSTER_IDX' }
],
groupBy: 'CLUSTER_IDX'
}
}
}
],
tooltip: {}
};
myChart.setOption(baseOption, { lazyUpdate: true });
}
function setRawScatterOption() {
var option = {
grid: {
containLabel: true
},
xAxis: {
name: 'PRICE'
},
yAxis: {
name: 'COUNT'
},
series: {
type: 'custom',
coordinateSystem: 'cartesian2d',
animationDurationUpdate: ANIMATION_DURATION_UPDATE,
datasetId: 'raw_clustered_dataset',
encode: {
itemName: 'ID',
x: 'PRICE',
y: 'COUNT',
tooltip: ['PRICE', 'COUNT', 'WEIGHT']
},
renderItem: function (params, api) {
var pos = api.coord([api.value('PRICE'), api.value('COUNT')]);
return {
type: 'circle',
morph: true,
shape: {
cx: pos[0],
cy: pos[1],
r: 10
},
style: {
fill: '#5470c6'
},
transition: ['shape', 'style']
};
}
}
};
myChart.setOption(option, {
replaceMerge: ['xAxis', 'yAxis'],
transition: {
from: { seriesIndex: 0, dimension: 'CLUSTER_IDX' },
to: { seriesIndex: 0, dimension: 'CLUSTER_IDX' }
}
});
}
function setClusteredScatterOption() {
var option = {
grid: {
containLabel: true
},
xAxis: {
name: 'PRICE'
},
yAxis: {
name: 'COUNT'
},
series: {
type: 'custom',
coordinateSystem: 'cartesian2d',
animationDurationUpdate: ANIMATION_DURATION_UPDATE,
datasetId: 'raw_cluster_centers_dataset',
encode: {
x: 'CLUSTER_CENTER_PRICE',
y: 'CLUSTER_CENTER_COUNT',
tooltip: ['CLUSTER_CENTER_PRICE', 'CLUSTER_CENTER_COUNT']
},
renderItem: function (params, api) {
var context = params.context;
if (!context.layout) {
context.layout = true;
context.totalCount = 0;
for (var i = 0; i < params.dataInsideLength; i++) {
context.totalCount += api.value('COUNT', i);
}
}
var pos = api.coord([
api.value('CLUSTER_CENTER_PRICE'),
api.value('CLUSTER_CENTER_COUNT')
]);
var count = api.value('COUNT');
var radius = (count / context.totalCount) * 100 + 10;
return {
type: 'circle',
morph: true,
shape: {
cx: pos[0],
cy: pos[1],
r: radius
},
style: {
// fill: CONTENT_COLOR,
fill: CLUSTER_COLORS[params.dataIndex]
},
transition: ['shape', 'style']
};
}
}
};
myChart.setOption(option, {
replaceMerge: ['xAxis', 'yAxis'],
transition: {
from: { seriesIndex: 0, dimension: 'CLUSTER_IDX' },
to: { seriesIndex: 0, dimension: 'CLUSTER_IDX' }
}
});
}