當前位置:
首頁 > 知識 > SVG實現動態模糊動畫效果

SVG實現動態模糊動畫效果

今天我們將向大家展示如何製作SVG動態模糊效果,並將其應用於HTML元素的常規JS或CSS動畫。

動態模糊是一種廣泛使用於動態影像和動畫的技術,它能使動作看起來更加平滑自然。

SVG實現動態模糊動畫效果

在線演示源碼下載


動態模糊是靜止圖像或一系列圖像(如電影或動畫)中快速移動物體的明顯圖像拖尾。當記錄的圖像在單幀記錄期間發生變化時,由於快速移動或長時間曝光從而導致動態模糊的結果。——維基百科上對動態模糊的介紹

在這篇文章中,我們將介紹如何對水平或垂直的轉換製作出類似的動態模糊效果。


注意:這種效果非常實用,但只有一些現代瀏覽器才支持。到目前為止,貌似Chrome具有最佳的性能。

為了對動畫應用動態模糊效果,我們需要在每個幀中根據對象的速度和它移動的方嚮應用方向模糊。

SVG實現動態模糊動畫效果

那麼,怎麼才能產生這種效果呢?

設置模糊

由於常規CSS模糊濾鏡不支持定向模糊,所以我們不得不使用SVG濾鏡。

我們已經在《Creative Gooey Effects》這篇文章中介紹過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屬性用於設置模糊強度,並且可以佔用兩個參數,用於水平和垂直方向的模糊。

將濾鏡應用到一個元素上,就像我們之前看到的那樣,非常簡單:

.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屬性。例如,要設置一個水平12px的模糊:

blurFilter.setAttribute("stdDeviation","12,0");

SVG實現動態模糊動畫效果

記住,此模糊濾鏡只支持X或Y方向上的方向模糊,不能任意角度,因此你需要相應地規劃好動畫效果。

還有,改變模糊濾鏡會影響與其相關聯的所有對象,因此我們需要為將應用此效果的每個對象添加一個新的<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函數,這正是我們需要的:它返回元素的坐標,相對於文檔(而不是它的父類)而言,並且將transform屬性考慮在內。

為了能夠檢查改變並更新每一幀,我們將使用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);
})();

結果如下:

SVG實現動態模糊動畫效果

這不過是僅考慮一個要素的基本方法。更複雜的可能需要特別為其優化的代碼。對於更複雜的拍攝,你可以考慮將動態模糊效果應用於多個對象,在沒有動畫時禁用模糊和速度計算,等等。

到這裡本教程就結束了! 再說一次,請注意,這種效果可能很耗費資源,所以你應該避免在大型對象上使用它。

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 程序員小新人學習 的精彩文章:

VSCode配置Python編輯器
C從零開始寫 SharpDx 應用 控制台創建 Sharpdx 窗口

TAG:程序員小新人學習 |