如何实现含动画效果的 Material Design 中的 Snackbar

Snackbar 是 Material Design 中的一种弹出式交互控件,可以在屏幕底部或顶部弹出一条消息,类似于 Toast,但具有更加复杂的 UI 和交互特性。Snackbar 通常用于提示用户操作的状态或重要事件,并且支持包含图标、动作按钮等多种内容。

本文将介绍如何使用 HTML、CSS 和 JavaScript 实现含动画效果的 Material Design 中的 Snackbar。

实现思路

Snackbar 的实现可以分为以下三个部分:

  1. HTML 结构:Snackbar 包含消息内容、动作按钮等多个元素,需要用 HTML 定义它们的关系和样式。
  2. CSS 样式:Snackbar 包含很多动画效果,需要使用 CSS 规定它们的动画过渡、位置、尺寸和颜色等。
  3. JavaScript 控制:Snackbar 需要在页面加载时自动弹出并且能够接受用户的交互操作,需要使用 JavaScript 实现自动弹出和多种交互效果。

下面我们将分别介绍这三个方面的实现细节。

HTML 结构

Snackbar 的 HTML 结构主要包括以下几个部分:

  1. 消息内容:用一个 div 元素包含消息内容,可以使用标签、文本和图标等。
  2. 动作按钮:可以选择包含一个动作按钮,用于用户点击后执行操作,通常放在消息内容之后。
  3. 关闭按钮:Snackbar 包含一个关闭按钮,用于用户手动关闭它,通常放在消息内容之后。
  4. 容器元素:Snackbar 要放在页面的底部或顶部,需要使用一个固定定位的容器元素作为其父元素。

下面是一个简单的 Snackbar 的 HTML 结构示例:

<div class="snackbar-container">
  <div class="snackbar-message">
    <span>这是一条消息</span>
  </div>
  <div class="snackbar-action">
    <button>操作</button>
  </div>
  <div class="snackbar-close">✖</div>
</div>

CSS 样式

Snackbar 的 CSS 样式主要包括以下几个部分:

  1. 位置和尺寸:Snackbar 要定位在屏幕的底部或顶部,需要使用绝对定位或固定定位实现。另外,Snackbar 的尺寸可以根据内容的宽度和高度自适应。
  2. 动画效果:Snackbar 的出现、消失和用户交互过程需要使用 CSS 动画实现,包括渐显、渐隐、上下移动等效果。
  3. 颜色和特效:Snackbar 的颜色和特效可以使用 Material Design 风格的颜色和阴影实现。

下面是一个简单的 Snackbar 的 CSS 样式示例:

.snackbar-container {
  position: fixed;
  bottom: 0;
  width: 100%;
  padding: 0.5em 1em;
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
  background-color: #fff;
  animation: animateIn 0.3s ease-out;
  animation-fill-mode: forwards;
}

.snackbar-message {
  display: inline-block;
  margin-right: 1em;
}

.snackbar-action {
  display: inline-block;
}

.snackbar-close {
  position: absolute;
  top: 0.5em;
  right: 0.5em;
  font-size: 1.25em;
  cursor: pointer;
  animation: rotateIn 0.3s ease-out;
  animation-fill-mode: forwards;
}

@keyframes animateIn {
  from {
    transform: translateY(100%);
  }
  to {
    transform: translateY(0%);
  }
}

@keyframes animateOut {
  from {
    transform: translateY(0%);
  }
  to {
    transform: translateY(100%);
  }
}

@keyframes rotateIn {
  from {
    transform: rotate(0);
  }
  to {
    transform: rotate(45deg);
  }
}

@keyframes rotateOut {
  from {
    transform: rotate(45deg);
  }
  to {
    transform: rotate(0);
  }
}

这里定义了一个 .snackbar-container 的容器元素,和三个 .snackbar-message、.snackbar-action、.snackbar-close 的子元素。.snackbar-message 和 .snackbar-action 定义了消息内容和动作按钮的布局,.snackbar-close 定义了关闭按钮的样式。而.animateIn、.animateOut、.rotateIn、.rotateOut 则分别定义了出现、消失和关闭按钮旋转的动画效果。

JavaScript 控制

Snackbar 的 JavaScript 控制主要要实现以下几个功能:

  1. 自动弹出:Snackbar 要在页面加载时自动弹出,可以在页面加载完成时执行一个 JavaScript 函数来实现。
  2. 自动关闭:Snackbar 弹出后要自动关闭,可以使用 setTimeout() 来等待一定时间后自动关闭。
  3. 手动关闭:Snackbar 要支持用户手动关闭,可以给关闭按钮添加点击事件来实现。
  4. 动作按钮:Snackbar 的动作按钮要支持点击事件和回调函数,可以通过参数传递回调函数和事件处理逻辑。

下面是一个简单的 Snackbar 的 JavaScript 控制示例:

