这是一款效果十分炫酷的HTML5 SVG制作的运动模糊动画特效。该SVG运动模糊特效有三种效果:画廊效果、模态窗口效果和侧边栏菜单效果。它们使用SVG过滤器和js及css相配合,在元素运动时产生动态模糊的炫酷效果。
运动模糊是一种技术,广泛应用于一般的运动图形和动画,使运动更加流畅自然。维基百科对运动模糊的解释是:运动模糊是明显的在静止图像或图像序列如电影或动画的快速移动的物体。它是当图像被记录的变化对单帧记录过程中,由于快速运动或长时间曝光的结果。
这个运动模糊特效对浏览器的性能要求非常高,只在某些最新版本的现代浏览器中可以正常运行。使用Chrome和Firefox浏览器可以看到最佳效果。
为了在一个动画中应用运动模糊效果,我们需要在动画的每一个帧中,根据元素的速度和方向来定义一个定向的模糊效果。
制作方法
设置模糊
由于标准的CSS模糊过滤器不支持定向模糊,所以我们只有使用SVG过滤器来实现这个效果。关于SVG filters可以参考:7种炫酷HTML5 SVG液态水滴融合动画特效这篇文章。
在这个效果中,我们只使用feGaussianBlur
滤镜。
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" class="filters"> <defs> <filter id="blur"> <feGaussianBlur in="SourceGraphic" stdDeviation="0,0" /> </filter> </defs> </svg>
stdDeviation
属性用于设置模糊的强度,它的两个参数分别是水平和垂直的取向。
要在一个元素上使用过滤器是十分简单的,可以使用CSS来实现:
.selector{ -webkit-filter: url("#blur"); filter: url("../index.html#blur"); }
对于这个动态模糊效果,插件中使用js来为动画的每一个帧添加更多的动态模糊效果。
插件中首先将过滤器保存为变量,以便后面使用。由于jQuery不能直接选择SVG元素,所以插件中使用纯js来选择它。
var filters = document.querySelector(".filters"), // the SVG that contains the filters defs = filters.querySelector("defs"), // the element inside the SVG blur = defs.querySelector("#blur"), // the blur filter blurFilter = blur.firstElementChild; // the feGaussianBlur primitive
要设置运动模糊效果的强度,只需要stdDeviation
滤镜的值即可。例如:设置水平方向上12像素的模糊效果。
blurFilter.setAttribute("stdDeviation","12,0");
注意,模糊过滤器只支持在水平和垂直方向上的定向模糊,不支持任意角度方向的模糊效果。
另外需要注意的是,它会改变所有链接到它的对象的模糊效果,所以需要为每一个需要改效果的元素设置一个<filter>
元素。可以使用下面的方法来动态的生成所需的<filter>
元素。
// go through all the objects that need a blur filter $(".js-blur").each(function(i){ // clone the filter var blurClone=blur.cloneNode(true); // create and set a new ID so we can use the filter through CSS var blurId="blur"+i; blurClone.setAttribute("id",blurId); defs.appendChild(blurClone); // set the CSS var filter="url(#"+blurId+")"; $(this) .css({ webkitFilter:filter, filter:filter }) // store the filter reference on the object for practicity .data("blur",blurClone) ; });
速度测量
接下来我们需要计算对象移动每一帧移动了多少距离。每一帧都需要计算,根据设置的不同,计算的实现方法也可能会有所不同。这个例子中使用了一个比较通用的方法,适合于大多数js和css动画使用。
为了获取位置,使用jQuery的offset
方法,该方法会返回元素距离文档(而不是它的父元素)的坐标。
为了检测每一个动画帧的变化情况,插件中使用了requestAnimationFrame
方法。
// the element we want to apply the effect var $element=$(".selector"); // storing the last position, to be able to measure changes var lastPos=$element.offset(); // a multiplier, to be able to control the intensity of the effect var multiplier=0.25; // a helper to simplify setting the blur. function setBlur(x,y){ blurFilter.setAttribute("stdDeviation",x+","+y); } (function updateMotionBlur(){ // get the current position of the element var currentPos=$element.offset(); // calculate the changes from the last frame and apply the multiplier var xDiff=Math.abs(currentPos.left-lastPos.left)*multiplier; var yDiff=Math.abs(currentPos.top-lastPos.top)*multiplier; // set the blur setBlur(xDiff,yDiff); // store current position for the next frame lastPos=currentPos; // call to update in the next frame requestAnimationFrame(updateMotionBlur); })();
上面的方法只是一个基本的方法,它只考虑了一个元素的情况。更复杂的情况还需要优化这些代码。例如图片画廊的动态模糊效果,你可以看到多个对象同时做运动模糊,然后在静止时同时禁用模糊效果,进行速度计算等等。