ホームページ >ウェブフロントエンド >htmlチュートリアル >向かってくる瓦礫映像の3D爆発エフェクトを初体験_html/css_WEB-ITnose

向かってくる瓦礫映像の3D爆発エフェクトを初体験_html/css_WEB-ITnose

WBOY
WBOYオリジナル
2016-06-24 11:18:001395ブラウズ

以前、庭園を訪れたときに、ChokCoco さんの爆発エフェクト作品を拝見しました: [BOOM] 面白い Javascript アニメーションエフェクト (英語のスペル間違えましたか←。←)、なかなか面白いと思いました、エフェクトは

ただし、この爆発エフェクトはまだ少し柔らかく、爆発のような破片が飛び散る感覚はありません。私は常に 3D 爆発エフェクトを自分で作りたいと思っていました。過去 2 日間でいくつかの小さなアニメーションを作成し、3D 爆発も作成しました。 アニメーション効果:

実現

原理は非常に単純です。つまり、多くの小さな画像を使用して大きな画像をつなぎ合わせます。絵を描いてから、小さな絵を特定のパターンに従わせます。動きによって爆発的な効果が生まれます。ここでの爆発エフェクトはCSS3の3D変換を利用して作成しており、その変換パラメータをjsで動的に変化させてアニメーションを形成しています。実装手順の簡単な説明:

1. 画像のアセンブリ

このステップは、多くの div タグの背景画像を使用して、各 div タグの位置と背景位置を設定するだけです。ここで注意すべき点は、div タグを追加するときは、必ず innerHTML を使用してすべてを一度に追加することです。ここではピクチャは直接表示されませんが、ここでも新しいイメージが作成され、ロードイベントでピクチャが組み立てられて実行されます。エフェクトとコードは次のとおりです (実際のエフェクトにはグリッド線はありません):

var img = new Image();img.src = 'img/zoro.jpg';    //160*160,or you need to change wrapper's sizeimg.onload = function () {    var x = y = 0,    div = styleCtn = '',    imgWidth = this.width,    imgHeight = this.height,    pwidth = pheight = 10,    nx = Math.floor(imgWidth / pwidth),    //x方向粒子个数    ny = Math.floor(imgHeight / pheight),    //y方向粒子个数    wrap = document.getElementById('zd-wrap');                        for (var i = 0, num = nx * ny; i < num; i++) {        x = (i % nx) * pwidth;        y = Math.floor(i / ny) * 10;    styleCtn = 'left: ' + x + 'px; top: ' + y + 'px; background-position: ' + (-x) + 'px ' + (-y) + 'px;';    div = div + '<div class="bomb" style="background-image: url(' + this.src + '); ' + styleCtn + '"></div>';    }    wrap.innerHTML = div;    //添加图片};

2. 爆発エフェクト

このステップは 3 次元の動きであるため、比較的難しいです。翻訳と反転に分かれる どちらのスポーツもよりシンプルになります。

a) 並進運動: 3 次元空間での爆発は次のようになります:

平面空間に戻ると次のようになります:

上の図から、次のような動きの方向を要約できます。小さなブロック それぞれの場所で移動方向が異なります。 左上隅は左上隅に飛び、右下隅は右下隅に移動します。いくつかの小さな破片が画面に向かって飛んできたり、いくつかの破片が画面から離れて近づいてくる感覚を強調したりする必要があります。 Translate3d は、画面と絵の座標関係に注意して各軸の動きを表現します。実際には画面の Y 軸が垂直方向、下がプラス、Z 軸がプラスになります。ユーザーに向かう方向。動きは次のように要約できます:

左上隅: vx

左下隅: vx 0、vz ランダム

右上隅: vx > 0、vy

右下隅: vx > 0、vy > 0、vz ランダム

ここでの Y 方向は、全体的に上向きです。フィーリング。加速については、重力を模倣する必要があります。vxa = 0、vya = 0.5 (重力の模倣)、vza を適切に追加して、フェースに当たる感覚を高めることができます。

b) 反転モーション

