Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
wzj-java
uni-app
提交
3cf3ae3c
U
uni-app
项目概览
wzj-java
/
uni-app
与 Fork 源项目一致
Fork自
DCloud / uni-app
通知
1
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
1
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
U
uni-app
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
1
Issue
1
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
3cf3ae3c
编写于
12月 13, 2018
作者:
郭
郭胜强
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat: 实现基础组件:canvas 和相关接口:uni.createCanvasContext
上级
371d6c75
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
899 addition
and
8 deletion
+899
-8
src/core/service/api/context/canvas.js
src/core/service/api/context/canvas.js
+561
-0
src/core/view/components/canvas/index.vue
src/core/view/components/canvas/index.vue
+331
-2
src/core/view/mixins/subscriber.js
src/core/view/mixins/subscriber.js
+7
-6
未找到文件。
src/core/service/api/context/canvas.js
0 → 100644
浏览文件 @
3cf3ae3c
import
createCallbacks
from
'
uni-helpers/callbacks
'
const
canvasEventCallbacks
=
createCallbacks
(
'
canvasEvent
'
)
UniServiceJSBridge
.
subscribe
(
'
onDrawCanvas
'
,
({
reqId
,
res
})
=>
{
const
callback
=
canvasEventCallbacks
.
pop
(
reqId
)
if
(
callback
)
{
callback
(
res
)
}
})
function
operateCanvas
(
canvasId
,
pageId
,
type
,
data
)
{
UniServiceJSBridge
.
publishHandler
(
pageId
+
'
-canvas-
'
+
canvasId
,
{
canvasId
,
type
,
data
},
pageId
)
}
const
predefinedColor
=
{
aliceblue
:
'
#f0f8ff
'
,
antiquewhite
:
'
#faebd7
'
,
aqua
:
'
#00ffff
'
,
aquamarine
:
'
#7fffd4
'
,
azure
:
'
#f0ffff
'
,
beige
:
'
#f5f5dc
'
,
bisque
:
'
#ffe4c4
'
,
black
:
'
#000000
'
,
blanchedalmond
:
'
#ffebcd
'
,
blue
:
'
#0000ff
'
,
blueviolet
:
'
#8a2be2
'
,
brown
:
'
#a52a2a
'
,
burlywood
:
'
#deb887
'
,
cadetblue
:
'
#5f9ea0
'
,
chartreuse
:
'
#7fff00
'
,
chocolate
:
'
#d2691e
'
,
coral
:
'
#ff7f50
'
,
cornflowerblue
:
'
#6495ed
'
,
cornsilk
:
'
#fff8dc
'
,
crimson
:
'
#dc143c
'
,
cyan
:
'
#00ffff
'
,
darkblue
:
'
#00008b
'
,
darkcyan
:
'
#008b8b
'
,
darkgoldenrod
:
'
#b8860b
'
,
darkgray
:
'
#a9a9a9
'
,
darkgrey
:
'
#a9a9a9
'
,
darkgreen
:
'
#006400
'
,
darkkhaki
:
'
#bdb76b
'
,
darkmagenta
:
'
#8b008b
'
,
darkolivegreen
:
'
#556b2f
'
,
darkorange
:
'
#ff8c00
'
,
darkorchid
:
'
#9932cc
'
,
darkred
:
'
#8b0000
'
,
darksalmon
:
'
#e9967a
'
,
darkseagreen
:
'
#8fbc8f
'
,
darkslateblue
:
'
#483d8b
'
,
darkslategray
:
'
#2f4f4f
'
,
darkslategrey
:
'
#2f4f4f
'
,
darkturquoise
:
'
#00ced1
'
,
darkviolet
:
'
#9400d3
'
,
deeppink
:
'
#ff1493
'
,
deepskyblue
:
'
#00bfff
'
,
dimgray
:
'
#696969
'
,
dimgrey
:
'
#696969
'
,
dodgerblue
:
'
#1e90ff
'
,
firebrick
:
'
#b22222
'
,
floralwhite
:
'
#fffaf0
'
,
forestgreen
:
'
#228b22
'
,
fuchsia
:
'
#ff00ff
'
,
gainsboro
:
'
#dcdcdc
'
,
ghostwhite
:
'
#f8f8ff
'
,
gold
:
'
#ffd700
'
,
goldenrod
:
'
#daa520
'
,
gray
:
'
#808080
'
,
grey
:
'
#808080
'
,
green
:
'
#008000
'
,
greenyellow
:
'
#adff2f
'
,
honeydew
:
'
#f0fff0
'
,
hotpink
:
'
#ff69b4
'
,
indianred
:
'
#cd5c5c
'
,
indigo
:
'
#4b0082
'
,
ivory
:
'
#fffff0
'
,
khaki
:
'
#f0e68c
'
,
lavender
:
'
#e6e6fa
'
,
lavenderblush
:
'
#fff0f5
'
,
lawngreen
:
'
#7cfc00
'
,
lemonchiffon
:
'
#fffacd
'
,
lightblue
:
'
#add8e6
'
,
lightcoral
:
'
#f08080
'
,
lightcyan
:
'
#e0ffff
'
,
lightgoldenrodyellow
:
'
#fafad2
'
,
lightgray
:
'
#d3d3d3
'
,
lightgrey
:
'
#d3d3d3
'
,
lightgreen
:
'
#90ee90
'
,
lightpink
:
'
#ffb6c1
'
,
lightsalmon
:
'
#ffa07a
'
,
lightseagreen
:
'
#20b2aa
'
,
lightskyblue
:
'
#87cefa
'
,
lightslategray
:
'
#778899
'
,
lightslategrey
:
'
#778899
'
,
lightsteelblue
:
'
#b0c4de
'
,
lightyellow
:
'
#ffffe0
'
,
lime
:
'
#00ff00
'
,
limegreen
:
'
#32cd32
'
,
linen
:
'
#faf0e6
'
,
magenta
:
'
#ff00ff
'
,
maroon
:
'
#800000
'
,
mediumaquamarine
:
'
#66cdaa
'
,
mediumblue
:
'
#0000cd
'
,
mediumorchid
:
'
#ba55d3
'
,
mediumpurple
:
'
#9370db
'
,
mediumseagreen
:
'
#3cb371
'
,
mediumslateblue
:
'
#7b68ee
'
,
mediumspringgreen
:
'
#00fa9a
'
,
mediumturquoise
:
'
#48d1cc
'
,
mediumvioletred
:
'
#c71585
'
,
midnightblue
:
'
#191970
'
,
mintcream
:
'
#f5fffa
'
,
mistyrose
:
'
#ffe4e1
'
,
moccasin
:
'
#ffe4b5
'
,
navajowhite
:
'
#ffdead
'
,
navy
:
'
#000080
'
,
oldlace
:
'
#fdf5e6
'
,
olive
:
'
#808000
'
,
olivedrab
:
'
#6b8e23
'
,
orange
:
'
#ffa500
'
,
orangered
:
'
#ff4500
'
,
orchid
:
'
#da70d6
'
,
palegoldenrod
:
'
#eee8aa
'
,
palegreen
:
'
#98fb98
'
,
paleturquoise
:
'
#afeeee
'
,
palevioletred
:
'
#db7093
'
,
papayawhip
:
'
#ffefd5
'
,
peachpuff
:
'
#ffdab9
'
,
peru
:
'
#cd853f
'
,
pink
:
'
#ffc0cb
'
,
plum
:
'
#dda0dd
'
,
powderblue
:
'
#b0e0e6
'
,
purple
:
'
#800080
'
,
rebeccapurple
:
'
#663399
'
,
red
:
'
#ff0000
'
,
rosybrown
:
'
#bc8f8f
'
,
royalblue
:
'
#4169e1
'
,
saddlebrown
:
'
#8b4513
'
,
salmon
:
'
#fa8072
'
,
sandybrown
:
'
#f4a460
'
,
seagreen
:
'
#2e8b57
'
,
seashell
:
'
#fff5ee
'
,
sienna
:
'
#a0522d
'
,
silver
:
'
#c0c0c0
'
,
skyblue
:
'
#87ceeb
'
,
slateblue
:
'
#6a5acd
'
,
slategray
:
'
#708090
'
,
slategrey
:
'
#708090
'
,
snow
:
'
#fffafa
'
,
springgreen
:
'
#00ff7f
'
,
steelblue
:
'
#4682b4
'
,
tan
:
'
#d2b48c
'
,
teal
:
'
#008080
'
,
thistle
:
'
#d8bfd8
'
,
tomato
:
'
#ff6347
'
,
turquoise
:
'
#40e0d0
'
,
violet
:
'
#ee82ee
'
,
wheat
:
'
#f5deb3
'
,
white
:
'
#ffffff
'
,
whitesmoke
:
'
#f5f5f5
'
,
yellow
:
'
#ffff00
'
,
yellowgreen
:
'
#9acd32
'
,
transparent
:
'
#00000000
'
}
function
checkColor
(
e
)
{
var
t
=
null
if
((
t
=
/^#
([
0-9|A-F|a-f
]{6})
$/
.
exec
(
e
))
!=
null
)
{
let
n
=
parseInt
(
t
[
1
].
slice
(
0
,
2
),
16
)
let
o
=
parseInt
(
t
[
1
].
slice
(
2
,
4
),
16
)
let
r
=
parseInt
(
t
[
1
].
slice
(
4
),
16
)
return
[
n
,
o
,
r
,
255
]
}
if
((
t
=
/^#
([
0-9|A-F|a-f
]{3})
$/
.
exec
(
e
))
!=
null
)
{
let
n
=
t
[
1
].
slice
(
0
,
1
)
let
o
=
t
[
1
].
slice
(
1
,
2
)
let
r
=
t
[
1
].
slice
(
2
,
3
)
n
=
parseInt
(
n
+
n
,
16
)
o
=
parseInt
(
o
+
o
,
16
)
r
=
parseInt
(
r
+
r
,
16
)
return
[
n
,
o
,
r
,
255
]
}
if
((
t
=
/^rgb
\((
.+
)\)
$/
.
exec
(
e
))
!=
null
)
{
return
t
[
1
].
split
(
'
,
'
).
map
(
function
(
e
)
{
return
Math
.
min
(
255
,
parseInt
(
e
.
trim
()))
}).
concat
(
255
)
}
if
((
t
=
/^rgba
\((
.+
)\)
$/
.
exec
(
e
))
!=
null
)
{
return
t
[
1
].
split
(
'
,
'
).
map
(
function
(
e
,
t
)
{
return
t
===
3
?
Math
.
floor
(
255
*
parseFloat
(
e
.
trim
()))
:
Math
.
min
(
255
,
parseInt
(
e
.
trim
()))
})
}
var
i
=
e
.
toLowerCase
()
if
(
predefinedColor
.
hasOwnProperty
(
i
))
{
t
=
/^#
([
0-9|A-F|a-f
]{6,8})
$/
.
exec
(
predefinedColor
[
i
])
let
n
=
parseInt
(
t
[
1
].
slice
(
0
,
2
),
16
)
let
o
=
parseInt
(
t
[
1
].
slice
(
2
,
4
),
16
)
let
r
=
parseInt
(
t
[
1
].
slice
(
4
,
6
),
16
)
let
a
=
parseInt
(
t
[
1
].
slice
(
6
,
8
),
16
)
a
=
a
>=
0
?
a
:
255
return
[
n
,
o
,
r
,
a
]
}
console
.
group
(
'
非法颜色:
'
+
e
)
console
.
error
(
'
不支持颜色:
'
+
e
)
console
.
groupEnd
()
return
[
0
,
0
,
0
,
255
]
}
function
TextMetrics
(
width
)
{
this
.
width
=
width
}
function
Pattern
(
image
,
repetition
)
{
this
.
image
=
image
this
.
repetition
=
repetition
}
class
CanvasGradient
{
constructor
(
type
,
data
)
{
this
.
type
=
type
this
.
data
=
data
this
.
colorStop
=
[]
}
addColorStop
(
position
,
color
)
{
this
.
colorStop
.
push
([
position
,
checkColor
(
color
)])
}
}
var
methods1
=
[
'
scale
'
,
'
rotate
'
,
'
translate
'
,
'
setTransform
'
,
'
transform
'
]
var
methods2
=
[
'
drawImage
'
,
'
fillText
'
,
'
fill
'
,
'
stroke
'
,
'
fillRect
'
,
'
strokeRect
'
,
'
clearRect
'
,
'
strokeText
'
]
var
methods3
=
[
'
setFillStyle
'
,
'
setTextAlign
'
,
'
setStrokeStyle
'
,
'
setGlobalAlpha
'
,
'
setShadow
'
,
'
setFontSize
'
,
'
setLineCap
'
,
'
setLineJoin
'
,
'
setLineWidth
'
,
'
setMiterLimit
'
,
'
setTextBaseline
'
,
'
setLineDash
'
]
var
c2d
class
CanvasContext
{
constructor
(
id
,
pageId
)
{
this
.
id
=
id
this
.
pageId
=
pageId
this
.
actions
=
[]
this
.
currentTransform
=
[]
this
.
currentStepAnimates
=
[]
this
.
drawingState
=
[]
this
.
state
=
{
lineDash
:
[
0
,
0
],
shadowOffsetX
:
0
,
shadowOffsetY
:
0
,
shadowBlur
:
0
,
shadowColor
:
[
0
,
0
,
0
,
0
],
font
:
'
10px sans-serif
'
,
fontSize
:
10
,
fontWeight
:
'
normal
'
,
fontStyle
:
'
normal
'
,
fontFamily
:
'
sans-serif
'
}
}
draw
(
reserve
=
false
,
callback
)
{
var
actions
=
[...
this
.
actions
]
this
.
actions
=
[]
this
.
path
=
[]
var
callbackId
if
(
typeof
callback
===
'
function
'
)
{
callbackId
=
canvasEventCallbacks
.
push
(
callback
)
}
operateCanvas
(
this
.
id
,
this
.
pageId
,
'
actionsChanged
'
,
{
actions
,
reserve
,
callbackId
})
}
createLinearGradient
(
x0
,
y0
,
x1
,
y1
)
{
return
new
CanvasGradient
(
'
linear
'
,
[
x0
,
y0
,
x1
,
y1
])
}
createCircularGradient
(
x
,
y
,
r
)
{
return
new
CanvasGradient
(
'
radial
'
,
[
x
,
y
,
r
])
}
createPattern
(
image
,
repetition
)
{
if
(
undefined
===
repetition
)
{
console
.
error
(
"
Failed to execute 'createPattern' on 'CanvasContext': 2 arguments required, but only 1 present.
"
)
}
else
if
([
'
repeat
'
,
'
repeat-x
'
,
'
repeat-y
'
,
'
no-repeat
'
].
indexOf
(
repetition
)
<
0
)
{
console
.
error
(
"
Failed to execute 'createPattern' on 'CanvasContext': The provided type ('
"
+
repetition
+
"
') is not one of 'repeat', 'no-repeat', 'repeat-x', or 'repeat-y'.
"
)
}
else
{
return
new
Pattern
(
image
,
repetition
)
}
}
measureText
(
text
)
{
if
(
!
c2d
)
{
let
canvas
=
document
.
createElement
(
'
canvas
'
)
c2d
=
canvas
.
getContext
(
'
2d
'
)
}
c2d
.
font
=
this
.
state
.
font
return
new
TextMetrics
(
c2d
.
measureText
(
text
).
width
||
0
)
}
save
()
{
this
.
actions
.
push
({
method
:
'
save
'
,
data
:
[]
})
this
.
drawingState
.
push
(
this
.
state
)
}
restore
()
{
this
.
actions
.
push
({
method
:
'
restore
'
,
data
:
[]
})
this
.
state
=
this
.
drawingState
.
pop
()
||
{
lineDash
:
[
0
,
0
],
shadowOffsetX
:
0
,
shadowOffsetY
:
0
,
shadowBlur
:
0
,
shadowColor
:
[
0
,
0
,
0
,
0
],
font
:
'
10px sans-serif
'
,
fontSize
:
10
,
fontWeight
:
'
normal
'
,
fontStyle
:
'
normal
'
,
fontFamily
:
'
sans-serif
'
}
}
beginPath
()
{
this
.
path
=
[]
this
.
subpath
=
[]
}
moveTo
(
x
,
y
)
{
this
.
path
.
push
({
method
:
'
moveTo
'
,
data
:
[
x
,
y
]
})
this
.
subpath
=
[
[
x
,
y
]
]
}
lineTo
(
x
,
y
)
{
if
(
this
.
path
.
length
===
0
&&
this
.
subpath
.
length
===
0
)
{
this
.
path
.
push
({
method
:
'
moveTo
'
,
data
:
[
x
,
y
]
})
}
else
{
this
.
path
.
push
({
method
:
'
lineTo
'
,
data
:
[
x
,
y
]
})
}
this
.
subpath
.
push
([
x
,
y
])
}
quadraticCurveTo
(
cpx
,
cpy
,
x
,
y
)
{
this
.
path
.
push
({
method
:
'
quadraticCurveTo
'
,
data
:
[
cpx
,
cpy
,
x
,
y
]
})
this
.
subpath
.
push
([
x
,
y
])
}
bezierCurveTo
(
cp1x
,
cp1y
,
cp2x
,
cp2y
,
x
,
y
)
{
this
.
path
.
push
({
method
:
'
bezierCurveTo
'
,
data
:
[
cp1x
,
cp1y
,
cp2x
,
cp2y
,
x
,
y
]
})
this
.
subpath
.
push
([
x
,
y
])
}
arc
(
x
,
y
,
r
,
sAngle
,
eAngle
,
counterclockwise
=
false
)
{
this
.
path
.
push
({
method
:
'
arc
'
,
data
:
[
x
,
y
,
r
,
sAngle
,
eAngle
,
counterclockwise
]
})
this
.
subpath
.
push
([
x
,
y
])
}
rect
(
x
,
y
,
width
,
height
)
{
this
.
path
.
push
({
method
:
'
rect
'
,
data
:
[
x
,
y
,
width
,
height
]
})
this
.
subpath
=
[
[
x
,
y
]
]
}
arcTo
(
x1
,
y1
,
x2
,
y2
,
radius
)
{
this
.
path
.
push
({
method
:
'
arcTo
'
,
data
:
[
x1
,
y1
,
x2
,
y2
,
radius
]
})
this
.
subpath
.
push
([
x2
,
y2
])
}
clip
()
{
this
.
actions
.
push
({
method
:
'
clip
'
,
data
:
[...
this
.
path
]
})
}
closePath
()
{
this
.
path
.
push
({
method
:
'
closePath
'
,
data
:
[]
})
if
(
this
.
subpath
.
length
)
{
this
.
subpath
=
[
this
.
subpath
.
shift
()]
}
}
}
[...
methods1
,
...
methods2
].
forEach
(
function
(
method
)
{
function
get
(
method
)
{
switch
(
method
)
{
case
'
fill
'
:
case
'
stroke
'
:
return
function
()
{
this
.
actions
.
push
({
method
:
method
+
'
Path
'
,
data
:
[...
this
.
path
]
})
}
case
'
fillRect
'
:
return
function
(
x
,
y
,
width
,
height
)
{
this
.
actions
.
push
({
method
:
'
fillPath
'
,
data
:
[{
method
:
'
rect
'
,
data
:
[
x
,
y
,
width
,
height
]
}]
})
}
case
'
strokeRect
'
:
return
function
(
x
,
y
,
width
,
height
)
{
this
.
actions
.
push
({
method
:
'
strokePath
'
,
data
:
[{
method
:
'
rect
'
,
data
:
[
x
,
y
,
width
,
height
]
}]
})
}
case
'
fillText
'
:
case
'
strokeText
'
:
return
function
(
text
,
x
,
y
,
maxWidth
)
{
var
data
=
[
text
.
toString
(),
x
,
y
]
if
(
typeof
maxWidth
===
'
number
'
)
{
data
.
push
(
maxWidth
)
}
this
.
actions
.
push
({
method
,
data
})
}
case
'
drawImage
'
:
return
function
(
imageResource
,
dx
,
dy
,
dWidth
,
dHeight
,
sx
,
sy
,
sWidth
,
sHeight
)
{
if
(
sHeight
===
undefined
)
{
sx
=
dx
sy
=
dy
sWidth
=
dWidth
sHeight
=
dHeight
dx
=
undefined
dy
=
undefined
dWidth
=
undefined
dHeight
=
undefined
}
var
data
function
isNumber
(
e
)
{
return
typeof
e
===
'
number
'
}
data
=
isNumber
(
dx
)
&&
isNumber
(
dy
)
&&
isNumber
(
dWidth
)
&&
isNumber
(
dHeight
)
?
[
imageResource
,
sx
,
sy
,
sWidth
,
sHeight
,
dx
,
dy
,
dWidth
,
dHeight
]
:
isNumber
(
sWidth
)
&&
isNumber
(
sHeight
)
?
[
imageResource
,
sx
,
sy
,
sWidth
,
sHeight
]
:
[
imageResource
,
sx
,
sy
]
this
.
actions
.
push
({
method
,
data
})
}
default
:
return
function
(...
data
)
{
this
.
actions
.
push
({
method
,
data
})
}
}
}
CanvasContext
.
prototype
[
method
]
=
get
(
method
)
})
methods3
.
forEach
(
function
(
method
)
{
function
get
(
method
)
{
switch
(
method
)
{
case
'
setFillStyle
'
:
case
'
setStrokeStyle
'
:
return
function
(
color
)
{
this
.
actions
.
push
({
method
,
data
:
[
'
normal
'
,
checkColor
(
color
)]
})
}
case
'
setGlobalAlpha
'
:
return
function
(
alpha
)
{
alpha
=
Math
.
floor
(
255
*
parseFloat
(
alpha
))
this
.
actions
.
push
({
method
,
data
:
[
alpha
]
})
}
case
'
setShadow
'
:
return
function
(
offsetX
,
offsetY
,
blur
,
color
)
{
color
=
checkColor
(
color
)
this
.
actions
.
push
({
method
,
data
:
[
offsetX
,
offsetY
,
blur
,
color
]
})
this
.
state
.
shadowBlur
=
blur
this
.
state
.
shadowColor
=
color
this
.
state
.
shadowOffsetX
=
offsetX
this
.
state
.
shadowOffsetY
=
offsetY
}
case
'
setLineDash
'
:
return
function
(
pattern
,
offset
)
{
pattern
=
pattern
||
[
0
,
0
]
offset
=
offset
||
0
this
.
actions
.
push
({
method
,
data
:
[
pattern
,
offset
]
})
this
.
state
.
lineDash
=
pattern
}
case
'
setFontSize
'
:
return
function
(
fontSize
)
{
this
.
state
.
font
=
this
.
state
.
font
.
replace
(
/
\d
+
\.?\d
*px/
,
fontSize
+
'
px
'
)
this
.
state
.
fontSize
=
fontSize
this
.
actions
.
push
({
method
,
data
:
[
fontSize
]
})
}
default
:
return
function
(...
data
)
{
this
.
actions
.
push
({
method
,
data
})
}
}
}
CanvasContext
.
prototype
[
method
]
=
get
(
method
)
})
export
function
createCanvasContext
(
id
,
context
)
{
if
(
context
)
{
return
new
CanvasContext
(
id
,
context
.
$page
.
id
)
}
const
app
=
getApp
()
if
(
app
.
$route
&&
app
.
$route
.
params
.
__id__
)
{
return
new
CanvasContext
(
id
,
app
.
$route
.
params
.
__id__
)
}
else
{
UniServiceJSBridge
.
emit
(
'
onError
'
,
'
createCanvasContext:fail
'
)
}
}
src/core/view/components/canvas/index.vue
浏览文件 @
3cf3ae3c
<
template
>
<uni-canvas/>
<uni-canvas>
<canvas
ref=
"canvas"
:canvas-id=
"canvasId"
:disable-scroll=
"disableScroll"
:width=
"width"
:height=
"height"
@
touchmove=
"_touchmove"
/>
</uni-canvas>
</
template
>
<
script
>
import
{
subscriber
}
from
'
uni-mixins
'
function
resolveColor
(
color
)
{
color
=
color
.
slice
(
0
)
color
[
3
]
=
color
[
3
]
/
255
return
'
rgba(
'
+
color
.
join
(
'
,
'
)
+
'
)
'
}
export
default
{
name
:
'
Canvas
'
name
:
'
Canvas
'
,
mixins
:
[
subscriber
],
props
:
{
canvasId
:
{
type
:
String
,
default
:
''
},
disableScroll
:
{
type
:
[
Boolean
,
String
],
default
:
false
}
},
data
()
{
return
{
width
:
300
,
height
:
150
,
actionsWaiting
:
false
}
},
computed
:
{
id
()
{
return
this
.
canvasId
}
},
created
()
{
this
.
_actionsDefer
=
[]
this
.
_images
=
{}
},
mounted
()
{
var
canvas
=
this
.
$refs
.
canvas
this
.
width
=
canvas
.
offsetWidth
this
.
height
=
canvas
.
offsetHeight
},
methods
:
{
_handleSubscribe
({
type
,
data
=
{}
})
{
var
method
=
this
[
type
]
if
(
type
.
indexOf
(
'
_
'
)
!==
0
&&
typeof
method
===
'
function
'
)
{
method
(
data
)
}
},
_touchmove
(
event
)
{
if
(
this
.
disableScroll
)
{
event
.
preventDefault
()
}
},
actionsChanged
({
actions
,
reserve
,
callbackId
})
{
var
self
=
this
if
(
!
actions
)
{
return
}
if
(
this
.
actionsWaiting
)
{
this
.
_actionsDefer
.
push
([
actions
,
reserve
,
callbackId
])
return
}
var
canvas
=
this
.
$refs
.
canvas
var
c2d
=
canvas
.
getContext
(
'
2d
'
)
if
(
!
reserve
)
{
c2d
.
fillStyle
=
'
#000000
'
c2d
.
strokeStyle
=
'
#000000
'
c2d
.
shadowColor
=
'
#000000
'
c2d
.
shadowBlur
=
0
c2d
.
shadowOffsetX
=
0
c2d
.
shadowOffsetY
=
0
c2d
.
setTransform
(
1
,
0
,
0
,
1
,
0
,
0
)
c2d
.
clearRect
(
0
,
0
,
canvas
.
width
,
canvas
.
height
)
}
this
.
preloadImage
(
actions
)
for
(
let
index
=
0
;
index
<
actions
.
length
;
index
++
)
{
let
action
=
actions
[
index
]
let
method
=
action
.
method
let
data
=
action
.
data
if
(
/^set/
.
test
(
method
)
&&
method
!==
'
setTransform
'
)
{
let
method1
=
method
[
3
].
toLowerCase
()
+
method
.
slice
(
4
)
let
color
if
(
method1
===
'
fillStyle
'
||
method1
===
'
strokeStyle
'
)
{
if
(
data
[
0
]
===
'
normal
'
)
{
color
=
resolveColor
(
data
[
1
])
}
else
if
(
data
[
0
]
===
'
linear
'
)
{
let
LinearGradient
=
c2d
.
createLinearGradient
(...
data
[
1
])
data
[
2
].
forEach
(
function
(
data2
)
{
let
offset
=
data2
[
0
]
let
color
=
resolveColor
(
data2
[
1
])
LinearGradient
.
addColorStop
(
offset
,
color
)
})
}
else
if
(
data
[
0
]
===
'
radial
'
)
{
let
x
=
data
[
1
][
0
]
let
y
=
data
[
1
][
1
]
let
r
=
data
[
1
][
2
]
let
LinearGradient
=
c2d
.
createRadialGradient
(
x
,
y
,
0
,
x
,
y
,
r
)
data
[
2
].
forEach
(
function
(
data2
)
{
let
offset
=
data2
[
0
]
let
color
=
resolveColor
(
data2
[
1
])
LinearGradient
.
addColorStop
(
offset
,
color
)
})
}
else
if
(
data
[
0
]
===
'
pattern
'
)
{
let
loaded
=
this
.
checkImageLoaded
(
data
[
1
],
actions
.
slice
(
index
+
1
),
callbackId
,
function
(
image
)
{
if
(
image
)
{
c2d
[
method1
]
=
c2d
.
createPattern
(
image
,
data
[
2
])
}
})
if
(
!
loaded
)
{
break
}
continue
}
c2d
[
method1
]
=
color
}
else
if
(
method1
===
'
globalAlpha
'
)
{
c2d
[
method1
]
=
data
[
0
]
/
255
}
else
if
(
method1
===
'
shadow
'
)
{
var
_
=
[
'
shadowOffsetX
'
,
'
shadowOffsetY
'
,
'
shadowBlur
'
,
'
shadowColor
'
]
data
.
forEach
(
function
(
color_
,
method_
)
{
c2d
[
_
[
method_
]]
=
_
[
method_
]
===
'
shadowColor
'
?
resolveColor
(
color_
)
:
color_
})
}
else
{
if
(
method1
===
'
fontSize
'
)
{
c2d
.
font
=
c2d
.
font
.
replace
(
/
\d
+
\.?\d
*px/
,
data
[
0
]
+
'
px
'
)
}
else
{
if
(
method1
===
'
lineDash
'
)
{
c2d
.
setLineDash
(
data
[
0
])
c2d
.
lineDashOffset
=
data
[
1
]
||
0
}
else
{
if
(
method1
===
'
textBaseline
'
)
{
if
(
data
[
0
]
===
'
normal
'
)
{
data
[
0
]
=
'
alphabetic
'
}
c2d
[
method1
]
=
data
[
0
]
}
else
{
c2d
[
method1
]
=
data
[
0
]
}
}
}
}
}
else
if
(
method
===
'
fillPath
'
||
method
===
'
strokePath
'
)
{
method
=
method
.
replace
(
/Path/
,
''
)
c2d
.
beginPath
()
data
.
forEach
(
function
(
data_
)
{
c2d
[
data_
.
method
].
apply
(
c2d
,
data_
.
data
)
})
c2d
[
method
]()
}
else
if
(
method
===
'
fillText
'
)
{
c2d
.
fillText
.
apply
(
c2d
,
data
)
}
else
if
(
method
===
'
drawImage
'
)
{
var
A
=
(
function
()
{
var
dataArray
=
[...
data
]
var
url
=
dataArray
[
0
]
var
otherData
=
dataArray
.
slice
(
1
)
self
.
_images
=
self
.
_images
||
{}
if
(
!
self
.
checkImageLoaded
(
url
,
actions
.
slice
(
index
+
1
),
callbackId
,
function
(
image
)
{
if
(
image
)
{
c2d
.
drawImage
.
apply
(
c2d
,
[
image
].
concat
([...
otherData
.
slice
(
4
,
8
)],
[...
otherData
.
slice
(
0
,
4
)]))
}
}))
return
'
break
'
}())
if
(
A
===
'
break
'
)
{
break
}
}
else
{
if
(
method
===
'
clip
'
)
{
data
.
forEach
(
function
(
data_
)
{
c2d
[
data_
.
method
].
apply
(
c2d
,
data_
.
data
)
})
c2d
.
clip
()
}
else
{
c2d
[
method
].
apply
(
c2d
,
data
)
}
}
}
if
(
!
this
.
actionsWaiting
&&
callbackId
)
{
UniViewJSBridge
.
publishHandler
(
'
onDrawCanvas
'
,
{
errMsg
:
'
drawCanvas:ok
'
,
callbackId
},
this
.
$page
.
id
)
}
},
preloadImage
:
function
(
actions
)
{
var
sefl
=
this
actions
.
forEach
(
function
(
action
)
{
var
method
=
action
.
method
var
data
=
action
.
data
var
src
=
''
if
(
method
===
'
drawImage
'
)
{
src
=
data
[
0
]
src
=
sefl
.
$getRealPath
(
src
)
data
[
0
]
=
src
}
else
if
(
method
===
'
setFillStyle
'
&&
data
[
0
]
===
'
pattern
'
)
{
src
=
data
[
1
]
src
=
sefl
.
$getRealPath
(
src
)
data
[
1
]
=
src
}
if
(
src
&&
!
sefl
.
_images
[
src
])
{
loadImage
()
}
/**
* 加载图像
*/
function
loadImage
()
{
sefl
.
_images
[
src
]
=
new
Image
()
sefl
.
_images
[
src
].
onload
=
function
()
{
sefl
.
_images
[
src
].
ready
=
true
}
/**
* 从Blob加载
* @param {Blob} blob
*/
function
loadBlob
(
blob
)
{
sefl
.
_images
[
src
].
src
=
window
.
URL
.
createObjectURL
(
blob
)
}
/**
* 从本地文件加载
* @param {string} path 文件路径
*/
function
loadFile
(
path
)
{
var
bitmap
=
new
plus
.
nativeObj
.
Bitmap
(
'
bitmap
'
+
Date
.
now
())
bitmap
.
load
(
path
,
function
()
{
sefl
.
_images
[
src
].
src
=
bitmap
.
toBase64Data
()
bitmap
.
clear
()
},
function
()
{
bitmap
.
clear
()
console
.
error
(
'
preloadImage error
'
)
})
}
/**
* 从网络加载
* @param {string} url 文件地址
*/
function
loadUrl
(
url
)
{
function
plusDownload
()
{
plus
.
downloader
.
createDownload
(
url
,
{
filename
:
'
_doc/uniapp_temp/download/
'
},
function
(
d
,
status
)
{
if
(
status
===
200
)
{
loadFile
(
d
.
filename
)
}
}).
start
()
}
var
xhr
=
new
XMLHttpRequest
()
xhr
.
open
(
'
GET
'
,
url
,
true
)
xhr
.
responseType
=
'
blob
'
xhr
.
onload
=
function
()
{
if
(
this
.
status
===
200
)
{
loadBlob
(
this
.
response
)
}
}
xhr
.
onerror
=
plusDownload
xhr
.
send
()
}
// 解决 plus-app wkwebview 图像跨域问题
if
(
window
.
plus
&&
window
.
webkit
&&
window
.
webkit
.
messageHandlers
)
{
if
(
src
.
indexOf
(
'
http://
'
)
===
0
||
src
.
indexOf
(
'
https://
'
)
===
0
)
{
loadUrl
(
src
)
}
else
if
(
/^data:
[
a-z-
]
+
\/[
a-z-
]
+;base64,/
.
test
(
src
))
{
sefl
.
_images
[
src
].
src
=
src
}
else
{
loadFile
(
src
)
}
}
else
{
sefl
.
_images
[
src
].
src
=
src
}
}
})
},
checkImageLoaded
:
function
(
src
,
actions
,
callbackId
,
fn
)
{
var
self
=
this
var
image
=
this
.
_images
[
src
]
if
(
image
.
ready
)
{
fn
(
image
)
return
true
}
else
{
this
.
_actionsDefer
.
unshift
([
actions
,
true
])
this
.
actionsWaiting
=
true
image
.
onload
=
function
()
{
image
.
ready
=
true
fn
(
image
)
self
.
actionsWaiting
=
false
var
actions
=
self
.
_actionsDefer
.
slice
(
0
)
self
.
_actionsDefer
=
[]
for
(
var
action
=
actions
.
shift
();
action
;)
{
self
.
actionsChanged
({
actions
:
action
[
0
],
reserve
:
action
[
1
],
callbackId
})
action
=
actions
.
shift
()
}
}
return
false
}
}
}
}
</
script
>
<
style
>
uni-canvas
{
width
:
300px
;
height
:
150px
;
display
:
block
;
position
:
relative
;
}
uni-canvas
>
canvas
{
position
:
absolute
;
top
:
0
;
left
:
0
;
width
:
100%
;
height
:
100%
;
}
</
style
>
src/core/view/mixins/subscriber.js
浏览文件 @
3cf3ae3c
...
...
@@ -3,12 +3,13 @@ import {
}
from
'
uni-shared
'
export
default
{
props
:
{
id
:
{
type
:
String
,
default
:
''
}
},
// 取消id的定义,某些组件(canvas)内不在props内定义id
// props: {
// id: {
// type: String,
// default: ''
// }
// },
mounted
()
{
this
.
_toggleListeners
(
'
subscribe
'
,
this
.
id
)
// 初始化监听
this
.
$watch
(
'
id
'
,
(
newId
,
oldId
)
=>
{
// watch id
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录