anime.js_如何使用CSS,anime.js和segment.js与微交互构建下载按钮

anime.js

引言 (Introductions)

In user experience design, microinteractions are small moments of feedback that help a user navigate an interface. Often, microinteractions are made with subtle animation in website design.

在用户体验设计中, 微交互是反馈的一小部分,可帮助用户导航界面。 通常,微交互是通过网站设计中的微妙动画实现的。

In this tutorial, you will build a functional download button with microinteractions. To get it working, we will be using CSS transitions and animations, along with the lightweight animation library anime.js and segment.js for SVG path animations.

在本教程中,您将构建一个具有微交互功能的下载按钮。 为了使其正常工作,我们将使用CSS过渡和动画,以及用于SVG path动画的轻量级动画库anime.jssegment.js

At the end of the tutorial, we will get a download button like this:

在本教程的最后,我们将获得一个下载按钮,如下所示:

The original design of the download button belongs to Pedro Aquino, and can be found on this Dribbble shot. The full code can be found on this Github repository, and here is the demo page.

下载按钮的原始设计属于Pedro Aquino,可以在此Dribbble镜头中找到。 完整的代码可以在这个Github仓库中找到, 是演示页面

第1步-制作HTML结构 (Step 1 — Making the HTML Structure)

Let’s see the HTML code we will be using:

让我们看看我们将使用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>

It is important to note that the SVG path elements have been drawn by hand to get the result we want. For example, at some point, we want the button border to perform an elastic animation, so we need an SVG path ready for that morphing animation with anime.js (same structure in both paths):

重要的是要注意,SVG path元素是手工绘制的,以获得我们想要的结果。 例如,在某个时候,我们希望按钮边框执行弹性动画,因此我们需要一个带有anime.js(两个paths结构相同)的SVG path准备该变形动画:

第2步-添加样式 (Step 2 — Adding Styles)

With our markup ready, let’s style our button. Please note that we are not including the whole stylesheet here, but rather the most important parts; you can find the entire code on the Github repository. The code has been fully commented for better understanding.

准备好标记后,让我们设计按钮的样式。 请注意,我们这里没有包括整个样式表,而是最重要的部分。 您可以在Github存储库中找到整个代码。 该代码已被完全注释以更好地理解。

Let’s see the SCSS variables we have defined, and the helper class to hide elements:

让我们看看我们已定义的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;
}

The styles for the real button element:

实际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%);
  }
}

Our button can be in three different states: downloading, progressing, and completed. We therefore have defined the styles needed for each state using the following structure:

我们的按钮可以处于三种不同的状态: downloadingprogressing中和completed 。 因此,我们使用以下结构定义了每个状态所需的样式:

// 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...
  }
}

Another interesting piece of code is used to achieve the ball animation when the download has finished:

下载完成后,另一段有趣的代码用于实现球形动画:

.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;
  }
}

All the other styles used can be found on the Github repository.

可以在Github存储库中找到所有其他使用的样式。

第3步-使用Java动画制作 (Step 3 — Animating with Javascript)

We will be using anime.js and segment.js, both lightweight libraries to help with animations.

我们将使用anime.jssegment.js ,它们都是轻量级的库来帮助制作动画。

Please note that we will not include some variables declarations in the following code snippets, for the sake of clarity. If you have any doubts, please check the Github repository.

请注意,为了清楚起见,我们在以下代码片段中将不包含某些变量声明。 如有任何疑问,请检查Github存储库

Here is the basic code we are using to capture the click events on the button and perform the behavior we want:

这是我们用来捕获button上的click事件并执行所需行为的基本代码:

// 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']});
}

The animation progress has been faked in the demo; for a real use case it will be replaced with real progress data. This is the function that handles the progress:

动画进度在演示中是伪造的; 对于实际用例,它将被实际进度数据替换。 这是处理进度的函数:

// 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});
}

Finally, here is the piece of code used to perform the animation when download has been completed, where the ball animation is triggered and we morph the path elements.

最后,这是用于在下载完成后执行动画的代码段,其中触发了球动画,并且我们对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);
}

结论 (Conclusion)

This article showed the main pieces of code used to build this download button:

本文展示了用于构建此下载按钮的主要代码片段:

You can play with the live DEMO, or get the full code on Github. Please also note that this component is not fully ready for production, as it needs real progress data and some considerations on how the backend will affect the microinteractions.

您可以玩现场演示 ,或在Github上获取完整代码 。 另请注意,此组件尚未完全准备好投入生产,因为它需要真实的进度数据以及有关后端如何影响微交互的一些注意事项。

翻译自: https://www.digitalocean.com/community/tutorials/how-to-build-a-download-button-with-microinteractions-with-css-anime-js-and-segment-js

anime.js

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当然,我可以使用Anime.js来为你创建一个具有连续动作的动态火柴人动画。请确保已经在HTML文件中引入了Anime.js库,然后可以使用以下代码: ```html <!DOCTYPE html> <html> <head> <title>火柴人动画</title> <style> #canvas { width: 400px; height: 400px; border: 1px solid black; } </style> </head> <body> <div id="canvas"></div> <script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/3.2.1/anime.min.js"></script> <script> const canvas = document.getElementById('canvas'); const animation = anime.timeline({ autoplay: true, loop: true, }); const drawStickMan = () => { const stickMan = document.createElement('div'); stickMan.classList.add('stickman'); canvas.appendChild(stickMan); }; drawStickMan(); animation .add({ targets: '.stickman', translateY: [ { value: 0, duration: 500 }, { value: -80, duration: 300 }, { value: 0, duration: 500 }, ], rotateZ: [ { value: 0, duration: 500 }, { value: 360, duration: 1000 }, ], easing: 'linear', }) .add({ targets: '.stickman', translateY: [ { value: 0, duration: 500 }, { value: -40, duration: 300 }, { value: 0, duration: 500 }, ], rotateZ: [ { value: 0, duration: 500 }, { value: -360, duration: 1000 }, ], easing: 'linear', }) .add({ targets: '.stickman', translateY: [ { value: 0, duration: 500 }, { value: -80, duration: 300 }, { value: 0, duration: 500 }, ], rotateZ: [ { value: 0, duration: 500 }, { value: 360, duration: 1000 }, ], easing: 'linear', }); </script> </body> </html> ``` 在上述代码中,我们使用了Anime.js来创建一个时间轴(timeline),并为火柴人动画添加了一系列连续的动作。在`drawStickMan`函数中,我们创建了一个`div`元素,添加了`stickman`类,并将其附加到Canvas容器中。然后,我们使用Anime.js的时间轴来定义火柴人的动作序列。每个动作都使用`targets`属性指定要应用动画的元素,这里是具有`stickman`类的div元素。通过指定`translateY`和`rotateZ`属性,我们定义了火柴人在垂直和水平方向上的移动和旋转动画效果。我们还设置了持续时间和缓动效果。 你可以根据需要调整动画效果,例如修改持续时间、添加更多动作等。同时,你也可以通过添加CSS样式来美化火柴人的外观。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值