function showSnackbar(message, action, callback) {
  var container = document.createElement("div");
  container.className = "snackbar-container";
  var messageEle = document.createElement("div");
  messageEle.className = "snackbar-message";
  messageEle.innerHTML = message;
  var actionEle = null;
  if (action) {
    actionEle = document.createElement("div");
    actionEle.className = "snackbar-action";
    var button = document.createElement("button");
    button.innerHTML = action;
    button.onclick = function () {
      callback();
      hideSnackbar(container);
    };
    actionEle.appendChild(button);
  }
  var closeEle = document.createElement("div");
  closeEle.className = "snackbar-close";
  closeEle.innerHTML = "✖";
  closeEle.onclick = function () {
    hideSnackbar(container);
  };
  container.appendChild(messageEle);
  if (actionEle) {
    container.appendChild(actionEle);
  }
  container.appendChild(closeEle);
  document.body.appendChild(container);
  setTimeout(function () {
    hideSnackbar(container);
  }, 5000);
}

function hideSnackbar(container) {
  container.classList.add("animateOut");
  container.addEventListener("animationend", function () {
    container.remove();
  });
}

这里定义了一个 showSnackbar() 函数来创建 Snackbar,它接受三个参数,分别是消息内容、动作按钮内容和回调函数。在函数内部,首先创建一个 .snackbar-container 的容器元素,然后根据参数创建消息内容、动作按钮等元素,最后添加到容器元素中,并将容器元素添加到body中。同时通过 setTimeout() 定时器来控制 Snackbar 自动关闭。

最后定义了一个 hideSnackbar() 函数,用于处理 Snackbar 的关闭效果。在这个函数中通过给容器元素添加 .animateOut 类,来触发 CSS 动画,并在动画结束后将容器元素从页面中删除。

示例代码

下面是一个完整的含动画效果的 Material Design 中的 Snackbar 的示例代码,可以直接运行在浏览器中。

<!DOCTYPE html>
<html>
<head>
  <title>Snackbar</title>
  <style>
    .snackbar-container {
      position: fixed;
      bottom: 0;
      width: 100%;
      padding: 0.5em 1em;
      box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
      background-color: #fff;
      animation: animateIn 0.3s ease-out;
      animation-fill-mode: forwards;
    }

    .snackbar-message {
      display: inline-block;
      margin-right: 1em;
    }

    .snackbar-action {
      display: inline-block;
    }

    .snackbar-close {
      position: absolute;
      top: 0.5em;
      right: 0.5em;
      font-size: 1.25em;
      cursor: pointer;
      animation: rotateIn 0.3s ease-out;
      animation-fill-mode: forwards;
    }

    @keyframes animateIn {
      from {
        transform: translateY(100%);
      }
      to {
        transform: translateY(0%);
      }
    }

    @keyframes animateOut {
      from {
        transform: translateY(0%);
      }
      to {
        transform: translateY(100%);
      }
    }

    @keyframes rotateIn {
      from {
        transform: rotate(0);
      }
      to {
        transform: rotate(45deg);
      }
    }

    @keyframes rotateOut {
      from {
        transform: rotate(45deg);
      }
      to {
        transform: rotate(0);
      }
    }
  </style>
</head>
<body>
  <button onclick="showSnackbar('这是一条消息', '操作', function(){console.log('点击操作按钮')})">弹出 Snackbar</button>
  <script>
    function showSnackbar(message, action, callback) {
      var container = document.createElement("div");
      container.className = "snackbar-container";
      var messageEle = document.createElement("div");
      messageEle.className = "snackbar-message";
      messageEle.innerHTML = message;
      var actionEle = null;
      if (action) {
        actionEle = document.createElement("div");
        actionEle.className = "snackbar-action";
        var button = document.createElement("button");
        button.innerHTML = action;
        button.onclick = function () {
          callback();
          hideSnackbar(container);
        };
        actionEle.appendChild(button);
      }
      var closeEle = document.createElement("div");
      closeEle.className = "snackbar-close";
      closeEle.innerHTML = "✖";
      closeEle.onclick = function () {
        hideSnackbar(container);
      };
      container.appendChild(messageEle);
      if (actionEle) {
        container.appendChild(actionEle);
      }
      container.appendChild(closeEle);
      document.body.appendChild(container);
      setTimeout(function () {
        hideSnackbar(container);
      }, 5000);
    }

    function hideSnackbar(container) {
      container.classList.add("animateOut");
      container.addEventListener("animationend", function () {
        container.remove();
      });
    }
  </script>
</body>
</html>

总结

通过本文的介绍,我们了解了如何使用 HTML、CSS 和 JavaScript 实现含动画效果的 Material Design 中的 Snackbar。Snackbar 具有复杂的 UI 和交互特性,涉及到 HTML、CSS 和 JavaScript 的多个方面,需要具备一定的前端开发能力才能很好地实现它。但是,掌握 Snackbar 的技术原理和实现方法,对于提升前端开发能力和应用 Material Design 风格有重要的学习和指导意义。

来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/659e6054add4f0e0ff759c7d


纠错反馈