前端动效整理

649 阅读12分钟

在日常网站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:

nav 缓动动效果

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动效库:

Animate.css

Bounce.js

CSS Animate

snabbt

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贝塞尔曲线实现定制路径渐变动画。资料:

贝塞尔曲线绘制

github.com/Aaaaaaaty/b…

二、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

eg: www.jq22.com/yanshi9266

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

资料:

SVG教程

SVG动效教程

在线svg编辑器

三、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())

资料:

教程

echarts

svg和canvas对比

SVG 是一种使用 XML 描述 2D 图形的语言,Canvas 通过 JavaScript 来绘制 2D 图形或3D图形。 下面列出了 canvas 与 SVG 之间的一些不同之处:

Canvas

依赖分辨率
不支持事件处理器(渲染引擎不能就单个对象绑定事件)
弱的文本渲染能力
能够以 .png 或 .jpg 格式保存结果图像
最适合图像密集型的游戏,其中的许多对象会被频繁重绘

SVG

不依赖分辨率
支持事件处理器
最适合带有大型渲染区域的应用程序(比如谷歌地图)
复杂度高会减慢渲染速度(任何过度使用 DOM 的应用都不快)
不适合游戏应用

适用场景

Canvas提供的功能更原始,适合像素处理,动态渲染和大数据量绘制。

SVG功能更完善但只能绘制矢量图,不能引入普通的图片,在项目中我们会用来做一些动态的小图标。但是由于其本质为矢量图,可以被无限放大而不会失真,这很适合被用来做地图,而canvas可以看做是一个画布。其绘制出来的图形为标量图,因此,可以在canvas中引入jpg或png这类格式的图片,在实际开发中,大型的网络游戏都是用canvas画布做出来的。