具有CSS3过渡功能的优秀应用

分享于 

22分钟阅读

Web开发

  繁體

在10天内开发 Windows 8应用程序。

good的应用程序必须为用户提供视觉反馈。 用户必须始终知道订单( 点击,点击或者任何其他) 被应用程序接受和理解,而且收费的动画是一个不错的工具。

新的收费 5 规范( 说实话我应该说"新的收费CSS规范") 引入了一个出色的工具来处理简单的动画: 转换

根据"CSS转换模块级别 3"的站点规范,CSS3 Transitions Transitions允许在指定时间段内对CSS值的属性更改进行平滑的

本文的目的是首先描述转换的概念,然后看:转换如何工作以及如何处理不支持该功能的浏览器。

另外,我建议你阅读"。动画的动画简介"( by,David ),这是本文的一个好伴侣。

我发开了一个游戏的示例,用于对游戏中的( 如果浏览器不支持CSS3转换,它将回退到 JavaScript ) 进行动画处理:

要获得这个游戏的一个可以玩的版本,请在这里的我的博客上找到我的博客。 这个游戏的代码是有效的,这里是

CSS3过渡

介绍

刚开始,W3C CSS工作组抵制向CSS添加过渡,认为转换不是真正的样式属性。 最终设计师和开发人员设法说服他们,转换是关于动态样式的,可以在CSS文件中进行。

根据W3C站点,CSS3转换可以对以下类型的属性进行动画处理: ( 点击这里显示)

  • 用红色。绿色。蓝色和alpha分量( 分别为数字,请参见下面的数字) 对颜色进行插值
  • 长度: 作为实数插入。
  • 百分比: 作为实数插入。
  • 整数: 通过离散步骤( 整数) 进行插值。 插值在实数空间中发生,并使用 floor() 转换为整数。
  • : 作为真实的( 浮点) 编号插入。
  • 转换列表: 请参阅CSS转换规范: http://www.w3.org/TR/css3-2d-transforms/
  • 用x,y,宽度和高度组件( 将每个作为数字处理) 进行插值,以磅为单位。
  • 可见性: 通过离散步骤插入。 在 0和 1之间的实数空间内插值,1是"可见",所有其他值都是"隐藏"。
  • 通过颜色,x,y 和模糊组件(。将它们当作颜色和数字进行适当处理) 进行插值的阴影。 在有阴影列表的情况下,更短的列表将填充在它的颜色透明且所有长度( x,y,模糊) 为 0的末尾。
  • 按每个停止点的位置和颜色对 gradient进行插值。 它们必须具有相同的类型( 径向或者线性) 和相同数量的停止以进行动画处理。
  • 油漆服务器 ( SVG ): 仅在以下情况之间支持插值: 渐变到渐变,颜色为颜色。 然后它们作为 上面 工作。
  • 用逗号分隔的上面的空间: 如果列表具有相同数量的项,则列表中的每个项都使用规则 上面 插入。 否则,没有插值。
  • shorthand 属性: 如果 shorthand的所有部分都可以动画处理,那么就像每个属性都被单独指定一样执行插值。

转换必须支持以下属性:( 单击这里以显示它们)

  • background-color ( 颜色 )
  • background-image ( 仅适用于渐变的渐变)
  • background-position ( 百分比和长度 )
  • border-bottom-color ( 颜色 )
  • border-bottom-width ( 长度 )
  • border-color ( 颜色 )
  • border-left-color ( 颜色 )
  • border-left-width ( 长度 )
  • border-right-color ( 颜色 )
  • border-right-width ( 长度 )
  • border-spacing ( 长度 )
  • border-top-color ( 颜色 )
  • border-top-width ( 长度 )
  • border-width ( 长度 )
  • 底部( 长度和百分比 )
  • 颜色( 颜色 )
  • 裁剪( rectangle )
  • font-size ( 长度和百分比 )
  • font-weight ( 号 )
  • grid-* ( )
  • 高度( 长度和百分比 )
  • 左侧( 长度和百分比 )
  • letter-spacing ( 长度 )
  • 行高( ,长度和百分比 )
  • margin-bottom ( 长度 )
  • margin-left ( 长度 )
  • margin-right ( 长度 )
  • margin-top ( 长度 )
  • max-height ( 长度和百分比 )
  • max-width ( 长度和百分比 )
  • min-height ( 长度和百分比 )
  • min-width ( 长度和百分比 )
  • 不透明度( 号 )
  • outline-color ( 颜色 )
  • 轮廓偏移量( 整数 )
  • outline-width ( 长度 )
  • padding-bottom ( 长度 )
  • padding-left ( 长度 )
  • padding-right ( 长度 )
  • padding-top ( 长度 )
  • 右( 长度和百分比 )
  • text-indent ( 长度和百分比 )
  • text-shadow ( 阴影 )
  • 顶部( 长度和百分比 )
  • vertical-align ( 关键字,长度和百分比 )
  • 可见性( 可见性 )
  • 宽度( 长度和百分比 )
  • word-spacing ( 长度和百分比 )
  • z-index ( 整数 )
  • 缩放( 号 )

