You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@echarts.apache.org by SHUANG SU <su...@gmail.com> on 2020/04/10 20:54:44 UTC

[DISCUSS] option merge/replace/remove API and transition API

Hi,

As Yi mentioned in this thread:
https://lists.apache.org/thread.html/r2bccd1778522b29be776bdd7339f545969d50baa2be4a89d03b09590%40%3Cdev.echarts.apache.org%3E

Could we make further discussion in this thread about:
(1) `setOption` supports replace/remove series or certain component (also
mentioned in #6202, #4356, #4033, #8246, #3002).
(2) transition related in API in `setOption`.


-----------------------------------------------------------
*Support replace/remove series or certain type of component in setOption*

`chart.setOption` should support only replace/remove series or certain type
of component, which is necessary to replace/remove them rather than merge
them while the other components can keep existing to retain their states
that might have been modified by user behavior since the last `setOption`
called.


*[Some use cases for `setOption` are list below to check the API to be
proposed] *

+ Only "replace or add" the specified series (in `option`) but retain the
other old series.
+ Only "merge or add" the specified series (in `option`) but remove the
other old series.
+ Only "replace or merge or add" the specified series and delete the
specified series.


*[Notice this factor: `seriesIndex changed` vs `hole in the container
array`]*
That is:
Currently, component index will never changed no matter how `setOption`
called. If the index can be changed, the index reference (like xAxisIndex)
need to be changed consequently, which might bring some troubles.
But if we enable component deletion and keep the component index not
changed, we need to expose the job of "component index management" to
users, otherwise there might be "hole" in the index sequence (more
specifically, generate "hole" in the array that stored the components).
Having compared of them, I think that users should not be force to manage
the index sequence, which might bring lots of trouble. We should better
choose to allow component index changed if remove happen, and tell users to
use "id reference" instead of "index reference" is those cases (e.g., use
`xAxisId` instead of `xAxisIndex` to refer `xAxis`).


*[The proposed API]*
That use the second parameter to control the behavior of
merge/replace/remove (say, `updateMode`):

For example, suppose their has been three series in a chart:
```js
series: [
  {id: 'id1'},
  {id: 'id3'},
  {id: 'id6'}
]
```

Now we `setOption`:

```js
chart.setOption({
  // Give 5 series in the new option.
  series: [
      {id: 'id1', ...},
      {id: 'id2', ...},
      {id: 'id3', ...},
      {id: 'id4', ...},
      {id: 'id5', ...}
  ]
}, {
  // Use `updateConfig` prop control the behavior
  updateConfig: {
    // The keys are each component main type,
    // the same as `option`
    series: {
      // The keys here can only be:
      // 'replace' | 'merge' | 'remove'
      // The items are `seriesId`.
      // We only support `seriesId` here.
      // `seriesIndex` and `seriesName` do not
      // make sense in most cases here.
      replace: ['id1', 'id4'],
      merge: ['id3', 'id5'],
      remove: ['id6', 'id7']
      // `replace` means: replace or add the given series.
      // `merge` means: merge or add the given series.
      // `remove` means: delete if the given series exists.
    }
  }
});
```

We can also make some shorthand or complements for common cases:

```js
chart.setOption({
  series: [{id: 'xx'}, {id: 'yy'}]
}, {
  updateConfig:{
    series: {
        merge: ['xx', 'yy'],
        // `remove` can also be `true`,
        // means remove all of the existing
        // other series.
        remove: true
    }
  }
});

chart.setOption({
  series: [{id: 'xx'}, {id: 'yy'}]
}, {
  updateConfig: {
    // Here the value can be string of
    // 'replace' | 'merge'(default)
    // Means replace all of the existing series.
    series: 'replace'
    // It is the same as:
    // series: {replace: ['xx', 'yy'], remove: true}
  }
});
```




-----------------------------------------------------------
*Transition API in setOption*


Based on the `chart.setOption` proposed above, we can discuss the
transition.

Firstly, transition will be performed by default is the replace or merging
happen.

For example, suppose their has been three series in a chart:
```js
series: [
  {id: 'id1'},
  {id: 'id2'},
  {id: 'id3'}
]
```

Now we `setOption`:

```js
chart.setOption({
  series: [
    {id: 'id1', ...},
    {id: 'id2', ...},
    {id: 'id3', ...},
    {id: 'id8', ...},
    {id: 'id9', ...}
  ]
}, {
  updateConfig: {
    series: {
      // The new series 'id1' will transitioned from
      // The old series 'id1' by default, mapping by
      // datum name/id.
      // The new series 'id8' do nothing transition.
      replace: ['id1', 'id8'],
      // The new series 'id2' will transitioned from
      // it self, mapping by datum name/id.
      // The new series 'id9' do nothing transition.
      merge: ['id2', 'id9']
    }
  }
});
```

Next, if needed to specify more complicated transition, users can do it
like that:

Suppose their has been three series in a chart:
```js
series: [
  {id: 'idKeep1'},
  {id: 'idOld1'},
  {id: 'idOld2'}
]
```

Now we `setOption`:
```js
chart.setOption({
  series: [
    {id: 'idKeep1'},
    {id: 'id4'},
    {id: 'id8'},
    {id: 'id9'}
  ]
}, {
  updateConfig: {
    series: {
      // Each item of `replace` could be an
      // object instead of a string.
      replace: [{
        // series 'idKeep1' transition with
        // itself, but the mapping key is
        // on dimension 1 of its old data
        // and on dimension 2 of its new data.
        id: 'idKeep1', onDimension: 1,
        transitionFrom: {id: 'idKeep1', onDimension: 2}
      }, {
        // series 'id4' transitions from
        // 'idOld1' and 'idOld2'.
        id: 'id4', onDimension: 4,
        transitionFrom: [
            {id: 'idOld1', onDimension: 2},
            {id: 'idOld2', onDimension: 5}
        ]
      },
      // Both series 'id8' and 'id9' are
      // transitioned from 'idOld1'.
      {
        // If `onDimension` is not provided,
        // map by datum name/id.
        id: 'id8', transitionFrom: {id: 'idOld1'}
      }, {
        id: 'id9', transitionFrom: {id: 'idOld1'}
      }]

      // We could also specify them like that
      // on "merge" property.
    }
  }
});
```
In fact, the example above have shown how to define the series-mapping
explicitly or implicitly.

Notice that for each case above, transition "split"/"merge" animation might
happen, depending on the data-mapping whether is one-many or one-one.



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

Re: [DISCUSS] option merge/replace/remove API and transition API

Posted by Yi Shen <sh...@gmail.com>.
>
> series: {
>       // Each item of `replace` could be an
>       // object instead of a string.
>       replace: [{
>         // series 'idKeep1' transition with
>         // itself, but the mapping key is
>         // on dimension 1 of its old data
>         // and on dimension 2 of its new data.
>         id: 'idKeep1', onDimension: 1,
>         transitionFrom: {id: 'idKeep1', onDimension: 2}
>       }, {
>         // series 'id4' transitions from
>         // 'idOld1' and 'idOld2'.
>         id: 'id4', onDimension: 4,
>         transitionFrom: [
>             {id: 'idOld1', onDimension: 2},
>             {id: 'idOld2', onDimension: 5}
>         ]
>       },
>       // Both series 'id8' and 'id9' are
>       // transitioned from 'idOld1'.
>       {
>         // If `onDimension` is not provided,
>         // map by datum name/id.
>         id: 'id8', transitionFrom: {id: 'idOld1'}
>       }, {
>         id: 'id9', transitionFrom: {id: 'idOld1'}
>       }]
>       // We could also specify them like that
>       // on "merge" property.
> }
>

I'm worrying this API will let developers have to do a lot of
preprocessing, for example querying the dimension index, before `setOption`
to get the transition work properly. Especially when data is dynamic.
Unless it is designed for the developers who processing the data all by
themselves.
In this case, we should only expose this kind of API to advanced users and
make it clear in the document. To avoid developers thinking this transition
API is hard to use.

On Sat, Apr 11, 2020 at 4:55 AM SHUANG SU <su...@gmail.com> wrote:

> Hi,
>
> As Yi mentioned in this thread:
>
> https://lists.apache.org/thread.html/r2bccd1778522b29be776bdd7339f545969d50baa2be4a89d03b09590%40%3Cdev.echarts.apache.org%3E
>
> Could we make further discussion in this thread about:
> (1) `setOption` supports replace/remove series or certain component (also
> mentioned in #6202, #4356, #4033, #8246, #3002).
> (2) transition related in API in `setOption`.
>
>
> -----------------------------------------------------------
> *Support replace/remove series or certain type of component in setOption*
>
> `chart.setOption` should support only replace/remove series or certain type
> of component, which is necessary to replace/remove them rather than merge
> them while the other components can keep existing to retain their states
> that might have been modified by user behavior since the last `setOption`
> called.
>
>
> *[Some use cases for `setOption` are list below to check the API to be
> proposed] *
>
> + Only "replace or add" the specified series (in `option`) but retain the
> other old series.
> + Only "merge or add" the specified series (in `option`) but remove the
> other old series.
> + Only "replace or merge or add" the specified series and delete the
> specified series.
>
>
> *[Notice this factor: `seriesIndex changed` vs `hole in the container
> array`]*
> That is:
> Currently, component index will never changed no matter how `setOption`
> called. If the index can be changed, the index reference (like xAxisIndex)
> need to be changed consequently, which might bring some troubles.
> But if we enable component deletion and keep the component index not
> changed, we need to expose the job of "component index management" to
> users, otherwise there might be "hole" in the index sequence (more
> specifically, generate "hole" in the array that stored the components).
> Having compared of them, I think that users should not be force to manage
> the index sequence, which might bring lots of trouble. We should better
> choose to allow component index changed if remove happen, and tell users to
> use "id reference" instead of "index reference" is those cases (e.g., use
> `xAxisId` instead of `xAxisIndex` to refer `xAxis`).
>
>
> *[The proposed API]*
> That use the second parameter to control the behavior of
> merge/replace/remove (say, `updateMode`):
>
> For example, suppose their has been three series in a chart:
> ```js
> series: [
>   {id: 'id1'},
>   {id: 'id3'},
>   {id: 'id6'}
> ]
> ```
>
> Now we `setOption`:
>
> ```js
> chart.setOption({
>   // Give 5 series in the new option.
>   series: [
>       {id: 'id1', ...},
>       {id: 'id2', ...},
>       {id: 'id3', ...},
>       {id: 'id4', ...},
>       {id: 'id5', ...}
>   ]
> }, {
>   // Use `updateConfig` prop control the behavior
>   updateConfig: {
>     // The keys are each component main type,
>     // the same as `option`
>     series: {
>       // The keys here can only be:
>       // 'replace' | 'merge' | 'remove'
>       // The items are `seriesId`.
>       // We only support `seriesId` here.
>       // `seriesIndex` and `seriesName` do not
>       // make sense in most cases here.
>       replace: ['id1', 'id4'],
>       merge: ['id3', 'id5'],
>       remove: ['id6', 'id7']
>       // `replace` means: replace or add the given series.
>       // `merge` means: merge or add the given series.
>       // `remove` means: delete if the given series exists.
>     }
>   }
> });
> ```
>
> We can also make some shorthand or complements for common cases:
>
> ```js
> chart.setOption({
>   series: [{id: 'xx'}, {id: 'yy'}]
> }, {
>   updateConfig:{
>     series: {
>         merge: ['xx', 'yy'],
>         // `remove` can also be `true`,
>         // means remove all of the existing
>         // other series.
>         remove: true
>     }
>   }
> });
>
> chart.setOption({
>   series: [{id: 'xx'}, {id: 'yy'}]
> }, {
>   updateConfig: {
>     // Here the value can be string of
>     // 'replace' | 'merge'(default)
>     // Means replace all of the existing series.
>     series: 'replace'
>     // It is the same as:
>     // series: {replace: ['xx', 'yy'], remove: true}
>   }
> });
> ```
>
>
>
>
> -----------------------------------------------------------
> *Transition API in setOption*
>
>
> Based on the `chart.setOption` proposed above, we can discuss the
> transition.
>
> Firstly, transition will be performed by default is the replace or merging
> happen.
>
> For example, suppose their has been three series in a chart:
> ```js
> series: [
>   {id: 'id1'},
>   {id: 'id2'},
>   {id: 'id3'}
> ]
> ```
>
> Now we `setOption`:
>
> ```js
> chart.setOption({
>   series: [
>     {id: 'id1', ...},
>     {id: 'id2', ...},
>     {id: 'id3', ...},
>     {id: 'id8', ...},
>     {id: 'id9', ...}
>   ]
> }, {
>   updateConfig: {
>     series: {
>       // The new series 'id1' will transitioned from
>       // The old series 'id1' by default, mapping by
>       // datum name/id.
>       // The new series 'id8' do nothing transition.
>       replace: ['id1', 'id8'],
>       // The new series 'id2' will transitioned from
>       // it self, mapping by datum name/id.
>       // The new series 'id9' do nothing transition.
>       merge: ['id2', 'id9']
>     }
>   }
> });
> ```
>
> Next, if needed to specify more complicated transition, users can do it
> like that:
>
> Suppose their has been three series in a chart:
> ```js
> series: [
>   {id: 'idKeep1'},
>   {id: 'idOld1'},
>   {id: 'idOld2'}
> ]
> ```
>
> Now we `setOption`:
> ```js
> chart.setOption({
>   series: [
>     {id: 'idKeep1'},
>     {id: 'id4'},
>     {id: 'id8'},
>     {id: 'id9'}
>   ]
> }, {
>   updateConfig: {
>     series: {
>       // Each item of `replace` could be an
>       // object instead of a string.
>       replace: [{
>         // series 'idKeep1' transition with
>         // itself, but the mapping key is
>         // on dimension 1 of its old data
>         // and on dimension 2 of its new data.
>         id: 'idKeep1', onDimension: 1,
>         transitionFrom: {id: 'idKeep1', onDimension: 2}
>       }, {
>         // series 'id4' transitions from
>         // 'idOld1' and 'idOld2'.
>         id: 'id4', onDimension: 4,
>         transitionFrom: [
>             {id: 'idOld1', onDimension: 2},
>             {id: 'idOld2', onDimension: 5}
>         ]
>       },
>       // Both series 'id8' and 'id9' are
>       // transitioned from 'idOld1'.
>       {
>         // If `onDimension` is not provided,
>         // map by datum name/id.
>         id: 'id8', transitionFrom: {id: 'idOld1'}
>       }, {
>         id: 'id9', transitionFrom: {id: 'idOld1'}
>       }]
>
>       // We could also specify them like that
>       // on "merge" property.
>     }
>   }
> });
> ```
> In fact, the example above have shown how to define the series-mapping
> explicitly or implicitly.
>
> Notice that for each case above, transition "split"/"merge" animation might
> happen, depending on the data-mapping whether is one-many or one-one.
>
>
>
> Thanks,
> ------------------------------
>  Su Shuang (100pah)
> ------------------------------
>


-- 
Yi Shen
Apache ECharts(incubating) PPMC