動かない!?anime.jsでsvgのテキストアニメーションの作り方【fillのサンプル】

anime jsの使い方覚書です。

前半はqiitaに寄稿しました。後半は主にsvgアニメーションの解説です。

Qiita
anime.jsの使い方(callback/timeline/fade/blur)【vue(nuxt.js)】 - Qiita 実経験に基づき、anime.jsの使い方まとめです。callback、timeline、fade、blurなどの機能を試しました。JSのアニメーションライブラリ比較、anime.jsを採用した理由まずJS...

anime jsはtimeline内loopできない!?

タイムラインの最後でループさせようと思いました。

iconが上下に移動するコードですが、こういうコードでは1回しか実装されません。

.add({
  targets: '.icon-anime',
  loop: true,
  keyframes: [
    {
      translateY: [-20, 0],
      duration: 1000,
      easing: 'linear'
    },
    {
      translateY: [0, -20],
      duration: 1000,
      easing: 'linear'
    }
  ]
})

こういう画面はcompleteの使い所のようです。これでうまくいきました。

complete: () => {
  anime({
    targets: '.icon-anime',
    loop: true,
    keyframes: [
        {
          translateY: [-20, 0],
          duration: 1000,
          easing: 'linear'
        },
        {
          translateY: [0, -20],
          duration: 1000,
          easing: 'linear'
        }
    ]
  })
}

短くかくなら、direction: ‘alternate’を使うとよいです。座標飛びしないように基本的にこの書き方がよさそうです。

anime({
    targets: '.icon-anime',
    loop: true,
    direction: 'alternate',
    duration: 3000,
    translateY: -30,
    easing: 'linear'
})

keyframesはどちらかというと、loopではなく順番に実行するものに使った方がよさそうです。

スポンサーリンク

動かない!?anime.jsでsvgのpathアニメーションの作り方【サンプル】

svgのフォントが変わる原因はエスクポートデータがおかしい

illustratorやaffinity designer、クリスタでSVGファイルを作成します。

もっていない人はこの機会に契約や入手してもよいでしょう。

AdobeはxdがあったりAdobe fontsがついていたりすることがメリットです。

ER Game Design
値上げ!Adobeプラチナスクールパートナーの通信講座比較! Adobe製品を安く買う方法まとめです。 Adobeプラチナスクールパートナーの通信講座が値上げ?【速報】 残念ながら2024年12月1日(日)から値上げされます。ヾ(。・ω・)ノ゚  ...

クリスタとaffinity designerは安価な買い切りです。

ER Game Design
クリスタを安く買う!買い切りのセールはいつで頻度は!?割引は? CLIP STUDIO PAINT ProとEXは公式サイトが最安値です。 クリスタを安く買う!買い切りのセールはいつで頻度は!?割引は? クリスタの過去セールは!? クリスタはあまりセールを...
ER Game Design
Affinity Designer v2の使い方!何ができる!? Affinity Designerを導入しました。 UIはクリスタよりわかりやすく迷うことがありませんでした。数時間で実作業レベルまで使えるようになりましたので、解説不要なソフトか...

フォントはいい感じのものを用意します。フォントワークス などの有料フォントやフリーフォントがありますが、アウトライン化のライセンスを確認します。SVGはアウトライン化しますがHtmlに変換されるため組み込みとは別のようです。

ebookbrain
買い切り/月額/商用フリーのフォントワークスなど(手書き風/筆文字/ペン字/スクリプト)おすすめ本 スクリプト、手書き風、筆文字、ペン字などのフォントをまとめていきます。いろいろなところから情報収集しました。書籍Photoshopvipさんcolissさんフォントワークス の有...

データを作る際、注意事項があります。

1、アウトライン化して書き出す必要があります(勘違いする人は少ないかもですが、ラスタライズはピクセル化ですから違いますよ)。

2、文字が表示される順番がある場合、グラフィックソフトでデータを作る際に下側にあるデータから表示されるようなので1文字ずつ分割してデータを作っておきます。アウトライン化した時点でそうなるはずですが、テキストや図形が複数ある場合はこの点を注意しましょう。

3、グラフィックソフトによりますが、レイヤーなど日本語で名前をつけているとidが日本語になる場合があります。グラフィックソフト側で英語に変えとくべきでしょう。なお、グラフィックソフトによるかもしれませんが、非表示レイヤーの情報は書き出されないようです。

