>
> 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).


Yeah, it's not precise to use the term "series type changed" in the
previous email. Actually I mean the view and model of series have been
changed.
So the "DIVISION_ASSEMBLY_C" should be in case 4.

On Fri, Apr 10, 2020 at 2:07 AM SHUANG SU <sushuang0...@gmail.com> wrote:

> 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
> >
>


-- 
Yi Shen
Apache ECharts(incubating) PPMC

Reply via email to