SVG

SVG对象的属性在SVG规范中定义为 animatable:true 时是可以设置动画的: http://www.w3.org/TR/SVG/struct.html

声明

要在CSS文件中声明转换,你只需编写下面的代码:

69.transition-property: all;70.transition-duration: 0.5s;71.transition-timing-function: ease;72.transition-delay: 0s;

这里声明定义任何属性的任何更新都将在 0.5的( 而不是立即) 中进行。

你还可以根据每个属性定义你的翻译:

73.transition-property: opacity left top;74.transition-duration: 0.5s 0.8s 0.1s;75.transition-timing-function: ease linear ease;76.transition-delay: 0s 0s 1s;

finally 可以使用 shorthand 属性"转换"在一行中定义所需的所有内容:

77.transition: all 0.5s ease 0s;

在这里 shorthand 版本中,你可以精确地使用逗号分隔任意多个属性:

78.transition: opacity 0.5s ease 0s, left 0.8s linear 0s;

更新目标对象的属性时,将触发转换。 更新可以用 JavaScript JavaScript,或者通过给标签分配 new CSS3。

例如如果你有以下CSS3声明,则使用 IE10:

79.-ms-transition-property: opacity left top;80.-ms-transition-duration: 0.5s 0.8s 0.5s;81.-ms-transition-timing-function: ease linear ease;

当你更新标签的不透明度时,当前值将被动画设置为超过 0.5秒的新值,并使用ease函数( 它提供了一个平滑的动画)。

非线性过渡

行定义转换不是线性的,而是使用计时函数产生的非线性动画。

CSS3将使用三次贝塞尔曲线来平滑过渡,通过计算不同时间的不同速度来平滑过渡。