4、1つのアニメーショングループに対して、1つのSVGファイルがよいです。1回テキストやパーツごとに分けて書き出してテストしたのですが、座標調整が大変になります。1つのviewBoxで管理するとよいです。もしもマスクなどを作る場合は、VsCode上で切り分ける形にします。

5、affinity designer側で特殊効果(FX)などをつけると、エクスポート時にdefsに大量のデータが生成されてうまく表示されないことがあります。たとえば、やりがちなのが文字の縁取りです。ただのベタ塗りがよいでしょう。

svgの表示

エクスポートしたのち、SVGファイルを右クリックしてVsCodeで開きます。

そうするとSVGのデータを取得できます。

svgの部分をhtmlに埋め込むと表示できます。

<svg width="100%" height="100%">
</svg>

幅と高さは100%になっていましたが、削ってCSS側で指定してあげてもいいかもしれません。

svgのviewbox

viewboxは描画領域のことです。

viewBox="x, y, width, height"

下記の例は幅1200、高さ2100です。

<svg width="100%" height="100%" viewBox="0 0 1200 2100"

anime.jsでsvgのpathが動かない!?

あとはanime.jsでアニメーションさせるだけです。

とはいえ、最初、コピペするだけでは動きませんでした。動かない場合はidやclass名を見直しましょう。グラフィックソフトの階層構造や図形なのか否かによって名前が変わるようです。

pathにclassが全部あれば動くはずです。

<path class="text-anime'">
</path>
anime({
    targets: '.text-anime',
    strokeDashoffset: [anime.setDashoffset, 0],
    easing: 'easeInOutSine',
    duration: 500,
    delay(el, i) {
      return i * 3000
    }
})

実際は面倒なのでid pathなんか指定されて紹介されていますね。

targets: '#id path',

図形にclass名の指定がなかったため手動指定しました。

また文字や図形が線だと思っていたけど実は塗りだったというオチでも動きません。線にアニメをかけているわけなので。うっかりと塗りを書き出さないようにします。

複数指定

targets: '#id path, #id2 path, .class path, #shap rect, #shap path',

アウトラインはpath、図形はrectになっていました。他useなどいろいろあるようです。

fill(塗りつぶし)

タイムラインにすると線画アニメーションしたあと、塗りつぶせます。

const timeline = anime.timeline({
    targets: '#id path, #id2 path, .class path',
    direction: 'normal',
    loop: false
})
timeline.add({
    strokeDashoffset: [anime.setDashoffset, 0],
    easing: 'easeInOutSine',
    fill: ['transparent', 'transparent'],
    duration: 2000,
    delay(el, i) {
    return i * 150
    }
})
timeline.add(
    {
    easing: 'easeInOutSine',
    fill: ['transparent', '#ffffff'],
    duration: 500
    },
    '-=200'
)
スポンサーリンク

動かない!?anime.jsでsvgのマスクアニメーションの作り方【サンプル】

マスクアニメーションを利用すると手書きアニメーションが実現できます。

上記の方法は線画を描いて塗りです。ただ、文字を普通に描いていく方法がデザイン的にはしっくりきますし、企業サイトで使われているものはそっちの方が多いです。

まず、マスクの理解が必要です。

囲った場所が消えます。

<defs>
    <mask id="maskname">
        <!-- pathを入れる -->
    </mask>
</defs>
<image :href="require('~/assets/images/anime/sample.svg')" width="100%" height="100%" mask="url(#maskname)" />

ただ、こちら実際に作ってみましたが手間暇かかります。一応、ざっくりと解説してみました。

