CSS、anime.js、segment.jsとのマイクロインタラクションを使用してダウンロードボタンを作成する方法
はじめに
ユーザーエクスペリエンスデザインでは、マイクロインタラクションは、ユーザーがインターフェイスをナビゲートするのに役立つ小さなフィードバックの瞬間です。 多くの場合、マイクロインタラクションはウェブサイトのデザインの微妙なアニメーションで行われます。
このチュートリアルでは、マイクロインタラクションを備えた機能的なダウンロードボタンを作成します。 これを機能させるために、CSSトランジションとアニメーションを使用し、SVGpath
アニメーション用の軽量アニメーションライブラリanime.jsとsegment.jsを使用します。
チュートリアルの最後に、次のようなダウンロードボタンが表示されます。
ダウンロードボタンのオリジナルデザインはPedroAquinoのもので、このドリブルショットにあります。 完全なコードはこのGithubリポジトリにあり、ここにデモページがあります。
ステップ1—HTML構造を作成する
使用するHTMLコードを見てみましょう。
<!-- Button container --> <div class="download-button-container"> <!-- The real button --> <button class="download-button"> <span class="button-text-real hidden">download</span> <!-- Extra elements to perform the animations --> <span class="button-icon"> <span class="button-linear-progress"> <span class="button-linear-progress-bar"></span> </span> <svg class="button-icon-svg" viewBox="0 0 60 60"> <path class="button-icon-path button-icon-path-square" d="M 20 40 l 0 -20 l 20 0 l 0 20 Z"></path> <path class="button-icon-path button-icon-path-line" d="M 40 20 l -20 20"></path> </svg> </span> </button> <!-- Extra elements to perform the animations --> <svg class="border-svg" width="240px" height="100px" viewBox="0 0 240 100"> <path class="border-path hidden" d="M 40 3.5 a 36.5 36.5 0 0 0 -36.5 36.5 a 36.5 36.5 0 0 0 36.5 36.5 C 70 76.5 90 76.5 120 76.5 S 170 76.5 200 76.5 a 36.5 36.5 0 0 0 36.5 -36.5 a 36.5 36.5 0 0 0 -36.5 -36.5 Z"></path> </svg> <span class="button-text button-text-download">download</span> <span class="button-text button-text-done">done!</span> <div class="button-wave"></div> <div class="button-progress-container"> <svg class="button-svg"> <path class="button-circular-progress" d="M 50 50 m 0 -32.5 a 32.5 32.5 0 0 1 0 65 a 32.5 32.5 0 0 1 0 -65"></path> </svg> <span class="button-ball"></span> </div> </div>
SVG path
要素は、目的の結果を得るために手作業で描画されていることに注意してください。 たとえば、ある時点で、ボタンの境界線に弾力性のあるアニメーションを実行させたいので、anime.jsを使用したモーフィングアニメーション用のSVG path
が必要です(paths
の両方で同じ構造) :
ステップ2—スタイルを追加する
マークアップの準備ができたら、ボタンのスタイルを設定しましょう。 ここにはスタイルシート全体ではなく、最も重要な部分が含まれていることに注意してください。 コード全体はGithubリポジトリにあります。 理解を深めるために、コードは完全にコメント化されています。
定義したSCSS変数と、要素を非表示にするヘルパークラスを見てみましょう。
// Some variables to use later $button-width: 300px; $button-height: 70px; $button-border: 3px; $icon-padding: 5px; $icon-width: $button-height - ($icon-padding * 2); $ball-width: 18px; // Helper class to hide elements .hidden { visibility: hidden !important; opacity: 0 !important; }
実際のbutton
要素のスタイル:
// Real button styles .download-button { position: relative; display: inline-block; width: $button-width; height: $button-height; background-color: #2C2E2F; border: none; box-shadow: 0 0 0 $button-border #02D1FF; // This will be our 'border' border-radius: 100px; cursor: pointer; transition: 1s width, 0.3s box-shadow; // Remove the custom behavior in some browsers &, &:focus { padding: 0; outline: none; } &::-moz-focus-inner { border: 0; } // Styles for the different states of the button &:hover, &:active, &:focus { box-shadow: 0 0 0 $button-border #02D1FF, 0 0 20px $button-border darken(#02D1FF, 20%); } }
ボタンは、downloading
、progressing
、およびcompleted
の3つの異なる状態にすることができます。 したがって、次の構造を使用して、各状態に必要なスタイルを定義しました。
// Button container .download-button-container { // ...CODE... // Following are the different states for the button: downloading, progressing and completed // We have defined the states in the container to have access to all descendants in CSS // Downloading: The download button has been pressed &.downloading { // ...CODE... } // Progressing: The progress starts &.progressing { // ...CODE... } // Completed: The progress ends &.completed { // ...CODE... } }
ダウンロードが終了したときにボールアニメーションを実現するために、もう1つの興味深いコードが使用されます。
.button-ball { left: 50%; transition: none; // CSS animations for the ball. All of them start at the same time, so we need to take care of delays animation: ball-throw-up 0.5s ease-out forwards, // Throw up the ball for 0.5s ball-throw-down 0.5s 0.5s ease-in forwards, // Wait 0.5 seconds (throw up), and throw down the ball for 0.5s ball-rubber 1s forwards; // Move the ball like a rubber deformation during 1s (throw up + throw down) } // Throw up animation @keyframes ball-throw-up { from { transform: translate(-50%, 17.5px); } to { transform: translate(-50%, -60px); background-color: #00FF8D; } } // Throw down animation @keyframes ball-throw-down { from { transform: translate(-50%, -60px); } to { transform: translate(-50%, 80px); } } // Rubber animation @keyframes ball-rubber { from { width: $ball-width; } 25% { width: $ball-width * 0.75; } 50% { width: $ball-width; } to { width: $ball-width / 2; } }
使用されている他のすべてのスタイルは、Githubリポジトリにあります。
ステップ3—Javascriptを使用したアニメーション
アニメーションを支援する軽量ライブラリであるanime.jsとsegment.jsを使用します。
わかりやすくするために、以下のコードスニペットには一部の変数宣言を含めないことに注意してください。 疑問がある場合は、Githubリポジトリを確認してください。
button
のクリックイベントをキャプチャし、必要な動作を実行するために使用している基本的なコードは次のとおりです。
// Capture click events button.addEventListener('click', function () { if (!completed) { // Don't do anything if downloading has been completed if (downloading) { // If it's downloading, stop the download stopDownload(); } else { // Start the download startDownload(); } } }); // Start the download function startDownload() { // Update variables and CSS classes downloading = true; buttonContainer.classList.add('downloading'); animateIcon(); // Update progress after 1s progressTimer = setTimeout(function () { buttonContainer.classList.add('progressing'); animateProgress(); }, 1000); } // Stop the download function stopDownload() { // Update variables and CSS classes downloading = false; clearTimeout(progressTimer); buttonContainer.classList.remove('downloading'); buttonContainer.classList.remove('progressing'); // Stop progress and draw icons back to initial state stopProgress(); iconLine.draw(0, '100%', 1, {easing: anime.easings['easeOutCubic']}); iconSquare.draw('30%', '70%', 1, {easing: anime.easings['easeOutQuad']}); }
アニメーションの進行状況はデモで偽造されています。 実際のユースケースでは、実際の進捗データに置き換えられます。 これは、進行状況を処理する関数です。
// Progress animation function animateProgress() { // Fake progress animation from 0 to 100% // This should be replaced with real progress data (real progress percent instead '100%'), and maybe called multiple times circularProgressBar.draw(0, '100%', 2.5, {easing: anime.easings['easeInQuart'], update: updateProgress, callback: completedAnimation}); }
最後に、ダウンロードが完了したときにアニメーションを実行するために使用されるコードを次に示します。ここで、ボールアニメーションがトリガーされ、path
要素がモーフィングされます。
// Animation performed when download has been completed function completedAnimation() { // Update variables and CSS classes completed = true; buttonContainer.classList.add('completed'); // Wait 1s for the ball animation setTimeout(function () { button.classList.add('button-hidden'); ball.classList.add('hidden'); borderPath.classList.remove('hidden'); // Morphing the path to the second shape var morph = anime({ targets: borderPath, d: 'M 40 3.5 a 36.5 36.5 0 0 0 -36.5 36.5 a 36.5 36.5 0 0 0 10.5 26.5 C 35 86.5 90 91.5 120 91.5 S 205 86.5 226 66.5 a 36.5 36.5 0 0 0 10.5 -26.5 a 36.5 36.5 0 0 0 -36.5 -36.5 Z', duration: 100, easing: 'linear', complete: function () { // Morphing the path back to the original shape with elasticity morph = anime({ targets: borderPath, d: 'M 40 3.5 a 36.5 36.5 0 0 0 -36.5 36.5 a 36.5 36.5 0 0 0 36.5 36.5 C 70 76.5 90 76.5 120 76.5 S 170 76.5 200 76.5 a 36.5 36.5 0 0 0 36.5 -36.5 a 36.5 36.5 0 0 0 -36.5 -36.5 Z', duration: 1000, elasticity: 600, complete: function () { // Update variables and CSS classes, and return the button to the original state completed = false; setTimeout(function () { buttonContainer.classList.remove('completed'); button.classList.remove('button-hidden'); ball.classList.remove('hidden'); borderPath.classList.add('hidden'); stopDownload(); }, 500); } }); } }); }, 1000); }
結論
この記事では、このダウンロードボタンの作成に使用される主なコードを示しました。
ライブデモで遊ぶか、Githubで完全なコードを取得できます。 また、このコンポーネントは、実際の進捗データと、バックエンドがマイクロインタラクションにどのように影響するかについての考慮事項が必要なため、完全に本番環境に対応できる状態ではないことにも注意してください。