AIイラストをCSSで簡単にモーションコミックにする方法
以前、実験的にCSSで「AIイラストエロ漫画風「お姉ちゃんが弟のお世話をするやさしい世界」(の最後のコマだけ)をモーションコミック風にしてみましたが、そのやり方について簡単に解説してみます。
そんな解説どこにでもありそうなものだけれど、軽くググった限りではAdobeのAfterEffectsを使う大仰な方法が多く、それじゃ毎月のコストで断念してしまう人もいるのでは、と。
CSS(スタイルシート)が使えないブログとか見たことないし、文字が書けるならHTMLタグは書けるし、HTMLタグ書けるならCSSだって書けるとぼくは思っているので、必要としている人のところに届けばいいな。
下準備(コマの分割)
今回モーションコミック風にするのはこちらの1枚。
最初から複雑なことをすると二の足を踏むかもなので、今回は簡単に6コマに分けます。
ぼくはInkscapeで作っているので、背景色を透明にした後、不要なコマを削除してエクスポート、というのを6回やっただけ。
使っているソフトによるけれど、レイヤー使えないソフトで漫画描く人はいないでしょう。
レイヤー(=層)という横文字聞くだけで拒否反応起こす人もいるけれど、単に紙を重ねているだけの話です。上に紙を重ねるときにハサミで一部切り取っておけば、下の紙が見えるでしょ。紙芝居でも使われる手法だし、窓あき封筒と思っても良い。
要はそういう切り抜いた同じサイズの紙をゆっくりと6回重ねていくだけの話です。
今回はコマの中で人物が動いたり、背景がスクロールするような表現はせず、単にじわじわコマが進んでいく感じにするだけなのでとても単純。
コマごとにサイズの違う画像を用意しなきゃいけないのかな?とか複雑に考えちゃう人いそうなので、まずはとにかく簡単に、同じサイズの紙を重ねる、これに集中します。
HTMLで画像を重ねる方法
ブログをやっていれば<img src="[画像]">という書き方で画像を貼るのは知っていると思いますが、先ほど作った画像1~6をそのまま貼り付けても横か縦に並んで表示されるだけで、重なり合うことはありません。
これを重ねるためにCSSを使います。
<div class="img_wrapper">
<img src="[画像1]">
<img src="[画像2]">
<img src="[画像3]">
<img src="[画像4]">
<img src="[画像5]">
<img src="[画像6]">
</div>
<style>
.img_wrapper {
position:relative;
}
.img_wrapper img {
position:absolute;
}
</style>
少しややこしくなったかな? でも、ここが一番のポイントで、ここさえ理解すればレイヤーをブログ上で表現することが自由自在にできるようになる、ハズ。ポイントは以下のとおり。
- 6枚並べた画像をdivタグで囲む
- そのdivタグのクラス名にimg_wrapperと名付ける(名前は何でもいい)
- styleタグでクラス名img_wrapperのpositionプロパティをrelative(相対配置)に変更
- クラス名img_wrapperの中にある全てのimgタグのpositionプロパティをabsolute(絶対指定)に変更
するとどうなるか。
こうなります。
最初に表示したコミックと何が違うねん!って感じですが、今回は1枚の絵ではなく、分割した6枚を重ねて表示している点が大きく異なります。
CSSアニメーションでコマを順番に出す方法
まずは結果から、↓の枠をクリック(タップ)すると3秒ごとに新しいコマが増えていきます。
最後まで再生したら、もう一回クリックすると白紙に。さらにもう一回クリックすることでアニメ再生がはじまります。
全然難しいことはしていません。先ほどの6枚重ねが出来たなら、あとはそれらを順番に表示するだけ。
なにも1枚1枚バカ正直に重ねていく必要はありません。CSSにopacity(透明度)という便利なプロパティがあるので、最初に6枚を重ねてしまって、あとは下から順番にopacityを0(透明)から1(不透明)にするだけなのです。
やり方ですが、まず先ほど書いたCSSにopacity:0;を加えます。
.img_wrapper img {
position:absolute;
opacity:0;
}
そして、アニメーションのキーフレーム(要は動き方)を定義。
@keyframes fadeIn {
0% { opacity:0; }
100% { opacity:1; }
}
アニメーションの進行度0%~100%の範囲で、細かな制御もできますが、今回はとにかく簡単に、がテーマなので0と100しか定義していません。開始時点では0(透明)、終了時は1(不透明)、ただそれだけ。
そして、画像6コマ分にこのキーフレームを指定するのですが、6個あるのでさすがにちょっと長いです。
.motion_comic img:nth-of-type(1) {
animation:3s fadeIn 0s 1 normal forwards ease-in-out;
}
.motion_comic img:nth-of-type(2) {
animation:3s fadeIn 3s 1 normal forwards ease-in-out;
}
.motion_comic img:nth-of-type(3) {
animation:3s fadeIn 6s 1 normal forwards ease-in-out;
}
.motion_comic img:nth-of-type(4) {
animation:3s fadeIn 9s 1 normal forwards ease-in-out;
}
.motion_comic img:nth-of-type(5) {
animation:3s fadeIn 12s 1 normal forwards ease-in-out;
}
.motion_comic img:nth-of-type(6) {
animation:3s fadeIn 15s 1 normal forwards ease-in-out;
}
motion_comicという新しいクラス名を作っていますが、これはクリックでの開始/終了を実現するためです。
CSSアニメーションにはそもそもアニメの開始や終了をさせる仕組みがないため、motion_comicというimg_wrapperとは別のクラス名で定義しておいて、アニメの開始時にJavaScriptでこのクラス名を設定/除去してあげることで、ユーザー操作によるアニメの開始/停止を実現しています。
CSSだけじゃないじゃん!というツッコミがあるかもですが、あくまで開始/終了にしか使っていないのでCSSだけでモーションコミックの実現は可能だし、なんなら一生ループするように書くことも可能です。ただ、終了タイミング(=白紙にする)の秒数計算が面倒くさいので、1行書くだけで済むJavaScriptで再生/停止を実装しました。
<div class="img_wrapper" onclick="this.classList.toggle('motion_comic');">
実際こんだけなんですよ。toggleという関数でクラス名の切り替えができるので、下手にループアニメをがんばるより、クリックで再生/停止させたほうが楽なの。
CSSのほうに話を戻します。
img:nth-of-type(1)~nth-of-type(6)については何となく字面だけでわかるんじゃないかと思いますが、同じタグの何番目か、という指定。つまり、nth-of-type(1)は1個目のimgタグ。nth-of-type(6)は6個目のimgタグってことですね。imgタグひとつひとつにクラス名書くのめんどいから、こんな書き方をしています。
animation:3s fadeIn 0s 1 normal forwards ease-in-out;
アニメーションプロパティについてはパッと見じゃワケがわからないと思うけれど、ググればドキュメントが出てくるし、順番を覚えるだけです。
- 1個目はアニメーションの再生時間。3sと指定されているので3秒間再生されるという意味。
- 2個目はキーフレーム名の指定。先ほど作った fadeIn というキーフレームを指定。
- 3個目は開始ディレイ。アニメを開始するまでに何秒待つかって指定。1~6コマあるため、それぞれ0s 3s 6s 9s ...とそれぞれ3秒遅れてアニメ再生を開始していることがわかるはず。
- 4個目は繰り返し回数。1を指定しているので1回のみ。infiniteと指定すればループ再生も可能。
- 5個目は終了時の動作。forwardsは終了時のアニメの状態を保ったままという意味。noneやbackwardsを指定することで最初の状態(=透明)にして終わることも可能。
- 6個目はアニメーションの周期タイミング。ease-in-outは徐々に早くなる。linearを指定すると一定速度にすることも可能。
まぁこのへんは解説されればされるほど複雑に感じちゃうかも知れない。実際には上で書いた単純なタグで済むのだから、習うより慣れろ、が正解かも。
応用編
応用…というほどすごいものでもないのだけれど、じわじわ表示するだけでどこがモーションやねん、とガッカリする人もいるかもなので、もう少しだけ動作を追加。
クリックするとコミックが再生されます。
先ほどのサンプルに加え、スライドとシェイクのモーションを加えただけだけれど、少しはそれっぽくなったんじゃないでしょうか。
HTMLソース
参考までにHTMLソースの全文も載せておきます。お好きにお使いください。
<div class="img_wrapper" onclick="this.classList.toggle('motion_comic');">
<p>クリックするとコミックが再生されます。</p>
<img src="[画像1]">
<img src="[画像2]">
<img src="[画像3]">
<img src="[画像4]">
<img src="[画像5]">
<img src="[画像6]">
</div>
<style>
.img_wrapper {
position:relative;
border:1px solid lightgray;
width:100%;
aspect-ratio:10/16;
cursor:pointer;
}
.img_wrapper p {
position:absolute;
display:block;
height:2em;
width:100%;
text-align:center;
top:0;bottom:0;
margin:auto;
color:gray;
}
.img_wrapper img {
position:absolute;
max-width:100%;
opacity:0;
}
.motion_comic p {
opacity:0;
}
.motion_comic img:nth-of-type(1) {
animation:3s fadeIn 0s 1 normal forwards ease-in-out;
}
.motion_comic img:nth-of-type(2) {
animation:3s fadeIn 5s 1 normal forwards ease-in-out;
}
.motion_comic img:nth-of-type(3) {
animation:1s slide 10s 1 normal forwards ease-in-out;
}
.motion_comic img:nth-of-type(4) {
animation:3s fadeIn 11s 1 normal forwards ease-in-out;
}
.motion_comic img:nth-of-type(5) {
animation:1s fadeIn 11s infinite alternate forwards ease-in-out;
}
.motion_comic img:nth-of-type(6) {
animation:0.1s shake 18s 15 normal forwards linear;
}
@keyframes fadeIn {
0% { opacity:0; }
100% { opacity:1; }
}
@keyframes slide {
0% { left:-100%;opacity:1; }
100% { left:0%;opacity:1; }
}
@keyframes shake {
0% { opacity:1;top:-2%; }
100% { opacity:1;top:0%; }
}
</style>
まとめ
AIイラストの普及でエロ漫画モーションコミック作る人増えるといいなぁ。














