react-marquee-slider
Have a look through the various usecases and their code. At the end is a demo with adjustable settings.
StarTake me to the project siteNote: The flickering ("jumping") of the items in the Marquee is not a bug. When you want to position items inside the slider randomly, the slider needs to actually render them, to see if the random positioning will fit inside the given area. If it doesn't (e.g. items are overlapping), it tries to find another place for the overlapping item. Depending on the number and size of items, and the size of the available space, overlapping items are more or less likely.
You can hide the flickering by overlaying the slider with a loading div, until it finishes. The slider provides an onFinish
callback for this very reason. You can see an example with an overlaying loading div further down.
The above Marquee is still rendering.
Here is the essential code for the above example, or you can have a more in depth look at the original, full code:
import React from "react";
import Marquee from "react-marquee-slider";
import times from "lodash/times";
const Reviews = () => (
<Marquee key={key} velocity={25} scatterRandomly minScale={0.7}>
{times(5, String).map(id => (
<Box key={`marquee-example-review-${id}`} scale={scale}>
<Review scale={scale}>
<Avatar scale={scale}>
<img src="https://randomuser.me/api/portraits/women/68.jpg" />
</Avatar>
<Content scale={scale}>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua.
</p>
</Content>
</Review>
</Box>
))}
</Marquee>
);
The above Marquee is still rendering.
Here is the essential code for the above example, or you can have a more in depth look at the original, full code:
import React from "react";
import Marquee, { Motion } from "react-marquee-slider";
import times from "lodash/times";
const Reviews = () => (
<FullWidth>
<Height height={500}>
<Marquee key={key} velocity={12} scatterRandomly minScale={0.7} resetAfterTries={200}>
{_.times(8, Number).map(id => (
<Motion
key={`marquee-example-company-${id}`}
initDeg={randomIntFromInterval(0, 360)}
direction={Math.random() > 0.5 ? "clockwise" : "counterclockwise"}
velocity={10}
radius={scale * 100}
>
<Company scale={scale}>
<Circle scale={scale}>
<Logo src={icons[id]} />
</Circle>
</Company>
</Motion>
))}
</Marquee>
</Height>
</FullWidth>
);
The above Marquee shows instantly and doesn't require computation time, because the child elements are not positioned (scattered) randomly.
Here is the essential code for the above example, or you can have a more in depth look at the original, full code:
import React from "react";
import Marquee from "react-marquee-slider";
import styled from "styled-components";
import times from "lodash/times";
const Photo = styled.img`
width: 368px;
height: 200px;
border-radius: 4px;
box-shadow: 0 7px 20px 0 rgba(0, 0, 0, 0.12);
object-fit: cover;
object-position: top;
`;
const Reviews = () => (
<div>
<div style={{ height: 200 }}>
<Marquee key={key} velocity={25}>
{times(7, Number).map(id => (
<Photo src={photos[id]} key={`marquee-example-people-${id}`} style={{
marginLeft: "87px",
}} />
))}
</Marquee>
</div>
<div style={{ height: scale * 60 }} />
<div style={{ height: 200 }}>
<Marquee key={key} velocity={25}>
{times(7, Number).map(id => (
<Photo
src={photos[id + 7]}
key={`marquee-example-people-${id + 7}`}
style={{
marginLeft: "7px",
marginRight: "80px",
}}
/>
))}
</Marquee>
</div>
</div>
);
The above Marquee is still rendering.
Have a look at the original, full code for this example or just the basic, simplified gist:
import React, { useState } from "react";
import Marquee, {
Scale,
Motion,
randomIntFromInterval,
randomFloatFromInterval
} from "react-marquee-slider";
import styled from "styled-components";
import times from "lodash/times";
const icons = [
"https://url.com/to/some/icon1.png",
"https://url.com/to/some/icon2.png",
// ... more of those paths
];
const Loading = styled.div`
display: flex;
position: absolute;
left: 0;
top: 0;
right: 0;
left: 0;
width: 100%;
height: 100%;
transition: all 1s linear;
background: #fff;
justify-content: center;
align-items: center;
`;
const Reviews = () => {
const [loading, setLoading] = useState(true);
const iconsMeta = [];
for (let i = 0; i < icons.length; i++) {
iconsMeta.push({
initDeg: randomIntFromInterval(0, 360),
direction: Math.random() > 0.5 ? "clockwise" : "counterclockwise",
scale: randomFloatFromInterval(0.7, 1),
});
}
return (
<div style={{
position: "relative",
width: "100%",
height: "500px";
background: "transparent"
}}>
<Marquee
direction={ltr}
velocity={15}
scatterRandomly={true}
minScale={0.7}
maxScale={1}
resetAfterTries={200}
onFinish={() => setLoading(false)}
>
{times(8, Number).map(index => (
<Scale scale={iconsMeta[index].scale} key={`marquee-example-playground-${index}`}>
<Motion
{...iconsMeta[index]}
velocity={15}
radius={100}
backgroundColors={{
"container": "transparent",
"buffer": "transparent",
"earth": "transparent",
"solarSystem": "transparent"
}}
>
<Company>
<Circle>
<Logo src={icons[index]} />
</Circle>
</Company>
</Motion>
</Scale>
))}
</Marquee>
<Loading style={{ opacity: 1; }}>
<LoadingIcon />
</Loading>
</div>
);
};