在日常网站APP交互中,我们经常会在页面下拉时、刷新界面时、输入用户名等场景中看到一些动效,稍许动效交互能增加用户的趣味和黏着度,为产品增添个性亮点。
一、css
transition
动画过渡效果属性,使css的属性值在一定的时间内平滑的过渡。这种效果可以在鼠标点击、划过、获取焦点或对元素任何改变中触发,并圆滑的以动画效果改变css属性值。
可定义的属性有:
transition-property:设置那些属性进行过渡,all:所有属性
transition-duration:完成过渡动画效果的时间,默认是0
transition-timing-function:设置动画的缓动效果,默认是ease(逐渐变慢)。 (其他常用值:ease-in,加速;ease-out,减速;ease-in-out,加速然后减速)
transition-delay:设置动画开始的延迟时间,默认是0
eg. 使用transition,实现过渡动画。一个红色的正方形,当鼠标移入该区域后,红色正方形放大一倍,并且颜色变为灰色。鼠标移开,还原到初始状态:
.box{
width: 100px;
height: 100px;
margin:50px auto;
background-color: #f00;
/* 为离开的动作也添加过渡效果 */
transition: all 1s ease-in 1s;
}
.box:hover{
height: 200px;
width: 200px;
border-radius: 50%;
background-color: #666;
/* transition-property:width,height,border-radius;
transition-duration: 1s;
transition-timing-function:ease-in;
transition-delay:1s; */
transition: all 1s ease-in 1s;
}
在同一行transition语句中,可以分别指定多个属性,eg: 宽度延迟一秒变化:
img {
transition: 1s height, 1s 1s width;
}
注意:
(1)目前,各大浏览器(包括IE 10)都已经支持无前缀的transition,所以transition已经可以很安全地不加浏览器前缀(Internet Explorer 9 以及更早版本的浏览器不支持 transition 属性)。
(2)不是所有的CSS属性都支持transition,完整的列表查看这里,以及具体的效果。(www.cnblogs.com/xiaoky/p/39…)
(3)transition需要明确知道,开始状态和结束状态的具体数值,才能计算出中间状态。比如,height从0px变化 到100px,transition可以算出中间状态。但是,transition没法算出0px到auto的中间状态,也就是说,如果开始或结束的设置是height: auto,那么就不会产生动画效果。类似的情况还有,display: none到block,background: url(foo.jpg)到url(bar.jpg)等等。
transition的局限:
- transition需要事件触发,所以没法在网页加载时自动发生。
- transition是一次性的,不能重复发生,除非一再触发。
- transition只能定义开始状态和结束状态,不能定义中间状态,也就是说只有两个状态。 example:
css3 animation
可定义的属性有:
animation: "animation-name"
duration: 动画持续时间
animation-timing-function: 动画的速度曲线,linear ease ease-in ease-out ease-in-out cubic-bezier(n,n,n,n): 自定义速度模式
animation-delay:动画延迟时间
animation-iteration-count: 动画应该播放的次数, n infinite(默认情况下,动画只播放一次,加入infinite关键字,可以让动画无限次播放);
animation-direction: 是否应该轮流反向播放动画,normal|alternate; animation-fill-mode: 动画结束以后,会立即从结束状态跳回到起始状态。如果想让动画保持在结束状态,需要使用animation-fill-mode属性,forwards
keyframes关键字用来定义动画的各个状态,它的写法相当自由,如果省略某个状态,浏览器会自动推算中间状态。0%可以用from代表,100%可以用to代表,甚至,可以把多个状态写在一行。
@keyframes rainbow {
50% { background: orange }
to { background: yellowgreen }
}
@keyframes rainbow {
to { background: yellowgreen }
}
eg: 物体五秒内红变绿,延迟一秒执行
@keyframes 'mymove'
{
0% { background: #c00; }
50% { background: orange; }
100% { background: yellowgreen; }
}
div
{
animation:mymove 5s ease 1s infinite;
-webkit-animation:5s ease 1s infinite; /* Safari 和 Chrome */
/* animation: 1s 1s rainbow linear 3 forwards normal; */
}
注意:
目前,IE 10和Firefox(>= 16)支持没有前缀的animation,而chrome不支持,所以必须使用webkit前缀。
animation 和 transition 可借助transform函数对对象进行复杂动画操作,比如放大,斜切等。
transform-function表示一个或多个变换函数,以空格分开,因此可以同时对一个元素进行transform的多种属性操作。
rotate(angle):旋转元素
scale(number[,_number]):缩放元素
translate(translation-value[, translation-value]):移动元素
skew(angle [,angle]):倾斜元素
matrix(number,number,number,number,number,number):矩阵变形
perspective(length):透视
eg:鼠标经过变大1.2倍、旋转360度并改变背景色。
.demo_rotate{
-webkit-transition:1s ease all;
-moz-transition:1s ease all;
padding:10px;
margin:90px auto;
}
.demo_rotate:hover{
-webkit-transform:rotate(360deg) scale(1.2,1.2);
-moz-transform:rotate(360deg) scale(1.2,1.2);
background:#ff9900;
}
@keyframes octocat-wave
{0%,100%{transform:rotate(0)}
20%,60%{transform:rotate(-25deg)}
40%,80%{transform:rotate(10deg)}}
css3动效库:
less(sass) + js 可计算属性
目前渐变实现方式:线性渐变、径向渐变,不能实现按自定义路径进行渐变。
#grad {
background-image: linear-gradient(#e66465, #9198e5);
}
#grad {
background-image: radial-gradient(red, yellow, green);
}
<defs>
<linearGradient id="orange_red" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style="stop-color:rgb(255,255,0);
stop-opacity:1"/>
<stop offset="100%" style="stop-color:rgb(255,0,0);
stop-opacity:1"/>
</linearGradient>
</defs>
<ellipse cx="200" cy="190" rx="85" ry="55"
style="fill:url(#orange_red)"/>
利用css预处理语言,结合少量js,对可计算属性进行处理可实现部分动画效果。
eg: 渐变
同此原理,我们可以利用js贝塞尔曲线实现定制路径渐变动画。资料:
贝塞尔曲线绘制
二、svg
SVG 意为可缩放矢量图形(Scalable Vector Graphics), 是一种XML语言,类似XHTML,可以用来绘制矢量图形。SVG可以通过定义必要的线和形状来创建一个图形,也可以修改已有的位图,或者将这两种方式结合起来创建图形。图形和其组成部分可以形变(be transformed)、合成、或者通过滤镜完全改变外观。用来定义用于网络的基于矢量的图形,在放大或改变尺寸的情况下其图形质量不会有所损失。
与其他图像格式相比,使用 SVG 的优势在于:
- SVG 可被非常多的工具读取和修改(比如记事本)
- SVG 与 JPEG 和 GIF 图像比起来,尺寸更小,且可压缩性更强。
- SVG 是可伸缩的
- SVG 图像可在任何的分辨率下被高质量地打印
- SVG 可在图像质量不下降的情况下被放大
- SVG 图像中的文本是可选的,同时也是可搜索的(很适合制作地图)
- SVG 可以与 Java 技术一起运行
- SVG 是开放的标准
- SVG 文件是纯粹的 XML
SVG也提供了一些元素,用于定义圆形、矩形、简单或复杂的曲线。一个简单的SVG文档由根元素和基本的形状元素构成。另外还有一个g元素,它用来把若干个基本形状编成一个组。SVG支持渐变、旋转、动画、滤镜效果、与JavaScript交互等等功能,但是所有这些额外的语言特性,都需要在一个定义好的图形区域内实现。
<svg version="1.1"
baseProfile="full"
width="300" height="200"
xmlns="http://www.w3.org/2000/svg">
<rect width="100%" height="100%" fill="red" />
<circle cx="150" cy="100" r="80" fill="green" />
<text x="150" y="125" font-size="60" text-anchor="middle" fill="white">SVG</text>
</svg>
注意:
元素的渲染顺序十分重要,SVG文件全局有效的规则是“后来居上”,越后面的元素越可见。
对于所有元素,SVG使用的坐标系统或者说网格系统,以页面的左上角为(0,0)坐标点,坐标以像素为单位,x轴正方向是向右,y轴正方向是向下。 SVG也可以定义绝对大小同时SVG也能使用相对大小,只需给出数字,不标明单位,输出时就会采用用户的单位。
<svg width="200" height="200" viewBox="0 0 100 100">
基本形状:圆,矩形,线段,多边形,路径:
<?xml version="1.0" standalone="no"?>
<svg width="200" height="250" version="1.1" xmlns="http://www.w3.org/2000/svg">
<rect x="10" y="10" width="30" height="30" stroke="black" fill="transparent" stroke-width="5"/>
<rect x="60" y="10" rx="10" ry="10" width="30" height="30" stroke="black" fill="transparent" stroke-width="5"/>
<circle cx="25" cy="75" r="20" stroke="red" fill="transparent" stroke-width="5"/>
<ellipse cx="75" cy="75" rx="20" ry="5" stroke="red" fill="transparent" stroke-width="5"/>
<line x1="10" x2="50" y1="110" y2="150" stroke="orange" fill="transparent" stroke-width="5"/>
<polyline points="60 110 65 120 70 115 75 130 80 125 85 140 90 135 95 150 100 145"
stroke="orange" fill="transparent" stroke-width="5"/>
<polygon points="50 160 55 180 70 180 60 190 65 205 50 195 35 205 40 190 30 180 45 180"
stroke="green" fill="transparent" stroke-width="5"/>
<path d="M20,230 Q40,205 50,230 T90,230" fill="none" stroke="blue" stroke-width="5"/>
</svg>//(二次)贝塞尔曲线
填充、描边、渐变、图案,遮罩、文字、图片、变形等。
<?xml version="1.0" standalone="no"?>
<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg" version="1.1">
<defs>
<linearGradient id="Gradient1">
<stop offset="5%" stop-color="white"/>
<stop offset="95%" stop-color="blue"/>
</linearGradient>
<linearGradient id="Gradient2" x1="0" x2="0" y1="0" y2="1">
<stop offset="5%" stop-color="red"/>
<stop offset="95%" stop-color="orange"/>
</linearGradient>
<pattern id="Pattern" x="0" y="0" width=".25" height=".25">
<rect x="0" y="0" width="50" height="50" fill="skyblue"/>
<rect x="0" y="0" width="25" height="25" fill="url(#Gradient2)"/>
<circle cx="25" cy="25" r="20" fill="url(#Gradient1)" fill-opacity="0.5"/>
</pattern>
</defs>
<rect fill="url(#Pattern)" stroke="black" x="0" y="0" width="200" height="200"/>
</svg>
路径动画:dasharray、dashofset
stroke:画短线于,在...上划线。
stroke-dasharray:用于创建虚线,stroke-dasharray为一个参数时: 其实是表示虚线长度和每段虚线之间的间距,如stroke-dasharray = '10' 表示:虚线长10,间距10,然后重复 虚线长10,间距10。
stroke-dashoffset:偏移,该线段数组相对于起始点的偏移,正数偏移x值的时候,相当于往左移动了x个长度单位,负数偏移x的时候,相当于往右移动了x个长度单位。
藉由线段和偏倚可以形成很有意思的路径动画(线从无到有):
第一步:设置stroke-dasharray虚线长度等于当前svg的宽度,间隔大于或者等于svg宽度
<svg >
<line id="line" x1="30" y1="30" x2="300" y2="30" stroke-width="20" stroke="red" stroke-dasharray="300,320"/>
</svg>
第二步:设置stroke左移 300单位(stroke-dashoffset:300),也就是刚好隐藏了虚线,可视区域内变成了320单位的间隔。
第三步:当鼠标移入的时候,使offset由300变成0
svg:hover #line{
stroke-dashoffset: 0;
}
#line{
transition: all 2s;
}
设置stroke-dasharray虚线长度等于当前圆的周长,间隔大于或者等于圆的周长,可实现圆圈进度读取效果。
<svg width="200" height="200" viewBox="0 0 200 200">
<circle id="circle" cx="100" cy="80" r="50" stroke-width="5" stroke="green" />
</svg>
#circle{
transition: all 2s;
stroke-dasharray:314,314;
stroke-dashoffset:314;
}
svg:hover #circle{
stroke-dashoffset:0;
}
路径动画插件:www.jq22.com/yanshi9266
对象动画:SVG animation
<set>: 设置某个状态点 <set attributeName="x" attributeType="XML" to="60" begin="3s" />
<animate>
<animateColor>
<animateTransform>
<animateMotion>
svg配合animation小动效:hover 波浪
.a_link:hover, .entry a[href*='m/study/']:hover {
color: #f30;
text-decoration: none;
background: url(data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 4'%3E%3Cpath fill='none' stroke='%23ff3300' d='M0 3.5c5 0 5-3 10-3s5 3 10 3 5-3 10-3 5 3 10 3'/%3E%3C/svg%3E) repeat-x 0 100%;
background-size: 20px auto;
animation: waveMove 1s infinite linear;
}
animateMotion元素可以让SVG各种图形沿着特定的path路径运动(rotate="auto"):
<svg width="360" height="200" xmlns="http://www.w3.org/2000/svg">
<text font-family="microsoft yahei" font-size="40" x="0" y="0" fill="#cd0000">马
<animateMotion path="M10,80 q100,120 120,20 q140,-50 160,0" begin="0s" dur="3s" rotate="auto" repeatCount="indefinite"/>
</text>
<path d="M10,80 q100,120 120,20 q140,-50 160,0" stroke="#cd0000" stroke-width="2" fill="none" />
</svg>
from, to, by, values, begin, end
<svg width="320" height="200" xmlns="http://www.w3.org/2000/svg">
<text font-family="microsoft yahei" font-size="120" y="160" x="160">马
<animate id="x" attributeName="x" to="60" begin="0s" dur="3s" repeatCount="indefinite" />
<animate attributeName="y" to="100" begin="x.repeat(2)" dur="3s" fill="freeze" />
</text>
</svg>
拓展:
svg滤镜: feGaussianBlur将对象进行高斯模糊,feColorMatrix用来对原图的每个像素点的RGBA颜色进行处理生产新的RGBA颜色,两者相结合使用可产生融合效果。(先让图形高斯模糊,再使用feColorMatrix滤镜增加alpha透明通道的对比度,于是可以把高斯模糊重合的部分进行合并,形成融合效果)
eg: elastic
资料:
三、canvas
Canvas 是由 HTML 代码配合高度和宽度属性而定义出的可绘制区域。JavaScript 代码可以访问该区域,类似于其他通用的二维 API,通过一套完整的绘图函数来动态生成图形。它可以用来制作照片集或者制作相对简单的动画,甚至可以进行实时视频处理和渲染。
canvas会创建一个固定大小的画布,会公开一个或多个渲染上下文(画笔),使用渲染上下文来绘制和处理要展示的2D活3D内容。
特点:js绘制,多用于展示数据交互效果。
Canvas主要应用的领域
-
可视化数据: 各类统计图表,比如:百度的echart
-
场景秀: 用Canvas实现动态的广告效果能够非常融洽的跨平台运行。如:手机中微产品在移动端兼容性很好
-
游戏: canvas在基于Web的图像显示方面比Flash更加立体、更加精巧,canvas成为HTML5小游戏开发首选。现阶段h5做游戏,营业方式不是很明确。
-
其他可嵌入网站的内容 (多用于活动页面、特效):类似图表、音频、视频,还有许多元素能够更好地与Web融合,并且不需要任何插件。
-
趋势=> 模拟器: 无论从视觉效果还是核心功能方面来说,模拟器产品可以完全由JavaScript来实现。模拟真实硬件环境,如移动端各种类型手机。
-
趋势=> 远程计算机控制: Canvas可以让开发者更好地实现基于Web的数据传输,构建一个完美的可视化控制界面。
-
趋势=> 图形编辑器: Photoshop图形编辑器将能够100%基于Web实现。
<canvas id="tutorial" width="300" height="300"></canvas>
<script type="text/javascript">
function draw(){
var canvas = document.getElementById('tutorial');
if(!canvas.getContext) return;
var ctx = canvas.getContext("2d");
//开始代码
ctx.fillStyle="#FF0000";
ctx.fillRect(0,0,150,75);
}
draw();
</script>
操作类似svg,能绘制基本形状:圆、矩形、线段、多边形、路径,可进行填充、描边、渐变、图案,遮罩、添加文字图片、变形等操作,与svg相比更加复杂和灵活。
let time = new Date();
//绘制地球
ctx.rotate(2 * Math.PI / 60 * time.getSeconds() + 2 * Math.PI / 60000 * time.getMilliseconds())
资料:
svg和canvas对比
SVG 是一种使用 XML 描述 2D 图形的语言,Canvas 通过 JavaScript 来绘制 2D 图形或3D图形。 下面列出了 canvas 与 SVG 之间的一些不同之处:
Canvas
依赖分辨率
不支持事件处理器(渲染引擎不能就单个对象绑定事件)
弱的文本渲染能力
能够以 .png 或 .jpg 格式保存结果图像
最适合图像密集型的游戏,其中的许多对象会被频繁重绘
SVG
不依赖分辨率
支持事件处理器
最适合带有大型渲染区域的应用程序(比如谷歌地图)
复杂度高会减慢渲染速度(任何过度使用 DOM 的应用都不快)
不适合游戏应用
适用场景
Canvas提供的功能更原始,适合像素处理,动态渲染和大数据量绘制。
SVG功能更完善但只能绘制矢量图,不能引入普通的图片,在项目中我们会用来做一些动态的小图标。但是由于其本质为矢量图,可以被无限放大而不会失真,这很适合被用来做地图,而canvas可以看做是一个画布。其绘制出来的图形为标量图,因此,可以在canvas中引入jpg或png这类格式的图片,在实际开发中,大型的网络游戏都是用canvas画布做出来的。