如何在Angular 2中创建可重用的动画
我正在玩动画API,我想为顶级路由器视图创建一个可重用的动画,比如说滑入内容。我成功地通过了时髦的元数据语法(一旦克服了使用元数据的疯狂想法,它实际上非常酷)使动画大部分工作正常如何在Angular 2中创建可重用的动画,angular,angular2-animation,Angular,Angular2 Animation,我正在玩动画API,我想为顶级路由器视图创建一个可重用的动画,比如说滑入内容。我成功地通过了时髦的元数据语法(一旦克服了使用元数据的疯狂想法,它实际上非常酷)使动画大部分工作正常 @Component({ //moduleId: module.id, selector: 'album-display', templateUrl: './albumDisplay.html', animations: [ trigger('sli
@Component({
//moduleId: module.id,
selector: 'album-display',
templateUrl: './albumDisplay.html',
animations: [
trigger('slideIn', [
state('*', style({
transform: 'translateX(100%)',
})),
state('in', style({
transform: 'translateX(0)',
})),
state('out', style({
transform: 'translateX(-100%)',
})),
transition('* => in', animate('600ms ease-in')),
transition('in => out', animate('600ms ease-in'))
])
]
})
export class AlbumDisplay implements OnInit {
slideInState = 'in';
...
}
然后将其指定给组件中的顶级元素:
<div class="container" [@slideIn]="slideInState">
这是可行的,但我如何使其可重复使用?我不想把这些元数据粘贴到每个视图上。由于这是元数据,我不确定如何使其可重用。一种可能的方法是将动画触发代码放在单独的文件中,并将其导出为
const
变量,并在组件中使用,如下所示
动画。ts
import { trigger, state, style, transition, animate } from '@angular/core';
export const slideIn = trigger('slideIn', [
state('*', style({
transform: 'translateX(100%)',
})),
state('in', style({
transform: 'translateX(0)',
})),
state('out', style({
transform: 'translateX(-100%)',
})),
transition('* => in', animate('600ms ease-in')),
transition('in => out', animate('600ms ease-in'))
]);
import { slideIn } from './animations'; // path to your animations.ts file
@Component({
//moduleId: module.id,
selector: 'album-display',
templateUrl: './albumDisplay.html',
animations: [
slideIn
]
})
export class AlbumDisplay implements OnInit {
slideInState = 'in';
...
}
import { AnimationEntryMetadata, trigger, state, style, transition, animate } from '@angular/core';
export function TranslateX( name: string, x: string, duration: number ): AnimationEntryMetadata {
return trigger( name, [
state('false', style({ transform: 'translateX(0)' }) ),
state('true', style({ transform: 'translateX(' + x + ')' }) ),
transition('0 => 1', animate( duration + 'ms ease-in')),
transition('1 => 0', animate( duration + 'ms ease-out')),
]);
}
import { TranslateX } from './translate';
@Component({
...
templateUrl: './app.component.html',
animations: [
TranslateX( 'trigger1Title','-100%', 200 ),
TranslateX( 'trigger2Title','20vw', 700 )
]
...
})
相册显示.component.ts
import { trigger, state, style, transition, animate } from '@angular/core';
export const slideIn = trigger('slideIn', [
state('*', style({
transform: 'translateX(100%)',
})),
state('in', style({
transform: 'translateX(0)',
})),
state('out', style({
transform: 'translateX(-100%)',
})),
transition('* => in', animate('600ms ease-in')),
transition('in => out', animate('600ms ease-in'))
]);
import { slideIn } from './animations'; // path to your animations.ts file
@Component({
//moduleId: module.id,
selector: 'album-display',
templateUrl: './albumDisplay.html',
animations: [
slideIn
]
})
export class AlbumDisplay implements OnInit {
slideInState = 'in';
...
}
import { AnimationEntryMetadata, trigger, state, style, transition, animate } from '@angular/core';
export function TranslateX( name: string, x: string, duration: number ): AnimationEntryMetadata {
return trigger( name, [
state('false', style({ transform: 'translateX(0)' }) ),
state('true', style({ transform: 'translateX(' + x + ')' }) ),
transition('0 => 1', animate( duration + 'ms ease-in')),
transition('1 => 0', animate( duration + 'ms ease-out')),
]);
}
import { TranslateX } from './translate';
@Component({
...
templateUrl: './app.component.html',
animations: [
TranslateX( 'trigger1Title','-100%', 200 ),
TranslateX( 'trigger2Title','20vw', 700 )
]
...
})
正确的解决方案是在指令中支持动画 事实并非如此,但Angular的Github存在一个问题:
希望它能很快解决。通过一个类,您可以扩展
import { trigger, style, state, animate, transition, AnimationMetadata } from "@angular/core";
export class MyAwesomeAnimations {
/**
*
* @param nameTrigger Name of triggers
* @param setNewsStates add states for animations
* @param setNewTransitions add transitions for states
*/
SetTrigger(nameTrigger: string, setNewsStates?: AnimationMetadata[], setNewTransitions?: AnimationMetadata[]): any {
let metaData: AnimationMetadata[] = [
state('*', style({
transform: 'translateX(100%)',
})),
state('in', style({
transform: 'translateX(0)',
})),
state('out', style({
transform: 'translateX(-100%)',
})),
transition('* => in', animate('600ms ease-in')),
transition('in => out', animate('600ms ease-in'))
];
if (setNewsStates)
metaData.concat(setNewsStates);
if (setNewTransitions)
metaData.concat(setNewTransitions);
return trigger(nameTrigger, metaData);
}
}
供使用
@Component({
selector: "orden-detail-component",
animations: [new MyAwesomeAnimations().SetTrigger("slideIn")],
template:"<div class="container" [@slideIn]="slideInState">"
})
export class OrdenDetailComponent {
slideInState = 'in';
}
@组件({
选择器:“orden详图构件”,
动画:[新建MyAwesomeAnimations().SetTrigger(“slideIn”)],
模板:“”
})
导出类OrdenDetailComponent{
slideInState='in';
}
我希望这种方式可以帮助您Angular 4中的路由器动画示例 我刚刚用Angular 4完成了路由器动画的处理,下面是我为淡入过渡和滑入/滑出过渡设计的两个示例动画 查看更多详细信息和现场演示 角度4滑入/滑出动画
// import the required animation functions from the angular animations module
import { trigger, state, animate, transition, style } from '@angular/animations';
export const slideInOutAnimation =
// trigger name for attaching this animation to an element using the [@triggerName] syntax
trigger('slideInOutAnimation', [
// end state styles for route container (host)
state('*', style({
// the view covers the whole screen with a semi tranparent background
position: 'fixed',
top: 0,
left: 0,
right: 0,
bottom: 0,
backgroundColor: 'rgba(0, 0, 0, 0.8)'
})),
// route 'enter' transition
transition(':enter', [
// styles at start of transition
style({
// start with the content positioned off the right of the screen,
// -400% is required instead of -100% because the negative position adds to the width of the element
right: '-400%',
// start with background opacity set to 0 (invisible)
backgroundColor: 'rgba(0, 0, 0, 0)'
}),
// animation and styles at end of transition
animate('.5s ease-in-out', style({
// transition the right position to 0 which slides the content into view
right: 0,
// transition the background opacity to 0.8 to fade it in
backgroundColor: 'rgba(0, 0, 0, 0.8)'
}))
]),
// route 'leave' transition
transition(':leave', [
// animation and styles at end of transition
animate('.5s ease-in-out', style({
// transition the right position to -400% which slides the content out of view
right: '-400%',
// transition the background opacity to 0 to fade it out
backgroundColor: 'rgba(0, 0, 0, 0)'
}))
])
]);
// import the required animation functions from the angular animations module
import { trigger, state, animate, transition, style } from '@angular/animations';
export const fadeInAnimation =
// trigger name for attaching this animation to an element using the [@triggerName] syntax
trigger('fadeInAnimation', [
// route 'enter' transition
transition(':enter', [
// css styles at start of transition
style({ opacity: 0 }),
// animation and styles at end of transition
animate('.3s', style({ opacity: 1 }))
]),
]);
角度4淡入动画
// import the required animation functions from the angular animations module
import { trigger, state, animate, transition, style } from '@angular/animations';
export const slideInOutAnimation =
// trigger name for attaching this animation to an element using the [@triggerName] syntax
trigger('slideInOutAnimation', [
// end state styles for route container (host)
state('*', style({
// the view covers the whole screen with a semi tranparent background
position: 'fixed',
top: 0,
left: 0,
right: 0,
bottom: 0,
backgroundColor: 'rgba(0, 0, 0, 0.8)'
})),
// route 'enter' transition
transition(':enter', [
// styles at start of transition
style({
// start with the content positioned off the right of the screen,
// -400% is required instead of -100% because the negative position adds to the width of the element
right: '-400%',
// start with background opacity set to 0 (invisible)
backgroundColor: 'rgba(0, 0, 0, 0)'
}),
// animation and styles at end of transition
animate('.5s ease-in-out', style({
// transition the right position to 0 which slides the content into view
right: 0,
// transition the background opacity to 0.8 to fade it in
backgroundColor: 'rgba(0, 0, 0, 0.8)'
}))
]),
// route 'leave' transition
transition(':leave', [
// animation and styles at end of transition
animate('.5s ease-in-out', style({
// transition the right position to -400% which slides the content out of view
right: '-400%',
// transition the background opacity to 0 to fade it out
backgroundColor: 'rgba(0, 0, 0, 0)'
}))
])
]);
// import the required animation functions from the angular animations module
import { trigger, state, animate, transition, style } from '@angular/animations';
export const fadeInAnimation =
// trigger name for attaching this animation to an element using the [@triggerName] syntax
trigger('fadeInAnimation', [
// route 'enter' transition
transition(':enter', [
// css styles at start of transition
style({ opacity: 0 }),
// animation and styles at end of transition
animate('.3s', style({ opacity: 1 }))
]),
]);
连接了转换的组件
import { Component } from '@angular/core';
// import fade in animation
import { fadeInAnimation } from '../_animations/index';
@Component({
moduleId: module.id.toString(),
templateUrl: 'home.component.html',
// make fade in animation available to this component
animations: [fadeInAnimation],
// attach the fade in animation to the host (root) element of this component
host: { '[@fadeInAnimation]': '' }
})
export class HomeComponent {
}
也许有点晚了,但我还是想为更具动态性的触发器提供一个答案 将动画触发代码放在单独的文件中,并将其导出为
函数
translate.ts
import { trigger, state, style, transition, animate } from '@angular/core';
export const slideIn = trigger('slideIn', [
state('*', style({
transform: 'translateX(100%)',
})),
state('in', style({
transform: 'translateX(0)',
})),
state('out', style({
transform: 'translateX(-100%)',
})),
transition('* => in', animate('600ms ease-in')),
transition('in => out', animate('600ms ease-in'))
]);
import { slideIn } from './animations'; // path to your animations.ts file
@Component({
//moduleId: module.id,
selector: 'album-display',
templateUrl: './albumDisplay.html',
animations: [
slideIn
]
})
export class AlbumDisplay implements OnInit {
slideInState = 'in';
...
}
import { AnimationEntryMetadata, trigger, state, style, transition, animate } from '@angular/core';
export function TranslateX( name: string, x: string, duration: number ): AnimationEntryMetadata {
return trigger( name, [
state('false', style({ transform: 'translateX(0)' }) ),
state('true', style({ transform: 'translateX(' + x + ')' }) ),
transition('0 => 1', animate( duration + 'ms ease-in')),
transition('1 => 0', animate( duration + 'ms ease-out')),
]);
}
import { TranslateX } from './translate';
@Component({
...
templateUrl: './app.component.html',
animations: [
TranslateX( 'trigger1Title','-100%', 200 ),
TranslateX( 'trigger2Title','20vw', 700 )
]
...
})
因此,在Componentapp.Component.ts中
import { trigger, state, style, transition, animate } from '@angular/core';
export const slideIn = trigger('slideIn', [
state('*', style({
transform: 'translateX(100%)',
})),
state('in', style({
transform: 'translateX(0)',
})),
state('out', style({
transform: 'translateX(-100%)',
})),
transition('* => in', animate('600ms ease-in')),
transition('in => out', animate('600ms ease-in'))
]);
import { slideIn } from './animations'; // path to your animations.ts file
@Component({
//moduleId: module.id,
selector: 'album-display',
templateUrl: './albumDisplay.html',
animations: [
slideIn
]
})
export class AlbumDisplay implements OnInit {
slideInState = 'in';
...
}
import { AnimationEntryMetadata, trigger, state, style, transition, animate } from '@angular/core';
export function TranslateX( name: string, x: string, duration: number ): AnimationEntryMetadata {
return trigger( name, [
state('false', style({ transform: 'translateX(0)' }) ),
state('true', style({ transform: 'translateX(' + x + ')' }) ),
transition('0 => 1', animate( duration + 'ms ease-in')),
transition('1 => 0', animate( duration + 'ms ease-out')),
]);
}
import { TranslateX } from './translate';
@Component({
...
templateUrl: './app.component.html',
animations: [
TranslateX( 'trigger1Title','-100%', 200 ),
TranslateX( 'trigger2Title','20vw', 700 )
]
...
})
在模板中app.component.html
...
<div [@trigger1Title]="token1"> ... </div>
<div [@trigger2Title]="token2"> ... </div>
...
。。。
...
...
...
您可以使用更多的输入数据自定义触发器,例如分离转换时间等。谢谢您,这非常有效。在最初考虑WTF这种基于元的时髦实现之后,在使用此语法创建了一些组件之后,为组件创建动画变得非常容易。此解决方案将阻止您使用AOT编译:/n有没有一种方法可以在不将
[@slideIn]
手动应用于每个元素的情况下使用此方法?就像在ng1中,所有元素都会自动生成动画。我知道这是一个老话题,但是关于如何将其用于AOT编译有什么想法吗?这确实适用于AOT-也许一年前没有,但现在有了。别忘了键入触发器:export const myTrigger:AnimationEntryMetadata=trigger(……或者你会得到一个构建错误。很好的例子。你为什么使用绝对移动而不是优化得更好的翻译?@JJB是的,我使用了一个右负位置移动表单,同时将背景保留在适当的位置以淡出,当我尝试使用翻译时,它会将表单和背景从页面上滑下。我做不到找到一种在“:leave”转换上设置子元素动画的方法,否则我会在本可以使用translate的背景和表单中使用单独的div。这是我唯一能够找到的方法,即仅使用单个html元素在背景中淡入并在表单中滑动。与AOT编译Your stateme一起使用时,这将失败仅当使用了生成触发器类、枚举或对其他函数进行内部调用时,nt才是正确的。我目前正在使用Angular 4、TypeScript 2.4.2,如上所述编写,一切正常。如果使用模板字符串(backticks),看起来会失败您说得对,使用加号+
代替了传统的字符串连接,并且正如您所看到的,在示例中没有使用反勾号。@Simon_Weaver它已被AnimationTriggerMetadata