看到一个喜欢的动画,存下来了,对照着做出来一个demo,记录笔记
动手前先复习相关概念
Transform
简单来说是一个元素的变形属性,而且不改变原来定位及相关元素,可以说是浮动于文本变化,但级别(z-index等)还是会遵守原来的级别。
作为一个属性来说,就是有唯一值的。如果你之前使这个元素向左移动了5px,如果在想让他往左移动,应该是10px而不是再写5px。后面的,新添加的style会覆盖掉原来的transform状态。意味着,你写动画的时候要十分小心,尤其是动态变换的时候,需要动态写相关的transform。当需要新增变换时,在原基础上加空格然后写变换就行。注意同名变化会覆盖。
再强调一次 在使用css3 transtion做动画效果时,优先选择transform,尽量不要使用height,width,margin和padding,真的很容易卡顿
transform-origin
用于指定元素变形的中心点。
表示2维的x-offset/y-offset可以设px值也可以设%百分比,也可设top / right / bottom / left / center等keyword。表示3维的z-offset只能设px值,不能设%百分比,也没有keyword。
可以不使用,用translate模拟出来。
perspective
指定3D的视距。默认值是none表示无3D效果,即2D扁平化。
perspective只能设px值,不能设%百分比。相当于你离屏幕的距离,元素的z轴越大,离你越近,当z轴大于这个值时,相当于大于你的视线,到你脑后,元素不可见。
借用W3C的图配合translateZ来帮助理解视距。
Transition
- transition-property: 过渡属性(默认值为all)
- transition-duration: 过渡持续时间(默认值为0s)
- transiton-timing-function: 过渡函数(默认值为ease函数)
- transition-delay: 过渡延迟时间(默认值为0s)
[注意]IE9-不支持该属性,safari3.1-6、IOS3.2-6.1、android2.1-4.3需要添加-webkit-前缀;而其余高版本浏览器支持标准写法
说到transform就不得不提一下transition了。过渡transition是一个复合属性,通过四个子属性的配合完成整个过渡过程。
过渡transition的这四个子属性只有<transition-duration>是必需值且不能为0。其中,<transition-duration>和<transition-delay>都是时间。当两个时间同时出现时,第一个是<transition-duration>,第二个是<transition-delay>;当只有一个时间时,它是<transition-duration>,而<transition-delay>为默认值0。可以多个规则一起写,用逗号隔开。
transition-timing-function
有linear,ease,ease-in,ease-out,ease-in-out,cubic-bezier(n,n,n,n),steps。其实它们都是贝赛尔曲线。
linear是匀速过渡,ease是先快再慢的节奏,ease-in是加速冲刺的节奏,ease-out是减速到停止的节奏,ease-in-out是先加速后减速的节奏。自制贝塞尔曲线工具:贝塞尔魔方。
steps步进函数将过渡时间划分成大小相等的时间时隔来运行.eg:steps(3, start)
Animation
调用写好的@keyframes规则,为元素选择动画效果,执行时间,延迟时间,执行后状态。
可用transform和delay实现简化的animation,不推荐。
常规动画控制技巧
使用类名控制
常规的一般是用类名active,在active类名下写动画。元素classlist.add('active')时调用动画。动画执行时间设置setTimeout remove掉active类停止动画。这样会在高频点击时出现不连贯问题,由于用的timeout,需要注意控制状态,不能被上一次动画影响下一次动画。
优化选择
可以直接在原元素下写所有动画,设置成pause和infinite。然后单独写一个active类控制动画running和pause。有一种“无侵入”的感觉,代码层次清晰,控制关系明确。有利于后期的维护与扩展。需注意animation-play-state: paused;
是最好分开写,不要简写到animate里。对于IE10/IE11浏览器不会读去animate的animation-play-state属性。
多个动画
可以在animate里用逗号隔开写。eg:animation: fadeIn 1s, float .5s 1s infinite;
。
优化
提取出公用动画规则减少重复代码,避免变换冲突(就是后者动画的transform覆盖掉之前动画的transform)
无侵入定位和居中定位准则
1 这里的“无侵入定位”指不受animation影响的元素定位,包含两部分:
- 一 不使用keyframes关键帧决定初始位置。
- 二 不要使用keyframes中出现的属性定位。
2 这里的“居中定位准则”包含两部分:
- 一 元素定位在容器中间位置。
- 二 元素的定位方式为居中定位。即用left,top定位到父元素中心,然后用margin定位到原位置。
常规动画实现
1 直接全部用tranform加delay实现(不要keyframes)把图片元素切割成一个个可动小块。
2 CSS3细节强调动画,即把原图切成更小的模块,各自写infinite动画让他动起来。
3 SVG动画,主要特点,沿着运动路径运动。
svg篇幅有点多,新一篇写吧。。。ok,说了这么多概念动手吧~
先看原图
之前没怎么做过类似的复杂动画效果,刚好拿这个练习一下
成果,想玩点这里
操作步骤(看起来)分成三个步骤
- 框选项目
- 拖动,删除
- 扩张一个白块
界面
先画出整个界面雏形。整个界面分成,白块儿,灰块儿背景,垃圾桶,红色提示,框选拦。方块一开始用的是flex布局,但发现要变动长度之类的不好操作,就换成了absolute,用id乘长度可以动态定位。用chrome的控制台的css随便一个颜色选项对原图去色,大概作出大小和形状。至于垃圾桶动画,我上网随便找了个icon,用ps分成帽子和身子,做了个动画就凑合了(他那个没找到。。画不好很尴尬)。。cursor的话。。。懒得做。。。。。
逻辑设计
由于只是一张图片,我就按我的理解来做了。
- 点击拖动出现出现框选,选中active变色
- 点击active对象可以拖动
- 有空缺的地方时,直接单击白块儿拖动可以左右增减白块儿宽度
- 拖动到垃圾桶位置时,垃圾桶出现动画,删去框选白块儿并出现提示
图中大概就是这些功能,我自己想的附加功能
- 点击垃圾桶返回所有删去白块
- 拖动单个变形模块时,模块变回原形
ok,大概就这么多了然后就实现了。
不足和优化
client,offset,layer,page
client相对于整个浏览器界面可视区域的位置
page相对于整个文档开头的位置不随滑动条移动而变化。IE没有该属性。解决办法:PageY=clientY+scrollTop-clientTop;
layer相对于相对于最近祖先定位的位置。
offset相对于最近的祖先定位元素
ps:
1 offsetX和layerX都是以border为参考点
2 只有clientX和screenX 皆大欢喜是W3C标准.
3 chrome和safari一条龙通杀
写框选的时候因为这个头疼的不行。。网上资料好杂,赶紧记下来。我是通过查询父元素left等值计算了。。尴尬的一批
vue和@keyframes
由于不想违背尽量少使用transform改变top,left,width等属性避免卡顿的原则。坚持用translateX等来写拖动,到了删除的动画时,整个人都呆了。因为是要在当前位置缩小进入垃圾桶,然后变换的x,y都是动态的,直接写keyframes会覆盖掉变换的位置。但是!但是!我想写动态keyframes时,翻了半天vue文档愣是没发现:style里面怎么写@keyframes,格式和关键字冲突。最后是用transform写了个简易动画,这个很不舒服。。
查询元素
细节操作元素时,还是直接用的js原生。。实在是不知道怎么优雅的操作数据驱动(yyx大佬对不起。。)做款选时,我需要知道白块儿的具体位置,这个直接用数据绑定的话,没想出逻辑应该怎么写,因为一开始白块儿都是用flex写死的,愣是没找到获取渲染位置的api,这很不优雅的感觉。
高频触发
拖动删除和点击还原时,都会出现字样和动画。然而动画和字样是有1s时间的。如果设置remove的话,有可能会和下一个动画出现矛盾冲突。目前解决的办法是,用两个警告模版交替,做到2次/1s的兼容,垃圾桶动画的话,只能保证运行时不会被之前的settimeout关掉,还是没有更好的办法,可能这是逻辑设计的问题吧