反転効果は X 軸の回転です。効果をよりリアルにするために、Z 軸の回転を導入する必要があります。無視されました。パーティクル パッチのサイズが小さいため、ここで回転パラメータを厳密に制御する必要はありません。これにより、一方ではモデルが簡素化され、他方ではブラウザの負荷が軽減されます。もちろん、回転変数を導入する必要はありません。rotateX(xdeg)rotateY(ydeg) のように X 座標と Y 座標を直接置換することによって、優れた反転効果を得ることができます。ここで Zachstronaut のアルゴリズムを引用しました。終了条件では、パーティクル パッチの x 座標と y 座標に基づいてアニメーション ループを終了するかどうかを判断できます。

このようにして、親オブジェクトの遠近属性をオンにするだけでアニメーションが実現されます。

後ほど

私が使用した画像サイズは 160*160、粒子サイズは 10*10 です。iOS で良好なパフォーマンスを発揮し、モバイル Chrome でも良好なパフォーマンスを発揮します。 GPUアクセラレーションレンダリングといわれていますが、多くの国内モバイルブラウザでは上限に達しているため、パーティクル数を増やすことは推奨されていません。パフォーマンスも改善されましたが、良い突破口は見つかりませんでした。もっと良いアイデアがあれば、私に連絡してください。

時間のかかるテスト:

さらに細分化すると、主にレイヤーの再構成がボトルネックであることがわかります。次に、アニメーション プロセスを見てみましょう:

最初に密集した領域があり、緑色のボックスはペイントのフラッシュ (再描画) が頻繁に発生する場所です。最初に絶対位置 + 左 + 上を使用して背景画像をつなぎ合わせた方法を見てみましょう。これにより、多くの再描画が必要になります。最初にtranslate3d(0, 0, 0)を使用してレンダリングレイヤーを制限して緑のフレームを消すこともできますが、主に時間がかかるのは描画ではなくレイヤーの合成であるため、あまり効果はありません。レイヤー化は必須です。translate を使用して左 + 上を置換することも試しましたが、レンダリングのパフォーマンスを向上させるためのより良い方法は今のところ思いつきません。

DOM の操作を改善することができます。 、そして今度はアニメーション効果です コードは次のとおりです:

rotateX: Math.cos(0.1 *ys) + 'radrotateY: Math.sin(0.1 * xs) + 'rad

循环中每次都会操作dom,而且在设置style上还是用属性查找的方式,那这里应该是可以改善的。一是重写style,避免查找属性。二就是重写父对象div里面的innerHTML,就像开头设置背景图一样,一次更新所有粒子块。

不过我在步进调试的时候发现,除了第一次执行时会一个一个地设置粒子块的属性,后面的动画循环中都已经被浏览器优化成整体重写了,每次更新都是全体更新的,所以上面的方法貌似也不能提升太多。真的没想到其他优化的办法了,如果你有点子,请联系我!

如何使用

源码已经放到GitHub(bomb.js)上面去了,有兴趣的同学可以fork来看看,求星星!

我已经将 js+HTML+CSS 都封装好了,设置好容器之后直接引用bomb.js就可以了,如下:

<style type="text/css">    .wrapper {        width: 160px;        margin: 100px auto 0;        position: relative;        cursor: pointer;        perspective: 200px;    }</style><div class="wrapper" id="zd-wrap"></div>        <script src="js/bomb.js" type="text/javascript" charset="utf-8"></script><script type="text/javascript">    var explore = new ParticlesTemplate(),        exploreImg = new Image(),        wrapper = document.getElementById('zd-wrap');    exploreImg.src = 'img/zoro.jpg';        exploreImg.onload = function () {        explore.init(exploreImg, wrapper);        wrapper.addEventListener('click', function () {            explore.go();        }, false);    };</script>

 

就写到这了,码字不易,随手点赞哈~~~

参考资料:

1) 【BOOM】一款有趣的Javascript动画效果

2) 前端性能优化(CSS动画篇)

3) http://www.zachstronaut.com/

 

(图片出处:小周)

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。