svgのマスクアニメーションの作り方
  • Step1
    データを作成します。

    マスクのスタイルは消すので、わかりやすい色でOKです。ここは特に難しくありませんし、解説したサイトもたくさんあります。

    Adobe Illustrator、クリスタ、affinity designerなどの選択肢があります。ソフトにより若干吐き出されるデータが違う気もしますが、SVGは後から編集できるため、どれでもいいです。

    ER Game Design
    値上げ!Adobeプラチナスクールパートナーの通信講座比較! Adobe製品を安く買う方法まとめです。 Adobeプラチナスクールパートナーの通信講座が値上げ?【速報】 残念ながら2024年12月1日(日)から値上げされます。ヾ(。・ω・)ノ゚  ...
    ER Game Design
    クリスタを安く買う!買い切りのセールはいつで頻度は!?割引は? CLIP STUDIO PAINT ProとEXは公式サイトが最安値です。 クリスタを安く買う!買い切りのセールはいつで頻度は!?割引は? クリスタの過去セールは!? クリスタはあまりセールを...
    ebookbrain
    Affinity Designer v2(アフィニティデザイナー)の書き出し(エクスポート)(ai/eps/svg/psd/png/pdf/互換性) Affinity Designerの書き出しの覚書です。Mac版のuiは書き出しなのですが、Windowsのuiはエクスポートです(両方持ちです)。翻訳が違う!?。。ため、そこは補完して読んでく...

    書き出す際に、マスクをかける画像と、その他全部(マスクを含む)は別々に書き出します。座標は合致するようにしておきます。

    SVGの外にあるコードは削ってOKです。Vs Codeで開いて削る手順になります。

    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
    ↑いらないコード
    <svg>
    いるコード
    <svg>

    そのうえでマスクをかける画像データはVs Codeのassets内にいれておきます。

  • Step2
    まず外部リンクを表示しましょう。

    マスク云々の前にまずはマスクする画像を外部リンクとして表示しましょう。作業は切り分けておこなうとよいです。

    <image :href="require('~/assets/images/anime/sample.svg')" width="100%" height="100%" mask="url(#maskname)" />

    リンク先がフォントを指定した画像です。リンク元がなぞったマスクです。逆にしないように注意してください。

    いくつかひっかりそうなところがあります。

    参考まですが、nuxt(vue)の場合、リンクの書き方が変わります。

    あわせて読みたい

    xlink:hrefは非推奨になっています。

    MDN Web Docs
    xlink:href - SVG: Scalable Vector Graphics | MDN The xlink:href attribute defines a reference to a resource as a reference IRI. The exact meaning of that link depends on the context of each element using it.

    nuxtの場合、imageのリンクはrequareを使わないとうまく表示されません。:をつけてあげること。:href

    検証方法はChromeの検証から画像がリンクされているか確認すればOKです。また座標があっているかですね。凡ミスはたいてい座標系です。

  • Step3
    マスクだけ表示する

    次マスクだけ表示します。あえてマスクのコードをコメントアウトします。

    <!-- <defs>
        <mask id="maskname"> -->
        <g id="mask">
        マスクのpath
        </g>
        <!-- </mask>
    </defs> -->

    defsとmaskをコメントアウトするとマスクの形を見ることができます。cssの適応が正しくできるか検証できます。defsはなくてもいいですけど、推奨になっています。

    マスクの部分だけコピペすると、作りによって階層構造ががあわず座標ずれする場合もあります。その場合は上位階層も含めてコピペします。

    imageのmaskのurlを#にすると、マスクがかかっていない状態になります。
    urlを適用するとはじめてマスクがかかります。

    マスクのコードにはなぞった色のstyleが適応されています。

    そのコードは全部省いて白で塗りつぶします。

    マスクを省いた状態でアニメーションまでできるか検証してもよいでしょう。

  • Step4
    マスクの適用

    ここまで動いたら簡単です。マスクを適用して画像を消しましょう。

  • Step5
    アニメーション

    最後にアニメーションを適用させましょう。

    anime.jsの場合、strokeDashoffsetでよさそうです。今回、マスクがラインなので。

    strokeDashoffset: [anime.setDashoffset, 0]
    あわせて読みたい
    Documentation A fast and versatile JavaScript animation library

templeteをまとめるとこんな感じです。コンポーネント化した方がよいでしょう。

<template>
  <div>
    <b-row class="mx-0 my-0 py-5 px-0">
      <b-col cols="12">
        <div class="animebox box-centering">
          <div style="width: 800px;">
            <svg id="svg" x="0px" y="0px" viewBox="0 0 1200 600" xmlns="http://www.w3.org/2000/svg">
              <defs>
                <mask id="maskname">
                  <g id="mask"></g>
                </mask>
              </defs>
              <image
                :href="require('~/assets/images/anime/sample.svg')"
                width="100%"
                height="100%"
                mask="url(#maskname)"
              />
            </svg>
          </div>
        </div>
      </b-col>
    </b-row>
  </div>
</template>
スポンサーリンク

anime.js側でscaleすると座標がおかしくなる!transformが効かない!

scaleすると、次のCSSが効いていませんでした。!importantを使うとアニメーションしなくなるため、anime.js側で解決する必要がありそうです。

transform: translateX(-50%) translateY(-50%);

初期値で座標を固定してあげるとよさそうです。改善しました。

anime({
  targets: '.logo-anime',
  translateX: ['-50%', '-50%'],
  translateY: ['-50%', '-50%']
})

他に解決方法があれば知りたいところです。

簡単でしたが、参考になれば幸いです。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする