在交互式可视化中,有一个词叫reactive,指的是以可视化的方式来响应用户的行为,帮助用户进行可视化并理解其结果。这个很有用。那如何来实现这种交互呢?通过动画。

  如果处理得当,动画可以展现出不错的可视化交互数据...

  是怎样的呢?

  • 交互可以有效地提供用户的反馈。我们可以知道自上次用户操作之后发生了什么变化?如果屏幕上的内容从一种状态变成另一种状态,动画可以使这一过程更加明显,突出而更具含义。另外,当需要显示任何形式的实时数据时,动画是必不可少的。
  • 动画可以使人们更加关注图表的重要部分。我们的视觉对运动非常敏感,因此引入和使用这些transitions可以大大地帮助我们更加容易地从图表中获取到有用的信息。

    比较下面两个图表:

    哪一个更能让用户注意到柱状图中最后的那一个柱子呢?

    [说明:以上两个图使用了相同的model。点击按钮可以开始一个动画。如果图中内容为空,点击按钮可以显示图表。]

  • 动画可以和隐喻一起使用,比如增大,展开,移动,缩小等等。所以它可以真正提高可视化的表现力,并试图传达任何要表达的意思。

  这就是说,动画也肯定会破坏你的可视化。这里有三个普遍问题。

  • 动画非常突出。把注意力放在图表的一个特定的,明确的部分是很好的。但是当动画太多时会发生什么呢?没有其它的提示,用户很难将注意力集中到他们需要关注的地方。
  • 动画跨越了多种状态(如动画数据视频),使得它们难以相互比较,这不同于我们将各种不同状态的静态图并排显示出来可以很容易地进行比对。
  • 如果动画不连续,又或者图表忽然莫名其妙地消失,这就会导致一个变化盲视,从而大大地抵消了你希望从动画中能获得的效果。

    看这个例子。

    动画过程中线经过了一个空白状态,从而使我们很难去跟踪原始状态和最终状态之间的变化。找出变化的唯一方法是将注意力集中到一个点上,然后记住它的原始位置,但这样做效率太低。

现在我们怎么做呢?

  我们已经看到动画在数据可视化中的作用了。现在我们来做吧!我们使用d3,它提供了多种数据动画的方式,使用它实现动画效果会相对容易一些。

原则

  如果你知道如何在d3中绘图,你就知道如何实现动画。(如果你还不知道,Alignedleft有一个精彩的教程集,可以帮助你如何开始,d3站点也列出了很多,包括一些我提供的。)出于某种原因,动画在d3中被称之为transitions。动画在技术上被定义为,对象的一个或多个特征在经过一段时间之后,从一个值过渡(transitions)到了另一个值。

  那么我们所说的特征指的是什么呢?它基本上代表了任何可以用数字表示的东西。

几个transitions的例子

  不出所料,当你随着时间来平滑地更新item的位置时,它就移动了。在svg中,对大多数形状而言位置是确定的,例如我们这里的蓝色矩形,它的位置由属性x和y的值来确定,对应于形状的左上角。对于圆形,使用cx和cy或者中心点的坐标来确定位置。对于路径,例如我们的红色三角形,实际上通过"d"属性指定了所有点的位置。

  同样,当你改变大小时,对象会增大(或收缩)。你可以使用width(宽)和height(高)来确定矩形的大小,或者使用r(半径)来确定圆形的大小。

  颜色也是一个数字属性,从一种颜色过度到另一种颜色也是可能的(这个也很有用)。在svg中,颜色是由fill或stroke定义的样式属性。

  与颜色一样,改变透明度也很有用。当opacity被设置为0时,对象是完全透明的。所以要实现对象的淡入淡出效果,需要对opacity属性进行transition操作。

如何实现

  现在我们已经看到transitions可以用来些干什么了,让我们来看看如何用d3来编写代码。

  我们回到第一个例子。我们尽量简单一点。

  在d3中要创建一个像这样的方块,我们可以这样写:

var mySquare=svg.append("rect").attr("x",60).attr("y",60).attr("width",60).attr("height",60);

  4个属性,很简单。

  如果你想让它移动到右边,只需要更新属性x的值。像这样:

mySquare.transition().attr("x",320);

  就是这么简单:使用transition方法,然后指定你想要改变的值,就像创建一个新对象一样。通过这种方式,我们可以很容易地实现上面任何一个例子的效果。

mySquare.transition().attr("width",120); // 将会变大

mySquare.style("fill","white") // 如果fill的值一开始是空白,然后再指定样式,那么动画将从黑色开始
  .transition().style("fill","blue");mySquare.transition().style("opacity",0);

  我们的例子并非如此。Transitions发生在event之后,即当用户点击按钮时才开始动画。事实上,transitions通常会与事件和交互关联在一起。不过这并不复杂。我们可以这样写:

button.on("click", function() {mySquare.transition().attr("x",320);
})

  现在,我们的动画仅当按钮被点击时才开始。很明显,由于transition是在一个函数内部,所以我们可以通过编程来决定方块走向哪里。不过这个例子我们还是让它简单一点。

动画102

  到目前为止,我们已经看到了如何在d3中实现一些简单的动画,甚至进行一些交互。正如我们所看到的,动画的实现方式和创建元素一样简单。好消息是,d3中的transitions非常灵活,同时也可以通过很多的技巧来进行自定义,而不用编写很复杂的代码。我们更多需要知道的是该如何来做。

  在使用transition()方法之后,我们可以指定一个duration和delay的值。Duration是transition将要持续的毫秒数,而delay是动画在执行之前需要等待的毫秒数。写法:

mySquare.transition().attr("x",320).duration(1000) // 持续时间为1秒.delay(100)     // 延迟0.1秒执行

  默认的duration是250ms,没有delay。

  我发现250ms的duration时间有点太短了。大多数时候,我们都希望动画要明显,我自己经常将duration的值增加到500或1000.除非有特殊原因,动画的持续时间不应太长。如果你使用它们来可视化数据,你肯定不希望动画要花好几秒才将数据都显示出来。观察下面这两个例子(点击按钮开始)。

  第二个是不是会让人抓狂?你很难相信它纯粹浪费了你25秒的时间。

  缓动是一个技术名称,它实际上是一个将时间转换为属性值变化的函数。在前面的例子中,你可能已经注意到了,一开始的时候值变化得很慢,然后加快,然后又变慢。是的,这表明你可以使用不同的函数来获得不同的结果。我这里的例子只给出了3个缓动函数,而事实上还有很多的缓动函数。你可以自己编写缓动函数,这个不在本文的讨论范围。

  写法类似于这样:

mysquare.transition().attr("x",320).ease("elastic")

  (顺便说一下,修改属性和指定动画方式的顺序没有任何影响,你可以先使用.ease,后使用.attr)

  对于路径对象,通过transition来更新每一个点的位置,你可以有效地改变路径的形状。这对于线图或任何一个路径图来说特别有意思。

  像这样,如果你绘制的值发生了变化,你可以轻易地发现这些变化。相反,如果你只是清除并重绘,那么就很难发现数据的变化。在这几个例子中,路径的属性"d"的值被修改了(所以它们与最简单的例子本质上是不同的)。

  有时(事实上经常会有),你希望在一个transition完成之后马上启动另一个transition。然而下面这种方式不起作用:

mysquare.transition().attr("x",320);
mysquare.transition().attr("y",200);

  你可能会认为方块会向右移动,然后再向下移动。但事实并非如此,它会开始一个向右的移动,然后紧接着启动第二个transition使其向下移动。由于这两个transition的duration相同并且都没有delay,因此第二个transition的效果更明显。

  如果第二个transition有一个delay,并且比第一个transition的duration要小,那么第一个transition会持续一段时间直到第二个transition的delay时间到期。然后,第二个transition会接管第一个transition开始执行。然而这并不是你想要的,因为第一个transition完成到什么程度完全取决于用户的机器和浏览器等,而这些都是不可预知的(看下面一段的解释)。

  那么给第二个transition一个精确的delay使其能够刚好对应上第一个transition的duration如何呢?这通常是可以的,但是delay和duration的值并非十分精准。启动一个transition需要一定的时间(在我的机器上大约需要15毫秒,但可能会有变化),因此我们很难通过这种方式将两个transitions无缝地连接起来。

  在更加复杂一点的程序中,有时候好几个事件会尝试对同一个对象触发transition。在这种情况下,第一个过程会被启动然后运行,直到另一个transition开始。第二个transition会取代第一个transition。这意味着在第一个transition中被改变的属性值将会保留到第二个transition开始,这个值处于开始值和目标值之间。

  如果你想要确保所有的transitions都能将其属性更新为要达到的值,那么你可能需要在第一个transition的后续transitions中重新指定属性值,就像这样:

mysquare.transition().attr("x",320);
mysquare.transition().delay(250).attr("y",200).attr("x",320); // 即使第一个transition没有执行完,这里也会将x更新为320。

  这里还有一个方法能确定将两个transitions连接起来。使用下面这种写法,一个事件可以精准地在一个transition结束时开始。这个事件可以是另一个transition(上面的例子就是这样)。

mysquare.transition() ....each("end", function() { ... });

  这里,由.each("end")引入的最后一行的回调函数中的内容会正好在transition结束时被触发。

  那要怎么做呢?这里有3种常见的场景。

  (顺便说一句,这里的例子和前面的例子没有什么不同,仅仅只是为了方便查看)。一种情况是在同一个item上启动另一个transition。这里,方块会向右移动,然后向下移动。

  这里是实现的代码:

mysquare.transition().attr("x",320).each("end",function() { // 正如上面所说的,这是一个新的transition对象d3.select(this).       // 这里我们还可以有另一个.each("end")
      transition()         .attr("y",180);});

  另一种情况是在transition执行完后删除对象。这个很有用,特别是在创建大量临时对象时。一个有趣的组合动画是,当你将透明度一直减到0,使对象不可见,如果你不再需要它了,那么你就可以使用remove()方法来删除它。

mysquare.transition().attr("x",320).each("end",function() { d3.select(this).       // 如上所述,这里我们将对象删除了
      remove(); });

  最后,我们可以创建一个新对象。我们可以通过这种方式添加一个特效。下面是一个例子:

  这里,在transition结束时,创建了一个圆形,随后在圆形上开始了一个transition,并将透明度减少为0,然后删除该圆形。

  这是最后一个带有多个效果合并的例子。

进一步

  信不信由你,我们只是接触到了d3动画一些非常基础的东西。

  还有两个transition的用处我们没有讲到,因为稍微有点复杂,所以这里我只是简单提一下。

  到目前为止,我们看到的一直都是基于一个特定对象的属性的transition。例如我们将这个方块的x属性的值变到200。

  但有时候我们需要根据一个变量值的变化来更新可视化图形中的许多部分。

  我们可以通过.tween和.interpolate方法来实现。所有的方法在d3的文档中都有说明。

  还有一个是d3 timer的使用,它允许重复调用一个函数,也可以用来创建动画。

  我一直希望可以通过相对简单的代码和技术来实现你想要的东西,特别是对于连接多个transitions,以及在恰当的时刻添加和删除对象。要创建更强大的效果,还有很长的路要走!

原文地址:animations and transitions

转载于:https://www.cnblogs.com/jaxu/p/8431718.html

