blob: db0699e2d1dd3e18533022d2a25118fffd993930 [file] [log] [blame]
/*
title: Custom Spiral Race
category: custom
titleCN: 自定义螺旋线竞速
difficulty: 11
*/
var _animationDuration = 5000;
var _animationDurationUpdate = 7000;
var _animationEasingUpdate = 'linear';
var _radianLabels = ['Aries', 'Taurus', 'Gemini', 'Cancer', 'Leo', 'Virgo', 'Libra', 'Scorpius', 'Sagittarius', 'Capricornus', 'Aquarius', 'Pisces'];
var _valOnRoundRadian = _radianLabels.length;
var _radianStep = Math.PI / 45;
var _barWidthValue = 0.4;
var _valOnRadiusStep = 4;
// angleAxis.startAngle is 90 by default.
var _startRadian = Math.PI / 2;
var _colors = [
{fill: '#5470c6', text: '#2747a5'},
{fill: '#91cc75', text: '#447f27'},
{fill: '#fac858', text: '#a0761c'}
];
var _currentDataIndex = 0;
var _datasourceList = [
[ [1, 3], [2, 6], [3, 9] ], // datasource 0
[ [1, 12], [2, 16], [3, 14] ], // datasource 1
[ [1, 17], [2, 22], [3, 19] ], // datasource 2
[ [1, 19], [2, 33], [3, 24] ],
[ [1, 24], [2, 42], [3, 29] ],
[ [1, 27], [2, 47], [3, 41] ],
[ [1, 36], [2, 52], [3, 52] ],
[ [1, 46], [2, 59], [3, 63] ],
[ [1, 60], [2, 63], [3, 69] ],
];
var _barNamesByOrdinal = {1: 'A', 2: 'B', 3: 'C'};
function getMaxRadius() {
var radius = 0;
var datasource = _datasourceList[_currentDataIndex];
for (var j = 0; j < datasource.length; j++) {
var dataItem = datasource[j];
radius = Math.max(radius, getSpiralValueOnRadius(dataItem[0], dataItem[1]));
}
return Math.ceil(radius * 1.2);
}
function getSpiralValueOnRadius(valOnStartRadius, valOnEndAngle) {
return valOnStartRadius + _valOnRadiusStep * (valOnEndAngle / _valOnRoundRadian);
}
function getSpiralRadius(startRadius, endRadian, radiusStep) {
return startRadius + radiusStep * ((_startRadian - endRadian) / (Math.PI * 2));
}
function renderItem(params, api) {
var children = [];
var dataIdx = params.dataIndex;
addShapes(params, api, children, api.value(0), api.value(1), _colors[dataIdx]);
return {
type: 'group',
children: children
};
}
function addShapes(params, api, children, valOnStartRadius, valOnEndRadian, color) {
var coords = api.coord([valOnStartRadius, valOnEndRadian]);
var startRadius = coords[2];
var endRadian = coords[3];
var widthRadius = api.coord([_barWidthValue, 0])[2];
addPolygon(params, children, widthRadius, startRadius, endRadian, color);
addLabel(params, children, widthRadius, startRadius, endRadian, color);
}
function addPolygon(params, children, widthRadius, startRadius, endRadian, color) {
children.push({
type: 'polygon',
shape: {
points: makeShapePoints(params, widthRadius, startRadius, endRadian)
},
extra: {
widthRadius: widthRadius,
startRadius: startRadius,
endRadian: endRadian,
transition: ['widthRadius', 'startRadius', 'endRadian']
},
style: {
fill: color.fill
},
during: function (apiDuring) {
apiDuring.setShape('points', makeShapePoints(
params,
apiDuring.getExtra('widthRadius'),
apiDuring.getExtra('startRadius'),
apiDuring.getExtra('endRadian')
));
}
});
}
function makeShapePoints(params, widthRadius, startRadius, endRadian) {
var points = [];
var radiusStep = getRadiusStepByWidth(widthRadius);
// angleAxis.clockwise is true by default. So when rotate clickwisely, radian decreases.
for (
var iRadian = _startRadian, end = endRadian - _radianStep;
iRadian > end;
iRadian -= _radianStep
) {
iRadian < endRadian && (iRadian = endRadian);
var iRadius = getSpiralRadius(startRadius - widthRadius, iRadian, radiusStep);
points.push(convertToPolarPoint(params, iRadius, iRadian));
}
for (
var iRadian = endRadian;
iRadian < _startRadian + _radianStep;
iRadian += _radianStep
) {
iRadian > _startRadian && (iRadian = _startRadian);
var iRadius = getSpiralRadius(startRadius + widthRadius, iRadian, radiusStep);
points.push(convertToPolarPoint(params, iRadius, iRadian));
}
return points;
}
function getRadiusStepByWidth(widthRadius) {
return widthRadius / _barWidthValue * _valOnRadiusStep;
}
function addLabel(params, children, widthRadius, startRadius, endRadian, color) {
var point = makeLabelPosition(params, widthRadius, startRadius, endRadian);
children.push({
type: 'text',
x: point[0],
y: point[1],
transition: [],
extra: {
startRadius: startRadius,
endRadian: endRadian,
widthRadius: widthRadius,
transition: ['startRadius', 'endRadian', 'widthRadius']
},
style: {
text: makeText(endRadian),
fill: color.text,
stroke: '#fff',
lineWidth: 3,
fontSize: 16,
align: 'center',
verticalAlign: 'middle',
rich: {
round: { fontSize: 24 },
percent: { fontSize: 18 }
}
},
z2: 50,
during: function (apiDuring) {
var endRadian = apiDuring.getExtra('endRadian');
var point = makeLabelPosition(
params,
apiDuring.getExtra('widthRadius'),
apiDuring.getExtra('startRadius'),
endRadian
);
apiDuring.setTransform('x', point[0]).setTransform('y', point[1]);
apiDuring.setStyle('text', makeText(endRadian));
}
});
function makeText(endRadian) {
var radian = _startRadian - endRadian;
var PI2 = Math.PI * 2;
var round = Math.floor(radian / PI2);
var percent = (((radian / PI2) % 1) * 100).toFixed(1) + '%';
return 'Round {round|' + round + '}\n{percent|' + percent + '}';
}
}
function makeLabelPosition(params, widthRadius, startRadius, endRadian) {
var radiusStep = getRadiusStepByWidth(widthRadius);
var iRadius = getSpiralRadius(startRadius, endRadian, radiusStep);
return convertToPolarPoint(params, iRadius, endRadian - 10 / iRadius);
}
function convertToPolarPoint(renderItemParams, radius, radian) {
return [
Math.cos(radian) * radius + renderItemParams.coordSys.cx,
-Math.sin(radian) * radius + renderItemParams.coordSys.cy
];
}
option = {
animationDuration: _animationDuration,
animationDurationUpdate: _animationDurationUpdate,
animationEasingUpdate: _animationEasingUpdate,
dataset: {
source: _datasourceList[_currentDataIndex]
},
tooltip: {},
angleAxis: {
type: 'value',
splitArea: { show: true },
axisLabel: {
formatter: function(val) {
return _radianLabels[val];
},
color: 'rgba(0,0,0,0.2)'
},
axisLine: { lineStyle: { color: 'rgba(0,0,0,0.2)' } },
min: 0,
max: _valOnRoundRadian
},
radiusAxis: {
type: 'value',
interval: 1,
splitLine: { show: false },
axisLabel: {
color: 'rgba(0,0,0,0.6)',
formatter: function (value) {
return _barNamesByOrdinal[value] || '';
}
},
axisTick: { show: false },
axisLine: { lineStyle: { color: 'rgba(0,0,0,0.2)' } },
min: 0,
max: getMaxRadius()
},
polar: {},
series: [{
type: 'custom',
coordinateSystem: 'polar',
renderItem: renderItem
}]
};
function next() {
++_currentDataIndex;
myChart.setOption({
dataset: {
source: _datasourceList[_currentDataIndex]
},
radiusAxis: {
max: getMaxRadius()
}
});
if (_currentDataIndex < _datasourceList.length - 1) {
setTimeout(next, _animationDurationUpdate);
}
}
setTimeout(next, 1000);