Open Ovilia opened 2 years ago
See also: #14239 #10233
What about api like this? This is my initial idea. @Ovilia 😊
series: [
{
data: [150, 230, 224, 218, 135, 147, 260],
type: 'line',
// itemStyle and areastyle is also like this
lineStyle:{
type: "dotted", // global style
styles:{ // part style
type:'solid',
scope:[0,1],
},
}
}
]
sorry ,styles should be an array 😅
@pe-2 Thanks for your suggestion. Although we do not have something like this for other options, theoretically speeking, this could also be a solution. I would suggest comparing each of these solutions and getting to a conclusion which one is the best. The thinking behind the choice of API design is the most important thing for this task.
P.S. We don't have any application on this task yet. Please make sure you submit the application on time.
Thanks!
You’re welcome, It’s my pleasure. I will submit the application after I complete it. 😁
We should also provide a way to set the lineStyle for the lines from
connectNulls
. The API may be{ nullLineStyle: {...}, nullAreaStyle: {...} }
or
{ connectNullStyle: { lineStyle: {...}, areaStyle: {...} } }
If we use these two APIs for setting lineStyle for null item, how could we set lineStyle for each null item individually?
@Ovilia I'd like to add following properties to option in LineSeries.ts#L72 for implementing the second proposal:
export interface LinePieceData {
index: number
leftValue: number
rightValue: number
lineStyle: LineStyleOption
isConnectNulls: boolean
}
export interface LinePiecesOption {
indexes?: number[]
rules: (piece: LinePieceData) => boolean
lineStyle?: LineStyleOption
}
export interface LineSeriesOption {
// ...
linePieces?: LinePiecesOption[]
}
The new API can be call by providing the linePieces
option as you proposed:
or something similar to visualMap.pieces:
{ linePieces: [{ index: [0, 2, 4], // the index of line segments lineStyle: {...}, areaStyle: {...} }] }
or callback rules:
{ linePieces: [{ rule: function(params) { return params.dataIndex % 4 === 1; }, lineStyle: {...}, areaStyle: {...} }] }
When using property rules
to indicate which pieces should this style applied to, the callback function will receive the following arguments as a piece
object:
export interface LinePieceData {
// index of the line piece
index: number
// left endpoint value of the line piece
leftValue: number
// right endpoint value of the line piece
rightValue: number
// line style will be applied to the line piece
lineStyle: LineStyleOption
// indicates if the piece is used to connect null data
isConnectNulls: boolean
}
What do you think of this implement?
@zz5840 Thanks for the update. I want to clearify that if linePieces.index
is the index of the data
? I'm not sure what does index: [0, 2, 4]
mean? Does this mean the lines between (data[0]
, data[1]
), (data[2]
, data[3]
), (data[3]
, data[4]
) appy this style?
We should better use names like startValue
and endValue
rather than leftValue
and rightValue
because if the axis is inversed, the order of data is not the same as in the chart.
areaStyle
should also be provided in the API.
@Ovilia Thanks for reply.
I'd rather make linePieces.index
be the index of the line segment, which is showed in the image below. The red number is line index and the blue is data index.
Line index will be different from data index only if a null data exist. So if we use line index, all index will be valid, and things like index pointing to a null data will not happen.
But there still exist disadvantage in line index. For example, it's hard to control the style of data segment (eg. to set the style for all data whose x-axis data is small than a certain value) when using dynamic data and number of nulls is unknown.
So which index should we provide, or should we provide both?
If the index means the ordinal number of the lines, then you must be careful because when the data is dense enough with line series, the data item (empty circles) is not always visible. Do you wish to have
or
?
Also, I feel it strange to exclude null data when making this index. It would mean the nth non-null line. I'm not sure if this is helpful for developers. Can you think of an example when this way is more convenient?
it's hard to control the style of data segment (eg. to set the style for all data whose x-axis data is small than a certain value) when using dynamic data and number of nulls is unknown.
This is a common situation so I think we shouldn't exclude null data in the index unless we have some solid reasons.
Also, I feel it strange to exclude null data when making this index. It would mean the nth non-null line. I'm not sure if this is helpful for developers. Can you think of an example when this way is more convenient?
I didn't mean to exclude null data, I mean this is what will happen if we use the index of the left endpoint as the index of line segment. But as you say, it's very common to set the style for all data whose x-axis data is small than a certain value, so we must accept a inconsecutive index if we use choose this solution.
Also, if we choose this solution, only the following image will show the correct index.
@zz5840 Thanks for the clarification. Just a few updates on the API design:
export interface LineSeriesOption {
lineSegments?: LineSegmentsOption[],
nullItemStyle?: {...}, // item style for null data
nullLineStyle?: {...},
nullAreaStyle?: {...},
// ...
}
export interface LineSegmentsOption {
dataIndexRange: number[][]
includeEndItem: boolean = true
itemStyle?: ItemStyleOption
lineStyle?: LineStyleOption
areaStyle?: AreaStyleOption
}
isConnectNulls
in LinePieceData
(or at least you can make an PR without this first and later add this feature when you have time). For now, isConnectNulls
is a series-level option and it doesn't seem very necessary to provide a segment-level option to me.number
only. It could be number
s like 123
, or string
s like '123'
or arrays like ['2020-10-10 13:00:00', 123]
. Use LineDataValue
if you are referencing to input data types.dataIndex
is a better name than index
because the latter one can also mean series index or others.dataIndexRange
is an array containing an array of length two. It works like Array.slice
, where the first number means the starting index and the second number means the length. So [[2, 1], [7, 2]]
means data with index 2, 7, and 8.itemStyle
, if includeEndIndex
is set to be true, the data at the end of the segment will be applied the itemStyle
. For example, if dataIndexRange
is [[2, 1], [7, 2]]
and includeEndIndex
is false, then data item 2, 7, and 8 will apply the itemStyle
. If includeEndIndex
is true, then data item 2, 3, 7, 8 and 9 will apply the itemStyle
.lineSegments
to implement the requirement. So I think we can go without it and see if it's necessary in the future.nullItemStyle
, nullLineStyle
, and nullAreaStyle
in the API. When data contains null, we should automatically create a segment from the null data and use corresponding styles.Maybe how PlottableJs handles property updates can be of help for you to decide which API is best. For each property that you can set in PlottableJs, you have the choice of either give the value statically or give an accessor function:
https://github.com/palantir/plottable/blob/develop/src/core/interfaces.ts#L13-L19
/**
* Accesses a specific datum property. Users supply Accessors to their
* plots' .x, .y, .attr, etc. functions.
*/
export interface IAccessor<T> {
(datum: any, index: number, dataset: Dataset): T; // Inputs should be replaced by charts specific dataset data structures
}
Then when creating a Plot in Plottable:
const stackedBarPlot = new Plottable.Plots.StackedBar()
.datasets(datasets)
.attr('fill', (d: any, I: number, dataset: Dataset) => dataset.metadata().color);
How it would look like in echarts:
export interface LineSeriesOption .... {
lineStyle: LineStyleOption | IAccessor<LineStyleOption>;
...
}
Then in user-land:
const baseLineStyle = {...};
...
lineStyle: (datum: any, index: number, dataset: Dataset) => {
return {... baseLineStyle, dashOffset: index > 10 ? 0 : 4 };
}
...
That way a user of the library can very easily create its own logic, that even reusable because it's a simple function.
What about api like this? This is my initial idea. @Ovilia 😊
series: [ { data: [150, 230, 224, 218, 135, 147, 260], type: 'line', // itemStyle and areastyle is also like this lineStyle:{ type: "dotted", // global style styles:{ // part style type:'solid', scope:[0,1], }, } } ]
there is no any styles in lineStyle , and did you submit application ?
Will this feature be implemented in the next version?
I really need lineStyle!!!
{ data: [{ lineStyle: {...}, }] }
Is there a way to simply make lineStyle.color and lineStyle.type accept a function. itemStyle.color already accepts a function and can give you the ability to change color based on dataPoint and index.
您好,最终能实现到可以根据第三维信息,通过visualmap获取映射对应的颜色;然后两点之间根据首尾节点的颜色做渐变的效果吗? 或者是输入和数据等长的信息,描述每个节点的颜色,然后折线段根据2个节点的颜色做渐变呢?
thank you, i'll give it a try
I agree with @sgtsaughter. If lineStyle.color and lineStyle.type could accept a function that would solve the issue.
When I was looking through the documentation, I saw that symbolSize accepts a function so I assumed lineStyle would too. When it didn't accept a function, I searched the issue list and ended up here.
PS Really impressive project! Thanks for all of the consistent updates and documentation, I know that takes a lot of work!
@Ovilia any updates? what the current state of this issue?
@mountpoint I plan to make a PR for v6.0.
What problem does this feature solve?
Current API lacks the ability to control line style for varied segments. For example, if we want to make different styles for a line series, we have to mock it using many series, which is not an elegant way to do.
What does the proposed API look like?
The new option should give the developer the control over line styles for different line segments. The API could be:
or something similar to visualMap.pieces:
or callback rules:
We should also provide a way to set the lineStyle for the lines from
connectNulls
. The API may beor
or
This issue is a task for OSPP so it will probably be fixed by a student from the program. Discussion about the design and your own requirement is always welcomed.