0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Reactとemotionで実装する無限ループのアニメーション

Posted at

本来やりたかったこと

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;
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?