2017-06-27

tobijibu

anime.jsでfilterが使えない

JavaScriptのアニメーションライブラリで、anime.jsというものがあります。 非常に軽く、設定も簡単なのでとても使いやすいライブラリです。 ホームページはネオンカラーでまとめられていてカッコイイ。

そんなanime.jsを使って、以下のような処理で「文字列のぼかし」をフェードインするようなアニメーションを実装しようとしました。 しかし、動きません。opacityは動くのに、blurだと動きません。 CSSプロパティに問題があるのでしょうか。

html
<span style="filter: blur(10px);">ぼかし</span>
JavaScirpt
let anime = require('animejs');
anime({
  targets: 'span',
  filter: 'blur(0px)',
});

気になったのでanime.jsのソースを見てみました。

どうやら、アニメーションを生成する処理の中で、 CSSのプロパティを分割してアニメーションを生成しているようです(decomposeValue)。 その分割の基準がプロパティの「単位」でした。

function getUnit(val) {
  const split = /([\+\-]?[0-9#\.]+)(%|px|pt|em|rem|in|cm|mm|ex|pc|vw|vh|deg|rad|turn)?/.exec(val);
  if (split) return split[2];
}

opacityは動くのに、blurで動かない理由は、単位の有無による処理の違いだったようです。 ということは、単位で分割しなければいけるかも?と思い、試してみました。

function validateValue(val, unit) {
  unit = ''; // --> unit(単位)を空にする
  if (is.col(val)) return colorToRgb(val);
  //const originalUnit = getUnit(val);      // --> この処理を ↓ に変える
  let originalUnit = val.match(/blur/) ? null : getUnit(val);   // --> 'blur'があればnull
  const unitLess = originalUnit ? val.substr(0, arrayLength(val) - arrayLength(originalUnit)) : val;
  return unit ? unitLess + unit : unitLess;
}

blurでもアニメーションが動くようになりました。
※あくまでテストとして変更しただけなのでコピペ厳禁です。



考えてみればfilterは複雑なプロパティです。 複数のエフェクトをスペース区切りで指定することができますので、 アニメーションの計算が複雑になるのは容易に想像できます。

似たようなプロパティとして、transformがありますが、 translate用の処理は他のプロパティとは別処理になっています。

filterも今後、特殊なパターンとして処理が追加されるかもしれません。 それまでfilterプロパティは使わないか、他のライブラリで処理するか、悩ましいところですね。

そもそもIE系ではfilter自体使えないので、まだまだ先の話と言えそうです。