Hi Yi,

Trill-down and roll-up is a great and important case in this topic.


I am thinking we should probably better finally come up with a "*simple
concept*" from user perspective so that users can understand it easily.
And the concept should also be correspondingly "powerful"/"flexible" so
that users can manipulate it creatively for their various cases.

For example, wrapping up the cases we already have in the previous posts,
could the "simple but powerful concept" about "transition" be one sentence:

*"If you want to make transition, you only need to specify some keys to
define the data mappings from the old series to new series."*



And then the details of the concept can be expanded:

**[ What is "old series" and "new series"? ]**
When you calling `setOption`, the series existed before the calling are
"old series", whilst the series existing after that calling are "new
series".
If a series is not deleted after `setOption` called, it belongs to both
"old series" and "new series".

**[ What if we do not provide the keys? ]**
If an "old series" and a "new series" is the same one, the key would be by
default datum name or datum id if possible.
Otherwise, no transition.
That is what we already have in echarts4.

**[ What is the keys and what is data mappings? ]**
Key is what echarts depends on to make mappings.
There are two levels of mappings: `series mapping` and `data mapping`.
(1). *<SERIES MAPPING>*:
The mapping from "old series" to "new series".
It can be done explicitly or implicitly.
If a series do not be deleted after `setOption` called, it by default have
that mapping from the old self to the new self.
Otherwise, if a series is deleted by `setOption` but a new one created with
the same `seriesId` or `seriesName`, the mapping should also be built
automatically, no matter whether they have the same `seriesType` or not. In
this case I prefer not to make auto mapping by `seriesIndex`, being afraid
of unexpected mapping.
Note that if auto-mapped by `seriesName`, it is possible that the mapping
is `many-series-to-one-series` or a `one-series-to-many-series` (say
`one-many` for short), which should be allowed and useful in some cases,
like transit from a bar series to several pie series, or vise versa.
Finally, users should be allowed to specify series mapping explicitly in
API, where one-many mapping are also available.
(2). *<DATA MAPPING>*:
The mappings from "old data" to "new data" within a given "series mapping".
Having a series mapping established, echarts get a scope to build data
mappings. The old datum and the new datum will be mapped if they have the
same value on key. The key can be "datum name" or "datum id" or the values
in a certain dimension on the data source.
Notice the a datum can be mapped to any datum within the scope defined by
the series mapping, no matter whether crosses series.
And data mapping can also be `one-one` or `one-many`.

**[ How to specify the keys? ]**
That is an issue in practice level, not totally sure yet. But at least we
already have:
Keys can be specified in the second parameter of `setOption` explicitly.
If users use aggregation, the key could be the aggregation key.

That all about the "concept" from user perspective.


--------------------------------------------------------


Next, let's check the "concept" in the cases the last two email mentioned:

> *1. The series type is not changed. Only data changes.*

If explain it by the "concept", that is the "old series" and the "new
series" are the same one, and the keys are datum name / datum name, one-one
data mapping.

> *2. The series type is changed.* Transition between two different types
of series is more difficult because the view and model have been changed.
...

If explain it by the "concept", that is the "old series" and the "new
series" are not the same one but auto mapped by `seriesId` or `seriesName`.
The original intention of this case might only cover `one-one` data
mappings within each `one-one` series mapping.

> 3. The series type is not changed. But new data is a subset or superset.
* The very common scenario is drill-down and roll-up. Data is usually being
aggregated from one single source.

If explain it by the "concept", that is the "old series" and the "new
series" are the same one, and `one-many` data mappings exists within each
`one-one` series mapping. `one-many` data mappings requires "split" and
"merge" transition.

> 4. *Series type is changed when drill-down, roll-up.* For example, a
rectangle in the bar series is animated to multiple sectors in another pie
series. In this case, we need to combine the strategy used in both 2 and 3.

If explain it by the "concept", that is the "old series" and the "new
series" are not the same one, and `one-one` data mappings exists within
each `one-many` series mapping.

But I prefer not to distinguish "whether series type changed" when
describing the requirements. For examples, case "DIVISION_ASSEMBLY_C" in
the first email, it is essentially `one-one` data mapping within each
`one-many` series mapping. Whether the series type changes or not ("bar" to
"bar" or "bar" to other), the "old series" and the "new series" should be
different series (because of the `one-many` series mapping).



Thanks,
------------------------------
 Su Shuang (100pah)
------------------------------



On Thu, 9 Apr 2020 at 13:51, Yi Shen <shenyi....@gmail.com> wrote:

> Hi Shuang, It's a very detailed explanation for the scenarios.
>
> I like the idea of specifying mapping rules from the old option to the new
> option in the second parameter.
> It gives developers a lot of flexibility, things like which series should
> be deleted can be easily achieved.
> I think it's a general solution of model preparing, should not
> be restricted in the transition domain.
> Perhaps we can discuss the specification of this mapping rule in a separate
> thread.
>
> About the strategy. Here are 4 scenarios I concluded.
>
> *1. The series type is not changed. Only data changes.*
> Currently, we only handle this situation by mapping data with name / id /
> index as keys.
>
> *2. The series type is changed.*
> Transition between two different types of series is more difficult because
> the view and model have been changed.
> In this case, we need to keep the removed series and diff the data with the
> new series. The mapping key can be seriesId / seriesName / seriesIndex.
> And usually, we need to morph between two different shapes when series type
> is changed.
>
> *3. The series type is not changed. But new data is a subset or superset. *
> The very common scenario is drill-down and drill-up. Data is usually being
> aggregated from one single source.
> In this case, we need to find a key used in the aggregation algorithm.
> For example, the `sex` field used in `groupBy` method can also be used to
> map from one source element to multiple target elements and apply the
> animation.
>
> If we apply the aggregation algorithm in the dataset transform. As I
> mentioned in [1]. It's easy to get the key.
> But if developers do the aggregation outside and only give the data. They
> should specify the key explicitly.
>
> 4. *Series type is changed when drill-down, drill-up.*
> For example, a rectangle in the bar series is animated to multiple sectors
> in another pie series. In this case, we need to combine the strategy used
> in both 2 and 3.
>
> In these four scenarios, I think it's not necessary to add
> prepareCrossTransition
> stage*.* The mapping comes from the information collected during model
> preparation.
>
> About the CrossTransitionManager you mentioned. I'm thinking perhaps we
> need a structure to manage the mapping of data and graphic elements.
> Instead of storing the graphic element in the data directly.
>
> [1]
>
> https://lists.apache.org/thread.html/r0cc1ead9c131031fc18fc10ff7a7a7ffa0718c5bd5b226d70e9ee192%40%3Cdev.echarts.apache.org%3E
>
> On Thu, Apr 9, 2020 at 2:31 AM SHUANG SU <sushuang0...@gmail.com> wrote:
>
> > Transition
> >
> > Transition animation will enhance the customization power and would be
> one
> > of the infrastructures for storytelling capability.
> >
> >
> >
> > ------------------------------
> > Framework of transition related API
> >
> > Via setOption:
> >
> > // Forward
> > chart.setOption(optionA);
> > chart.setOption(optionB);
> > chart.setOption(optionC);
> > chart.setOption(optionD);
> > // Backward
> > chart.setOption(optionD);
> > chart.setOption(optionC);
> > chart.setOption(optionB);
> > chart.setOption(optionA);
> > // Note that this sentences above are just illustrative.// in practice
> > those sentences should commonly be// triggered by user behaviors
> > rather than called// synchronously.
> >
> > Note that if intending to keep some of the component in merge mode, the
> > capacity of deleting part of the components (or hide components) should
> be
> > implemented: Probably:
> >
> > chart.setOption({
> >     // Full option
> > });
> > chart.setOption({
> >     series: [
> >         {id: 'ser0'},
> >         {id: 'ser1'},
> >     ]
> >     // Only replace series
> > }, {replace: 'series'});
> > chart.setOption({
> >     dataset: { ... },
> >     series: [
> >         {id: 'ser0'},
> >         {id: 'ser1'},
> >     ]
> >     // Only replace series and dataset
> > }, {replace: ['series', 'dataset']});
> >
> >
> >
> >
> > ------------------------------
> > Transition casesTERMS
> >
> > I am not sure whether these terms below are appropriate. Before better
> one
> > are promoted, we use them in this thread.
> >
> >    - Transform/Transformation: means transit a data item to another data
> >    item one by one.
> >    - Division/Divide: means split a data item to some of data items,
> which
> >    might belong to different new series.
> >    - Assembly/Assemble: the opposite of division.
> >
> > Case OTHERS
> >
> > These cases below are correspondingly clear so we do not need to make
> > further discussion.
> >
> >    - Use dispatchAction to trigger "dataZoom" or "geoRoam" with
> animation.
> >    - Dynamic data as we already have.
> >
> > Case TRANSFORMATION_A
> >
> > var optionA = {
> >     dataset: {...},
> >     xAxis: {id: 'A'},
> >     yAxis: {id: 'A'},
> >     series: [{
> >         id: 'serA',
> >         xAxisId: 'A',
> >         yAxisId: 'A',
> >         type: 'scatter'
> >     }]
> > };var optionB = {
> >     xAxis: {id: 'B'},
> >     yAxis: {id: 'B'},
> >     series: [{
> >         id: 'serB',
> >         xAxisId: 'B',
> >         yAxisId: 'B',
> >         type: 'bar',
> >     }]
> > };var optionC = {
> >     xAxis: {id: 'C'},
> >     yAxis: {id: 'C'},
> >     series: [{
> >         id: 'serC',
> >         xAxisId: 'C',
> >         yAxisId: 'C',
> >         type: 'line'
> >     }]
> > };
> >
> > If we want the transition to be: Use the same data, but transit the
> > elements to another coordinate system. From scatter to bar, can be morph.
> > From bar to line, can be fade out/in. Also consider, the case: a series
> > change its coordinate system from cartesian to polar, where morph may
> need
> > to be applied.
> > Case TRANSFORMATION_B
> >
> > var optionA = {
> >     dataset: {
> >         source: [
> >             //             dim1     dim2      dim3
> >             ['2020-03-01',  32,     4413,     0.17     ],
> >             ['2020-03-02',  42,     1423,     0.47     ],
> >             ['2020-03-03',  62,     5467,     0.87     ],
> >             ['2020-03-04',  12,     1498,     0.17     ],
> >             ['2020-03-05',  52,     2435,     0.57     ],
> >         ]
> >     },
> >     xAxis: {},
> >     yAxis: {},
> >     series: [{
> >         type: 'scatter',
> >         coordinateSystem: 'cartesian',
> >         encode: {x: 0, y: 1}
> >     }]
> > };var optionB = {
> >     series: [{
> >         // Update the series: encode.y is modified to `2`.
> >         encode: {x: 0, y: 2}
> >     }]
> > };
> >
> > If we want the transition to be: The the same coordinate system. But map
> a
> > different dimension to yAxis. The scatter points should be transformed to
> > the new location in the same coordinate system and the yAxis should be
> > transformed properly.
> > Case DIVISION_ASSEMBLY_A
> >
> > var optionA = {
> >     dataset: {
> >         id: 'dsA',
> >         source: [
> >             // Date       Month  HP       Category
> >             ['2020-03-29',  3,   32,      'Rice'    ], // item0
> >             ['2020-03-30',  3,   42,      'Pizza'   ], // item1
> >             ['2020-03-31',  3,   62,      'Noodles' ], // item2
> >             ['2020-04-01',  4,   18,      'Rice'    ], // item3
> >             ['2020-04-02',  4,   52,      'Pizza'   ], // item4
> >         ]
> >     },
> >     series: [
> >         {id: 'ser0', type: 'bar', datasetId: 'dsA', encode: {x: 0, y: 2}}
> >     ]
> > };var optionB = {
> >     dataset: {
> >         id: 'dsB',
> >         source: [
> >             // HP       Category
> >             [  50,      'Rice'    ], // dsA.item0 + dsA.item3
> >             [  94,      'Pizza'   ], // dsA.item1 + dsA.item4
> >             [  62,      'Noodles' ], // dsA.item2
> >         ]
> >     },
> >     series: [
> >         {id: 'ser1', type: 'bar', datasetId: 'dsB', encode: {x: 1, y: 0}}
> >     ]
> > };
> >
> > If we want the transition to be: Bars of "ser0" are assembled by
> "Category"
> > and transit to "ser1". Or event, consider there is:
> >
> > var optionC = {
> >     dataset: {
> >         id: 'dsB',
> >         source: [
> >             // Month    HP
> >             [   3,      136,   ], // dsA.item0 + dsA.item1 + dsA.item2
> >             [   4,      70,    ], // dsA.item3 + dsA.item4
> >         ]
> >     },
> >     series: [
> >         {id: 'ser2', type: 'bar', datasetId: 'dsC', encode: {x: 1, y: 0}}
> >     ]
> > };
> >
> > Can we make transition from optionB to optionC, where both division and
> > assembly happen?
> > Case DIVISION_ASSEMBLY_B
> >
> > var optionA = {
> >     dataset: {
> >         source: [
> >             // X            Y1=Y2+Y3   Y2   Y3
> >             ['2020-03-01',  32,        12,  20   ],
> >             ['2020-03-02',  42,        22,  20   ],
> >             ['2020-03-03',  62,        30,  32   ],
> >             ['2020-03-04',  18,        2,   16   ],
> >             ['2020-03-05',  52,        12,  40   ],
> >         ]
> >     },
> >     series: [
> >         {id: 'ser0', type: 'bar', encode: {x: 0, y: 1}}
> >     ]
> > };var optionB = {
> >     series: [
> >         {id: 'ser1', type: 'bar', encode: {x: 0, y: 2}},
> >         {id: 'ser2', type: 'bar', encode: {x: 0, y: 3}}
> >     ]
> > };
> >
> > If we want the transition to be: Each bar of "ser0" is divided to a bar
> of
> > "ser1" and a bar of "ser2".
> > Case DIVISION_ASSEMBLY_C
> >
> > var optionA = {
> >     dataset: [{
> >         id: 'dsA',
> >         source: [
> >             // X            Y_ser0  Y_ser1  Y_ser2
> >             ['2020-03-01',  32,     44,     17     ],
> >             ['2020-03-02',  42,     14,     47     ],
> >             ['2020-03-03',  62,     54,     87     ],
> >             ['2020-03-04',  12,     14,     17     ],
> >             ['2020-03-05',  52,     24,     57     ],
> >         ]
> >     }, {
> >         id: 'dsB',
> >         source: [
> >             ['Breakfast', 200], // sum of "dsA" dimension 1.
> >             ['Lunch', 150], // sum of "dsA" dimension 2.
> >             ['Supper', 225] // sum of "dsA" dimension 3.
> >         ]
> >     }],
> >     series: [{
> >         // Also  consider the type can be 'line' with `areaStyle: {}`,
> >         // where there is only one polygon for a series.
> >         id: 'ser0', type: 'bar', stack: 's', datasetId: 'dsA',
> >         name: 'Breakfast', encode: {x: 0, y: 1}
> >     }, {
> >         id: 'ser1', type: 'bar', stack: 's', datasetId: 'dsA',
> >         name: 'Lunch', encode: {x: 0, y: 2}
> >     }, {
> >         id: 'ser2', type: 'bar', stack: 's', datasetId: 'dsA',
> >         name: 'Supper', encode: {x: 0, y: 3}
> >     }]
> > };var optionB = {
> >     series: [{
> >         id: 'ser3', type: 'bar', name: 'sum', datasetId: 'dsB',
> >         encode: {x: 0, y: 1}
> >     }]
> > };
> >
> > If we want the transition to be: bars from "ser0" are assembled to "ser3"
> > bar0, bars from "ser1" are assembled to "ser3" bar1, bars from "ser2" are
> > assembled to "ser3" bar2, or vice versa (division). That is, the entire
> > series of "ser0"/"ser1"/"ser2" are mapped to an datum of "ser3".
> > Proposed transition API
> >
> > How to describe this mapping relationship in option?
> >
> > The key point is how to map the old graphic element to the new one. But
> > follow the conventional principle, we should better firstly consider to
> > describe the mapping in data rather than expose the concept "graphic
> > element" to users.
> >
> > Moreover, since the description of transition might be volatile rather
> than
> > persistent (only works while the setOption being called), probably we
> > should not put the "transition description" in optoin. Instead, put it as
> > one extra optional param of setOption, which has the same life-cycle as
> an
> > Payload object. (But I am not totally sure about that, whether put the
> > "transition" setting in option or in setOption param?)
> >
> > A proposed transition API to cover the cases above would be:
> >
> > chart.setOption(
> >     newOption,
> >     {
> >         // Transition mapping rules. Can be
> >         // a single rule (object) or rules (Array<object>).
> >         // For a single series, only one rule (from top to bottom)
> >         // can be accepted.
> >         transition: [
> >             {
> >                 from: {seriesId: 'ser0', dimension: 1},
> >                 to: [
> >                     {seriesId: 'ser1', dimension: 1},
> >                     {seriesId: 'ser2', dimension: 2},
> >                     {seriesId: 'ser3', dimension: 3}
> >                 ]
> >             },
> >             ...
> >         ],
> >         // If `true`, transit from "to" to "from".
> >         transitionBackward: true
> >     }
> > );
> >
> > Take the cases above as examples:
> >
> > // Case TRANSFORMATION_A
> > chart.setOption(
> >     newOption,
> >     {
> >         replace: ['series', 'xAxis', 'yAxis', 'grid'],
> >         transition: {
> >             // By default, mapping by index.
> >             from: {seriesId: 'serA'},
> >             to: {seriesId: 'serB'}
> >         }
> >     }
> > );// Case DIVISION_ASSEMBLY_A
> > chart.setOption(
> >     newOption,
> >     {
> >         replace: 'series',
> >         transition: {
> >             // Use the category dimension as the mapping key.
> >             from: {seriesId: 'ser0', mapOnDimension: 3},
> >             to: {seriesId: 'ser1', mapOnDimension: 1}
> >         }
> >     }
> > );// Case DIVISION_ASSEMBLY_B
> > chart.setOption(
> >     newOption,
> >     {
> >         replace: 'series',
> >         transition: {
> >             // Both use dimension 0 (date string) as the mapping key.
> >             from: {seriesId: 'ser0', mapOnDimension: 0},
> >             to: [
> >                 {seriesId: 'ser1', mapOnDimension: 0},
> >                 {seriesId: 'ser2', mapOnDimension: 0}
> >             ]
> >         }
> >     }
> > );// Case DIVISION_ASSEMBLY_C// Theoretically DIVISION_ASSEMBLY_C is
> > the same as DIVISION_ASSEMBLY_A// We can add three extra dimensions to
> > dataset with all the values being series names:var optionA = {
> >     dataset: [{
> >         id: 'dsA',
> >         source: [
> >             // X            SeriesName0 Y_ser0  SeriesName1 Y_ser1
> > SeriesName2 Y_ser2
> >             ['2020-03-01',  'Breakfast', 32,      'Lunch',  44,
> > 'Supper',  17   ],
> >             ['2020-03-02',  'Breakfast', 42,      'Lunch',  14,
> > 'Supper',  47   ],
> >             ['2020-03-03',  'Breakfast', 62,      'Lunch',  54,
> > 'Supper',  87   ],
> >             ['2020-03-04',  'Breakfast', 12,      'Lunch',  14,
> > 'Supper',  17   ],
> >             ['2020-03-05',  'Breakfast', 52,      'Lunch',  24,
> > 'Supper',  57   ],
> >         ]
> >     }, {
> >         id: 'dsB',
> >         source: [
> >             ['Breakfast', 200], // sum of "dsA" dimension 2.
> >             ['Lunch', 150],     // sum of "dsA" dimension 4.
> >             ['Supper', 225]     // sum of "dsA" dimension 6.
> >         ]
> >     }],
> >     ...
> > };// Add specify transition rules:
> > chart.setOption(
> >     optionB,
> >     {
> >         replace: ['series', 'xAxis', 'yAxis', 'grid'],
> >         transition: {
> >             from: [
> >                 {seriesId: 'ser0', mapOnDimension: 1},
> >                 {seriesId: 'ser1', mapOnDimension: 3},
> >                 {seriesId: 'ser2', mapOnDimension: 5}
> >             ],
> >             // If `mapOnDimension` provided, use the values of that
> >             // dimension as the key to make transition mapping.
> >             // In this case, the value of dimension 0 in "ser3"
> >             // are "Breakfast", "Lunch", "Supper". They are mapped
> >             // to the series name of "ser0"/"ser1"/"ser2".
> >             to: {seriesId: 'ser3', mapOnDimension: 0}
> >         }
> >     }
> > );
> >
> > Implementation of "Internal-Series-Transition"
> >
> > Transition inside a single series has been implemented via data.diff and
> > graphic.initProps/graphic.updateProps. But consider the cases
> > TRANSFORMATION_A and TRANSFORMATION_B, the original updateProps should
> > better be enhanced to support morph.
> > Implementation of "Cross-Series-Transition"
> >
> > The implementation of "Cross-Series-Transition", which is probably not
> only
> > necessary for "Division"/"Assembly" but also useful in other transform
> > requirements above, might be more complicated. I am not sure about the
> > detail of this implementation.
> >
> > Before we make further discussion, we assume that these design is
> > appropriate: "Cross-Series-Transition" can only happen on "create new
> > series". The "transition target" is a new series, and the "transition
> > source" is an existing series, or an series having just been deleted (the
> > latter one might be more common).
> >
> > First of all, consider "delete series", we need to introduce an unified
> > mechanism to temporarily store the "previous series model" (just deleted)
> > or, more specifically, the "previous data with graphic elements".
> Currently
> > these "previous data" are stored on each series view, which is not able
> to
> > "cross series".
> >
> > Secondly, we may need to introduce one extra stage before the render
> stage,
> > say prepareCrossTransition.
> >
> > The stage prepareCrossTransition travels and recognizes the "transition
> > rules" given in the params of setOption calling, finds a proper rule for
> > each series, and detects mappings for each data item based on the key get
> > from mapOnDimension, similar as what DataDiffer.ts did. After these
> > mappings established, we can known how many pieces a single graphic
> element
> > will be "divided to" or "assembled from". Then for each old graphic
> element
> > related to any mapping: (A) If it will be "divided", we use a algorithm
> > (say, splitAlgorithm) to calculate the polygons it can be split, and get
> > sourcePolygons. (B) If it will not be "divided", we trade itself as the
> > sourcePolygons. The result of the mappings and sourcePolygons are finally
> > stored in a data structure, say crossTransitionManager.
> >
> > In the chartView.render, it receives new parameters indicating whether
> this
> > series needs to "Crose-Series-Transition". If not, do things as usually.
> If
> > so, for each element to be created, instead of calling graphic.initProps,
> > we initialize a morph transition animation for the creating procedure.
> > Firstly we retrieve the sourcePolygons from crossTransitionManager. And
> > then, (A) If the element should be "assembled", we use splitAlgorithm to
> > generate targetPolygons for each sourcePolygon, and start morph
> transition
> > animations for each sourcePolygon-targetPolygon tuple. (B) If the element
> > should not be "assembled", we trade the element itself as the
> > targetPolygon,
> > and start a morph transition animation for the
> sourcePolygon-targetPolygon
> >  tuple.
> >
> >
> >
> > ------------------------------
> > Transition on custom series
> >
> > Having the transition framework established, the transition description
> for
> > "custom series" is similar. And we can customize more in graphic element
> > definitions, since "custom series" has exposed the graphic element
> > definitions to users.
> >
> > custom animation should be at least applied on
> >
> >    - properties in "shape": e.g., shape.x, shape.height, shape.points,
> ...
> >    - "transform" propeties: x, y, scaleX, scaleY, originX, originY,
> > rotation
> >    .
> >    - numeric "style" properties: style.x, style.y, style.opacity.
> >    - text, which we will discussed in the next section.
> >
> > Entering transition and leaving transition of custom series
> >
> > For example, if we want to implement the "enter animation" as: "the
> radius
> > increases from 0 and the opacity increase from 0", the proposed option
> can
> > be as follows:
> >
> > renderItem: function () {
> >     return {
> >         type: 'group',
> >         children: [{
> >             type: 'circle',
> >             shape: {
> >                 cx: 100,
> >                 cy: 100,
> >                 // Means that the final radius is 50
> >                 r: 50
> >             },
> >             style: {
> >                 // Means that the final opacity is 1
> >                 opacity: 1,
> >                 fill: 'red'
> >             },
> >             // Set all "enter transition related props" here.
> >             // Notice that only needed props needs to set here.
> >             // Then the enter animation will be performed from
> >             // these props.
> >             // The arguments of the enter animation will follow the
> >             // settings like `animationEasing`, `animationDuration`
> >             // on seriesModel, as other series did.
> >             enterTransition: {
> >                 // The initial radius is 0
> >                 shape: {
> >                     r: 0
> >                 },
> >                 // The initial opacify is 0
> >                 style: {
> >                     opacity: 0
> >                 }
> >             },
> >             // Set all of the "out props" here. It works when the element
> >             // will be disappeared.
> >             // In most case, simply set opacity: 0 as follows is enough.
> >             leaveTransition: {
> >                 style: {
> >                     opacity: 0
> >                 }
> >             }
> >         }]
> >     };
> > }
> >
> > [[PENDING]] Do we need to support setting style.opcity on a group, which
> > can be adopted on every descendants in this group. This probably enhance
> > the animation performance for custom series.
> > Updating transition of custom series
> >
> > As we already have (what scatter series did), data item mappings can be
> > made automatically by dataItem.name or index. But we should better
> > automatically make transition animation when updating, because echarts
> does
> > not known which properties changed. This work should better be left to
> > users.
> >
> > chart.setOtion({
> >     dataset: {
> >         source: [
> >             ['2020-02-02', 12, 553],
> >             ['2020-02-03', 55, 172],
> >             ['2020-02-04', 16, 812],
> >             ['2020-02-05', 94, 756],
> >         ]
> >     },
> >     series: {
> >         type: 'custom',
> >         renderItem: function (params, api) {
> >             var pos = api.coord([api.value(0), api.value(1)]);
> >             return {
> >                 type: 'group',
> >                 children: [{
> >                     type: 'rect',
> >                     shape: {x: -20, y: -20, width: 40, height: 40},
> >                     // Instead of setting `x`/`y` on the root level of
> > this `rect`,
> >                     // we set them in `updateTransition`, which means if
> > update
> >                     // transition occurs, auto make transition
> > animation (additive
> >                     // animation) targeting to these `x`/`y`, otherwise
> > set this
> >                     // `x`/`y` directly. The behavior is like what
> > `graphic.updateProps`
> >                     // did.
> >                     updateTransition: {
> >                         x: pos[0],
> >                         y: pos[1],
> >                     }
> >                 }]
> >             };
> >         },
> >         // Mapping can be established by itemName.
> >         // If itemName not specified, mapping can be established by
> index,
> >         // which makes sense when dataZoom exists.
> >         encode: {x: 1, y: 2, itemName: 0}
> >     }
> > });// Now update
> > chart.setOption({
> >     dataset: {
> >         source: [
> >             // ['2020-02-02', 12, 553], // remove one
> >             ['2020-02-03', 55, 172],
> >             ['2020-02-04', 16, 812],
> >             ['2020-02-05', 94, 756],
> >             ['2020-02-06', 71, 318],    // add one
> >         ]
> >     }
> > });
> >
> > Cross-Series-Transition of custom series
> >
> > This kind of API will be discuss later, after the final morph API
> > (division/assembly) decided.
> >
> > Thanks,
> > ------------------------------
> >  Su Shuang (100pah)
> > ------------------------------
> >
>
>
> --
> Yi Shen
> Apache ECharts(incubating) PPMC
>

Reply via email to