序文
あるウェブサイトに思わずアクセスしたところ、ホームページのカルーセル効果に惹かれ、ブラウザのデバッグで実装原理を理解し、自分でコピーを書きましたDemo
。最終的な効果は次のとおりです。ソースコードは最後にあります)
平面効果:
3D効果:
このカルーセルは、画像をいくつかの部分にカットし、次にアニメーション効果を使用してカットされた部分を再生し、最後にそれらを新しい画像にステッチします。
フロントエンドのテクノロジースタックをリコールする過程で、画像を直接トリミングして複数の部分に分割できるテクノロジーはないようです。通常適用される画像トリミング効果はcanvas
、生成をシミュレートするためにのみ使用されます。
私自身のデバッグにより、このカルーセル画像はcanvas
同じトリミング効果を実現するためのより簡単な方法を使用していることがわかりました。
次に、実装の原則を明らかにするために、浅いものから深いものへと段階的に進みます。
平面効果
平面効果から始めましょう。最初に一般的なhtml
カルーセル図を書きます。構造は次のとおりです。
<div class="main" id="el">
<div class="item">
<img src="./img/1.jpg" />
</div>
<div class="item">
<img src="./img/2.jpg" />
</div>
<div class="item">
<img src="./img/3.jpg" />
</div>
</div>
el
これは、3枚のカルーセル画像が入っている外側のコンテナです。
アニメーション効果を作成したい場合は、手順に従う必要があります。
- アニメーション化する
dom
要素を生成または取得します dom
要素にアニメーション効果を追加します
次の図に示すように、平面効果のアニメーションを遅くし、その特性を注意深く観察します。
html
この画像スライスは元のコードにはありません。つまり、アニメーション化する要素を生成し、レンダリングのためにページドキュメントに追加する必要があります。
設定画像を5
パーツにカットする場合、スライス画像構造は次のように生成されます。
<div class="main" id="el">
<div class="item">
<img src="./img/1.jpg" />
</div>
<div class="item">
<img src="./img/2.jpg" />
</div>
<div class="item">
<img src="./img/3.jpg" />
</div>
<!--做动画的dom元素-->
<div class="hook">
<div><img src="./img/2.jpg" /></div>
<div><img src="./img/2.jpg" /></div>
<div><img src="./img/2.jpg" /></div>
<div><img src="./img/2.jpg" /></div>
<div><img src="./img/2.jpg" /></div>
</div>
</div>
元のページ内のjs
期間と呼ばれるクラスの生成hook
のをhtml片段
測位モードとして、absolute
。
hook
5がありdiv
、それぞれ、SHOW2.jpg
対応する映像カットの問題が今直面しは、どのようにこのようにすることです5
1は、div
この絵その一部を拡大していましたか?
hook
外側のコンテナを設定する場合1000px
、サブ要素5
数のdiv
平均の合計幅が200px
1秒で提供される場合があり、2番目のカットdiv
のみを表示img
します。
<div style="position:absolute;width:200px;left:200px;overflow:hidden">
<img src="./img/2.jpg" style="position:absolute;width:500%;left:-200px"/>
</div>
外層の全幅なので、それぞれを表す部分1000px
にカットし(実際のコーディングでは計算による)、次に2番目のスライス位置を占める右に移動します。5
div
200px
200
js
200px
img
width
合計のleft
割り当てが重要なポイントであり、その特定の値は、合計幅とスライス数によっても計算されます。
width
に設定します500%
。これは、画像の幅が1000px
最も外側のコンテナと等しいことを意味し、次に左に移動し200px
ます。親がdiv
設定されているのでoverflow:hidden
、効果を想像してください。
上記のこれらのプロセスは、次のように接続してjs
文字列html字符串
で計算する必要があります:
for(i=0;i<n;i++){ //循环i次,n(总共将图片切成n份),unit_width对应每一个切块的宽度
html += `
<div
style="position:absolute;
width:${unit_width}px;
top:-100%;
left:${ i * unit_width};
overflow:hidden">
<img src="${src}"
style="position:absolute;
width:${n*100}%;
left:${-i * unit_width}px"/>
</div>
`
}
5
後div
のステッチが完了すると、中にそれを入れ<div class="hook"></div>
て、ページの文書のレンダリングに追加します。最終的に生成されたdom
要素は次のアニメーション化するための要素です。
以来、絶対位置との組の値が設定され、それらは一度レンダリングようにページの一番上の位置にあります。5
div
top
-100%
次のアニメーション効果は非常に簡単に実現できます。上記のループでそれぞれにdiv
1つずつ追加するだけですtransition:top linear 0.25s
。
ことを一度レンダリングが完了すると、私たちはできる動的それぞれに設定されたのの値アニメーションがトリガされ、各ページには、ゆっくりと上から下にスライドします。5
div
js
div
top
0
div
すべてのアニメーションプロセスが完了するまで待ちます。hook
この使用法js
はdom
削除されて生成され、表示されるはずですitem
(元の静止画像を含むdom
)は、この時点から非表示で表示されるように設定され、アニメーションプロセス全体が完了します。
3D効果
平面効果の実装は比較的簡単であり、3D
反転効果では最初に属性を理解する必要がcss
あり3d
ます。
3Dプロパティレビュー
rotateX
:X
回転軸の周り、Lenovo 单杠运动
。
rotateY
:Y
回転軸の周り、Lenovo 钢管舞
。
rotateZ
:Z
回転軸の周り、Lenovo 老式钟表盘
。
上記の3つの属性は通常頻繁に連絡されるため、繰り返しません。以下では3d
属性に焦点を当てます。
.container{
perspective: 1200px;
perspective-origin: right center;
.wrapper {
transform-style: preserve-3d;
transform:translateZ(-100px);
}
}
外側のコンテナcontainer
には子が含まれていますwrapper
。子は3d
アニメーション化される特定の要素であるため、プロパティを設定する必要がありますtransform-style: preserve-3d
。
設定されている場合にのみ、preserve-3d
要素はその3d
効果を示すことができます。
translateZ
そしてtranslateX
、translateY
これら2つの属性は同じではありません。translateX
平面内を移動しようとしていtranslateY
ます。垂直平面内を移動します。
translateZ
これは3d
属性です。平面上で上下左右の変位を作成するのではなく、平面に垂直な方向の内外に変位を作成します。
translateZ(-100px)
これは、要素が画面の内側に移動したことを意味します100px
。近い、大きい、遠い、小さいの規則に従って、要素の最終的な視覚効果は全体として100px
減少します。正の場合100px
、要素はに移動します。画面の外側にあり、要素の視覚効果が拡大されます。
translateZ
preserve-3d
属性が設定されている要素にのみ適用すると効果があり、preserve-3d
すべての3d
属性が効果を発揮します。
block
要素される3d
形質転換dom
、それは設定する必要があるので、preserve-3d
そしてtransform
形質転換した。親要素であるcontainer
段階に相当し、block
ステージパフォーマンスのアクターとみなすことができます。
perspective
観客とステージとの距離を表しておりperspective
、値が小さいほど観客がステージに近づき、ステージ上のシーンがより鮮明に見えると考えられます。
実際のシーンにperspective
対応しdom
、ユーザーの目の要素間の距離に対応して、距離が大きくなるほどwrapper
、内部は小さくなり、透明度が低くなります。逆に、perspective
大きくwrapper
なるほど、外観は大きくなり、内部の詳細がより明確になります。
perspective-origin
講堂の左、中、右のいずれに座って舞台での演奏を見ているのかがわかり、視野の効果が異なります。
ここでトピックに戻り3d
、フリップ効果のカルーセル図の調査を続けます。次の図に示すように、アニメーション時間を遅くして、その詳細を観察します。
上の写真を見て、アニメーション化する要素が現在のページでは利用できず、js
動的に生成する必要があることにすぐに気付きました。
アニメーション要素は、2つのモーションエフェクトを含む立方体です。1つは左に移動し、もう1つは前方に反転します。左に移動するのは簡単で、絶対位置の動的変更left
値に設定します。RotateX(-90deg)
Arrived(X
軸に沿った反転90
度に相当)を設定することによって実行されます。
立方体のアニメーション効果を実現するのは難しくありません。難しいのは、そのような立方体を生成する方法にあります。
立方体を描く
現在のシーンでは、立方体は上、前、左、右の4つの面を描画するだけで済みます。上はカルーセルになる次の画像用に保存され、前面は現在表示されている画像用に保存され、左と右は黒。背景は画像をより立体的にするために塗りつぶされてhtml
います。構造は次のとおりです。
<div class="wrapper">
<div class="left"></div>
<div class="right"></div>
<div class="front"><img src="1.jpg"></div>
<div class="up"><img src="2.jpg"></div>
</div>
left
、right
、front
およびup
親要素、充填されている絶対位置、幅及び高さに設定されているleft
とtop
設定0
。
front
真正面の顔で、もともとは平面に表示されているので、何もする必要はありません。
left
中心点を左上隅に配置するには、y
軸に沿ったレンダリング90
度が側面を形成します。
.left {
transform-origin: 0% 0%;
transform: rotateY(90deg);
background-color: #333;
}
right
幅全体を右に移動してから、y軸90
に沿って回転して右側を形成する必要があります。
html += `
... //js中dom字符串拼接
<div class="right" style="transform: translateX(${unit_width}px) rotateY(90deg);">
...
</div>
...
`
up
サーフェスは最初に左下隅に中心点を設定し、X
軸90
を中心に回転してから、高さ全体を上に移動して上部を形成します。
.up{
transform-origin: 0% 100%;
}
html += `
... //js中dom字符串拼接
<div class="up" style="transform: rotateX(90deg) translateZ(${container_height}px);">
...
</div>
...
`
これらの4つの面のdom
構造はjs
内部で接合され、wrapper
対応する親に配置されdiv
ます。前述のように、属性wrapper
は内部preserve-3d
で設定する必要wrapper
があり、要素は実際にアニメーション化される要素ですdom
。
wrapper
要素がカプセル化された後、ステージ要素に投げ込まれcontainer
、および属性とcontainer
設定されています。3d
perspective
perspective-origin
1つcontainer
はキューブスライスに対応し、カットされたすべてのキューブによって形成されたhtml
文字列がページドキュメントに配置されてレンダリングされます。このようにして、アニメーション化されたdom
要素が生成されます。
フリップアニメーションを追加する
アニメーションdom
を実行する要素が生成され、ページにレンダリングされています。前の分析によると、各キューブ(wrapper
対応するdiv
)にrotateX(-90deg)
属性を追加すると、キューブが反転する可能性があります。結果は次のとおりです。
wrapper
さらに、rotateX(-90deg)
属性は実際に前方に反転されますが、最終的な位置は地面に近くありません。
事故の原因は、wrapper
単純な平面ではなく立方体であり、4つの平面も含まれていたためです。立方体を回転させるとき、その中心点の位置は非常に重要です。
wrapper
の高さは100%
親全体でいっぱいです。テストの結果、立方体の属性変換は実際には正面(front
面)に基づいていることがわかりました。立方体の中心点は面の高さのfront
中央にあります。 。front
面の高さが、の600px
場合300px
、X
軸を描画するときは、立方体全体をこの軸に沿って回転させます。front
面の高さが800px
、の場合、立方体は400px
軸に沿って回転します。
上記の場合に戻りfront
、面の高さが100%
親要素を満たすように設定されます。次に、立方体が中央に軸を描画して前方90
に反転するため、下にくぼみができます。立方体を配置することはできません。空中で向きを変えて停止し、地面に戻す方法を見つけます。
前に言ったように、立方体はfront
サーフェスを参照サーフェスとして使用します。90
次数を反転すると、front
サーフェスが下になります。次にfront
、この時点で立方体が下を向いているため、立方体を下に移動します。translateZ(contrainer_height/2)
立方体を下に動かすためにそれを設定する必要があるだけです。高さの半分は底に取り付けられています。
この設定により、反転した立方体を確実に下部に取り付けることができますが、その中の画像は変形します。
立方体をrotateX(-90deg)
前に倒すように設定すると、実際には前に移動します。大小のルールに従って、画像の視覚効果が拡大されます。この問題を解決するには、まず立方体translateZ(-contrainer_height/2)
を使用して半分を押します。内側の高さを計算してから、立方体を前方に反転させて、画像のストレッチの問題を解決します。コードは次のとおりです。
while ((el = eles.shift())) {
//el对应着每个立方体的dom
//立方体先沿Z轴往后推一半高度,再朝前做翻转,翻转完后向下移动一半高度贴底
el.style.transform = `translateZ(${
-this.container_height / 2
}px) rotateX(-90deg) translateZ(${this.container_height / 2}px)`;
...
}
反転効果が終了すると、立方体が私たちの方を向いて反転していることがわかります。背景が黒の立方体の右側が見えないright
ため、非常に無次元に見えます。
先ほど属性を紹介しましたが、perspective-origin:right center
これは講堂の右側に座っている観客のようなもので、ステージは講堂と同じくらい広く、観客の正面を向いたステージには鉄の檻があります。観客の視界は鉄の檻の正面でしか見ることができません。ケージをステージの左側に押すと、観客の右側に座っている顧客は鉄の檻の正面だけを見ることができません。 、しかし彼はまた鉄の檻の右側を見ることができます。
同様に、立方体を反転させたときに立体的に見えるようにするには、アニメーション中に右側の黒い背景を表示できます。この目的を達成するには、立方体を左側に移動する必要があります。 、さらにperspective-origin
属性のサポート、キューブ反転した3次元効果が出てきます。
キューブを左に移動する場合dom
は、キューブの要素を取得してleft
動的に割り当てるだけで済みます。