Reputation: 297
I got a dynamic component, where I add material cards horizontally. After a few cards, the component gets filled, and I can scroll the component. But how can I make it auto scroll horizontally, so that I don't have to use the mouse all the time?
I already tried playing with some css attributes like overflow and so on.
.blocksWrapper {
display: flex;
overflow: auto;
min-height: 305px;
}
I expect, that it autoscrolls horizontally.
This is how it should look like:
But instead it never scrolls automatically.
Upvotes: 3
Views: 18273
Reputation: 175
There are several ways to automatically scroll images:
Move the automatic elements by changing their coordinates with a timer, in this case the animation will be activated even if there is no scrolling.
Use the automatic scrolling of the container with a timer,in this case the animation will be activated only if there is a scolling
Here is an example of automatic scrolling implemented with the first solution.
Html
<div
id="animation1"
class="animatedElementsContainerStyle"
(mouseover)="setAnimationsStatus('pause')"
(mouseout)="setAnimationsStatus('animate')"
>
<div id="animatedItem1" class="animatedItem">
<div class="contentContainer">Item 1</div>
</div>
<div id="animatedItem2" class="animatedItem">
<div class="contentContainer">Item 2</div>
</div>
<div id="animatedItem3" class="animatedItem">
<div class="contentContainer">Item 3</div>
</div>
<div id="animatedItem4" class="animatedItem">
<div class="contentContainer">Item 4</div>
</div>
<div id="animatedItem5" class="animatedItem">
<div class="contentContainer">Item 5</div>
</div>
<div id="animatedItem6" class="animatedItem">
<div class="contentContainer">Item 6</div>
</div>
</div>
CSS
.animatedElementsContainerStyle {
height: 160px;
width: 500px;
height: 140px;
overflow-x: hidden;
overflow-y: hidden;
white-space: nowrap;
position: relative;
}
.animatedItem {
display: inline-block;
width: 200px;
height: 130px;
position: absolute;
background-color: yellow;
font-size: 30;
font-weight: bold;
margin: 0 auto;
cursor: pointer;
}
.animatedItem {
display: inline-block;
}
.contentContainer {
width: 100;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
TypeScript
import { Component } from '@angular/core';
@Component({
selector: 'app-horizentral-animation',
imports: [],
templateUrl: './horizentral-animation.component.html',
styleUrl: './horizentral-animation.component.css',
})
export class HorizentralAnimationComponent {
animationStatus: boolean = true;
constructor() {}
ngAfterViewInit() {
this.startAnimationContainer('animation1');
}
startAnimationContainer(containerName: string) {
let animationContainer = document.getElementById(containerName)!;
let mapArrayLefts = new Map<string, any>();
let marginBetweenAnimatedItems = 200;
let lastElementLeft = 0;
let isViewInitilized: boolean = false;
let allAnimatedItemsWidth = 0;
let containerAnimatedWidth = 0;
var timer = setInterval(() => {
let animatedNodes = animationContainer.querySelectorAll<HTMLElement>(
'#' + containerName + ' .animatedItem'
);
containerAnimatedWidth = animationContainer.getBoundingClientRect().width;
//Init the View before Starting the animation
if (animatedNodes.length > 0) {
if (isViewInitilized == false) {
isViewInitilized = true;
animatedNodes?.forEach((element, index) => {
let itemWidth = element.getBoundingClientRect().width;
allAnimatedItemsWidth = allAnimatedItemsWidth + itemWidth;
});
animatedNodes?.forEach((element, index) => {
if (index == 0 && allAnimatedItemsWidth < containerAnimatedWidth) {
let elLeft = containerAnimatedWidth + 1;
element.style.left = elLeft + 'px';
mapArrayLefts.set(element.id, elLeft);
} else if (
index == 0 &&
allAnimatedItemsWidth > containerAnimatedWidth
) {
let elLeft = 0;
element.style.left = elLeft + 'px';
mapArrayLefts.set(element.id, elLeft);
} else {
let leftPrecdElement =
animatedNodes[index - 1]?.getBoundingClientRect().left;
let leftNewElem = leftPrecdElement + marginBetweenAnimatedItems;
element.style.left = leftNewElem + 'px';
mapArrayLefts.set(element.id, leftNewElem);
}
});
lastElementLeft = mapArrayLefts.get(
animatedNodes[animatedNodes.length - 1].id
);
}
}
// Starting the Animation
if (this.animationStatus == true) {
for (let i = 0; i < animatedNodes!.length; i++) {
let elLeft = mapArrayLefts.get(animatedNodes[i].id);
let newElLX = Number.parseFloat(elLeft) - 1;
mapArrayLefts.set(animatedNodes[i].id, newElLX);
animatedNodes[i].style.left = newElLX + 'px';
}
let topHtmlElement = document.querySelector<HTMLElement>(
'#' + containerName + ' .animatedItem'
);
let topHtmlElementRight = topHtmlElement!.getBoundingClientRect().right;
if (topHtmlElementRight < 0) {
topHtmlElement!.style.left = lastElementLeft + 'px';
animationContainer!.removeChild(topHtmlElement!);
animationContainer!.appendChild(topHtmlElement!);
mapArrayLefts.set(topHtmlElement!.id, lastElementLeft);
}
}
}, 10);
}
setAnimationsStatus(status: string) {
if (status == 'pause') {
this.animationStatus = false;
}
if (status == 'animate') {
this.animationStatus = true;
}
}
}
The implementation of this example can be found on stackblitz here .
Upvotes: 0
Reputation: 6909
There is no automatic feature to auto scroll a div when the size changes.
I suppose you dynamically add your cards using some button? Then you could scroll programatically when adding a card!
Here are multiple suggested solutions:
scrollTo()
behavior of your html element (see this thread). direction: rtl
to set the default scroll bar position to the right (see this thread)Here is an example using the solution 2) : https://angular-dfjmej.stackblitz.io
Maybe it's not the exact render you want, but it's only a matter of settings then.
Upvotes: 3