因为我对角很陌生,我需要你的帮助。我已经看了很多教程并尝试了很多东西,但是这次我需要将JavaScript函数合并到我的角度组件中。
这是我想要在角内使用的实际滑块(非常感谢SomoKRoceS):
document.getElementsByTagName("body")[0].onload = createAnimation;
function createAnimation(){
let e = document.getElementById("logo-gallery"); // Get the element
var style = document.createElement('style'); // Create styling element
style.type = 'text/css'; // Append a css type
// Now create the dynamic keyFrames (that are depend on logo-gallery final width)
// Notice that the width of e is given to translateX at 100%
let keyframes = '\
@keyframes scroll-left {\
0% {\
transform: translateX(0);\
}\
100% {\
transform: translateX(-'+e.scrollWidth+'px);\
}\
}';
style.innerHTML = keyframes; // Set innerHTML of the styling element to the keyframe
document.getElementsByTagName('head')[0].appendChild(style); // append the element to the head of the document as a stylesheet
e.setAttribute("style","animation: scroll-left 20s linear infinite; animation-iteration-count: infinite;"); // Give the element its animation properties.
}#logo-gallery-wrapper {
overflow: hidden;
position: relative;
}
#logo-gallery {
margin: 0;
padding: 0;
position: relative;
list-style-type: none;
display: flex;
}
#logo-gallery .logo-gallery-figure {
margin: 0;
padding: 0 1.6rem;
overflow: hidden;
}
#logo-gallery .logo-gallery-figure img {
height: auto;
max-height: 50px;
position: relative;
filter: grayscale(1);
transition: all .4s;
}
#logo-gallery .logo-gallery-figure img:hover {
filter: grayscale(0);
}<div id="logo-gallery-wrapper">
<ul id="logo-gallery">
<li>
<figure class="logo-gallery-figure">
<img src="https://www.ikea.com/de/de/static/ikea-logo.f88b07ceb5a8c356b7a0fdcc9a563d63.svg">
</figure>
</li>
<li>
<figure class="logo-gallery-figure">
<img src="https://www.ikea.com/de/de/static/ikea-logo.f88b07ceb5a8c356b7a0fdcc9a563d63.svg">
</figure>
</li>
<li>
<figure class="logo-gallery-figure">
<img src="https://www.ikea.com/de/de/static/ikea-logo.f88b07ceb5a8c356b7a0fdcc9a563d63.svg">
</figure>
</li>
<li>
<figure class="logo-gallery-figure">
<img src="https://www.ikea.com/de/de/static/ikea-logo.f88b07ceb5a8c356b7a0fdcc9a563d63.svg">
</figure>
</li>
<li>
<figure class="logo-gallery-figure">
<img src="https://www.ikea.com/de/de/static/ikea-logo.f88b07ceb5a8c356b7a0fdcc9a563d63.svg">
</figure>
</li>
<li>
<figure class="logo-gallery-figure">
<img src="https://www.ikea.com/de/de/static/ikea-logo.f88b07ceb5a8c356b7a0fdcc9a563d63.svg">
</figure>
</li>
<li>
<figure class="logo-gallery-figure">
<img src="https://www.ikea.com/de/de/static/ikea-logo.f88b07ceb5a8c356b7a0fdcc9a563d63.svg">
</figure>
</li>
</ul>
</div>
实际上,我有一个.css、.html和.ts文件的组件。HTML和CSS文件的内容属于这里的内容,但现在我需要将JavaScript转换为角。这是我的.ts文件:
import { Component, Input } from '@angular/core';
@Component({
selector : 'app-logo-gallery',
templateUrl: './logo-gallery.component.html',
styleUrls : ['./logo-gallery.component.css']
})
export class LogoGalleryComponent {
@Input()
logos: string[];
constructor() {
}
}我知道@Component装饰器中有一个动画命令可用,但这是正确的方式吗?如果是,我如何在那里使用它?关键是,我需要以某种方式计算scrollWidth并将其设置为关键帧,否则动画就会出错。
我已经知道可以这样获得元素的宽度:
<ul id="logo-gallery" #logoGallery>TypeScript类
@ViewChild('logoGallery', {static: false}) logoGallery: ElementRef;
this.logoGallery.nativeElement.offsetWidth谢谢你的帮忙!
发布于 2021-01-10 13:14:46
另一种方法是使用角动画。唯一需要考虑的是使用@ViewChildren获取"htmlElement“。如果我可以使用*ngFor,我不喜欢写几个数组,所以我使用一个数组并使用数组编写一个li和另一个。有些人喜欢
有些人喜欢
<div #wrapper id="logo-gallery-wrapper">
<ul #banner id="logo-gallery" >
<li #logo>
<figure class="logo-gallery-figure">
<img (load)="resize()" src="https://www.ikea.com/de/de/static/ikea-logo.f88b07ceb5a8c356b7a0fdcc9a563d63.svg">
</figure>
</li>
<li *ngFor="let i of items;let first=first">
<figure class="logo-gallery-figure">
<img src="https://www.ikea.com/de/de/static/ikea-logo.f88b07ceb5a8c356b7a0fdcc9a563d63.svg">
</figure>
</li>
</ul>
</div>看到第一个“图像”有一个事件“加载”,这个事件就是让我计算出需要多少元素才能启动动画。
logoWidth: number = 0;
items: number[] = [0];
public player: AnimationPlayer;
@ViewChild("wrapper") wrapper: ElementRef;
@ViewChild("logo") logo: ElementRef;
@ViewChild("banner") banner: ElementRef;
constructor(private builder: AnimationBuilder) {}
resize() {
this.logoWidth = this.logo.nativeElement.getBoundingClientRect().width;
this.createAnimation();
}
createAnimation() {
if (this.wrapper && this.logo) {
//width of the "wrapper"
const totalWidth = this.wrapper.nativeElement.getBoundingClientRect()
.width;
//number of element I go to paint
const element = 2 * Math.floor(totalWidth / this.logoWidth);
//I go to translate the "half" of the "ul"
const inc = this.logoWidth * (element / 2);
//I recalculate the number of elements if you resize the window
if (this.items.length != element)
this.items = new Array(element > 0 ? element : 1);
// the time spend in the animation is proportional to the "total width"
const time = 9.2 * totalWidth + "ms";
//create a manual animation
const myAnimation: AnimationFactory = this.builder.build([
style({ transform: `translateX(0px)` }),
animate(time, style({ transform: `translateX(${-inc}px)` }))
]);
this.player = myAnimation.create(this.banner.nativeElement);
//when finish repeat process
this.player.onDone(() => {
this.createAnimation();
});
//finally lauch the animation
this.player.play();
}
}您可以在这一堆闪电战中看到小心!如果您更改了代码,则需要刷新.html以在-else之前执行动画步骤,您可以使导航器崩溃-
另外,您还可以使用mouseover和mouseout暂停/启动动画。
<ul (mouseover)="player.pause()"
(mouseout)="player.play()"
#banner id="logo-gallery" >
...
</ul>更新,如果我们想拥有一系列的imgs和noy,那么会发生什么呢?
技术假设我们有一个数组“重复”。我们需要做两个循环。我们的图像数组称为“徽标”。
<div #wrapper id="logo-gallery-wrapper">
<ul (mouseover)="player.pause()" (mouseout)="player.play()" #banner id="logo-gallery">
<li #logo>
<figure class="logo-gallery-figure">
<img (load)="resize()" [src]="logos[0].url">
</figure>
</li>
<ng-container *ngFor="let i of repeat;let firstRepeat=first">
<ng-container *ngFor="let logo of logos;let firstLogo=first">
<li *ngIf="!firstLogo || !firstRepeat">
<figure class="logo-gallery-figure">
<img [src]="logo.url">
</figure>
</li>
</ng-container>
</ng-container>
</ul>
</div>同样要考虑的是,我们首先编写第一个图像,然后进行这两个循环。这是必要的,因为这是事件中的第一个图像“加载”谁删除动画。不可能在循环中添加,因为我们将更改“重复数组”,这将使我们在每次调整大小时创建一个新的动画。
嗯,这是一个复杂的twoo循环,因为我们不需要绘制这个图像
同样,我们有一个函数createAnimations
createAnimation() {
if (this.wrapper && this.logo) {
//calculate the total width
const totalWidth = this.wrapper.nativeElement.getBoundingClientRect()
.width;
//number of copies necesary
let copies =
2 * Math.floor(totalWidth / (this.logos.length * this.logoWidth)) + 1;
//at least must be 2
if (copies == 1) copies = 2;
//create an array with somany elements than "copies"
this.repeat = ".".repeat(copies).split("");
//we are going to move lo the left only the width of the "first group of images"
const inc = this.logoWidth * this.logos.length;
//rest of code similar, but the speed is proportional to inc
const time = 9.2 * inc+ "ms";
const myAnimation: AnimationFactory = this.builder.build([
style({ transform: `translateX(0px)` }),
animate(time, style({ transform: `translateX(${-inc}px)` }))
]);
this.player = myAnimation.create(this.banner.nativeElement);
this.player.onDone(() => {
this.createAnimation();
});
this.player.play();
}
}(*)为了检查是否一切顺利,我们可以将.css样式更改为overflow:scroll,并添加这一行,以确保计算好了“副本”和"inc“
与通常一样,具有更改的新stackblitz
更新和..。有不同宽度的徽标是什么?
在这种情况下,我们将更改.html。我们用徽标做一个循环,用重复做另一个循环。
<div #wrapper id="logo-gallery-wrapper">
<ul (mouseover)="player.pause()" (mouseout)="player.play()" #banner id="logo-gallery">
<li *ngFor="let logo of logos" #logo>
<figure class="logo-gallery-figure">
<img (load)="loaded()" [src]="logo.url">
</figure>
</li>
<ng-container *ngFor="let i of repeat">
<li *ngFor="let logo of logos">
<figure class="logo-gallery-figure">
<img [src]="logo.url">
</figure>
</li>
</ng-container>
</ul>
</div>请注意,在本例中,(load)事件调用加载了一个函数。其思想是,在这个函数中增加一个变量- -picsLoaded-当所有的徽标被加载时,我们计算出总宽度。确保我们需要使用ViewChildren,而不是ViewChild
totalLogoWidth: number = 0;
picsLoaded=0;
@ViewChildren("logo") logo: QueryList<ElementRef>;
loaded()
{
this.picsLoaded++;
if (this.picsLoaded==this.logos.length)
{
let totalWidth=0;
this.logo.forEach(x=>{
totalWidth+=x.nativeElement.getBoundingClientRect().width;
})
this.totalLogoWidth=totalWidth
this.createAnimation()
}
}现在,只更新函数createAnimation以使用totalLogoWidth而不是this.logos.length*this.logoWidth。
createAnimation() {
if (this.wrapper && this.logo) {
const totalWidth = this.wrapper.nativeElement.getBoundingClientRect()
.width;
//in this case "copies" is simply Math.floor +1
let copies =Math.floor(totalWidth / (this.totalLogoWidth)) + 1;
this.repeat = ".".repeat(copies).split("");
const inc = this.totalLogoWidth;
const time = 9.2 * inc + "ms";
const myAnimation: AnimationFactory = this.builder.build([
style({ transform: `translateX(0px)` }),
animate(time, style({ transform: `translateX(${-inc}px)` }))
]);
this.player = myAnimation.create(this.banner.nativeElement);
this.player.onDone(() => {
this.createAnimation();
});
this.player.play();
}
}另一个stackblitz
发布于 2021-01-09 10:41:19
您可以将js函数放入组件中。演示
import { Component, OnInit } from "@angular/core";
function createAnimation() {
let e = document.getElementById("logo-gallery");
var style = document.createElement("style");
style.type = "text/css";
let keyframes =
"@keyframes scroll-left { 0% {transform: translateX(0);}100% {transform: translateX(-" +
e.scrollWidth +
"px); }}";
style.innerHTML = keyframes;
document.getElementsByTagName("head")[0].appendChild(style);
e.setAttribute(
"style",
"animation: scroll-left 20s linear infinite; animation-iteration-count: infinite;"
);
}
@Component({
selector: "my-app",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent implements OnInit {
name = "Angular";
ngOnInit() {
createAnimation();
}
}但是我通常不选择使用函数作为我选择将一个css放在组件css 演示中的方式。
@keyframes scroll-left
{
0% {transform: translateX(0)}
100% {transform: translateX(var(--m,100%))}
}并给css动画
#logo-gallery {
animation: scroll-left 20s linear infinite;
animation-iteration-count: infinite;
}还有Viwchild
@ViewChild('logoGallery', {static: false}) logoGallery: ElementRef;
ngAfterViewInit(): void {
let element=this.logoGallery.nativeElement;
element.style.setProperty('--m',element.scrollWidth+"px");
}https://stackoverflow.com/questions/65641547
复制相似问题