本来やりたかったこと
react-slickを使って無限ループするアニメーションを作成しようとしたところ、autoplay:true,autospeed:0にしても若干カルーセルスライドが中央に来るたびに一瞬止まってしまい、カクついたアニメーションになってしまう問題がありました。
そこで簡易のアニメーションをするコンポーネントを作成しました。
1. コンポーネントの概要
まずは、アニメーションを実装するための主要なコンポーネントAnimationを作ります簡略化のため、サンプルの画像表示用のSampleImageというコンポーネントを使用しています。
import React from 'react';
import { Box } from '@mui/material';
import styled from '@emotion/styled';
const Animation = ({ items }) => {
const animationDistance = 149 * items.length;
return (
<StyledSlider distance={animationDistance}>
<div className="custom-slider-container">
{renderItems(items)}
</div>
</StyledSlider>
);
};
const renderItems = (items) => (
<>
{items.map((item, index) => (
<div key={index} className="custom-slider-item">
<SampleImage item={item} />
</div>
))}
{items.map((item, index) => (
<div key={index} className="custom-slider-item">
<SampleImage item={item} />
</div>
))}
</>
);
const SampleImage = ({ item }) => (
<img src={item.src} alt={item.alt} width={139} height={65} />
);
2. スタイルとアニメーションの設定
次にemotionを利用してアニメーションとスタイルを適用します。
const StyledSlider = styled(Box)<{ distance: number }>`
width: 100vw;
overflow: hidden;
.custom-slider-container {
overflow: hidden;
white-space: nowrap;
height: 〇〇px; // 任意の数字を記載してください
align-items: center;
}
.custom-slider-item {
display: inline-block;
width: 139px; // 任意の数字を記載してください
margin-right: 10px;
animation: customSlide ${props => props.distance / 149 * 2}s linear infinite;
// 任意の数字に合わせてanimationを変更する必要があります
}
@keyframes customSlide {
from {
transform: translateX(0);
}
to {
transform: translateX(calc(-149px * ${props => props.distance / 149}));
// 任意の数字に合わせてanimationを変更する必要があります
}
}
`;
ポイントと詳細な説明
- 無限ループ: 同じリストを2回繰り返し表示することで、無限ループのように見せています。
- アニメーションの距離の計算: animationDistance = 149 * items.lengthでアニメーションが移動する総距離を計算しています。149は、画像の幅(139px)とマージン(10px)の合計です、任意の数に合わせて書き換える必要があります。
- items.lengthはアイテムの数を表し、アニメーションが完全に1サイクルするための移動距離を計算します。
例: 5つのアイテムがある場合、移動距離は149 * 5 = 745pxとなります。 - アニメーションの時間: props.distance / 149 * 2でアニメーションの速度を計算しています。5つのアイテムの場合、アニメーションの速度は745 / 149 * 2 = 10秒で、1サイクル完了するのに10秒かかることを意味します。
任意のスピードにしたい場合は書き換える必要があります
使用例
以下は、このコンポーネントの基本的な使用例です。
const sampleItems = [
{ src: 'path/to/image1.jpg', alt: 'image1' },
{ src: 'path/to/image2.jpg', alt: 'image2' },
// ...他の画像
];
function App() {
return <Animation items={sampleItems} />;
}
export default App;