Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
强哥很慌张
Echarts
提交
79fbcb92
E
Echarts
项目概览
强哥很慌张
/
Echarts
通知
8
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
E
Echarts
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
79fbcb92
编写于
6月 22, 2020
作者:
O
Ovilia
提交者:
GitHub
6月 22, 2020
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #12484 from apache/feat-bar-race
feat: bar race
上级
fe1666df
37376013
变更
14
展开全部
隐藏空白更改
内联
并排
Showing
14 changed file
with
962 addition
and
67 deletion
+962
-67
src/action/changeAxisOrder.ts
src/action/changeAxisOrder.ts
+47
-0
src/chart/bar.ts
src/chart/bar.ts
+1
-0
src/chart/bar/BarView.ts
src/chart/bar/BarView.ts
+217
-21
src/chart/helper/labelHelper.ts
src/chart/helper/labelHelper.ts
+12
-3
src/coord/Axis.ts
src/coord/Axis.ts
+1
-1
src/coord/cartesian/Axis2D.ts
src/coord/cartesian/Axis2D.ts
+14
-1
src/coord/cartesian/AxisModel.ts
src/coord/cartesian/AxisModel.ts
+10
-1
src/coord/cartesian/Grid.ts
src/coord/cartesian/Grid.ts
+10
-0
src/model/mixin/dataFormat.ts
src/model/mixin/dataFormat.ts
+14
-5
src/scale/Ordinal.ts
src/scale/Ordinal.ts
+23
-2
src/scale/Scale.ts
src/scale/Scale.ts
+2
-2
src/util/graphic.ts
src/util/graphic.ts
+150
-31
src/util/types.ts
src/util/types.ts
+6
-0
test/bar-race.html
test/bar-race.html
+455
-0
未找到文件。
src/action/changeAxisOrder.ts
0 → 100644
浏览文件 @
79fbcb92
/*
* 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.
*/
// @ts-nocheck
import
*
as
echarts
from
'
../echarts
'
;
import
*
as
zrUtil
from
'
zrender/src/core/util
'
;
/**
* @payload
* @property {string} [componentType=series]
* @property {number} [dx]
* @property {number} [dy]
* @property {number} [zoom]
* @property {number} [originX]
* @property {number} [originY]
*/
echarts
.
registerAction
({
type
:
'
changeAxisOrder
'
,
event
:
'
changeAxisOrder
'
,
update
:
'
update
'
},
function
(
payload
,
ecModel
)
{
const
componentType
=
payload
.
componentType
||
'
series
'
;
ecModel
.
eachComponent
(
{
mainType
:
componentType
,
query
:
payload
},
function
(
componentModel
)
{
}
);
});
src/chart/bar.ts
浏览文件 @
79fbcb92
...
...
@@ -24,6 +24,7 @@ import {layout, largeLayout} from '../layout/barGrid';
import
'
../coord/cartesian/Grid
'
;
import
'
./bar/BarSeries
'
;
import
'
./bar/BarView
'
;
import
'
../action/changeAxisOrder
'
;
// In case developer forget to include grid component
import
'
../component/gridSimple
'
;
...
...
src/chart/bar/BarView.ts
浏览文件 @
79fbcb92
...
...
@@ -27,18 +27,21 @@ import {
initProps
,
enableHoverEmphasis
,
setLabelStyle
,
clearStates
clearStates
,
updateLabel
,
initLabel
}
from
'
../../util/graphic
'
;
import
Path
,
{
PathProps
}
from
'
zrender/src/graphic/Path
'
;
import
*
as
numberUtil
from
'
../../util/number
'
;
import
Group
from
'
zrender/src/graphic/Group
'
;
import
{
throttle
}
from
'
../../util/throttle
'
;
import
{
createClipPath
}
from
'
../helper/createClipPathFromCoordSys
'
;
import
Sausage
from
'
../../util/shape/sausage
'
;
import
ChartView
from
'
../../view/Chart
'
;
import
List
from
'
../../data/List
'
;
import
List
,
{
DefaultDataVisual
}
from
'
../../data/List
'
;
import
GlobalModel
from
'
../../model/Global
'
;
import
ExtensionAPI
from
'
../../ExtensionAPI
'
;
import
{
StageHandlerProgressParams
,
ZRElementEvent
,
ColorString
}
from
'
../../util/types
'
;
import
{
StageHandlerProgressParams
,
ZRElementEvent
,
ColorString
,
OrdinalSortInfo
,
Payload
,
OrdinalNumber
,
OrdinalRawValue
,
DisplayState
,
ParsedValue
}
from
'
../../util/types
'
;
import
BarSeriesModel
,
{
BarSeriesOption
,
BarDataItemOption
}
from
'
./BarSeries
'
;
import
type
Axis2D
from
'
../../coord/cartesian/Axis2D
'
;
import
type
Cartesian2D
from
'
../../coord/cartesian/Cartesian2D
'
;
...
...
@@ -46,6 +49,9 @@ import type { RectLike } from 'zrender/src/core/BoundingRect';
import
type
Model
from
'
../../model/Model
'
;
import
{
isCoordinateSystemType
}
from
'
../../coord/CoordinateSystem
'
;
import
{
getDefaultLabel
}
from
'
../helper/labelHelper
'
;
import
OrdinalScale
from
'
../../scale/Ordinal
'
;
import
AngleAxis
from
'
../../coord/polar/AngleAxis
'
;
import
RadiusAxis
from
'
../../coord/polar/RadiusAxis
'
;
const
BAR_BORDER_WIDTH_QUERY
=
[
'
itemStyle
'
,
'
borderWidth
'
]
as
const
;
const
BAR_BORDER_RADIUS_QUERY
=
[
'
itemStyle
'
,
'
borderRadius
'
]
as
const
;
...
...
@@ -100,17 +106,18 @@ class BarView extends ChartView {
private
_backgroundEls
:
(
Rect
|
Sector
)[];
render
(
seriesModel
:
BarSeriesModel
,
ecModel
:
GlobalModel
,
api
:
ExtensionAPI
):
void
{
render
(
seriesModel
:
BarSeriesModel
,
ecModel
:
GlobalModel
,
api
:
ExtensionAPI
,
payload
:
Payload
)
{
this
.
_updateDrawMode
(
seriesModel
);
const
coordinateSystemType
=
seriesModel
.
get
(
'
coordinateSystem
'
);
const
isReorder
=
payload
&&
payload
.
type
===
'
changeAxisOrder
'
;
if
(
coordinateSystemType
===
'
cartesian2d
'
||
coordinateSystemType
===
'
polar
'
)
{
this
.
_isLargeDraw
?
this
.
_renderLarge
(
seriesModel
,
ecModel
,
api
)
:
this
.
_renderNormal
(
seriesModel
,
ecModel
,
api
);
:
this
.
_renderNormal
(
seriesModel
,
ecModel
,
api
,
isReorder
);
}
else
if
(
__DEV__
)
{
console
.
warn
(
'
Only cartesian2d and polar supported for bar.
'
);
...
...
@@ -138,23 +145,38 @@ class BarView extends ChartView {
}
}
private
_renderNormal
(
seriesModel
:
BarSeriesModel
,
ecModel
:
GlobalModel
,
api
:
ExtensionAPI
):
void
{
private
_renderNormal
(
seriesModel
:
BarSeriesModel
,
ecModel
:
GlobalModel
,
api
:
ExtensionAPI
,
isReorder
:
boolean
):
void
{
const
that
=
this
;
const
group
=
this
.
group
;
const
data
=
seriesModel
.
getData
();
const
oldData
=
this
.
_data
;
const
coord
=
seriesModel
.
coordinateSystem
;
const
baseAxis
=
coord
.
getBaseAxis
();
let
valueAxis
:
Axis2D
|
RadiusAxis
|
AngleAxis
;
let
isHorizontalOrRadial
:
boolean
;
if
(
coord
.
type
===
'
cartesian2d
'
)
{
isHorizontalOrRadial
=
(
baseAxis
as
Axis2D
).
isHorizontal
();
valueAxis
=
coord
.
getOtherAxis
(
baseAxis
as
Axis2D
);
}
else
if
(
coord
.
type
===
'
polar
'
)
{
isHorizontalOrRadial
=
baseAxis
.
dim
===
'
angle
'
;
valueAxis
=
coord
.
getOtherAxis
(
baseAxis
as
(
AngleAxis
|
RadiusAxis
));
}
const
animationModel
=
seriesModel
.
isAnimationEnabled
()
?
seriesModel
:
null
;
const
axisAnimationModel
=
baseAxis
.
model
;
const
axis2DModel
=
(
baseAxis
as
Axis2D
).
model
;
const
axisSort
=
coord
.
type
===
'
cartesian2d
'
&&
axis2DModel
.
get
(
'
sort
'
)
&&
axis2DModel
.
get
(
'
sortSeriesIndex
'
)
===
seriesModel
.
seriesIndex
;
const
realtimeSort
=
axisSort
&&
axis2DModel
.
get
(
'
realtimeSort
'
);
const
needsClip
=
seriesModel
.
get
(
'
clip
'
,
true
);
const
coordSysClipArea
=
getClipArea
(
coord
,
data
);
...
...
@@ -163,6 +185,8 @@ class BarView extends ChartView {
// We don't use clipPath in normal mode because we needs a perfect animation
// And don't want the label are clipped.
const
labelModel
=
seriesModel
.
getModel
(
'
label
'
);
const
roundCap
=
seriesModel
.
get
(
'
roundCap
'
,
true
);
const
drawBackground
=
seriesModel
.
get
(
'
showBackground
'
,
true
);
...
...
@@ -172,6 +196,50 @@ class BarView extends ChartView {
const
bgEls
:
BarView
[
'
_backgroundEls
'
]
=
[];
const
oldBgEls
=
this
.
_backgroundEls
;
let
hasDuringForOneData
=
false
;
let
getDuring
:
()
=>
(()
=>
void
)
=
()
=>
{
return
null
;
};
if
(
coord
.
type
===
'
cartesian2d
'
)
{
const
oldOrder
=
(
baseAxis
.
scale
as
OrdinalScale
).
getCategorySortInfo
();
const
orderMap
=
(
idx
:
number
)
=>
{
return
data
.
get
(
valueAxis
.
dim
,
idx
)
as
number
;
};
if
(
realtimeSort
)
{
// Sort in animation during
const
isOrderChanged
=
this
.
_isDataOrderChanged
(
data
,
orderMap
,
oldOrder
);
if
(
isOrderChanged
)
{
getDuring
=
()
=>
{
if
(
!
hasDuringForOneData
)
{
hasDuringForOneData
=
true
;
return
()
=>
{
const
orderMap
=
(
idx
:
number
)
=>
{
const
el
=
(
data
.
getItemGraphicEl
(
idx
)
as
Rect
);
if
(
el
)
{
const
shape
=
el
.
shape
;
return
isHorizontalOrRadial
?
shape
.
y
+
shape
.
height
:
shape
.
x
+
shape
.
width
;
}
else
{
return
0
;
}
};
that
.
_updateSort
(
data
,
orderMap
,
baseAxis
as
Axis2D
,
api
);
};
}
else
{
return
()
=>
null
;
}
};
}
}
else
if
(
axisSort
)
{
// Sort now in the first frame
this
.
_updateSort
(
data
,
orderMap
,
baseAxis
as
Axis2D
,
api
);
}
}
data
.
diff
(
oldData
)
.
add
(
function
(
dataIndex
)
{
const
itemModel
=
data
.
getItemModel
(
dataIndex
);
...
...
@@ -204,7 +272,7 @@ class BarView extends ChartView {
}
const
el
=
elementCreator
[
coord
.
type
](
dataIndex
,
layout
,
isHorizontalOrRadial
,
animationModel
,
false
,
roundCap
seriesModel
,
data
,
dataIndex
,
layout
,
isHorizontalOrRadial
,
animationModel
,
false
,
getDuring
()
,
roundCap
);
data
.
setItemGraphicEl
(
dataIndex
,
el
);
group
.
add
(
el
);
...
...
@@ -250,13 +318,52 @@ class BarView extends ChartView {
if
(
el
)
{
clearStates
(
el
);
updateProps
(
el
as
Path
,
{
shape
:
layout
},
animationModel
,
newIndex
);
if
(
coord
.
type
===
'
cartesian2d
'
&&
baseAxis
.
type
===
'
category
'
&&
(
baseAxis
as
Axis2D
).
model
.
get
(
'
sort
'
)
)
{
const
rect
=
layout
as
RectShape
;
let
seriesShape
,
axisShape
;
if
(
baseAxis
.
dim
===
'
x
'
)
{
axisShape
=
{
x
:
rect
.
x
,
width
:
rect
.
width
};
seriesShape
=
{
y
:
rect
.
y
,
height
:
rect
.
height
};
}
else
{
axisShape
=
{
y
:
rect
.
y
,
height
:
rect
.
height
};
seriesShape
=
{
x
:
rect
.
x
,
width
:
rect
.
width
};
}
if
(
!
isReorder
)
{
updateProps
(
el
as
Path
,
{
shape
:
seriesShape
},
animationModel
,
newIndex
,
null
,
getDuring
());
}
updateProps
(
el
as
Path
,
{
shape
:
axisShape
},
axisAnimationModel
,
newIndex
,
null
);
}
else
{
updateProps
(
el
as
Path
,
{
shape
:
layout
},
animationModel
,
newIndex
,
null
);
}
const
defaultTextGetter
=
(
values
:
ParsedValue
|
ParsedValue
[])
=>
{
return
getDefaultLabel
(
seriesModel
.
getData
(),
newIndex
,
values
);
};
updateLabel
(
el
,
data
,
newIndex
,
labelModel
,
seriesModel
,
animationModel
,
defaultTextGetter
);
}
else
{
el
=
elementCreator
[
coord
.
type
](
newIndex
,
layout
,
isHorizontalOrRadial
,
animationModel
,
true
,
roundCap
seriesModel
,
data
,
newIndex
,
layout
,
isHorizontalOrRadial
,
animationModel
,
true
,
getDuring
()
,
roundCap
);
}
...
...
@@ -316,7 +423,85 @@ class BarView extends ChartView {
}
}
remove
(
ecModel
?:
GlobalModel
):
void
{
_dataSort
(
data
:
List
<
BarSeriesModel
,
DefaultDataVisual
>
,
map
:
((
idx
:
number
)
=>
number
)
):
OrdinalSortInfo
[]
{
type
SortValueInfo
=
{
mappedValue
:
number
,
ordinalNumber
:
OrdinalNumber
,
beforeSortIndex
:
number
};
const
info
:
SortValueInfo
[]
=
[];
data
.
each
(
idx
=>
{
info
.
push
({
mappedValue
:
map
(
idx
),
ordinalNumber
:
idx
,
beforeSortIndex
:
null
});
});
info
.
sort
((
a
,
b
)
=>
{
return
b
.
mappedValue
-
a
.
mappedValue
;
});
// Update beforeSortIndex
for
(
let
i
=
0
;
i
<
info
.
length
;
++
i
)
{
info
[
info
[
i
].
ordinalNumber
].
beforeSortIndex
=
i
;
}
return
zrUtil
.
map
(
info
,
item
=>
{
return
{
ordinalNumber
:
item
.
ordinalNumber
,
beforeSortIndex
:
item
.
beforeSortIndex
};
});
}
_isDataOrderChanged
(
data
:
List
<
BarSeriesModel
,
DefaultDataVisual
>
,
orderMap
:
((
idx
:
number
)
=>
number
),
oldOrder
:
OrdinalSortInfo
[]
):
boolean
{
const
oldCount
=
oldOrder
?
oldOrder
.
length
:
0
;
if
(
oldCount
!==
data
.
count
())
{
return
true
;
}
let
lastValue
=
Number
.
MAX_VALUE
;
for
(
let
i
=
0
;
i
<
oldOrder
.
length
;
++
i
)
{
const
value
=
orderMap
(
oldOrder
[
i
].
ordinalNumber
);
if
(
value
>
lastValue
)
{
return
true
;
}
lastValue
=
value
;
}
return
false
;
}
_updateSort
(
data
:
List
<
BarSeriesModel
,
DefaultDataVisual
>
,
orderMap
:
((
idx
:
number
)
=>
number
),
baseAxis
:
Axis2D
,
api
:
ExtensionAPI
)
{
const
oldOrder
=
(
baseAxis
.
scale
as
OrdinalScale
).
getCategorySortInfo
();
const
isOrderChanged
=
this
.
_isDataOrderChanged
(
data
,
orderMap
,
oldOrder
);
if
(
isOrderChanged
)
{
// re-sort and update in axis
const
sortInfo
=
this
.
_dataSort
(
data
,
orderMap
);
baseAxis
.
setCategorySortInfo
(
sortInfo
);
const
action
=
{
type
:
'
changeAxisOrder
'
,
componentType
:
baseAxis
.
dim
+
'
Axis
'
,
axisId
:
baseAxis
.
index
}
as
Payload
;
api
.
dispatchAction
(
action
);
}
}
remove
(
ecModel
?:
GlobalModel
)
{
this
.
_clear
(
ecModel
);
}
...
...
@@ -399,8 +584,10 @@ const clip: {
interface
ElementCreator
{
(
dataIndex
:
number
,
layout
:
RectLayout
|
SectorLayout
,
isHorizontalOrRadial
:
boolean
,
animationModel
:
BarSeriesModel
,
isUpdate
:
boolean
,
roundCap
?:
boolean
seriesModel
:
BarSeriesModel
,
data
:
List
,
newIndex
:
number
,
layout
:
RectLayout
|
SectorLayout
,
isHorizontalOrRadial
:
boolean
,
animationModel
:
BarSeriesModel
,
isUpdate
:
boolean
,
during
:
()
=>
void
,
roundCap
?:
boolean
):
BarPossiblePath
}
...
...
@@ -409,8 +596,8 @@ const elementCreator: {
}
=
{
cartesian2d
(
data
Index
,
layout
:
RectLayout
,
isHorizontal
,
animationModel
,
isUpdate
seriesModel
,
data
,
new
Index
,
layout
:
RectLayout
,
isHorizontal
,
animationModel
,
isUpdate
,
during
)
{
const
rect
=
new
Rect
({
shape
:
zrUtil
.
extend
({},
layout
),
...
...
@@ -427,17 +614,25 @@ const elementCreator: {
const
animateTarget
=
{}
as
RectShape
;
rectShape
[
animateProperty
]
=
0
;
animateTarget
[
animateProperty
]
=
layout
[
animateProperty
];
(
isUpdate
?
updateProps
:
initProps
)(
rect
,
{
shape
:
animateTarget
},
animationModel
,
dataIndex
);
},
animationModel
,
newIndex
,
null
,
during
);
const
defaultTextGetter
=
(
values
:
ParsedValue
|
ParsedValue
[])
=>
{
return
getDefaultLabel
(
seriesModel
.
getData
(),
newIndex
,
values
);
};
const
labelModel
=
seriesModel
.
getModel
(
'
label
'
);
(
isUpdate
?
updateLabel
:
initLabel
)(
rect
,
data
,
newIndex
,
labelModel
,
seriesModel
,
animationModel
,
defaultTextGetter
);
}
return
rect
;
},
polar
(
dataIndex
:
number
,
layout
:
SectorLayout
,
isRadial
:
boolean
,
animationModel
,
isUpdate
,
roundCap
seriesModel
,
data
,
newIndex
,
layout
:
SectorLayout
,
isRadial
:
boolean
,
animationModel
,
isUpdate
,
during
,
roundCap
)
{
// Keep the same logic with bar in catesion: use end value to control
// direction. Notice that if clockwise is true (by default), the sector
...
...
@@ -462,8 +657,9 @@ const elementCreator: {
sectorShape
[
animateProperty
]
=
isRadial
?
0
:
layout
.
startAngle
;
animateTarget
[
animateProperty
]
=
layout
[
animateProperty
];
(
isUpdate
?
updateProps
:
initProps
)(
sector
,
{
shape
:
animateTarget
},
animationModel
,
dataIndex
);
shape
:
animateTarget
,
// __value: typeof dataValue === 'string' ? parseInt(dataValue, 10) : dataValue
},
animationModel
);
}
return
sector
;
...
...
src/chart/helper/labelHelper.ts
浏览文件 @
79fbcb92
...
...
@@ -20,22 +20,31 @@
import
{
retrieveRawValue
}
from
'
../../data/helper/dataProvider
'
;
import
List
from
'
../../data/List
'
;
import
{
ParsedValue
}
from
'
../../util/types
'
;
/**
* @return label string. Not null/undefined
*/
export
function
getDefaultLabel
(
data
:
List
,
dataIndex
:
number
):
string
{
export
function
getDefaultLabel
(
data
:
List
,
dataIndex
:
number
,
interpolatedValues
?:
ParsedValue
|
ParsedValue
[]
):
string
{
const
labelDims
=
data
.
mapDimensionsAll
(
'
defaultedLabel
'
);
const
len
=
labelDims
.
length
;
// Simple optimization (in lots of cases, label dims length is 1)
if
(
len
===
1
)
{
return
retrieveRawValue
(
data
,
dataIndex
,
labelDims
[
0
]);
return
interpolatedValues
==
null
?
retrieveRawValue
(
data
,
dataIndex
,
labelDims
[
0
])
:
interpolatedValues
;
}
else
if
(
len
)
{
const
vals
=
[];
for
(
let
i
=
0
;
i
<
labelDims
.
length
;
i
++
)
{
const
val
=
retrieveRawValue
(
data
,
dataIndex
,
labelDims
[
i
]);
const
val
=
interpolatedValues
==
null
?
retrieveRawValue
(
data
,
dataIndex
,
labelDims
[
i
])
:
interpolatedValues
;
vals
.
push
(
val
);
}
return
vals
.
join
(
'
'
);
...
...
src/coord/Axis.ts
浏览文件 @
79fbcb92
...
...
@@ -178,7 +178,7 @@ class Axis {
const
ticksCoords
=
map
(
ticks
,
function
(
tickValue
)
{
return
{
coord
:
this
.
dataToCoord
(
tickValue
),
tickValue
:
tickValue
tickValue
:
t
his
.
scale
instanceof
OrdinalScale
?
this
.
scale
.
getCategoryIndex
(
tickValue
)
:
t
ickValue
};
},
this
);
...
...
src/coord/cartesian/Axis2D.ts
浏览文件 @
79fbcb92
...
...
@@ -18,11 +18,12 @@
*/
import
Axis
from
'
../Axis
'
;
import
{
DimensionName
}
from
'
../../util/types
'
;
import
{
DimensionName
,
OrdinalSortInfo
}
from
'
../../util/types
'
;
import
Scale
from
'
../../scale/Scale
'
;
import
CartesianAxisModel
,
{
CartesianAxisPosition
}
from
'
./AxisModel
'
;
import
Grid
from
'
./Grid
'
;
import
{
OptionAxisType
}
from
'
../axisCommonTypes
'
;
import
OrdinalScale
from
'
../../scale/Ordinal
'
;
interface
Axis2D
{
...
...
@@ -110,6 +111,18 @@ class Axis2D extends Axis {
return
this
.
coordToData
(
this
.
toLocalCoord
(
point
[
this
.
dim
===
'
x
'
?
0
:
1
]),
clamp
);
}
/**
* Set ordinalSortInfo
* @param info new OrdinalSortInfo
*/
setCategorySortInfo
(
info
:
OrdinalSortInfo
[]):
boolean
{
if
(
this
.
type
!==
'
category
'
)
{
return
false
;
}
this
.
model
.
option
.
categorySortInfo
=
info
;
(
this
.
scale
as
OrdinalScale
).
setCategorySortInfo
(
info
);
}
}
...
...
src/coord/cartesian/AxisModel.ts
浏览文件 @
79fbcb92
...
...
@@ -25,6 +25,7 @@ import Axis2D from './Axis2D';
import
{
AxisBaseOption
}
from
'
../axisCommonTypes
'
;
import
GridModel
from
'
./GridModel
'
;
import
{
AxisBaseModel
}
from
'
../AxisBaseModel
'
;
import
{
OrdinalSortInfo
}
from
'
../../util/types
'
;
export
type
CartesianAxisPosition
=
'
top
'
|
'
bottom
'
|
'
left
'
|
'
right
'
;
...
...
@@ -35,6 +36,10 @@ interface CartesianAxisOption extends AxisBaseOption {
position
?:
CartesianAxisPosition
;
// Offset is for multiple axis on the same position.
offset
?:
number
;
sort
?:
boolean
;
realtimeSort
?:
boolean
;
sortSeriesIndex
?:
number
;
categorySortInfo
?:
OrdinalSortInfo
[];
}
class
CartesianAxisModel
extends
ComponentModel
<
CartesianAxisOption
>
...
...
@@ -61,7 +66,11 @@ zrUtil.mixin(CartesianAxisModel, AxisModelCommonMixin);
const
extraOption
:
CartesianAxisOption
=
{
// gridIndex: 0,
// gridId: '',
offset
:
0
offset
:
0
,
sort
:
false
,
realtimeSort
:
false
,
sortSeriesIndex
:
null
,
categorySortInfo
:
[]
};
axisModelCreator
<
CartesianAxisOption
,
typeof
CartesianAxisModel
>
(
'
x
'
,
CartesianAxisModel
,
extraOption
);
...
...
src/coord/cartesian/Grid.ts
浏览文件 @
79fbcb92
...
...
@@ -47,6 +47,7 @@ import { Dictionary } from 'zrender/src/core/types';
import
{
CoordinateSystemMaster
}
from
'
../CoordinateSystem
'
;
import
{
ScaleDataValue
}
from
'
../../util/types
'
;
import
List
from
'
../../data/List
'
;
import
OrdinalScale
from
'
../../scale/Ordinal
'
;
import
{
isCartesian2DSeries
,
findAxisModels
}
from
'
./cartesianAxisHelper
'
;
...
...
@@ -407,10 +408,19 @@ class Grid implements CoordinateSystemMaster {
* Update cartesian properties from series.
*/
private
_updateScale
(
ecModel
:
GlobalModel
,
gridModel
:
GridModel
):
void
{
const
sortedDataValue
:
number
[]
=
[];
const
sortedDataIndex
:
number
[]
=
[];
let
hasCategoryIndices
=
false
;
// Reset scale
each
(
this
.
_axesList
,
function
(
axis
)
{
axis
.
scale
.
setExtent
(
Infinity
,
-
Infinity
);
if
(
axis
.
type
===
'
category
'
)
{
const
categorySortInfo
=
axis
.
model
.
get
(
'
categorySortInfo
'
);
(
axis
.
scale
as
OrdinalScale
).
setCategorySortInfo
(
categorySortInfo
);
}
});
ecModel
.
eachSeries
(
function
(
seriesModel
)
{
if
(
isCartesian2DSeries
(
seriesModel
))
{
const
axesModelMap
=
findAxisModels
(
seriesModel
);
...
...
src/model/mixin/dataFormat.ts
浏览文件 @
79fbcb92
...
...
@@ -17,11 +17,12 @@
* under the License.
*/
import
*
as
zrUtil
from
'
zrender/src/core/util
'
;
import
Element
from
'
zrender/src/Element
'
;
import
{
retrieveRawValue
}
from
'
../../data/helper/dataProvider
'
;
import
{
formatTpl
}
from
'
../../util/format
'
;
import
{
DataHost
,
DisplayState
,
TooltipRenderMode
,
CallbackDataParams
,
ColorString
,
ZRColor
}
from
'
../../util/types
'
;
import
{
DataHost
,
DisplayState
,
TooltipRenderMode
,
CallbackDataParams
,
ColorString
,
ZRColor
,
OptionDataValue
,
ParsedValue
}
from
'
../../util/types
'
;
import
GlobalModel
from
'
../Global
'
;
import
Element
from
'
zrender/src/Element
'
;
const
DIMENSION_LABEL_REG
=
/
\{
@
(
.+
?)\}
/g
;
...
...
@@ -33,6 +34,7 @@ interface DataFormatMixin extends DataHost {
componentIndex
:
number
;
id
:
string
;
name
:
string
;
animatedValue
:
OptionDataValue
[];
}
class
DataFormatMixin
{
...
...
@@ -43,7 +45,7 @@ class DataFormatMixin {
getDataParams
(
dataIndex
:
number
,
dataType
?:
string
,
el
?:
Element
// May be used in override.
el
?:
Element
,
// May be used in override.
):
CallbackDataParams
{
const
data
=
this
.
getData
(
dataType
);
...
...
@@ -96,13 +98,20 @@ class DataFormatMixin {
status
?:
DisplayState
,
dataType
?:
string
,
dimIndex
?:
number
,
labelProp
?:
string
labelProp
?:
string
,
// interpolateValues?: ParsedValue | ParsedValue[]
extendParams
?:
Partial
<
CallbackDataParams
>
):
string
{
status
=
status
||
'
normal
'
;
const
data
=
this
.
getData
(
dataType
);
const
itemModel
=
data
.
getItemModel
(
dataIndex
);
const
params
=
this
.
getDataParams
(
dataIndex
,
dataType
);
const
params
=
this
.
getDataParams
(
dataIndex
,
dataType
,
null
);
if
(
extendParams
)
{
zrUtil
.
extend
(
params
,
extendParams
);
}
if
(
dimIndex
!=
null
&&
(
params
.
value
instanceof
Array
))
{
params
.
value
=
params
.
value
[
dimIndex
];
}
...
...
src/scale/Ordinal.ts
浏览文件 @
79fbcb92
...
...
@@ -28,7 +28,7 @@ import Scale from './Scale';
import
OrdinalMeta
from
'
../data/OrdinalMeta
'
;
import
List
from
'
../data/List
'
;
import
*
as
scaleHelper
from
'
./helper
'
;
import
{
OrdinalRawValue
,
OrdinalNumber
,
DimensionLoose
}
from
'
../util/types
'
;
import
{
OrdinalRawValue
,
OrdinalNumber
,
DimensionLoose
,
OrdinalSortInfo
}
from
'
../util/types
'
;
import
{
AxisBaseOption
}
from
'
../coord/axisCommonTypes
'
;
import
{
isArray
}
from
'
zrender/src/core/util
'
;
...
...
@@ -39,6 +39,7 @@ class OrdinalScale extends Scale {
readonly
type
=
'
ordinal
'
;
private
_ordinalMeta
:
OrdinalMeta
;
private
_categorySortInfo
:
OrdinalSortInfo
[];
constructor
(
setting
?:
{
...
...
@@ -54,6 +55,7 @@ class OrdinalScale extends Scale {
ordinalMeta
=
new
OrdinalMeta
({
categories
:
ordinalMeta
});
}
this
.
_ordinalMeta
=
ordinalMeta
;
this
.
_categorySortInfo
=
[];
this
.
_extent
=
this
.
getSetting
(
'
extent
'
)
||
[
0
,
ordinalMeta
.
categories
.
length
-
1
];
}
...
...
@@ -74,10 +76,12 @@ class OrdinalScale extends Scale {
* Normalize given rank or name to linear [0, 1]
*/
normalize
(
val
:
OrdinalRawValue
|
OrdinalNumber
):
number
{
return
scaleHelper
.
normalize
(
this
.
parse
(
val
),
this
.
_extent
);
val
=
this
.
getCategoryIndex
(
this
.
parse
(
val
));
return
scaleHelper
.
normalize
(
val
,
this
.
_extent
);
}
scale
(
val
:
number
):
OrdinalNumber
{
val
=
this
.
getCategoryIndex
(
val
);
return
Math
.
round
(
scaleHelper
.
scale
(
val
,
this
.
_extent
));
}
...
...
@@ -99,6 +103,23 @@ class OrdinalScale extends Scale {
return
;
}
setCategorySortInfo
(
info
:
OrdinalSortInfo
[]):
void
{
this
.
_categorySortInfo
=
info
;
}
getCategorySortInfo
():
OrdinalSortInfo
[]
{
return
this
.
_categorySortInfo
;
}
getCategoryIndex
(
n
:
OrdinalNumber
):
OrdinalNumber
{
if
(
this
.
_categorySortInfo
.
length
)
{
return
this
.
_categorySortInfo
[
n
].
beforeSortIndex
;
}
else
{
return
n
;
}
}
/**
* Get item on rank n
*/
...
...
src/scale/Scale.ts
浏览文件 @
79fbcb92
...
...
@@ -21,7 +21,7 @@
import
*
as
clazzUtil
from
'
../util/clazz
'
;
import
{
Dictionary
}
from
'
zrender/src/core/types
'
;
import
List
from
'
../data/List
'
;
import
{
DimensionName
,
ScaleDataValue
,
OptionDataValue
}
from
'
../util/types
'
;
import
{
DimensionName
,
ScaleDataValue
,
OptionDataValue
,
DimensionLoose
}
from
'
../util/types
'
;
import
{
ScaleRawExtentInfo
}
from
'
../coord/scaleRawExtentInfo
'
;
...
...
@@ -85,7 +85,7 @@ abstract class Scale {
/**
* Set extent from data
*/
unionExtentFromData
(
data
:
List
,
dim
:
DimensionName
):
void
{
unionExtentFromData
(
data
:
List
,
dim
:
DimensionName
|
DimensionLoose
):
void
{
this
.
unionExtent
(
data
.
getApproximateExtent
(
dim
));
}
...
...
src/util/graphic.ts
浏览文件 @
79fbcb92
...
...
@@ -46,7 +46,7 @@ import LRU from 'zrender/src/core/LRU';
import
Displayable
,
{
DisplayableProps
}
from
'
zrender/src/graphic/Displayable
'
;
import
{
PatternObject
}
from
'
zrender/src/graphic/Pattern
'
;
import
{
GradientObject
}
from
'
zrender/src/graphic/Gradient
'
;
import
Element
,
{
ElementEvent
,
ElementTextConfig
}
from
'
zrender/src/Element
'
;
import
Element
,
{
ElementEvent
,
ElementTextConfig
,
ElementProps
}
from
'
zrender/src/Element
'
;
import
Model
from
'
../model/Model
'
;
import
{
AnimationOptionMixin
,
...
...
@@ -58,7 +58,10 @@ import {
ColorString
,
DataModel
,
ECEventData
,
ZRStyleProps
ZRStyleProps
,
SeriesOption
,
ParsedValue
,
CallbackDataParams
}
from
'
./types
'
;
import
GlobalModel
from
'
../model/Global
'
;
import
{
makeInner
}
from
'
./model
'
;
...
...
@@ -72,6 +75,11 @@ import {
map
,
defaults
}
from
'
zrender/src/core/util
'
;
import
*
as
numberUtil
from
'
./number
'
;
import
SeriesModel
from
'
../model/Series
'
;
import
{
OnframeCallback
,
interpolateNumber
}
from
'
zrender/src/animation/Animator
'
;
import
List
from
'
../data/List
'
;
import
DataFormatMixin
from
'
../model/mixin/dataFormat
'
;
const
mathMax
=
Math
.
max
;
...
...
@@ -614,7 +622,8 @@ interface SetLabelStyleOpt<LDI> extends TextCommonParams {
state
:
DisplayState
,
dataType
:
string
,
labelDimIndex
:
number
,
labelProp
:
string
labelProp
:
string
,
extendParams
?:
Partial
<
CallbackDataParams
>
)
=>
string
},
labelDataIndex
?:
LDI
,
...
...
@@ -623,6 +632,33 @@ interface SetLabelStyleOpt<LDI> extends TextCommonParams {
}
function
getLabelText
<
LDI
>
(
opt
?:
SetLabelStyleOpt
<
LDI
>
,
interpolateValues
?:
ParsedValue
|
ParsedValue
[])
{
const
labelFetcher
=
opt
.
labelFetcher
;
const
labelDataIndex
=
opt
.
labelDataIndex
;
const
labelDimIndex
=
opt
.
labelDimIndex
;
const
labelProp
=
opt
.
labelProp
;
let
baseText
;
if
(
labelFetcher
)
{
baseText
=
labelFetcher
.
getFormattedLabel
(
labelDataIndex
,
'
normal
'
,
null
,
labelDimIndex
,
labelProp
,
{
value
:
interpolateValues
});
}
if
(
baseText
==
null
)
{
baseText
=
isFunction
(
opt
.
defaultText
)
?
opt
.
defaultText
(
labelDataIndex
,
opt
)
:
opt
.
defaultText
;
}
const
emphasisStyleText
=
retrieve2
(
labelFetcher
?
labelFetcher
.
getFormattedLabel
(
labelDataIndex
,
'
emphasis
'
,
null
,
labelDimIndex
,
labelProp
)
:
null
,
baseText
);
return
{
normal
:
baseText
,
emphasis
:
emphasisStyleText
};
}
/**
* Set normal styles and emphasis styles about text on target element
* If target is a ZRText. It will create a new style object.
...
...
@@ -652,26 +688,6 @@ export function setLabelStyle<LDI>(
// label should be displayed, where text is fetched by `normal.formatter` or `opt.defaultText`.
let
richText
=
isSetOnText
?
targetEl
as
ZRText
:
null
;
if
(
showNormal
||
showEmphasis
)
{
const
labelFetcher
=
opt
.
labelFetcher
;
const
labelDataIndex
=
opt
.
labelDataIndex
;
const
labelDimIndex
=
opt
.
labelDimIndex
;
const
labelProp
=
opt
.
labelProp
;
let
baseText
;
if
(
labelFetcher
)
{
baseText
=
labelFetcher
.
getFormattedLabel
(
labelDataIndex
,
'
normal
'
,
null
,
labelDimIndex
,
labelProp
);
}
if
(
baseText
==
null
)
{
baseText
=
isFunction
(
opt
.
defaultText
)
?
opt
.
defaultText
(
labelDataIndex
,
opt
)
:
opt
.
defaultText
;
}
const
normalStyleText
=
baseText
;
const
emphasisStyleText
=
retrieve2
(
labelFetcher
?
labelFetcher
.
getFormattedLabel
(
labelDataIndex
,
'
emphasis
'
,
null
,
labelDimIndex
,
labelProp
)
:
null
,
baseText
);
if
(
!
isSetOnText
)
{
// Reuse the previous
richText
=
targetEl
.
getTextContent
();
...
...
@@ -728,8 +744,9 @@ export function setLabelStyle<LDI>(
// auto slient is those cases.
richText
.
silent
=
!!
normalModel
.
getShallow
(
'
silent
'
);
normalStyle
.
text
=
normalStyleText
;
emphasisState
.
style
.
text
=
emphasisStyleText
;
const
labelText
=
getLabelText
(
opt
);
normalStyle
.
text
=
labelText
.
normal
;
emphasisState
.
style
.
text
=
labelText
.
emphasis
;
// Keep x and y
if
(
richText
.
style
.
x
!=
null
)
{
...
...
@@ -1056,9 +1073,11 @@ function animateOrSetProps<Props>(
getAnimationDelayParams
?:
(
el
:
Element
<
Props
>
,
dataIndex
:
number
)
=>
AnimationDelayCallbackParam
},
dataIndex
?:
number
|
(()
=>
void
),
cb
?:
()
=>
void
cb
?:
()
=>
void
,
during
?:
(
percent
:
number
)
=>
void
)
{
if
(
typeof
dataIndex
===
'
function
'
)
{
during
=
cb
;
cb
=
dataIndex
;
dataIndex
=
null
;
}
...
...
@@ -1095,7 +1114,8 @@ function animateOrSetProps<Props>(
delay
:
animationDelay
||
0
,
easing
:
animationEasing
,
done
:
cb
,
force
:
!!
cb
force
:
!!
cb
||
!!
during
,
during
:
during
})
:
(
el
.
stopAnimation
(),
el
.
attr
(
props
),
cb
&&
cb
());
}
...
...
@@ -1128,9 +1148,10 @@ function updateProps<Props>(
// TODO: TYPE AnimatableModel
animatableModel
?:
Model
<
AnimationOptionMixin
>
,
dataIndex
?:
number
|
(()
=>
void
),
cb
?:
()
=>
void
cb
?:
()
=>
void
,
during
?:
()
=>
void
)
{
animateOrSetProps
(
true
,
el
,
props
,
animatableModel
,
dataIndex
,
cb
);
animateOrSetProps
(
true
,
el
,
props
,
animatableModel
,
dataIndex
,
cb
,
during
);
}
export
{
updateProps
};
...
...
@@ -1148,9 +1169,107 @@ export function initProps<Props>(
props
:
Props
,
animatableModel
?:
Model
<
AnimationOptionMixin
>
,
dataIndex
?:
number
|
(()
=>
void
),
cb
?:
()
=>
void
cb
?:
()
=>
void
,
during
?:
()
=>
void
)
{
animateOrSetProps
(
false
,
el
,
props
,
animatableModel
,
dataIndex
,
cb
,
during
);
}
function
animateOrSetLabel
<
Props
extends
PathProps
>
(
isUpdate
:
boolean
,
el
:
Element
<
Props
>
,
data
:
List
,
dataIndex
:
number
,
labelModel
:
Model
<
LabelOption
>
,
seriesModel
:
SeriesModel
,
animatableModel
?:
Model
<
AnimationOptionMixin
>
,
defaultTextGetter
?:
(
value
:
ParsedValue
[]
|
ParsedValue
)
=>
string
)
{
const
element
=
el
as
Element
<
Props
>
&
{
__value
:
ParsedValue
[]
|
ParsedValue
};
const
valueAnimationEnabled
=
labelModel
&&
labelModel
.
get
(
'
valueAnimation
'
);
if
(
valueAnimationEnabled
)
{
const
precisionOption
=
labelModel
.
get
(
'
precision
'
);
let
precision
:
number
=
precisionOption
===
'
auto
'
?
0
:
precisionOption
;
let
interpolateValues
:
(
number
|
string
)[]
|
(
number
|
string
);
const
rawValues
=
seriesModel
.
getRawValue
(
dataIndex
);
let
isRawValueNumber
=
false
;
if
(
typeof
rawValues
===
'
number
'
)
{
isRawValueNumber
=
true
;
interpolateValues
=
rawValues
;
}
else
{
interpolateValues
=
[];
for
(
let
i
=
0
;
i
<
(
rawValues
as
[]).
length
;
++
i
)
{
const
info
=
data
.
getDimensionInfo
(
i
);
if
(
info
.
type
!==
'
ordinal
'
)
{
interpolateValues
.
push
((
rawValues
as
[])[
i
]);
}
}
}
const
during
=
(
percent
:
number
)
=>
{
let
interpolated
;
if
(
isRawValueNumber
)
{
const
value
=
interpolateNumber
(
0
,
interpolateValues
as
number
,
percent
);
interpolated
=
numberUtil
.
round
(
value
,
precision
);
}
else
{
interpolated
=
[];
for
(
let
i
=
0
,
j
=
0
;
i
<
(
rawValues
as
[]).
length
;
++
i
)
{
const
info
=
data
.
getDimensionInfo
(
i
);
// Don't interpolate ordinal dims
if
(
info
.
type
===
'
ordinal
'
)
{
interpolated
[
i
]
=
(
rawValues
as
[])[
i
];
}
else
{
const
value
=
interpolateNumber
(
0
,
(
interpolateValues
as
number
[])[
i
],
percent
);
interpolated
[
i
]
=
numberUtil
.
round
(
value
),
precision
;
++
j
;
}
}
}
const
text
=
el
.
getTextContent
();
if
(
text
)
{
const
labelText
=
getLabelText
({
labelDataIndex
:
dataIndex
,
labelFetcher
:
seriesModel
,
defaultText
:
defaultTextGetter
?
defaultTextGetter
(
interpolated
)
:
interpolated
+
''
},
interpolated
);
text
.
style
.
text
=
labelText
.
normal
;
text
.
dirty
();
}
};
const
props
:
ElementProps
=
{};
animateOrSetProps
(
isUpdate
,
el
,
props
,
animatableModel
,
dataIndex
,
null
,
during
);
}
}
export
function
updateLabel
<
Props
>
(
el
:
Element
<
Props
>
,
data
:
List
,
dataIndex
:
number
,
labelModel
:
Model
<
LabelOption
>
,
seriesModel
:
SeriesModel
,
animatableModel
?:
Model
<
AnimationOptionMixin
>
,
defaultTextGetter
?:
(
value
:
ParsedValue
[]
|
ParsedValue
)
=>
string
)
{
animateOrSetLabel
(
true
,
el
,
data
,
dataIndex
,
labelModel
,
seriesModel
,
animatableModel
,
defaultTextGetter
);
}
export
function
initLabel
<
Props
>
(
el
:
Element
<
Props
>
,
data
:
List
,
dataIndex
:
number
,
labelModel
:
Model
<
LabelOption
>
,
seriesModel
:
SeriesModel
,
animatableModel
?:
Model
<
AnimationOptionMixin
>
,
defaultTextGetter
?:
(
value
:
ParsedValue
[]
|
ParsedValue
)
=>
string
)
{
animateOrSet
Props
(
false
,
el
,
props
,
animatableModel
,
dataIndex
,
cb
);
animateOrSet
Label
(
false
,
el
,
data
,
dataIndex
,
labelModel
,
seriesModel
,
animatableModel
,
defaultTextGetter
);
}
/**
...
...
src/util/types.ts
浏览文件 @
79fbcb92
...
...
@@ -242,6 +242,10 @@ export type TooltipRenderMode = 'html' | 'richText';
// Check `convertDataValue` for more details.
export
type
OrdinalRawValue
=
string
|
number
;
export
type
OrdinalNumber
=
number
;
// The number mapped from each OrdinalRawValue.
export
type
OrdinalSortInfo
=
{
ordinalNumber
:
OrdinalNumber
,
beforeSortIndex
:
number
};
export
type
ParsedValueNumeric
=
number
|
OrdinalNumber
;
export
type
ParsedValue
=
ParsedValueNumeric
|
OrdinalRawValue
;
// FIXME:TS better name?
...
...
@@ -762,6 +766,8 @@ export interface LabelOption extends TextCommonOption {
overflow
?:
TextStyleProps
[
'
overflow
'
]
silent
?:
boolean
precision
?:
number
|
'
auto
'
valueAnimation
?:
boolean
// TODO: TYPE not all label support formatter
// formatter?: string | ((params: CallbackDataParams) => string)
...
...
test/bar-race.html
0 → 100644
浏览文件 @
79fbcb92
此差异已折叠。
点击以展开。
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录