Ramjet 基于 DOM 元素的动画变换插件

发布于 2017-06-27 10:39:57 字数 5587 浏览 2099 评论 0

Ramjet 是一个优雅的动画插件,支持将 DOM 从一种状态变换到另外一种状态,而且支持平滑的过度动画效果,可以是两个不同类型元素之间切换。

安装插件

你可以访问 Ramjet 的 Github 地址或者是官网地址,下载 Ramjet 的 JS 文件,然后引入到你的项目中,如果你使用的是 npm 包管理器,那么可以通过下面的代码安装。

npm install ramjet

快速入门

下面是一段很直观简介的代码,告诉你 Ramjet 是如何优雅的工作的:

<div id='a' style='background-color: red; font-size: 4em; padding: 1em;'>a</div>
<div id='b' style='background-color: blue; font-size: 4em; padding: 1em;'>b</div>

<script src='ramjet.js'></script>
<script>
  var element1 = document.getElementById('a'),
      element2 = document.getElementById('b');

  // to repeat, run this from the console!
  ramjet.transform( element1, element2 );
</script>

工作原理

Ramjet 的动画看起来像是两个元素之间的变换,Ramjet 会复制一个动画前的元素,其中还包括他的子元素,然后将尺寸动画前的元素的尺寸变化为动画后的元素尺寸,并且将这两个元素重叠,然后动画前的元素逐渐隐去,留下最后的 DOM 元素。

它基本上与 iOS 8 中使用的技术相同,使每个应用程序似乎都生活在图标中。

在现代浏览器中,它使用CSS动画,所以所有的事情都发生在主线上。其结果是平滑流畅的性能,即使在移动设备。

运动错觉

通过在转换前后立即改变元素的显示,我们可以创建一个错觉,即单个元素在屏幕上移动并进入 DOM 的不同部分。

// set the stage so ramjet copies the right styles...
b.classList.remove('hidden');

ramjet.transform( a, b, {
  done: function () {
    // this function is called as soon as the transition completes
    b.classList.remove('hidden');
  }
});

// ...then hide the original elements for the duration of the transition
a.classList.add('hidden');
b.classList.add('hidden');

API文档

ramjet.transform( a, b[, options] )

  • a is the DOM node we're transitioning from
  • b is the DOM node we're transitioning to
  • options can include the following properties:
    • done - a function that gets called once the transition completes
    • duration - the length of the transition, in milliseconds (default 400)
    • easing - a function used to control the animation. Should take a number between 0 and 1, and return something similar (though it can return a number outside those bounds, if you're doing e.g. an elastic easing function). I highly recommend eases by Matt DesLauriers, which is a handy collection of these functions
    • easingScale - if defined it will use a different easing function for scaling. It can be used to create cartoonish effects.
    • useTimer - by default, ramjet will use CSS animations. Sometimes (when transitioning to or from SVG elements, or in very old browsers) it will fall back to timer-based animations (i.e. with requestAnimationFrame or setTimeout). If you want to always use timers, make this option true - but I don't recommend it (it's much more juddery on mobile)
    • overrideClone (advanced) - look at the section Advanced options
    • appendToBody (advanced) - look at the section Advanced options

ramjet.hide( ...nodes )

Convenience function that sets the opacity of each node to 0 (temporarily disabling any transition that might otherwise interfere).

ramjet.show( ...nodes )

Opposite of ramjet.hide.

ramjet.linear, ramjet.easeIn, ramjet.easeOut, ramjet.easeInOut

A handful of easing functions, included for convenience.

浏览器兼容

能够兼容大多数主流的浏览器,例如IE9+、Chrome 桌面以及安卓上的、Firefox、Safari 6+ 和手机端的 Safari,主要使用到了CSS3的动画属性。

高级选项

The option overrideClone (function) overrides the function used to clone nodes (the default implementation uses a simple node.cloneNode()). It takes as a parameters the current node and the depth of this node compared to the original element (it is called recursively on the node subtree). It can be useful for removing annoying attributes or children from the cloned node. For example if a node contains a video element with autoplay, this can be excluded because it may be heavy to animate and you can heard the audio of it. Examples:

// cloning only the root node
ramjet.transform( element1, element2, {
  overrideClone: function (node, depth){
    if (depth == 0){
      return node.cloneNode(); // copy only the root node
    }
  }
});

// cloning everything but the id attribute
ramjet.transform( element1, element2, {
  overrideClone: function (node, depth){
    var clone = node.cloneNode();
    clone.removeAttr('id');
  }
});

// not cloning the video element
ramjet.transform( element1, element2, {
  overrideClone: function (node, depth){
    if (node.nodeType === 1 && node.tagName === "VIDEO"){
      return;
    }
    return node.cloneNode();
  }
});

By default the cloned nodes are appended to the parent to the original node. Inheriting the positioning and css inherited rules, they can behave in an unexpected way. For this reason you can use the flag appendToBody to append these nodes to the body instead. I invite everyone to set this to true and open an issue if it doesn't work, it may become the default in one of the next releases.

相关链接

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

JSmiles

生命进入颠沛而奔忙的本质状态,并将以不断告别和相遇的陈旧方式继续下去。

0 文章
0 评论
84961 人气
更多

推荐作者

浪漫人生路

文章 0 评论 0

620vip

文章 0 评论 0

羞稚

文章 0 评论 0

走过海棠暮

文章 0 评论 0

你好刘可爱

文章 0 评论 0

陌若浮生

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文