支持以下功能:

  • 线性: 恒定速度
  • 三次贝塞尔曲线:速度将符合由两个控制点定义的三次贝塞尔曲线: P0 ( 因此你必须在这里定义 4个值: P0x,P0y和 P1x,P1y。
  • 使用三次 bezier ( 0,25,0.1,0.25,1 ) 计算速度。
  • 在: 使用三次 bezier ( 0,42,0,1,1 ) 计算
  • ( 1 ): 使用三次贝塞尔曲线计算速度( 0.42.0.0.58.1 )
  • 使用三次 bezier ( 0,0,0.58,1 ) 计算速度:

下面是一个模拟工具(。使用 SVG ),用于显示每个计时函数的影响:

<p> 你的浏览器不支持 iframe。 </p> 单击这里显示演示: <href="http://www.catuhe.com/msdn/transitions/easingfunctions.htm"> http://www.catuhe.com/msdn/transitions/easingfunctions.htm </>

这个模拟器是用纯 JavaScript 代码编写的,以便于理解函数:

88.TRANSITIONSHELPER.computeCubicBezierCurveInterpolation = function (t, x1, y1, x2, y2) {89.// Extract X (which is equal to time here)90.var f0 = 1 - 3 * x2 + 3 * x1;91.var f1 = 3 * x2 - 6 * x1;92.var f2 = 3 * x1;93. 94.var refinedT = t;95.for (var i = 0; i <5; i++) {96.var refinedT2 = refinedT * refinedT;97.var refinedT3 = refinedT2 * refinedT;98. 99.var x = f0 * refinedT3 + f1 * refinedT2 + f2 * refinedT;100. var slope = 1.0/(3.0 * f0 * refinedT2 + 2.0 * f1 * refinedT + f2);101. refinedT -= (x - t) * slope;102. refinedT = Math.min(1, Math.max(0, refinedT));103. }104. 105. // Resolve cubic bezier for the given x106. return3 * Math.pow(1 - refinedT, 2) * refinedT * y1 +107. 3 * (1 - refinedT) * Math.pow(refinedT, 2) * y2 +108. Math.pow(refinedT, 3);109. };

这个代码是基于这个定义的cubic bezier,你可以在这里找到模拟器的源代码。

延迟

"过渡延迟"行定义属性更新和转换开始之间的延迟。

事件

在转换结束时引发事件: TransitionEnd"。 根据你的浏览器,正确的名称将为:

  • Chrome & Safari: webkitTransitionEnd
  • Firefox: mozTransitionEnd
  • Opera: oTransitionEnd
  • IE: MSTransitionEnd

此事件将给你提供以下信息:

  • propertyName: 动画属性的名称
  • elapsedTime: 转换已经运行的时间量,秒

以下是IE10的用法示例: 116.block.addEventListener("MSTransitionEnd", onTransitionEvent) ;

关于CSS3过渡的更多信息

我主要可以提出两个原因,为什么CSS3转换真的非常有用:

  • 硬件加速:在GPU上直接处理,并产生平滑的结果。 在移动设备上,计算能力非常有限,这一点非常重要
  • 代码与设计之间的分号更好: 对我来说,开发人员不必意识到动画或者与设计有关的任何东西。 以同样的方式,设计师/艺术家一定不知道 JavaScript。 因为设计师可以描述CSS中的所有转换而不需要开发人员,所以这就是为什么它真

支持和回退

由于 PP3, IE10 ( 你可以用 Windows 下载"8"开发人员预览在这里) 支持CSS3转换:

这里报告是由 http://caniuse.com/#search=CSS3 转换生成的。

当然,由于规范没有完成( 工作草案。),所以必须使用供应商的前缀,如 -ms-。-moz-。webkit。-o-。

显然我们可以看到,为了解决各种浏览器问题,我们需要提供一个的透明解决方案。 最好的方法是开发一个能够检测CSS3转换支持的API。 如果浏览器不支持该功能,我们将回退到一些JavaScript代码。

如果你依赖网站功能的转换,支持回退方法很重要。 如果你不想这样做,你应该考虑使用过渡,只有在设计增强的工作。 在这种情况下,站点仍然会工作,但是只有支持的浏览器才会提供完整的体验。 我们在这里谈到"渐进式增强"越强强,他获得的功能就越多。

没有CSS3过渡的过渡

所以,为了支持对xquery转换的回退,我们将开发一个小工具包来提供代码转换。

首先,我们将为我们的命名空间创建一个容器对象:

119. var TRANSITIONSHELPER = TRANSITIONSHELPER || {};120. 121. TRANSITIONSHELPER.tickIntervalID = 0;122. 123. TRANSITIONSHELPER.easingFunctions = {124. linear:0,125. ease:1,126. easein:2,127. easeout:3,128. easeinout:4,129. custom:5130. };131. 132. TRANSITIONSHELPER.currentTransitions = [];

为了支持相同级别的缓动函数,我们必须声明一个包含所有必需字段的"enum"。

这个工具包基于每个 17ms ( 在 60秒内实现动画)的函数。 函数将通过一个活动转换的Collection 枚举。 对于每个转换,代码将评估给定当前值和目标值的下一个值。

我们需要一些方便的函数来提取所使用属性和单元的值:

133. TRANSITIONSHELPER.extractValue = function (string) {134. try {135. var result = parseFloat(string);136. 137. if (isNaN(result)) {138. return0;139. }140. 141. return result;142. } catch (e) {143. return0;144. }145. };146. 147. TRANSITIONSHELPER.extractUnit = function (string) {148. 149. // if value is empty we assume that it is px150. if (string == "") {151. return"px";152. }153. 154. varvalue = TRANSITIONSHELPER.extractValue(string);155. var unit = string.replace(value, "");156. 157. return unit;158. };

main函数将处理活动的转换,并调用三次贝塞尔曲线来计算当前值:

159. TRANSITIONSHELPER.tick = function () {160. // Processing transitions161. for (var index = 0; index < TRANSITIONSHELPER.currentTransitions.length; index++) {162. var transition = TRANSITIONSHELPER.currentTransitions[index];163. 164. // compute new value165. var currentDate = (new Date).getTime();166. var diff = currentDate - transition.startDate;167. 168. var step = diff/transition.duration;169. var offset = 1;170. 171. // Timing function172. switch (transition.ease) {173. case TRANSITIONSHELPER.easingFunctions.linear:174. offset = TRANSITIONSHELPER.computeCubicBezierCurveInterpolation(step, 0, 0, 1.0, 1.0);175. break;176. case TRANSITIONSHELPER.easingFunctions.ease:177. offset = TRANSITIONSHELPER.computeCubicBezierCurveInterpolation(step, 0.25, 0.1, 0.25, 1.0);178. break;179. case TRANSITIONSHELPER.easingFunctions.easein:180. offset = TRANSITIONSHELPER.computeCubicBezierCurveInterpolation(step, 0.42, 0, 1.0, 1.0);181. break;182. case TRANSITIONSHELPER.easingFunctions.easeout:183. offset = TRANSITIONSHELPER.computeCubicBezierCurveInterpolation(step, 0, 0, 0.58, 1.0);184. break;185. case TRANSITIONSHELPER.easingFunctions.easeinout:186. offset = TRANSITIONSHELPER.computeCubicBezierCurveInterpolation(step,0.42, 0, 0.58, 1.0);187. break;188. case TRANSITIONSHELPER.easingFunctions.custom:189. offset = TRANSITIONSHELPER.computeCubicBezierCurveInterpolation(step, transition.customEaseP1X, transition.customEaseP1Y, transition.customEaseP2X, transition.customEaseP2Y);190. break;191. }192. 193. offset *= (transition.finalValue - transition.originalValue);194. 195. var unit = TRANSITIONSHELPER.extractUnit(transition.target.style[transition.property]);196. var currentValue = transition.originalValue + offset;197. 198. transition.currentDate = currentDate;199. 200. // Dead transition?201. if (currentDate >= transition.startDate + transition.duration) {202. currentValue = transition.finalValue; // Clamping203. TRANSITIONSHELPER.currentTransitions.splice(index, 1); // Removing transition204. index--;205. 206. // Completion event207. if (transition.onCompletion) {208. transition.onCompletion({propertyName:transition.property,elapsedTime:transition.duration});209. }210. }211. 212. // Affect it213. transition.target.style[transition.property] = currentValue + unit;214. }215. };

当前版本的工具箱只支持数值,但如果你想要动画复杂值( 如颜色),只需将它们分解为简单值。

在系统中注册转换将使用以下代码:

216. TRANSITIONSHELPER.transition = function (target, property, newValue, duration, ease, customEaseP1X, customEaseP1Y,
customEaseP2X, customEaseP2Y, onCompletion) {217. 218. // Create a new transition219. var transition = {220. target: target,221. property: property,222. finalValue: newValue,223. originalValue: TRANSITIONSHELPER.extractValue(target.style[property]),224. duration: duration,225. startDate: (new Date).getTime(),226. currentDate: (new Date).getTime(),227. ease:ease,228. customEaseP1X:customEaseP1X, 229. customEaseP2X:customEaseP2X,230. customEaseP1Y: customEaseP1Y,231. customEaseP2Y: customEaseP2Y,232. onCompletion: onCompletion233. };234. 235. // Launching the tick service if required236. if (TRANSITIONSHELPER.tickIntervalID == 0) {237. TRANSITIONSHELPER.tickIntervalID = setInterval(TRANSITIONSHELPER.tick, 17);238. }239. 240. // Remove previous transitions on same property and target241. for (var index = 0; index <TRANSITIONSHELPER.currentTransitions.length; index++) {242. var temp = TRANSITIONSHELPER.currentTransitions[index];243. 244. if (temp.target === transition.target && temp.property === transition.property) {245. TRANSITIONSHELPER.currentTransitions.splice(index, 1);246. index--;247. }248. }249. 250. // Register251. if (transition.originalValue!= transition.finalValue) {252. TRANSITIONSHELPER.currentTransitions.push(transition);253. }254. };

当第一个转换激活时,将启动" tick"函数。

最后,你只需使用来定义当前浏览器是否支持CSS3转换。 如果没有,你可以向我们的工具包中添加 fallback。

TransitionsHelper的代码可以在下面下载: http://www.catuhe.com/msdn/transitions/transitionshelper.js

例如在益智游戏中,下面的代码用于对单元格进行动画处理:

255. if (!PUZZLE.isTransitionsSupported) {256. TRANSITIONSHELPER.transition(block.div, "top", block.x * totalSize + offset, 500, TRANSITIONSHELPER.easingFunctions.ease);257. TRANSITIONSHELPER.transition(block.div, "left", block.y * totalSize + offset, 500, TRANSITIONSHELPER.easingFunctions.ease);258. }259. else {260. block.div.style.top = (block.x * totalSize + offset) + "px";261. block.div.style.left = (block.y * totalSize + offset) + "px";262. }

我们可以注意到,当支持CSS3转换时,我可以用另外一种方法为我的单元格设置动画以设置动画效果。 我可以定义一个 Collection 类的,它具有预定义的左和顶值( 每个单元格一个),以影响它们的右单元格。

一些框架和工具包已经存在,支持软件转换:

另外,你还可以使用jQuery的旧 animate() 方法。

结束语

我们看到,CSS3转换是一个真正的的简单方法来向项目添加动画。 你可以在需要更改值的情况下,只使用一些 transitions transitions reactive reactive。

如果你想要实现一个JavaScript回退,则有两种解决方案:

  • 如果你发现支持CSS3转换的支持,那么你可以在JavaScript方面对所有的进行权衡,你将在页面中注入CSS3声明。
  • 或者使用标准方式( 在CSS文件中使用 true CSS3声明),在JavaScript中检测回退的需要。 对于我来说,它是更好的选择,因为回退必须是一个选项而不是主体。 在不久的将来,所有浏览器都将支持jdo转换,在这种情况下,你只需删除回退代码。 此外,它是让所有的CSS都成为 creative团队而不是代码部分的更好方式。

更深入地学习


相关文章