画像スライスのカルーセル効果

序文

あるウェブサイトに思わずアクセスしたところ、ホームページのカルーセル効果に惹かれ、ブラウザのデバッグで実装原理を理解し、自分でコピーを書きました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

hook5がありdiv、それぞれ、SHOW2.jpg対応する映像カットの問題が今直面しは、どのようにこのようにすることです51は、divこの絵その一部を拡大していましたか?

hook外側のコンテナを設定する場合1000px、サブ要素5数のdiv平均の合計幅が200px1秒で提供される場合があり、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番目のスライス位置を占める右に移動します。5div200px200js200px

imgwidth合計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>
     `     
  }

5divのステッチが完了すると、中にそれを入れ<div class="hook"></div>て、ページの文書のレンダリングに追加します。最終的に生成されたdom要素は次のアニメーション化するための要素です。

以来、絶対位置との組の値が設定され、それらは一度レンダリングようにページの一番上の位置にあります。5divtop-100%

次のアニメーション効果は非常に簡単に実現できます上記のループでそれぞれにdiv1つずつ追加するだけですtransition:top linear 0.25s

ことを一度レンダリングが完了すると、私たちはできる動的それぞれに設定されたの値アニメーションがトリガされ、各ページには、ゆっくりと上から下にスライドします。5divjsdivtop0div

すべてのアニメーションプロセスが完了するまで待ちます。hookこの使用法jsdom削除れて生成され、表示されるはずですitem(元の静止画像を含むdom)は、この時点から非表示で表示されるように設定され、アニメーションプロセス全体が完了します。

3D効果

平面効果の実装は比較的簡単であり、3D反転効果では最初に属性を理解する必要がcssあり3dます。

3Dプロパティレビュー

rotateXX回転軸の周り、Lenovo 单杠运动
rotateYY回転軸の周り、Lenovo 钢管舞
rotateZZ回転軸の周り、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そしてtranslateXtranslateYこれら2つの属性は同じではありません。translateX平面内を移動しようとしていtranslateYます。垂直平面内を移動します。

translateZこれは3d属性です。平面上で上下左右の変位を作成するのではなく、平面に垂直な方向の内外に変位を作成します。

translateZ(-100px)これは、要素が画面の内側に移動したことを意味します100px。近い、大きい、遠い、小さいの規則に従って、要素の最終的な視覚効果は全体として100px減少します。正の場合100px、要素はに移動します。画面の外側にあり、要素の視覚効果が拡大されます。

translateZpreserve-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>

leftrightfrontおよびup親要素、充填されている絶対位置、幅及び高さに設定されているlefttop設定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サーフェスは最初に左下隅に中心点を設定し、X90中心に回転してから、高さ全体を上に移動して上部を形成します。

.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設定されています3dperspectiveperspective-origin

1つcontainerはキューブスライスに対応し、カットされたすべてのキューブによって形成されたhtml文字列がページドキュメントに配置されてレンダリングされます。このようにして、アニメーション化されたdom要素が生成されます。

フリップアニメーションを追加する

アニメーションdom実行する要素が生成され、ページにレンダリングされています。前の分析によると、各キューブ(wrapper対応するdiv)にrotateX(-90deg)属性追加すると、キューブが反転する可能性があります。結果は次のとおりです。

ここに画像の説明を挿入します
wrapperさらに、rotateX(-90deg)属性は実際に前方に反転されますが、最終的な位置は地面に近くありません。

事故の原因は、wrapper単純な平面ではなく立方体であり、4つの平面も含まれていたためです。立方体を回転させるとき、その中心点の位置は非常に重要です。

wrapperの高さは100%親全体でいっぱいです。テストの結果、立方体の属性変換は実際には正面(front面)に基づいていることがわかりました。立方体の中心点は面の高さのfront中央にあります。 。front高さが、の600px場合300pxX軸を描画するとき立方体全体をこの軸に沿って回転させます。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動的に割り当てるだけで済みます。

ソースコード

完全なコード

おすすめ

転載: blog.csdn.net/brokenkay/article/details/115034048
おすすめ