我正在开发一个Angular响应式应用程序,它在移动设备上有一个抽屉。
我喜欢Angular中的Web Animations API实现,但我找不到可以根据媒体查询断点配置动画的地方。
我所能找到的就是通过我的css表取消动画,但这让我开始在我的项目中的不同位置传播代码,而且我不确定这是我想做的角度......
真实的例子
我的应用程序抽屉使用此代码进行动画处理
<div class="mobile-menu" [@animateDrawer]="drawerOpened">
<!-- Drawer's menu goes here -->
</div>
drawerOpened
是一个布尔值,可在按下应用程序菜单按钮时切换。
我的组件看起来像这样:
@Component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.scss'],
animations: [
trigger('animateDrawer', [
state('inactive', style({
transform: 'translate3d(-100%, 0, 0)'
})),
state('active', style({
transform: 'translate3d(0, 0, 0)'
}))
])
]
})
我取消动画效果的CSS代码
.mobile-menu{
opacity: 1 !important;
display: flex !important;
transform: none !important;
}
除了在我的css代码中操作所有内容并禁用Desktop BreakPoint上的css属性之外,在Angular上下文中是否存在某种方式?
谢谢!
无法基于CSS @Media查询定义JavaScript行为。你将不得不做我所做的,在那里我创建了一个Angular外观服务,它监视视口尺寸并根据检测到的内容向组件发送命令。然后,您可以使用JavaScript逻辑而不是CSS逻辑来控制动画和外观。
添加示例:
创建一个监视视口宽度的服务。如果视口小于500px,则服务输出“mobile”,否则输出“desktop”。
在你的组件中,声明一个触发器,我们称之为@slide,具有多个状态。我们还将设置一个名为stateOfYourChoosing的私有变量,您可以将其设置为字符串。
然后,在您的模板中
<div [@slide]="stateOfYourChoosing"></div>
然后,您可以选择stateOfYourChoosing的默认状态,以及您希望组件如何根据组件逻辑进行转换。
因此,如果您的外观服务输出“桌面”,则您的默认stateOfYourChoosing将为“slideOut”。
transition('slideOut => slideIn', animate('100ms ease-in'))
如果外观服务输出“mobile”,它会将stateOfYourChoosing设置为“mobileSlideOut”,而您的转换代码则是
transition('mobileSlideOut => mobileSlideIn', animate('100ms ease-in'))
然后,您可以通过控制触发器的状态来控制动画模块中的所有响应动画。
一种方法是在运行时创建动画,而不是在组件装饰器中声明它们。
看起来有点像这样(下面的代码没有经过测试,只是一个例子):
export interface MediaQueryStyle
{
minWidth: number;
initialStyle: any; // Style object to apply before animation
endStyle: any; // Style object to apply after animation
}
export interface MediaQueryAnimationConfig
{
element: ElementRef;
mediaStyles: MediaQueryStyle[];
duration?: number | string;
... // Whatever you need to create your animation
}
服务:
@Injectable({
providedIn: 'root'
})
export class MediaQueryAnimationService
{
constructor(private builder: AnimationBuilder) { }
public create(config: MediaQueryAnimationConfig): AnimationPlayer
{
// Read animation configuration
const duration = config.duration || 1000;
const mediaStyle = this.findMediaStyle(config.styles);
// Build the animation logic (add here any other operation, e.g. query)
const animation = this.builder.build([
style(mediaStyle.initialStyle),
animate(duration, style(mediaStyle.endStyle)
]);
return animation.create(config.element);
}
private findMediaStyle(styles: MediaQueryStyle[])
{
const viewWidth = window.innerWidth;
// Some logic to scan the array and return the style that complies with `viewWidth`
return styles.find(style => ...);
}
}
在您的组件中:
<something ... #someElement></something>
@Component({
selector: 'something',
templateUrl: './something.component.html',
styleUrls: ['./something.component.scss']
})
export class SomethingComponent implements OnInit
{
@ViewChild('someElement')
private elementRef: ElementRef;
constructor(private mqAnimation: MediaQueryAnimationService) { }
ngOnInit() { ... }
public onSomeEvent()
{
const player = mqAnimation.create({ element: elementRef.element, minWidth: ... });
player.onDone(player.destroy);
player.play();
}
}
有用的阅读和例子:
https://angular.io/api/animations/AnimationBuilder
https://stackblitz.com/edit/angular-animation-builder
Animation inside of MatDialog is not working
祝你好运✌
不是最强大的解决方案,但如果动画的最终状态对于每个媒体查询都是相同的(例如,您要将两个项目设置为动画,但需要为移动设备和桌面设置不同的动画),那么您可以在css中定义初始状态使用媒体查询并在角度组件中使用'*'作为目标css属性的初始状态
trigger('animation', [
state('out, none, void', style({
transform: '*'
})),
state('in', style({
transform: 'translate3d(0, 0, 0)'
})),
transition('below => in, none => in', animate(`300ms ease`))
])
然后在CSS
.class {
//animate from bottom on mobile
transform: translate3d(0, -100%, 0);
@media all and (min-width: 920px) {
//animate from left on desktop
transform: translate3d(-100%, 0, 0)
}
}