摘要:在這片文章中,我將會(huì)專研的過渡中更加復(fù)雜的部分,從鏈?zhǔn)胶褪录接布铀俸蛣?dòng)畫函數(shù)。只有當(dāng)需要的時(shí)候,你才應(yīng)該用硬件加速,并且完全不需要在每個(gè)元素上都使用它。此外,不同的瀏覽器用不同的硬件加速的庫(kù),這可能會(huì)造成跨瀏覽器問題。
CSS3的過渡屬性,給web應(yīng)用帶來了簡(jiǎn)單優(yōu)雅的動(dòng)畫,但是比起初次相見,他(transition)有許多細(xì)則。
在這片文章中,我將會(huì)專研CSS3的過渡(transition)中更加復(fù)雜的部分,從鏈?zhǔn)胶褪录接布铀俸蛣?dòng)畫函數(shù)。
讓瀏覽器控制動(dòng)畫序列,通過改變幀率,減少繪畫和減少GPU的工作,能夠優(yōu)化性能和效率。
應(yīng)用 transition一個(gè)最簡(jiǎn)單使用transition的方法就是和CSS偽元素一起用,比如:hover。注意我們?cè)谥付▽傩悦?,transition的時(shí)長(zhǎng),以及默計(jì)時(shí)函數(shù),linear。
.element { height: 100px; transition: height 2s linear; } .element:hover { height: 200px; }
當(dāng):hover偽元素被激活的時(shí)候,這高度會(huì)動(dòng)態(tài)地在兩秒內(nèi)從100px過度到200px。
duration是唯一在transition縮寫中需要的項(xiàng)目。瀏覽器默認(rèn)的定時(shí)方法是ease,以及一個(gè)all的屬性,除非他們已經(jīng)提供了。
當(dāng)談?wù)摰郊せ顃ransition,我們不希望被限制于使用偽元素 —— 很顯然這不靈活。解決這個(gè)的方法就是用程序添加和刪除class
/* CSS */ .element { opacity: 0.0; transform: scale(0.95) translate3d(0,100%,0); transition: transform 400ms ease, opacity 400ms ease; } .element.active { opacity: 1.0; transform: scale(1.0) translate3d(0,0,0); } .element.inactive { opacity: 0.0; transform: scale(1) translate3d(0,0,0); } // JS with jQuery var active = function(){ $(".element").removeClass("inactive").addClass("active"); }; var inactive = function(){ $(".element").removeClass("active").addClass("inactive"); };
以上的列子,我們用了2個(gè)不同的過渡(transition),當(dāng)激活的時(shí)候,元素向上滑動(dòng),當(dāng)無(wú)效化之后,淡出。所有的javascript所做的事就是切換active 和 inactive這兩個(gè)class。
過渡漸變不是所有的CSS屬性都能過渡,最基本的規(guī)則是你只能過渡絕對(duì)值。比如,你不能讓height從 0px過渡到auto,瀏覽器不能計(jì)算中間過度值,因此屬性變化是瞬間的。Oli Studholme提供了便利的 一份完全過度屬性的列表。
同時(shí),有一些很好的解決方法。第一個(gè)方法包括添加透明度到漸變,然后過渡到背景色。比如:
.panel { background-color: #000; background-image: linear-gradient(rgba(255, 255, 0, 0.4), #FAFAFA); transition: background-color 400ms ease; } .panel:hover { background-color: #DDD; }
如果漸變是持續(xù)的,你可以過渡background-position,就像這里寫的,否則,你的最后手段是創(chuàng)建兩個(gè)元素,一個(gè)放在另一個(gè)之上,然后過渡你的透明度。
.element { width: 100px; height: 100px; position: relative; background: linear-gradient(#C7D3DC,#5B798E); } .element .inner { content: ""; position: absolute; left: 0; top: 0; right: 0; bottom: 0; background: linear-gradient(#DDD, #FAFAFA); opacity: 0; transition: opacity 1s linear; } .element:hover .inner { opacity: 1; }
后者方法的需要注意的是,這需要額外的標(biāo)記,并且在內(nèi)部的div能夠捕捉到指針事件。偽元素,類似:before和:after可以是過度理想的使用案例。
硬件加速過渡某個(gè)屬性,比如left和margin會(huì)導(dǎo)致瀏覽器每幀都會(huì)重新計(jì)算樣式。這消耗相當(dāng)昂貴,并且可能會(huì)導(dǎo)致不必要的重繪,特別是如果你在屏幕上有很多元素。這在低性能設(shè)備上顯得特別明顯,比如手機(jī)。
這個(gè)解決方案是使用CSS過渡來減少渲染給GPU帶來的壓力。簡(jiǎn)單來說,這在過渡的時(shí)候,將元素變成了一張圖片,避免任何樣式重新計(jì)算,這極大程度上增加了性能。一個(gè)簡(jiǎn)單強(qiáng)迫瀏覽器用硬件渲染一個(gè)元素的方法是,設(shè)置轉(zhuǎn)型的Z軸,這個(gè)你可以用translate3d:
transform: translate3d(0,0,0);
不過這不是根治性能的方法,并且會(huì)帶來許多本身的問題。只有當(dāng)需要的時(shí)候,你才應(yīng)該用硬件加速,并且完全不需要在每個(gè)元素上都使用它。
比如,硬件加速會(huì)導(dǎo)致微妙的字體問題,比如一個(gè)字體出現(xiàn)的時(shí)候失去了加粗效果。這是因?yàn)橐粋€(gè)bug,當(dāng)元素開啟硬件加速的時(shí)候,不支持子像素抗鋸齒。你可以看到在兩個(gè)渲染模式下的一個(gè)清晰的差別。
此外,不同的瀏覽器用不同的硬件加速的庫(kù),這可能會(huì)造成跨瀏覽器問題。比如,當(dāng)Chrome和Safari都是WebKit內(nèi)核的,Chrome使用Skia來做圖形渲染,然而同時(shí)Safari用的CoreGraphics。這兩個(gè)庫(kù)之間的差別是細(xì)微的,但是確是存在。
你可以用Chrome的開發(fā)者工具概覽頁(yè)面,顯示所有的重繪。外加你可以在開發(fā)者工具選項(xiàng)中選擇顯示三角形,甚至可以通過 about:flags 打開復(fù)合渲染層邊界,來看哪個(gè)層是作用在GPU上的。關(guān)鍵是批量在DOM刷新下,減少繪畫,并且從GPU上減少最多的的壓力。
如果你在瀏覽器之間因?yàn)橛布铀俣辛孙@示問題,比如閃爍或者顫動(dòng),確保你沒有用transform3d()的CSS屬性在元素上。
剪裁為了充分利用GPU渲染,你需要避免使用CSS樣式變換而不是像width這種重新計(jì)算樣式的屬性。若果你確實(shí)需要給元素的寬度做動(dòng)畫?解決方案就是剪裁。
在以下的例子中個(gè),你可以看到一個(gè)搜索框和2個(gè)過度狀態(tài)。第二個(gè)擴(kuò)展?fàn)顟B(tài)被一個(gè)剪裁的元素給隱藏了。
過渡這個(gè)擴(kuò)展的寬度,我們所需要做的就是轉(zhuǎn)變X軸到左邊。這邊的關(guān)鍵是我們用translate3d而不是改變?cè)氐膶挾取?/p>
.clipped { overflow: hidden; position: relative; } .clipped .clip { right: 0px; width: 45px; height: 45px; background: url(/images/clip.png) no-repeat } input:focus { -webkit-transform: translate3d(-50px, 0, 0); }
確保我們不會(huì)在每一幀重新計(jì)算元素的寬度,過渡會(huì)變得順滑和高性能。
時(shí)間函數(shù)到目前為止,我們用了一些瀏覽器預(yù)定義時(shí)間函數(shù)linear, ease, ease-in, ease-out和ease-in-out。對(duì)于更多復(fù)雜的時(shí)間函數(shù)來說,我們要寫我們自己的時(shí)間函數(shù),通過定義貝塞爾曲線的4個(gè)關(guān)鍵點(diǎn)。
transition: -webkit-transform 1s cubic-bezier(.17,.67,.69,1.33);規(guī)劃過渡
在CSS中寫過渡非常好,但是有時(shí)候你需要更多控制,特別是談到鏈?zhǔn)竭^渡的時(shí)候。幸運(yùn)的是我們不僅能從javascript中調(diào)用過渡,也能定義他們。
CSS過渡有一個(gè)魔法般的all屬性,這確保了任何屬性改變都是過渡的。讓我們看看如何實(shí)踐他們
var defaults = { duration: 400, easing: "" }; $.fn.transition = function (properties, options) { options = $.extend({}, defaults, options); properties["webkitTransition"] = "all " + options.duration + "ms " + options.easing; $(this).css(properties); };
現(xiàn)在我們有個(gè)jQuery函數(shù)$.fn.transition,我們可以用它來編程調(diào)用過渡。
$(".element").transition({background: "red"});過渡回調(diào)
接下來的步奏是鏈?zhǔn)竭^渡,是過渡結(jié)束后回調(diào)。你可以在Webkit中獲得這個(gè)狀態(tài),通過監(jiān)聽webkitTransitionEnd這個(gè)事件。
var callback = function () { // ... } $(this).one("webkitTransitionEnd", callback) $(this).css(properties);
記住有時(shí)候事件沒有綁定,經(jīng)常是在那些屬性不改變或者一個(gè)繪畫沒有被觸發(fā)的情況下。為了確保我們一直有一個(gè)回調(diào),讓我們?cè)O(shè)置一個(gè)超時(shí),這會(huì)手動(dòng)幫我們觸發(fā)時(shí)間。
$.fn.emulateTransitionEnd = function(duration) { var called = false, $el = this; $(this).one("webkitTransitionEnd", function() { called = true; }); var callback = function() { if (!called) $($el).trigger("webkitTransitionEnd"); }; setTimeout(callback, duration); };
我們?cè)谠O(shè)置元素css之前,請(qǐng)求 $.fn.emulateTransitionEnd(),以確保我們過渡之后會(huì)有CSS回調(diào)。
$(this).one("webkitTransitionEnd", callback); $(this).emulateTransitionEnd(options.duration + 50); $(this).css(properties);鏈?zhǔn)竭^渡
因此,現(xiàn)在我們能夠通過寫程引用過渡,當(dāng)他們結(jié)束之后獲得回調(diào),我們能夠開始排序過渡。我們能夠?qū)懽约旱男蛄衼碜鲞@件事,但是我們用了jQuery,我們最好滲透庫(kù)的現(xiàn)存方法。
jQuery提供了2個(gè)關(guān)鍵函數(shù)和他的隊(duì)列和API聯(lián)系,$.fn.queue(callback)和 $.fn.dequeue()。前者加了一個(gè)回調(diào)到隊(duì)列中,然后后者執(zhí)行下一個(gè)隊(duì)列中的項(xiàng)目。
換句話說,我們需要設(shè)置我們的CSS過渡在$.fn.queue回調(diào)之中,然后確保當(dāng)過渡完成的時(shí)候,我們調(diào)用了$.fn.dequeue
var $el = $(this); $el.queue(function(){ $el.one("webkitTransitionEnd", function(){ $el.dequeue(); }); $el.css(properties); });
這個(gè)例子相對(duì)簡(jiǎn)單,但是他讓我們創(chuàng)建了復(fù)雜的鏈?zhǔn)絼?dòng)畫,并且甚至使用jQuery的delay()函數(shù):比如:
$(".element").transition({left: "20px"}) .delay(200) .transition({background: "red"});重新繪制
在過渡的時(shí)候,你會(huì)需要兩組CSS屬性。最初的屬性是動(dòng)畫應(yīng)該從哪里開始,和最后的屬性,過渡應(yīng)該在哪里結(jié)束。
$(".element").css({left: "10px"}) .transition({left: "20px"});
然而,你會(huì)發(fā)現(xiàn)如果你應(yīng)用了兩組屬性,一個(gè)立馬在另一個(gè)之后運(yùn)行了,然后瀏覽器嘗試優(yōu)化屬性改變,無(wú)視你的初始屬性和阻止過渡。在場(chǎng)景之后,瀏覽器繪制之前,批處理屬性變動(dòng),經(jīng)常會(huì)加速渲染,經(jīng)常會(huì)有不良反應(yīng)。
解決方法是在兩組屬性之間強(qiáng)迫重繪。一個(gè)簡(jiǎn)單的方法是獲取Dom元素的offsetHeight屬性,就像這樣
$.fn.redraw = function(){ $(this).each(function(){ var redraw = this.offsetHeight; }); };
這在素有的瀏覽器中有有效,但是我有次很巧合地在Android中,這依然不行??晒┨娲姆椒ㄓ衪imeout或者切換class名。
$(".element").css({left: "10px"}) .redraw() .transition({left: "20px"});未來
過渡(Transition)正在活躍地應(yīng)用,以及下一個(gè)標(biāo)準(zhǔn)看上去很有前景。這個(gè)建議包括了一個(gè)新的javascript的API,這個(gè)api專注于過渡現(xiàn)存的限制,并給與開發(fā)者更多的靈活性。
實(shí)際上,你可以在github上找到新API的鋪墊。這包括了舉例一個(gè)Animation構(gòu)造函數(shù),傳遞到一個(gè)元素,讓它做動(dòng)畫,做動(dòng)畫的屬性,還有其他的屬性,諸如延遲。
var anim = new Animation(elem, { left: "100px" }, 3); anim.play();
有了這個(gè)新的API,你可以同步動(dòng)畫,提供私人定制的時(shí)間函數(shù),并且或者完整的回調(diào)。這真是一件激動(dòng)人心的事??!
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/54965.html
摘要:在這片文章中,我將會(huì)專研的過渡中更加復(fù)雜的部分,從鏈?zhǔn)胶褪录接布铀俸蛣?dòng)畫函數(shù)。只有當(dāng)需要的時(shí)候,你才應(yīng)該用硬件加速,并且完全不需要在每個(gè)元素上都使用它。此外,不同的瀏覽器用不同的硬件加速的庫(kù),這可能會(huì)造成跨瀏覽器問題。 CSS3的過渡屬性,給web應(yīng)用帶來了簡(jiǎn)單優(yōu)雅的動(dòng)畫,但是比起初次相見,他(transition)有許多細(xì)則。 在這片文章中,我將會(huì)專研CSS3的過渡(transi...
摘要:我們將使用純打造一些切換開關(guān)并使其擁有類似于的用戶體驗(yàn)??偨Y(jié)這是一個(gè)關(guān)于一些很好的切換開關(guān)示例這種技術(shù)使得一切完全復(fù)合語(yǔ)義,不會(huì)增加任何瘋狂的標(biāo)記,并且用純就可以完成。獲取開關(guān)按鈕代碼可以 我們將使用純CSS打造一些切換開關(guān)并使其擁有類似于checkbox的用戶體驗(yàn)。 很多時(shí)候我們都需要用戶通過勾選/取消checkbox來表明他們對(duì)一些問題的答案。我們?cè)O(shè)置了一個(gè)標(biāo)簽,一個(gè)checkbo...
摘要:我們將使用純打造一些切換開關(guān)并使其擁有類似于的用戶體驗(yàn)??偨Y(jié)這是一個(gè)關(guān)于一些很好的切換開關(guān)示例這種技術(shù)使得一切完全復(fù)合語(yǔ)義,不會(huì)增加任何瘋狂的標(biāo)記,并且用純就可以完成。獲取開關(guān)按鈕代碼可以 我們將使用純CSS打造一些切換開關(guān)并使其擁有類似于checkbox的用戶體驗(yàn)。 很多時(shí)候我們都需要用戶通過勾選/取消checkbox來表明他們對(duì)一些問題的答案。我們?cè)O(shè)置了一個(gè)標(biāo)簽,一個(gè)checkbo...
摘要:我們將使用純打造一些切換開關(guān)并使其擁有類似于的用戶體驗(yàn)??偨Y(jié)這是一個(gè)關(guān)于一些很好的切換開關(guān)示例這種技術(shù)使得一切完全復(fù)合語(yǔ)義,不會(huì)增加任何瘋狂的標(biāo)記,并且用純就可以完成。獲取開關(guān)按鈕代碼可以 我們將使用純CSS打造一些切換開關(guān)并使其擁有類似于checkbox的用戶體驗(yàn)。 很多時(shí)候我們都需要用戶通過勾選/取消checkbox來表明他們對(duì)一些問題的答案。我們?cè)O(shè)置了一個(gè)標(biāo)簽,一個(gè)checkbo...
摘要:讓我們?cè)阢^子里,把幫我們做的事,自己做一遍添加移除類名,監(jiān)聽事件。監(jiān)聽事件調(diào)用告訴動(dòng)畫已完成,以觸發(fā)鉤子目前來說,運(yùn)行良好,實(shí)現(xiàn)了交錯(cuò)過渡的效果,也不用寫大量的。參考資料譯小讓你的交互動(dòng)畫從還不錯(cuò)變成超級(jí)棒showImg(https://user-gold-cdn.xitu.io/2019/5/4/16a831cc937b2891); showImg(https://user-gold-cd...
閱讀 722·2021-11-24 09:39
閱讀 2409·2021-11-22 13:54
閱讀 2259·2021-09-23 11:46
閱讀 3299·2019-08-30 15:55
閱讀 2733·2019-08-30 15:54
閱讀 2472·2019-08-30 14:18
閱讀 1598·2019-08-29 14:15
閱讀 2793·2019-08-29 13:49