Animations and transitions相关推荐

  1. CSS Animations vs Web Animations API

    作者:Ollie Williams 原文:CSS Animations vs Web Animations API 在 JavaScript 有一个原生动画 API 叫 Web Animations ...

  2. 什么?你还不知道Web Animations API

    JavaScript 中有一个用于动画的原生 API,称为 Web Animations API.在这篇文章中,我们将其称为 WAAPI. 在本文中,我们将比较 WAAPI 和用 CSS 完成的动画. ...

  3. android 属性动画 弧形,CSS分层动画可以让元素沿弧形路径运动

    CSS 的 animations (动画) 和 transitions(变换)擅于实现从点 A 到点 B 的直线运动,运动轨迹是直线路径.给一个元素添加了 animation 或者 transitio ...

  4. 校招社招必备核心前端面试问题与详细解答

    本文总结了前端老司机经常问题的一些问题并结合个人总结给出了比较详尽的答案.网易阿里腾讯校招社招必备知识点. 原理讲解参考:前端增长-重新定义大前端 在线课程:网易云课堂课程      思否课堂 官方博 ...

  5. 盒子端 CSS 动画性能提升研究

    不同于传统的 PC Web 或者是移动 WEB,在腾讯视频客厅盒子端,接大屏显示器(电视)下,许多能流畅运行于 PC 端.移动端的 Web 动画,受限于硬件水平,在盒子端的表现的往往不尽如人意. 基于 ...

  6. 使用Modernizr探测HTML5/CSS3新特性

    HTML5, CSS3以及相关技术(例如canvas和web sockets)带来了非常有用的特性,可以让我们的web程序提升一个新的level.这些新技术允许我们只用HTML,CSS和JavaScr ...

  7. html效果属性是,htmltransition属性

    css3动画如何在动作结束时保持该状态不变 js怎样判断transition执行完毕 suface js判断css动画是否结束 一旦动画或变换结束,回调函数就会触发.不再需要大型类库支持. .samp ...

  8. UIView 动画进阶

    上一篇文章中介绍了 UIKit 中一些基础动画,这些动画足够应付普通的动画交互.但是作为开发者仅仅掌握基础用法显然是不够的,我们需要更强大的武器来应对将来可能的复杂场景.接下来我们来看看 UIView ...

  9. react动画库_React 2020动画库

    react动画库 Animations are important in instances like page transitions, scroll events, entering and ex ...

最新文章

  1. 服务器架设笔记——Apache模块开发基础知识
  2. 分形之闵可夫斯基(Minkowski)
  3. SAP HUM 锁住一个HU?
  4. 使用Memcached实现Session共享
  5. android 自定义text,android – 使用自定义textSize实现自定义TextView
  6. Java中HashMap的entrySet()你会用了吗
  7. 【牛客 - 302哈尔滨理工大学软件与微电子学院第八届程序设计竞赛同步赛(低年级)】小乐乐切割方块(思维,水题)
  8. 【转】iOS 10 UserNotifications 使用说明
  9. SpringBoot学习笔记001--创建第一个spring boot应用
  10. Linux操作系统原理与应用07:内核同步
  11. Puppeteer -headless Chrome 的 Node.js API
  12. python实现文字转语音播报
  13. 大众点评信息流基于文本生成的创意优化实践
  14. [经验教程]中国民生银行信用卡积分怎么兑换免费腾讯视频VIP会员?
  15. 带有鸿蒙logo的壁纸,鸿蒙OS Logo曝光
  16. Packetfence 开源网络准入系统
  17. DDOS 攻击的防范教程
  18. Android 底层知识拾零,字节跳动Android高级工程师
  19. copa文件服务器,Copa
  20. linux流媒体服务器架设

热门文章

  1. 笔记本电脑重装系统win10教程-u盘装系统教程
  2. Unity 对GPU的基础性能优化
  3. 微信公众号开发(2)-测试号申请
  4. 了解平面设计师培训内容,轻松找对方向不迷路
  5. 驻沈阳韩国总领事馆 - 签证结果查询网址
  6. C#让TextBox滚动条一直位于最下部
  7. python 分词工具对比_分词工具使用解析
  8. python 依赖注入_Dependency Injection-依赖注入详解
  9. php开发勋章插件,BiliBili-直播间勋章增强
  10. ISC 2022演讲回顾 | SOAR:为XDR扩展威胁检测响应提供响应解决方案