This is an automated email from the ASF dual-hosted git repository. sushuang pushed a commit to branch custom-series-enhance in repository https://gitbox.apache.org/repos/asf/incubator-echarts.git
commit d0315f25e9a4e6b8bcf86b76b2d5eb3e8a47c61d Author: 100pah <sushuang0...@gmail.com> AuthorDate: Thu May 21 22:43:10 2020 +0800 chore: tweak and make better example for tutorial. --- src/chart/custom.ts | 9 +- test/custom-feature.html | 483 ---------------------------------- test/custom-transition.html | 627 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 633 insertions(+), 486 deletions(-) diff --git a/src/chart/custom.ts b/src/chart/custom.ts index cfb9587..7af3ec0 100644 --- a/src/chart/custom.ts +++ b/src/chart/custom.ts @@ -286,7 +286,8 @@ const Z2_SPECIFIED_BIT = { emphasis: 1 } as const; -const tmpDuringElProps = { style: {} } as CustomDuringElProps; +const tmpDuringStyle = {} as CustomDuringElProps['style']; +const tmpDuringElProps = {} as CustomDuringElProps; export type PrepareCustomInfo = (coordSys: CoordinateSystem) => { coordSys: CustomSeriesRenderItemParamsCoordSys; @@ -696,7 +697,9 @@ function elUpdateDuringAnimation(this: Element, key: string): void { // PENDING: // Do not expose other style in case that is not stable. const isText = this.type === 'text'; - const textCurr = tmpDuringElProps.style.text = isText ? thisText.style.text : null; + // Always assign in case that user modify `.style`. + tmpDuringElProps.style = tmpDuringStyle; + const textCurr = tmpDuringStyle.text = isText ? thisText.style.text : null; customDuring(tmpDuringElProps); @@ -711,7 +714,7 @@ function elUpdateDuringAnimation(this: Element, key: string): void { tmpDuringElProps.rotation !== rotationCurr && (this.rotation = tmpDuringElProps.rotation); if (isText) { - const currTmpStl = tmpDuringElProps.style; + const currTmpStl = tmpDuringElProps.style; // Allow user modify `.style`. currTmpStl && currTmpStl.text !== textCurr && (thisText.style.text = currTmpStl.text, dirtyStyle = true); } diff --git a/test/custom-feature.html b/test/custom-feature.html index dabf8b1..cee7c53 100644 --- a/test/custom-feature.html +++ b/test/custom-feature.html @@ -38,10 +38,6 @@ under the License. <div id="main0"></div> <div id="main2"></div> <div id="main3"></div> - <div id="init-animation-additive"></div> - <!-- <div id="spiral"></div> --> - <div id="spiral2"></div> - <div id="texture-bar"></div> <script> @@ -368,485 +364,6 @@ under the License. - <script> - - require(['echarts'], function (echarts) { - - var animationDuration = 5000; - var animationDurationUpdate = 4000; - var option = { - xAxis: {}, - yAxis: {}, - dataZoom: [ - { type: 'slider' }, - { type: 'inside' } - ], - animationDuration: animationDuration, - animationDurationUpdate: animationDurationUpdate, - series: [{ - type: 'custom', - renderItem: function (params, api) { - return { - type: 'group', - position: api.coord([api.value(0), api.value(1)]), - children: [{ - type: 'rect', - shape: { - x: -50, - y: 50, - width: 100, - height: 150, - r: 10 - }, - style: { - fill: 'rgba(102,241,98,0.9)' - } - }, { - type: 'circle', - shape: { - cx: -50, - cy: 50, - r: 30 - }, - style: { - fill: 'blue' - }, - textContent: { - text: 'data', - style: { - fill: '#fff' - } - } - }] - }; - }, - data: [[121, 333], [29, 312]] - }] - }; - - var chart = testHelper.create(echarts, 'init-animation-additive', { - title: [ - 'Style merge:', - '(1) dataZoom hide a data item, and then show it, ensure the fade in animation normal.', - '(2) click button to setOption merge.' - ], - option: option, - info: { - animationDuration: animationDuration, - animationDurationUpdate: animationDurationUpdate - }, - buttons: [{ - text: 'merge style: border become blue, but background not changed', - onclick: function () { - chart.setOption({ - type: 'custom', - renderItem: function (params, api) { - return { - type: 'group', - children: [{ - type: 'rect', - style: { - stroke: 'red', - lineWidth: 5 - } - }] - }; - } - }); - } - }] - }); - }); - - </script> - - - - -<!-- - - <script> - require([ - 'echarts'/*, 'map/js/china' */ - ], function (echarts) { - var animationDuration = 5000; - var animationDurationUpdate = 4000; - var angleLabel = ['Aries', 'Taurus', 'Gemini', 'Cancer', 'Leo', 'Virgo', 'Libra', 'Scorpius', 'Sagittarius', 'Capricornus', 'Aquarius', 'Pisces']; - var angleRoundValue = angleLabel.length; - var radiusOffset = 10; - var angleStep = angleRoundValue / 90; - var barWidthValue = 0.4; - var radiusStep = 4; - var colors = { - 'A': { stroke: 'green', fill: 'rgba(0,152,0,0.6)' }, - 'B': { stroke: 'red', fill: 'rgba(152,0,0,0.6)' }, - 'C': { stroke: 'blue', fill: 'rgba(0,0, 152,0.6)' }, - }; - var allData = [[ - [[1, 3, 'A']], - [[2, 6, 'B']], - [[3, 9, 'C']], - ], [ - [[1, 12, 'A']], - [[2, 16, 'B']], - [[3, 14, 'C']], - ], [ - [[1, 17, 'A']], - [[2, 22, 'B']], - [[3, 19, 'C']], - ]]; - var currentDataIndex = 0; - - function getMaxRadius() { - var radius = 0; - for (var j = 0; j < allData.length; j++) { - var data = allData[j]; - for (var i = 0; i < data.length; i++) { - radius = Math.max(radius, getSpiralValueRadius(data[i][0][0], data[i][0][1])); - } - } - return Math.ceil(radius * 1.2); - } - - function getSpiralValueRadius(valRadius, valAngle) { - return valRadius + radiusStep * (valAngle / angleRoundValue); - } - - function renderItem(params, api) { - var valueRadius = api.value(0); - var valueAngle = api.value(1); - var points = []; - for (var iAngleVal = 0, end = valueAngle + angleStep; iAngleVal < end; iAngleVal += angleStep) { - iAngleVal > valueAngle && (iAngleVal = valueAngle); - var iRadiusVal = getSpiralValueRadius(valueRadius - barWidthValue, iAngleVal); - var point = api.coord([iRadiusVal, iAngleVal]).slice(0, 2); - points.push(point); - } - for (var iAngleVal = valueAngle; iAngleVal > -angleStep; iAngleVal -= angleStep) { - iAngleVal < 0 && (iAngleVal = 0); - var iRadiusVal = getSpiralValueRadius(valueRadius + barWidthValue, iAngleVal); - var point = api.coord([iRadiusVal, iAngleVal]).slice(0, 2); - points.push(point); - } - var name = api.value(2); - return { - type: 'polygon', - shape: { points: points }, - style: { - lineWidth: 1, - fill: colors[name].fill, - stroke: colors[name].stroke - } - }; - } - - var option = { - animationDuration: animationDuration, - animationDurationUpdate: animationDurationUpdate, - angleAxis: { - type: 'value', - // splitLine: { show: false }, - splitArea: {show: true}, - axisLabel: { - formatter: function(val) { - return angleLabel[val]; - }, - color: 'rgba(0,0,0,0.2)' - }, - axisLine: { lineStyle: { color: 'rgba(0,0,0,0.2)' } }, - min: 0, - max: angleRoundValue - }, - radiusAxis: { - type: 'value', - splitLine: { show: false }, - axisLabel: { color: 'rgba(0,0,0,0.2)' }, - axisLine: { lineStyle: { color: 'rgba(0,0,0,0.2)' } }, - min: 0, - max: getMaxRadius() - }, - polar: { - }, - tooltip: {}, - series: [{ - type: 'custom', - name: 'A', - coordinateSystem: 'polar', - renderItem: renderItem, - data: allData[currentDataIndex][0] - }, { - type: 'custom', - name: 'B', - coordinateSystem: 'polar', - renderItem: renderItem, - data: allData[currentDataIndex][1] - }, { - type: 'custom', - name: 'C', - coordinateSystem: 'polar', - renderItem: renderItem, - data: allData[currentDataIndex][2] - }] - }; - - var chart = testHelper.create(echarts, 'spiral', { - title: [ - 'animation: ', - ], - option: option, - buttons: [{ - text: 'next', - onclick: function () { - currentDataIndex++; - currentDataIndex >= allData.length && (currentDataIndex = 0); - chart.setOption({ - series: [{ - data: allData[currentDataIndex][0] - }, { - data: allData[currentDataIndex][1] - }, { - data: allData[currentDataIndex][2] - }] - }) - } - }, { - text: 'enable animation', - onclick: function () { - chart.setOption({ animation: true }); - } - }, { - text: 'disable animation', - onclick: function () { - chart.setOption({ animation: false }); - } - }] - }); - }); - </script> - --> - - - - - - - - <script> - require([ - 'echarts'/*, 'map/js/china' */ - ], function (echarts) { - var animationDuration = 5000; - var animationDurationUpdate = 7000; - var animationEasingUpdate = 'elasticOut'; - var angleLabel = ['Aries', 'Taurus', 'Gemini', 'Cancer', 'Leo', 'Virgo', 'Libra', 'Scorpius', 'Sagittarius', 'Capricornus', 'Aquarius', 'Pisces']; - var angleRoundValue = angleLabel.length; - var radiusOffset = 10; - var angleStep = angleRoundValue / 90; - var barWidthValue = 0.4; - var radiusStep = 4; - - var colors = [ - { border: 'green', inner: 'rgba(0,152,0,0.6)' }, - { border: 'red', inner: 'rgba(152,0,0,0.6)' }, - { border: 'blue', inner: 'rgba(0,0, 152,0.6)' }, - ]; - var currentDataIndex = 0; - var datasourceList = [ - [[3, 6, 9]], - [[12, 16, 14]], - [[17, 22, 19]], - ]; - var barValOnRadiusList = [1, 2, 3]; - - // PENDING: - // The radius max should be fixed rather than change dynamically. - // If need to support dynamic coord sys while animation: - // (A) The `api.coord` should be able to accept a customized extent and - // return value on the middle state. - // or (B) Use "data interpolate". - function getMaxRadius() { - var radius = 0; - for (var k = 0; k < barValOnRadiusList.length; k++) { - for (var i = 0; i < datasourceList.length; i++) { - var row = datasourceList[i][0]; - for (var j = 0; j < row.length; j++) { - var valOnAngle = row[j]; - radius = Math.max( - radius, - getSpiralValueRadius(barValOnRadiusList[k], valOnAngle) - ); - } - } - } - return Math.ceil(radius * 1.2); - } - - function getSpiralValueRadius(valOnRadius, valOnAngle) { - return valOnRadius + radiusStep * (valOnAngle / angleRoundValue); - } - - function addShapes(api, children, valOnRadius, valOnAngle, color) { - addPolygon(api, children, valOnRadius, valOnAngle, color); - addLabel(api, children, valOnRadius, valOnAngle, color); - } - - function addPolygon(api, children, valOnRadius, valOnAngle, color) { - children.push({ - type: 'polygon', - shape: { - points: makeShapePoints(api, valOnRadius, valOnAngle), - valOnAngle: valOnAngle - }, - style: { - lineWidth: 1, - fill: color.inner, - stroke: color.border - }, - during: function (elProps) { - elProps.shape.points = makeShapePoints( - api, valOnRadius, elProps.shape.valOnAngle - ); - } - }); - } - - function makeShapePoints(api, valOnRadius, valOnAngle) { - var points = []; - for (var iAngleVal = 0, end = valOnAngle + angleStep; iAngleVal < end; iAngleVal += angleStep) { - iAngleVal > valOnAngle && (iAngleVal = valOnAngle); - var iRadiusVal = getSpiralValueRadius(valOnRadius - barWidthValue, iAngleVal); - var point = api.coord([iRadiusVal, iAngleVal]).slice(0, 2); - points.push(point); - } - for (var iAngleVal = valOnAngle; iAngleVal > -angleStep; iAngleVal -= angleStep) { - iAngleVal < 0 && (iAngleVal = 0); - var iRadiusVal = getSpiralValueRadius(valOnRadius + barWidthValue, iAngleVal); - var point = api.coord([iRadiusVal, iAngleVal]).slice(0, 2); - points.push(point); - } - return points; - } - - function addLabel(api, children, valOnRadius, valOnAngle, color) { - var point = makeLabelPosition(api, valOnRadius, valOnAngle); - children.push({ - type: 'text', - x: point[0], - y: point[1], - shape: { - valOnAngle: valOnAngle - }, - style: { - text: getText(valOnAngle), - fill: color.inner, - stroke: '#fff', - lineWidth: 3, - fontSize: 16, - align: 'center', - verticalAlign: 'middle' - }, - z2: 50, - during: function (elProps) { - var iValOnAngle = elProps.shape.valOnAngle; - var point = makeLabelPosition(api, valOnRadius, iValOnAngle); - elProps.x = point[0]; - elProps.y = point[1]; - elProps.style.text = getText(iValOnAngle); - } - }); - - function getText(iValOnAngle) { - return (iValOnAngle / angleRoundValue * 100).toFixed(0) + '%' - } - } - - function makeLabelPosition(api, valOnRadius, valOnAngle) { - var iRadiusVal = getSpiralValueRadius(valOnRadius, valOnAngle); - return api.coord([iRadiusVal, valOnAngle + 1 / iRadiusVal / (2 * Math.PI) * angleRoundValue]); - } - - function renderItem(params, api) { - var children = []; - - addShapes(api, children, barValOnRadiusList[0], api.value(0), colors[0]); - addShapes(api, children, barValOnRadiusList[1], api.value(1), colors[1]); - addShapes(api, children, barValOnRadiusList[2], api.value(2), colors[2]); - - return { - type: 'group', - children: children - }; - } - - var option = { - // animation: false, - animationDuration: animationDuration, - animationDurationUpdate: animationDurationUpdate, - animationEasingUpdate: animationEasingUpdate, - dataset: { - source: datasourceList[currentDataIndex] - }, - angleAxis: { - type: 'value', - // splitLine: { show: false }, - splitArea: {show: true}, - axisLabel: { - formatter: function(val) { - return angleLabel[val]; - }, - color: 'rgba(0,0,0,0.2)' - }, - axisLine: { lineStyle: { color: 'rgba(0,0,0,0.2)' } }, - min: 0, - max: angleRoundValue - }, - radiusAxis: { - type: 'value', - splitLine: { show: false }, - axisLabel: { color: 'rgba(0,0,0,0.2)' }, - axisLine: { lineStyle: { color: 'rgba(0,0,0,0.2)' } }, - min: 0, - max: getMaxRadius() - }, - polar: {}, - tooltip: {}, - series: [{ - type: 'custom', - coordinateSystem: 'polar', - renderItem: renderItem - }] - }; - - var chart = testHelper.create(echarts, 'spiral2', { - title: [ - 'polygon animation should be corrent. (coordSys extent is fixed)', - ], - option: option, - buttons: [{ - text: 'next', - onclick: function () { - currentDataIndex++; - currentDataIndex >= datasourceList.length && (currentDataIndex = 0); - chart.setOption({ - dataset: { - source: datasourceList[currentDataIndex] - } - }); - } - }, { - text: 'enable animation', - onclick: function () { - chart.setOption({ animation: true }); - } - }, { - text: 'disable animation', - onclick: function () { - chart.setOption({ animation: false }); - } - }] - }); - }); - </script> diff --git a/test/custom-transition.html b/test/custom-transition.html new file mode 100644 index 0000000..77a6aab --- /dev/null +++ b/test/custom-transition.html @@ -0,0 +1,627 @@ +<!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/esl.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> + <link rel="stylesheet" href="lib/reset.css" /> + </head> + <body> + <style> + </style> + + + <div id="init-animation-additive"></div> + <div id="spiral-fixed-extent"></div> + <div id="spiral-dynamic-extent"></div> + <div id="texture-bar"></div> + + + + + <script> + + require(['echarts'], function (echarts) { + + var animationDuration = 5000; + var animationDurationUpdate = 4000; + var option = { + xAxis: {}, + yAxis: {}, + dataZoom: [ + { type: 'slider' }, + { type: 'inside' } + ], + animationDuration: animationDuration, + animationDurationUpdate: animationDurationUpdate, + series: [{ + type: 'custom', + renderItem: function (params, api) { + return { + type: 'group', + position: api.coord([api.value(0), api.value(1)]), + children: [{ + type: 'rect', + shape: { + x: -50, + y: 50, + width: 100, + height: 150, + r: 10 + }, + style: { + fill: 'rgba(102,241,98,0.9)' + } + }, { + type: 'circle', + shape: { + cx: -50, + cy: 50, + r: 30 + }, + style: { + fill: 'blue' + }, + textContent: { + text: 'data', + style: { + fill: '#fff' + } + } + }] + }; + }, + data: [[121, 333], [29, 312]] + }] + }; + + var chart = testHelper.create(echarts, 'init-animation-additive', { + title: [ + 'Style merge:', + '(1) dataZoom hide a data item, and then show it, ensure the fade in animation normal.', + '(2) click button to setOption merge.' + ], + option: option, + info: { + animationDuration: animationDuration, + animationDurationUpdate: animationDurationUpdate + }, + buttons: [{ + text: 'merge style: border become blue, but background not changed', + onclick: function () { + chart.setOption({ + type: 'custom', + renderItem: function (params, api) { + return { + type: 'group', + children: [{ + type: 'rect', + style: { + stroke: 'red', + lineWidth: 5 + } + }] + }; + } + }); + } + }] + }); + }); + + </script> + + + + + + + + <script> + require([ + 'echarts' + ], function (echarts) { + var _animationDuration = 5000; + var _animationDurationUpdate = 7000; + var _animationEasingUpdate = 'elasticOut'; + var _angleLabel = ['Aries', 'Taurus', 'Gemini', 'Cancer', 'Leo', 'Virgo', 'Libra', 'Scorpius', 'Sagittarius', 'Capricornus', 'Aquarius', 'Pisces']; + var _valOnRoundAngle = _angleLabel.length; + var _valOnAngleStep = _valOnRoundAngle / 90; + var _barWidthValue = 0.4; + var _valOnRadiusStep = 4; + + var _colors = [ + { border: 'green', inner: 'rgba(0,152,0,0.6)' }, + { border: 'red', inner: 'rgba(152,0,0,0.6)' }, + { border: 'blue', inner: 'rgba(0,0, 152,0.6)' }, + ]; + var _currentDataIndex = 0; + var _datasourceList = [ + [[3, 6, 9]], + [[12, 16, 14]], + [[17, 22, 19]], + ]; + var _barValOnRadiusList = [1, 2, 3]; + + function getMaxRadius() { + var radius = 0; + for (var k = 0; k < _barValOnRadiusList.length; k++) { + for (var i = 0; i < _datasourceList.length; i++) { + var row = _datasourceList[i][0]; + for (var j = 0; j < row.length; j++) { + var valOnAngle = row[j]; + radius = Math.max( + radius, + getSpiralValueOnRadius(_barValOnRadiusList[k], valOnAngle) + ); + } + } + } + return Math.ceil(radius * 1.2); + } + + function getSpiralValueOnRadius(valOnRadius, valOnAngle) { + return valOnRadius + _valOnRadiusStep * (valOnAngle / _valOnRoundAngle); + } + + function renderItem(params, api) { + var children = []; + + addShapes(api, children, _barValOnRadiusList[0], api.value(0), _colors[0]); + addShapes(api, children, _barValOnRadiusList[1], api.value(1), _colors[1]); + addShapes(api, children, _barValOnRadiusList[2], api.value(2), _colors[2]); + + return { + type: 'group', + children: children + }; + } + + function addShapes(api, children, valOnRadius, valOnAngle, color) { + addPolygon(api, children, valOnRadius, valOnAngle, color); + addLabel(api, children, valOnRadius, valOnAngle, color); + } + + function addPolygon(api, children, valOnRadius, valOnAngle, color) { + children.push({ + type: 'polygon', + shape: { + points: makeShapePoints(api, valOnRadius, valOnAngle), + valOnAngle: valOnAngle + }, + style: { + lineWidth: 1, + fill: color.inner, + stroke: color.border + }, + during: function (elProps) { + elProps.shape.points = makeShapePoints( + api, valOnRadius, elProps.shape.valOnAngle + ); + } + }); + } + + function makeShapePoints(api, valOnRadius, valOnAngle) { + var points = []; + for (var iAngleVal = 0, end = valOnAngle + _valOnAngleStep; iAngleVal < end; iAngleVal += _valOnAngleStep) { + iAngleVal > valOnAngle && (iAngleVal = valOnAngle); + var iRadiusVal = getSpiralValueOnRadius(valOnRadius - _barWidthValue, iAngleVal); + var point = api.coord([iRadiusVal, iAngleVal]).slice(0, 2); + points.push(point); + } + for (var iAngleVal = valOnAngle; iAngleVal > -_valOnAngleStep; iAngleVal -= _valOnAngleStep) { + iAngleVal < 0 && (iAngleVal = 0); + var iRadiusVal = getSpiralValueOnRadius(valOnRadius + _barWidthValue, iAngleVal); + var point = api.coord([iRadiusVal, iAngleVal]).slice(0, 2); + points.push(point); + } + return points; + } + + function addLabel(api, children, valOnRadius, valOnAngle, color) { + var point = makeLabelPosition(api, valOnRadius, valOnAngle); + children.push({ + type: 'text', + x: point[0], + y: point[1], + shape: { + valOnAngle: valOnAngle + }, + style: { + text: getText(valOnAngle), + fill: color.inner, + stroke: '#fff', + lineWidth: 3, + fontSize: 16, + align: 'center', + verticalAlign: 'middle' + }, + z2: 50, + during: function (elProps) { + var iValOnAngle = elProps.shape.valOnAngle; + var point = makeLabelPosition(api, valOnRadius, iValOnAngle); + elProps.x = point[0]; + elProps.y = point[1]; + elProps.style.text = getText(iValOnAngle); + } + }); + + function getText(iValOnAngle) { + return (iValOnAngle / _valOnRoundAngle * 100).toFixed(0) + '%' + } + } + + function makeLabelPosition(api, valOnRadius, valOnAngle) { + var iRadiusVal = getSpiralValueOnRadius(valOnRadius, valOnAngle); + return api.coord([iRadiusVal, valOnAngle + 1 / iRadiusVal / (2 * Math.PI) * _valOnRoundAngle]); + } + + var option = { + // animation: false, + animationDuration: _animationDuration, + animationDurationUpdate: _animationDurationUpdate, + animationEasingUpdate: _animationEasingUpdate, + dataset: { + source: _datasourceList[_currentDataIndex] + }, + angleAxis: { + type: 'value', + // splitLine: { show: false }, + splitArea: {show: true}, + axisLabel: { + formatter: function(val) { + return _angleLabel[val]; + }, + color: 'rgba(0,0,0,0.2)' + }, + axisLine: { lineStyle: { color: 'rgba(0,0,0,0.2)' } }, + min: 0, + max: _valOnRoundAngle + }, + radiusAxis: { + type: 'value', + splitLine: { show: false }, + axisLabel: { color: 'rgba(0,0,0,0.2)' }, + axisLine: { lineStyle: { color: 'rgba(0,0,0,0.2)' } }, + min: 0, + max: getMaxRadius() + }, + polar: {}, + series: [{ + type: 'custom', + coordinateSystem: 'polar', + renderItem: renderItem + }] + }; + + var chart = testHelper.create(echarts, 'spiral-fixed-extent', { + title: [ + 'Spiral race with fixed radius extent.', + 'Click **next**, polygon animation should be corrent.', + ], + option: option, + buttons: [{ + text: 'next', + onclick: function () { + _currentDataIndex++; + _currentDataIndex >= _datasourceList.length && (_currentDataIndex = 0); + chart.setOption({ + dataset: { + source: _datasourceList[_currentDataIndex] + } + }); + } + }, { + text: 'enable animation', + onclick: function () { + chart.setOption({ animation: true }); + } + }, { + text: 'disable animation', + onclick: function () { + chart.setOption({ animation: false }); + } + }] + }); + }); + </script> + + + + + + + + + + <script> + require([ + 'echarts' + ], function (echarts) { + var _animationDuration = 5000; + var _animationDurationUpdate = 7000; + // var _animationEasingUpdate = 'elasticOut'; + var _animationEasingUpdate = 'quadraticOut'; + 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 = [ + { border: 'green', inner: 'rgba(0,152,0,0.6)' }, + { border: 'red', inner: 'rgba(152,0,0,0.6)' }, + { border: 'blue', inner: 'rgba(0,0, 152,0.6)' }, + ]; + 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), + widthRadius: widthRadius, + startRadius: startRadius, + endRadian: endRadian + }, + style: { + lineWidth: 1, + fill: color.inner, + stroke: color.border + }, + during: function (elProps) { + var shp = elProps.shape; + shp.points = makeShapePoints(params, shp.widthRadius, shp.startRadius, shp.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], + shape: { + startRadius: startRadius, + endRadian: endRadian, + widthRadius: widthRadius + }, + style: { + text: makeText(endRadian), + fill: color.inner, + stroke: '#fff', + lineWidth: 3, + fontSize: 12, + align: 'center', + verticalAlign: 'middle', + rich: { + round: { fontSize: 16 }, + percent: { fontSize: 14 } + } + }, + z2: 50, + during: function (elProps) { + var shp = elProps.shape; + var point = makeLabelPosition(params, shp.widthRadius, shp.startRadius, shp.endRadian); + elProps.x = point[0]; + elProps.y = point[1]; + elProps.style.text = makeText(shp.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 + ]; + } + + var 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 + }] + }; + + var chart = testHelper.create(echarts, 'spiral-dynamic-extent', { + title: [ + 'Spiral race with dynamic radius extent.', + 'Click **next**. Polygon animation should be corrent.', + ], + option: option, + buttons: [{ + text: 'next', + onclick: function () { + _currentDataIndex++; + _currentDataIndex >= _datasourceList.length && (_currentDataIndex = 0); + chart.setOption({ + dataset: { + source: _datasourceList[_currentDataIndex] + }, + radiusAxis: { + max: getMaxRadius() + } + }); + } + }, { + text: 'enable animation', + onclick: function () { + chart.setOption({ animation: true }); + } + }, { + text: 'disable animation', + onclick: function () { + chart.setOption({ animation: false }); + } + }] + }); + }); + </script> + + + + + + + + + </body> +</html> \ No newline at end of file --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@echarts.apache.org For additional commands, e-mail: commits-h...@echarts.apache.org