phaser.tweens例子详解

phaser的相关方法

TP、sprite

TP每张图片都拥有一个target目标的锚点,在phaser中,可以通过add.sprite(x, y, ’场景‘, ‘图片位置’)来设置。

预加载sprite图:
1
this.load.multiatlas('cityscene', 'assets/cityscene.json', "assets")
使用sprite:
1
this.add.sprite(0, 0, 'cityscene', 'background.png')
sprite动画渲染:
1
2
3
4
5
let frameNames = this.anims.generateFrameNames('cityscene', { start: 1, end: 8, zeroPad: 4, prefix:'capguy/walk/', suffix:'.png' });

this.anims.create({ key: 'walk', frames: frameNames, frameRate: 10, repeat: -1 });

capguy.anims.play('walk')

关于调整canvas的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function resize(){
let canvas = document.querySelector("canvas");
let windowWidth = window.innerWidth;
let windowHeight = window.innerHeight;
let windowRatio = windowWidth / windowHeight;
let gameRatio = game.config.width / game.config.height;
if(windowRatio < gameRatio){
canvas.style.width = windowWidth + "px";
canvas.style.height = (windowWidth / gameRatio) + "px";
}
else{
canvas.style.width = (windowHeight * gameRatio) + "px";
canvas.style.height = windowHeight + "px";
}
}

tweens.timeline

config api: https://photonstorm.github.io/phaser3-docs/Phaser.Tweens.html#.TweenConfigDefaults__anchor

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
this.tweens.timeline({
targets: this.add.image(100, 100, 'block'), // sprite的也是ok的
ease: 'Linear',
duration: 3000,
loop: 4, // 动画循环播放次数
yoyo: true, // 动画往返播放 等于倒放
totalDuration: 2000, // 总动画时长
repeatDelay: 1000, // 动画播放 延迟 但是需要注意的是 这个延迟的yoyo:true的时候,动画来回 才算一次Delay
hold: 1000, // 保持动画结束的画面时间,随后yoyo为true的话,动画会往返跑,但是回到开始的动画,不会保持该画面。
// 开始动画 ---> 结束动画 --->hold保持结束动画时长 ---> 开始动画
alpha: 1, // 透明度
delay: i * 50, // 动画第一次开始的延迟时间 仅触发一次
completeDelay: 5000, // 动画结束方法onComplete() 延迟执行
easeParams: [ 1.70158 ], // ease的额外参数 1.70158 是当ease: 'Back' 的时候 的默认参数
flipX: true, // 翻转 在yoyo为True的时候 返回会翻转 在repeart: 大于1 或者-1的时候 单数次数会翻转 http://labs.phaser.io/view.html?src=src\tweens\flipx.js
tweens:[{
x: 100, // 这是target的x坐标
yoyo: true, // 动画往返播放
}, {
y: 100, // 这是target的y坐标
offset: 3000 // 这是动画时间的进行偏差值 0 表示同时进行上一个动画和这个动画 1500 表示上一个动画进行到一半的时候 这个动画也跟着上
// 3000就表示等上一个动画走完再走这个动画了 确切来说 就是 下一个动画的活动时间 数值可改 0到无限
}]
})

offset参数

本次动画的活动时间。

这里有一个坑,字符串的’’和数值的,运行是不同的,数值的是本次动画的活动时间。
而字符串的是不正规写法,-=500指的是上一个动画进行的时间减500就是本次动画的开始时间。+=500指的是上一个动画进行的时间加500就是本次动画的开始时间

例子:
①duration: 3000
②offset: ‘-=500’
那么②动画将会在2500的时候和①动画一起进行。

例子2(如果需要对应例子1但是写法是数值):
①duration: 3000
②offset: 2500

1
offset: '-=500' // starts 500ms before previous tween ends

通过add方法来添加动画

1
2
3
4
5
6
7
8
9
10
11
12
13
14
let timeLine = this.tweens.timeline({})
timeLine.add({
targets: this.add.image(100, 100, 'block')
x: 600,
ease: 'Power1',
duration: 3000
})
timeLine.add({
targets: this.add.image(100, 100, 'block')
y: 600,
ease: 'Power1',
duration: 3000
})
timeLine.play() // 启动动画

ease参数

https://easings.net/zh-cn
http://lets-gamedev.de/phasereasings/
这里需要注意的是Phaser 3的Easing不是放在Phaser上的,而是

