Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
x649585723
incubator-echarts
提交
e1fcc3db
I
incubator-echarts
项目概览
x649585723
/
incubator-echarts
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
I
incubator-echarts
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
e1fcc3db
编写于
10月 09, 2020
作者:
O
Ovilia
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat(decal): move decal logic to zrender
上级
64db4f5f
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
18 addition
and
293 deletion
+18
-293
src/model/mixin/makeStyleMapper.ts
src/model/mixin/makeStyleMapper.ts
+0
-5
src/util/decal.ts
src/util/decal.ts
+0
-285
test/decal.html
test/decal.html
+18
-3
未找到文件。
src/model/mixin/makeStyleMapper.ts
浏览文件 @
e1fcc3db
...
...
@@ -23,7 +23,6 @@ import * as zrUtil from 'zrender/src/core/util';
import
{
Dictionary
}
from
'
zrender/src/core/types
'
;
import
{
PathStyleProps
}
from
'
zrender/src/graphic/Path
'
;
import
Model
from
'
../Model
'
;
import
{
createOrUpdatePatternFromDecal
}
from
'
../../util/decal
'
;
export
default
function
(
properties
:
readonly
string
[][],
ignoreParent
?:
boolean
)
{
// Normalize
...
...
@@ -50,10 +49,6 @@ export default function (properties: readonly string[][], ignoreParent?: boolean
}
}
if
(
style
.
decal
)
{
createOrUpdatePatternFromDecal
(
style
.
decal
);
}
// TODO Text or image?
return
style
as
PathStyleProps
;
};
...
...
src/util/decal.ts
已删除
100644 → 0
浏览文件 @
64db4f5f
import
{
DecalObject
,
DecalDashArrayX
,
DecalDashArrayY
}
from
'
zrender/src/graphic/Decal
'
;
import
Pattern
,
{
PatternObject
}
from
'
zrender/src/graphic/Pattern
'
;
import
{
defaults
,
createCanvas
,
map
}
from
'
zrender/src/core/util
'
;
import
{
getLeastCommonMultiple
}
from
'
./number
'
;
/**
* Create or update pattern image from decal options
*
* @param {DecalObject} decalObject decal options
* @return {Pattern} pattern with generated image
*/
export
function
createOrUpdatePatternFromDecal
(
decalObject
:
DecalObject
):
PatternObject
{
if
(
decalObject
.
__pattern
)
{
return
decalObject
.
__pattern
;
}
const
decalOpt
=
defaults
({
shape
:
'
rect
'
,
symbolSize
:
1
,
symbolKeepAspect
:
true
,
color
:
'
rgba(255, 255, 255, 0.4)
'
,
backgroundColor
:
null
,
dashArrayX
:
10
,
dashArrayY
:
10
,
dashLineOffset
:
0
,
rotation
:
Math
.
PI
/
4
,
maxTileWidth
:
512
,
maxTileHeight
:
512
}
as
DecalObject
,
decalObject
);
if
(
decalOpt
.
backgroundColor
===
'
none
'
)
{
decalOpt
.
backgroundColor
=
null
;
}
const
dashArrayX
=
normalizeDashArrayX
(
decalOpt
.
dashArrayX
);
const
dashArrayY
=
normalizeDashArrayY
(
decalOpt
.
dashArrayY
);
const
lineBlockLengthsX
=
getLineBlockLengthX
(
dashArrayX
);
const
lineBlockLengthY
=
getLineBlockLengthY
(
dashArrayY
);
const
canvas
=
createCanvas
();
const
pSize
=
getPatternSize
();
canvas
.
width
=
pSize
.
width
;
canvas
.
height
=
pSize
.
height
;
canvas
.
style
.
width
=
canvas
.
width
+
'
px
'
;
canvas
.
style
.
height
=
canvas
.
height
+
'
px
'
;
const
ctx
=
canvas
.
getContext
(
'
2d
'
);
brush
();
const
base64
=
canvas
.
toDataURL
();
const
pattern
=
new
Pattern
(
base64
,
'
repeat
'
,
decalOpt
.
rotation
);
decalObject
.
__pattern
=
pattern
;
decalObject
.
dirty
=
function
()
{
console
.
log
(
'
dirty
'
);
};
return
pattern
;
/**
* Get minumum length that can make a repeatable pattern.
*
* @return {Object} pattern width and height
*/
function
getPatternSize
()
:
{
width
:
number
,
height
:
number
,
lines
:
number
}
{
/**
* For example, if dash is [[3, 2], [2, 1]] for X, it looks like
* |--- --- --- --- --- ...
* |-- -- -- -- -- -- -- -- ...
* |--- --- --- --- --- ...
* |-- -- -- -- -- -- -- -- ...
* So the minumum length of X is 15,
* which is the least common multiple of `3 + 2` and `2 + 1`
* |--- --- --- |--- --- ...
* |-- -- -- -- -- |-- -- -- ...
*
* When consider with dashLineOffset, it means the `n`th line has the offset
* of `n * dashLineOffset`.
* For example, if dash is [[3, 1], [1, 1]] and dashLineOffset is 3,
* and use `=` for the start to make it clear, it looks like
* |=-- --- --- --- --- -...
* | - = - - - - - - - - ...
* |- --- =-- --- --- -- ...
* | - - - - = - - - - - ...
* |--- --- --- =-- --- -...
* | - - - - - - - = - - ...
* In this case, the minumum length is 12, which is the least common
* multiple of `3 + 1`, `1 + 1` and `3 * 2` where `2` is xlen
* |=-- --- --- |--- --- -...
* | - = - - - -| - - - - ...
* |- --- =-- --|- --- -- ...
* | - - - - = -| - - - - ...
*/
const
offsetMultipleX
=
decalOpt
.
dashLineOffset
||
1
;
let
width
=
1
;
for
(
let
i
=
0
,
xlen
=
lineBlockLengthsX
.
length
;
i
<
xlen
;
++
i
)
{
const
x
=
getLeastCommonMultiple
(
offsetMultipleX
*
xlen
,
lineBlockLengthsX
[
i
]);
width
=
getLeastCommonMultiple
(
width
,
x
);
}
const
columns
=
decalOpt
.
dashLineOffset
?
width
/
offsetMultipleX
:
2
;
let
height
=
lineBlockLengthY
*
columns
;
return
{
width
:
Math
.
max
(
1
,
Math
.
min
(
width
,
decalOpt
.
maxTileWidth
)),
height
:
Math
.
max
(
1
,
Math
.
min
(
height
,
decalOpt
.
maxTileHeight
)),
lines
:
columns
};
}
function
fixStartPosition
(
lineOffset
:
number
,
blockLength
:
number
)
{
let
start
=
lineOffset
||
0
;
while
(
start
>
0
)
{
start
-=
blockLength
;
}
return
start
;
}
function
brush
()
{
ctx
.
clearRect
(
0
,
0
,
pSize
.
width
,
pSize
.
height
);
if
(
decalOpt
.
backgroundColor
)
{
ctx
.
fillStyle
=
decalOpt
.
backgroundColor
;
ctx
.
fillRect
(
0
,
0
,
pSize
.
width
,
pSize
.
height
);
}
ctx
.
fillStyle
=
decalOpt
.
color
;
let
yCnt
=
0
;
let
y
=
-
pSize
.
lines
*
lineBlockLengthY
;
let
yId
=
0
;
let
xId0
=
0
;
while
(
y
<
pSize
.
height
)
{
if
(
yId
%
2
===
0
)
{
let
x
=
fixStartPosition
(
decalOpt
.
dashLineOffset
*
(
yCnt
-
pSize
.
lines
)
/
2
,
lineBlockLengthsX
[
0
]
);
let
xId1
=
0
;
while
(
x
<
pSize
.
width
*
2
)
{
if
(
xId1
%
2
===
0
)
{
// E.g., [15, 5, 20, 5] draws only for 15 and 20
// brushShape(x, y, dashArrayX[xId0][xId1], dashArrayY[yId]);
ctx
.
fillRect
(
x
,
y
,
dashArrayX
[
xId0
][
xId1
],
dashArrayY
[
yId
]);
}
x
+=
dashArrayX
[
xId0
][
xId1
];
++
xId1
;
if
(
xId1
===
dashArrayX
[
xId0
].
length
)
{
xId1
=
0
;
}
}
++
xId0
;
if
(
xId0
===
dashArrayX
.
length
)
{
xId0
=
0
;
}
}
++
yCnt
;
y
+=
dashArrayY
[
yId
];
++
yId
;
if
(
yId
===
dashArrayY
.
length
)
{
yId
=
0
;
}
}
console
.
log
(
ctx
.
canvas
.
toDataURL
())
// ctx.strokeStyle = 'red';
// ctx.strokeRect(0, 0, pSize.width, pSize.height);
}
function
brushShape
(
x
:
number
,
y
:
number
,
width
:
number
,
height
:
number
)
{
if
(
decalOpt
.
image
)
{
return
;
}
// switch (decalOpt.shape) {
// case ''
// }
}
}
/**
* Convert dash input into dashArray
*
* @param {DecalDashArrayX} dash dash input
* @return {number[][]} normolized dash array
*/
function
normalizeDashArrayX
(
dash
:
DecalDashArrayX
):
number
[][]
{
if
(
!
dash
||
typeof
dash
===
'
object
'
&&
dash
.
length
===
0
)
{
return
[[
0
,
0
]];
}
if
(
typeof
dash
===
'
number
'
)
{
return
[[
dash
,
dash
]];
}
/**
* [20, 5] should be normalized into [[20, 5]],
* while [20, [5, 10]] should be normalized into [[20, 20], [5, 10]]
*/
let
isAllNumber
=
true
;
for
(
let
i
=
0
;
i
<
dash
.
length
;
++
i
)
{
if
(
typeof
dash
[
i
]
!==
'
number
'
)
{
isAllNumber
=
false
;
break
;
}
}
if
(
isAllNumber
)
{
return
normalizeDashArrayX
([
dash
as
number
[]]);
}
const
result
:
number
[][]
=
[];
for
(
let
i
=
0
;
i
<
dash
.
length
;
++
i
)
{
if
(
typeof
dash
[
i
]
===
'
number
'
)
{
result
.
push
([
dash
[
i
]
as
number
,
dash
[
i
]
as
number
]);
}
else
if
((
dash
[
i
]
as
number
[]).
length
%
2
===
1
)
{
// [4, 2, 1] means |---- - -- |---- - -- |
// so normalize it to be [4, 2, 1, 4, 2, 1]
result
.
push
((
dash
[
i
]
as
number
[]).
concat
(
dash
[
i
]));
}
else
{
result
.
push
((
dash
[
i
]
as
number
[]).
slice
());
}
}
return
result
;
}
/**
* Convert dash input into dashArray
*
* @param {DecalDashArrayY} dash dash input
* @return {number[]} normolized dash array
*/
function
normalizeDashArrayY
(
dash
:
DecalDashArrayY
):
number
[]
{
if
(
!
dash
||
typeof
dash
===
'
object
'
&&
dash
.
length
===
0
)
{
return
[
0
,
0
];
}
if
(
typeof
dash
===
'
number
'
)
{
return
[
dash
,
dash
];
}
return
dash
.
length
%
2
?
dash
.
concat
(
dash
)
:
dash
.
slice
();
}
/**
* Get block length of each line. A block is the length of dash line and space.
* For example, a line with [4, 1] has a dash line of 4 and a space of 1 after
* that, so the block length of this line is 5.
*
* @param {number[][]} dash dash arrary of X or Y
* @return {number[]} block length of each line
*/
function
getLineBlockLengthX
(
dash
:
number
[][]):
number
[]
{
return
map
(
dash
,
function
(
line
)
{
return
getLineBlockLengthY
(
line
);
});
}
function
getLineBlockLengthY
(
dash
:
number
[]):
number
{
let
blockLength
=
0
;
for
(
let
i
=
0
;
i
<
dash
.
length
;
++
i
)
{
blockLength
+=
dash
[
i
];
}
if
(
dash
.
length
%
2
===
1
)
{
// [4, 2, 1] means |---- - -- |---- - -- |
// So total length is (4 + 2 + 1) * 2
return
blockLength
*
2
;
}
return
blockLength
;
}
test/decal.html
浏览文件 @
e1fcc3db
...
...
@@ -52,6 +52,9 @@ under the License.
var
option
;
option
=
{
legend
:
{
data
:
[
'
a
'
,
'
b
'
]
},
xAxis
:
{
type
:
'
category
'
,
data
:
[
'
Mon
'
,
'
Tue
'
,
'
Wed
'
,
'
Thu
'
,
'
Fri
'
,
'
Sat
'
,
'
Sun
'
]
...
...
@@ -60,20 +63,32 @@ under the License.
type
:
'
value
'
},
series
:
[{
name
:
'
a
'
,
data
:
[
120
,
200
,
150
,
80
,
70
,
110
,
130
],
type
:
'
bar
'
,
itemStyle
:
{
decal
:
{
}
}
},
{
name
:
'
b
'
,
data
:
[
120
,
200
,
150
,
80
,
70
,
110
,
130
],
type
:
'
bar
'
,
itemStyle
:
{
decal
:
{
}
}
}]
}],
grid
:
{
left
:
50
,
right
:
'
40%
'
}
};
var
chart
=
testHelper
.
create
(
echarts
,
'
main0
'
,
{
title
:
[
'
Test Case Description of main0
'
,
'
(Muliple lines and **emphasis** are supported in description)
'
'
Default decals for different series
'
],
option
:
option
// height: 300,
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录