필기 스타일 SVG 패스 애니메이션 구현

필기 스타일의 패스 애니메이션을 구현하기위한 기초 및 절차에 대해 설명합니다.
결국 다음과 같은 것을 만들 수 있습니다.



패스 애니메이션의 기초



패스 애니메이션을 수행하는 데 중요한 것은 CSS stroke-dasharraystroke-dashoffset입니다.
stroke-dasharray 는 파선을 실현하기 위한 프로퍼티입니다.
값으로 실선 부분과 틈 부분의 길이를 지정할 수 있습니다.
path.line {
    /* 線の長さ(dash):10 隙間(gap):3 */
    stroke-dasharray: 10 3;
}


stroke-dashoffset는 점선 오프셋을 지정하는 속성입니다.
조금 이해하기 어렵지만이 속성을 지정하면 경로의 시작 방향으로 전체가 슬라이드됩니다.
path.line {
    /* 線の長さ(dash):10 隙間(gap):3 */
    stroke-dasharray: 10 3;
    /* オフセット: 5 */
    stroke-dashoffset: 5;
}



이미지는 왼쪽에서 오른쪽 경로이므로 전체가 왼쪽으로 슬라이드합니다.
(오프셋 부분은 실제로 표시되지 않습니다.)

실선의 길이와 오프셋을 동일하게 하면 패스가 틈에서 시작합니다.
path.line {
    /* 線の長さ(dash):10 隙間(gap):3 */
    stroke-dasharray: 10 3;
    /* オフセット: 10 */
    stroke-dashoffset: 10;
}



실선, 틈, 오프셋을 모두 같은 길이 그리고 패스의 길이 이상으로 했을 경우, 틈 부분만이 묘화 영역에 존재하게 되므로 아무것도 표시되지 않게 됩니다.
path.line {
    /* 線の長さと隙間が同じ場合は一つのみ指定する */
    stroke-dasharray: 30;
    /* オフセット: 30 */
    stroke-dashoffset: 30;
}



이 상태에서 오프셋을 조금씩 0에 가까이 하면 조금씩 선이 표시됩니다.
path.line {
    /* 線の長さ(dash):30 隙間(gap):30 */
    stroke-dasharray: 30;

    animation: pathanim 3s;
    animation-iteration-count: infinite;
}

@keyframes pathanim {
    0% {
        stroke-dashoffset: 30;
    }
    100% {
        stroke-dashoffset: 0;
    }
}



이것이 패스 애니메이션의 기본입니다.
(애니메이션 시작시 미묘하게 선이 표시되는 경우 stroke-dasharray를 조정하십시오.)

보충:SVG 파일 만들기



SVG 패스 애니메이션을 만들기 위해서는 무엇보다 SVG 파일이 필요합니다.
처음 SVG는 잉크스케이프에서 만들었습니다.
Inkscape에서 패스 애니메이션용 SVG 파일을 만들 때 저장할 때 파일 형식을 최적화 SVG로 만듭니다.

보충 2:SVG 파일을 수동으로 편집



Inkscape에서 출력한 SVG는 생각한 경로가 아닐 수 있습니다.
그 경우는 여기 를 참고로 하면서 텍스트 에디터로 패스를 편집합니다.

필기 바람 패스 애니메이션



이번에는 다음 두 가지를 구현합니다.
  • 1 패스씩 그리기
  • 그려진 중간 경로의 색상 변경

  • 후자는 사람에 따라 필요하지 않을 수 있습니다.
    이 컨트롤은 js를 사용해야하지만 이번에는 vivus.js이라는 라이브러리를 사용합니다.
    vivus.js 은 잘 만들어진 라이브러리로 1 패스씩 그려야 하는 요망을 충족하면 거의 아무것도 쓰지 않고 실현할 수 있습니다.

    한 패스씩 그리기


    <!-- vivus.js読み込み -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vivus/0.4.4/vivus.js"></script>
    
    <svg id="svg">
        <!-- ...複数のパス... -->
    </svg>
    
    new Vivus('svg', {
        // アニメーション再生タイプ
        // 'oneByOne'を指定すると1パスずつのアニメーションになる
        type: 'oneByOne',
    
        // アニメーション全体の長さ
        // 総フレーム数で指定する
        // fpsで割ると秒数になる
        // 60fpsで動いている場合は5秒になる
        duration: 300,
    });
    



    이것만으로 한 패스씩 애니메이션을 할 수 있습니다.
    이것이 요구 사항을 충족하는 경우 특히 더 이상 할 필요가 없습니다.

    그려진 중간 경로의 색상 변경



    vivus.js 표준은 이 기능을 제공하지 않으므로 직접 구현해야 합니다.
    구현 방법은 간단하고 현재의 재생 시간으로부터 그려지고 있는 중간의 패스를 특정해, 그 패스의 색을 바꿉니다.
    /* 描画中のパスに適応するスタイル */
    path.active {
        stroke: tomato;
    }
    
    const v = new Vivus('svg', {
        // アニメーション再生タイプ
        // 'oneByOne'を指定すると1パスずつのアニメーションになる
        type: 'oneByOne',
    
        // アニメーション全体の長さ
        // 総フレーム数で指定する
        // fpsで割ると秒数になる
        // 60fpsで動いている場合は5秒になる
        duration: 300,
    
        // 自動で更新されないようにする
        start: 'manual',
    });
    
    // 描画の更新
    const f = () => {
        // vivusの内部フレームを進める
        const progress = (v.currentFrame + 1) / v.duration;
        v.setFrameProgress(progress);
    
        // vivusが管理しているパスのリスト
        const map = v.map;
    
        // 完了していない場合
        if (progress < 1) {
            let frame = 0;
            // パスのリストから現在描画しているパスを特定する
            for (let i = 0; i < map.length; i++) {
                const path = map[i];
                // パスの終了フレーム
                const next = frame + path.duration
    
                // 描画中のパスではない
                if (v.currentFrame < frame || v.currentFrame >= next) {
                    // クラスを削除
                    path.el.classList.remove('active');
                }
                // 描画中のパス
                else {
                    // クラスを追加
                    if (!path.el.classList.contains('active')) {
                        path.el.classList.add('active');
                    }
                }
                frame = next;
            }
    
            requestAnimationFrame(f);
        }
        // 完了している場合
        else {
            for (let i = 0; i < map.length; i++) {
                map[i].el.classList.remove('active');
            }
    
            // ループさせる場合
            setTimeout(() => {
                v.setFrameProgress(0);
                f();
            }, 3000);
        }
    };
    
    requestAnimationFrame(f);
    



    마지막으로



    기초 부분을 모르더라도 vivus.js 그러면 쉽게 패스 애니메이션을 구현할 수 있습니다.
    라이브러리를 사용하지 않고 스스로 구현하는 경우나 vivus.js 로 실현할 수 없는 것을 실현하고 싶은 경우는 기초 부분이 도움이 되는 일도 있을지도 모릅니다.

    좋은 웹페이지 즐겨찾기