1
Phaser.Math.Easing.Back.InOut

http://labs.phaser.io/edit.html?src=src\tweens\ease%20equations.js

target等其他参数都是可以写进tweens里面

1
2
3
4
5
6
7
this.tweens.timeline({
tweens:[
{
targets: this.add.image(100, 100, 'block')
}
]
})

生命周期

onStart 动画开始。
onComplete 动画结束。
onYoyo 动画往返。
onRepeat 动画重复。

Phaser.Actions.GridAlign()做成组的动画

methods doc: https://photonstorm.github.io/phaser3-docs/Phaser.Tweens.Tween.html

tween.restart()

http://labs.phaser.io/edit.html?src=src\tweens\checkerboard%202.js

1
2
3
function preload() {
this.load.image('block', 'assets/sprites/pinkBlock50x50.png')
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
let blocks = this.add.group({key: ''block', repeat: 107, setScale: {x: 0.3, y:0.3}) // 添加成组的图片 重复103次 block图片
// 这里的setScale 是用来作为cell的间距的
Phaser.Actions.GridAlign(blocks.getChildren(), {
width: 12, // 正如grid-template那样的width 代表行个数 可以不填写height 就如css-grid
height: 10, // 正如grid-template那样的height 代表列个数 可以不填写width 就如css-grid
cellWidth: 20, // item的width
cellHeight: 20, // item的height
x: 70, // top align
y: 60, // left align
// https://photonstorm.github.io/phaser3-docs/global.html#GridAlignConfig
})

let i = 0

blocks.children.iterate((child) => {
this.tweens.add({
targets: child,
scaleX: 1, // 恢复缩放原来的尺寸
scaleY: 1, // as the same
_ease: '', // 暂不知道 _ease的作用
ease: 'Sine.easeInOut',
duration: 300, // 动画时间
delay: i * 50, // 动画第一次开始的延迟时间 仅触发一次
repeat: -1, // -1 无限重复
paused: true, // 动画不会开始 调用 .play() 方法将启动
yoyo: true,
hold: 1000, // 保持动画结束的画面时间,随后yoyo为true的话,动画会往返跑,但是回到开始的动画,不会保持该画面。
// 开始动画 ---> 结束动画 --->hold保持结束动画时长 ---> 开始动画
repeatDelay: 1000 // 动画播放 延迟 但是需要注意的是 这个延迟的yoyo:true的时候,动画来回 才算一次Delay
})
})

i++

if (i % 12 === 0) i = 0

一个角度旋转的正方形动画 angle: { getEnd(target, key, value){}, getStart(target, key, value){}}

http://labs.phaser.io/edit.html?src=src\tweens\checkerboard%20rotate.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
let a = [0, 90, 180, 270]
blocks.children.iterate((child) => {
child.angle = Phaser.Math.RND.pick(a) // 随机选择数组的方法

this.tweens.add({
targets: child,
ease: 'Power1',
duration: 250,
delay: (Math.random() * 6000),
repeatDelay: 3000 + (Math.random() * 6000),
repeat: -1,
angle: {
getEnd (target, key, value) {
let a = 90

if (Math.random() > .5) {
a = 180
return target.angle + a
} else {
return target.angle - a
}
},
getStart (target, key, value) { // 假如不设置getStart 则会告诉Phaser: 嘿帮我把这个方框旋转多少度
return target.angle // 假如设置了getStart return target.angle 则告诉Phaser: 嘿你从方框的原始角度开始,旋转到那个角度
}
}
})
})

一个蛋蛋球的动画

1
props:{ x:{value() => {}, ease: ''}, y:{value() => {}, ease: ''} }

http://labs.phaser.io/edit.html?src=src\tweens\dynamic%20end%20property.js

props 里面的xy,在一整个动画完成后(yoyo为true的时候,也是按照到末端执行一次的),是会执行一次value方法的,从而更改一次动画的xy位置。
这里可能有一些复杂
http://labs.phaser.io/edit.html?src=src\tweens\dynamic%20properties%20multiple.js
在getStart上面打一个alert(value),控制下过程你就可以知道了,yoyo为true的时候,返回的位置就是已经改变了的getStart(){return value + 30}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
let maker = this.add.image(400, 300, './bollShadow.png')
let img = this.add.image(400, 300, './boll.png')

this.input.on('pointerdown', (pointer) => {
marker.serPosition(poniter.x, pointer.y)
})

let tween = this.tweens.add({
targets: img,
props: {
x: {
value () {
return maker.x
},
ease: 'Power1'
},
y: {
value () {
return maker.y
},
ease: 'Power1'
}
},
duration: 500,
yoyo: true,
repeat: -1
})

深入蛋蛋球动画

1
props:{x:{value:{getEnd() => {}, getStart() => {}}, ease:'', tweensConfig}}

http://labs.phaser.io/edit.html?src=src\tweens\dynamic%20properties%20multiple.js

props x 或者 y 里面的value 是初始的value值, value 仅仅会在getStart() => { return 你想改变的Value值 }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
let destX = 600

let tween = this.tweens.add({
targets: imgae,
props: {
y: {
value: 500,
duration: 8000,
ease: 'Power1'
},
x: {
duration: 400,
yoyo: true,
repeat: 8,
easeL 'Sine.easeInOut',
value: { // value: '-=100' 这样就相对自身走100了
getEnd (target, key, value) {
destX -= 30
return destX
},
getStart (target, key, value) {
return value + 30
}
}
}
}
})

easeParams ease的额外参数

1
2
3
4
5
6
7
8
9
10
11
{
ease: 'Back',
easeParams: [ 3.2 ],
x: 600, // 注意是按照总的canvas的作为地点标记
y: 150, // 注意是按照总的canvas的作为地点标记
angle: {
getEnd () {
return 90
}
}
}

例子:
http://labs.phaser.io/edit.html?src=src\tweens\elasticity.js
http://labs.phaser.io/edit.html?src=src\tweens\ease%20params.js

Back api 文档:
https://photonstorm.github.io/phaser3-docs/Phaser.Math.Easing.Back.html
目前还不太清楚这个参数的调控
ease为 [‘Back’, ‘Elastic’] 的时候可用 (例子中看到的)

ease为back的时候,动画将会达到目标地点后继续悬着那个方向进行动画,然后返回
easeParams 中,默认值是1.70158(ease: ‘Back’的时候)
你可以增加一些旋转的参数进去,看看返回的动效是怎么样的
参数方面如果为0就不进行回滚

flipX配合props: {x: {}}来使用

1
2
3
4
5
6
7
8
{
props: {
x: { value: 700, duration: 4000 },
y: { value: 500, duration: 8000 }
},
yoyo: true,
repeat: -1
}

假如你想让图像只在x动画结束,flipX起效,那么你应该做的是

1
x: { value: 700, duration: 4000, flipX: true }

loop loopDelay 和 repeat repeatDelay 的区别

http://labs.phaser.io/edit.html?src=src\tweens\loop%20delay.js
loop和repeat直接用是没有任何区别的。
当loop和loopDelay组合的时候,动画是播放完毕,然后画面保持完成状态,等待loopDelay所设置的时间,然后再重复这个动画,马上执行。
当repeat和repeatDelay组合的时候,动画播放完毕,画面立刻回到开始状态,等待repeatDelay所设置的时间,然后重复这个动画。

onComplete onCompleteParams

1
2
3
4
5
6
7
8
{
onComplete: methodsName,
onCompleteParams: [ image ] // 传进去targets 作为MethodsName的第三个参数
}

methodsName (tween, targets, myImage) {
myImage.setScale(2)
}

动画的暂停与运行 this.tweens.pauseAll() this.tweens.resumeAll()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
let downButton = this.add.image(70, 530, 'down').setInteractive()
let upButton = this.add.image(730, 530, 'up').setInteractive()
// setInteractive()
// https://photonstorm.github.io/phaser3-docs/Phaser.GameObjects.Image.html
let tweens = this.tweens

this.input.on('gameobjectup', (pointer, gameobject) => {
// Scales the time applied to this Tween. A value of 1 runs in real-time. A value of 0.5 runs 50% slower, and so on. Value isn't used when calculating total duration of the tween, it's a run-time delta adjustment only.
// 1 代表真实运行速度 倍数形式 动画的duration不会受到影响,这仅仅是在运行时的调整。
if (gameobject === downButton && tweens.timeScale > 0) {
tweens.pauseAll()
} else if (gameobject === upButton && tweens.timeScale < 9.9) {
tweens.resumeAll()

}
})

input事件监听类型

https://photonstorm.github.io/phaser3-docs/Phaser.Events.EventEmitter.html#once__anchor
event: https://photonstorm.github.io/phaser3-docs/Phaser.Input.Events.html

lottie-web踩坑

lottie-web 踩坑

官网的demo是这样的

1
2
3
4
5
6
7
lottie.loadAnimation({
container: element, // the dom element that will contain the animation
renderer: 'svg',
loop: true,
autoplay: true,
path: 'data.json' // the path to the animation json
})

我实际使用的代码是

1
2
3
4
5
6
7
lottie.loadAnimation({
container: this.$refs.animationHeart, // the dom element that will contain the animation
renderer: 'svg',
loop: true,
autoplay: true,
path: path.join(__dirname, './4265-favoriete-producten.json') // the path to the animation json
})

报错:
Uncaught DOMException: Failed to read the ‘responseText’ property from ‘XMLHttpRequest’: The value is only accessible if the object’s ‘responseType’ is ‘’ or ‘text’ (was ‘json’).
at formatResponse (webpack-internal:///./node_modules/_lottie-web@5.4.4@lottie-web/build/player/lottie.js:4325:17)
at XMLHttpRequest.xhr.onreadystatechange (webpack-internal:///./node_modules/_lottie-web@5.4.4@lottie-web/build/player/lottie.js:4340:26)

查了一下在Vue使用的方法
https://github.com/bienvenidoY/blog/issues/4

注意下 lottie-web在vue运行下是有问题的,很多方法都无效。

正确使用

1
cnpm i vue-lottie --save

https://juejin.im/post/5b180a706fb9a01e780a49d4

小坑记录

lottie组件中,width和height在不设定的情况下,是根据父元素size来调整的,width将会是父元素的width。
但是组件的width不会超出父元素的width,即使你设置的width大于父元素的width。

paperjs 学习

paperjs在vuecli中使用

推荐方式:
cnpm i paper -s

import paper from ‘paper’
mounted(){
paper.install(window)
paper.setup(document.getElementById(‘mycanvas’))
paper.settings.handleSize = 0;
paper.settings.hitTolerance = 4;
}

methods{
paperStart(){
require(‘你写papaer动画的js’)
}
}

按照上面的方式,来进行初始化就OK了
当然你也可以通过script标签引入paper 然后在vue里面require(‘你写papaer动画的js’)
但是不能通过script标签的方式引入你写papaer动画的js(除非你直接在dist放入,好吧,你非要这样我也没办法。)

另外你可能会遇到onFrame(){}等等之类的操作不能使用,你需要改写成view.onFrame = ()=>{console.log(‘这样就有效果了’)}

如何获取相交的点?

链接

var path1 = new Path.Circle([100,100],50)
var path2 = new Path.Circle([100,100],50)

path1.strokeColor = ‘red’
path2.strokeColor = ‘green’

var ints = path1.getIntersections(path2)
console.log(ints.length)

var colors = [“red”, “green”, “orange”];
for (var i = 0; i < ints.length; i++) {
var p = new Path.Circle({radius: 5, fillColor: colors[i]});
p.position = ints[i].point;
}

就是通过一个getIntersections的方法来获取相交的点

如何改变fillColor?(动画)

1
path.fillColor.hue += 1;

如何添加文字?

[]
1
2
3
4
5
6
7
var text = new PointText({
point: view.center,
justification: 'center',
fontSize: 10,
fillColor: 'red'
})
text.content = 'asd'

如何获得point的随机数?还有point和位置的计算问题?

通过Point.random()*view.size 可以获得随机的point位置。
Path.position = Path.position + [10,10]加法减法乘法除法%运算都是这样。

小知识

所有绘图的东西都是路径构成的,而且你可以通过path.position = new Point(100,100),设置位置的方式通过一个点来控制


在canvas设置resize=’true’属性,假如width和height视乎不是你想要的,那么你需要设置
html,
body {
margin: 0;
overflow: hidden;
height: 100%;
}
canvas[resize] {
width: 100%;
height: 100%;
}


Point.length是两点起始的距离


在onFrame中,var value = destination - position 这只会执行一次var value 。
当destination或者position改变的时候,才会重新赋值

|