JS如何監聽動畫結束

場景描述

在使用JS控制動畫時一般需要在動畫結束后執行回調去進行DOM的相關操作,所以需要監聽動畫結束進行回調。JS提供了以下事件用于監聽動畫的結束,簡單總結學習下。

CSS3動畫監聽事件

transitionEnd事件

transitionEnd事件會在CSS transition動畫結束后觸發。

動畫結束后觸發監聽事件

<!DOCTYPE html>
<html>
<head><title>transtionend demo</title><style type="text/css">*{margin:0;padding: 0;}.demo{margin:100px;width:100px;height: 100px;background-color: #ddc;transition: all 0.5s ease-out;}.demo:hover{width: 200px;}</style>
</head>
<body><div id="demo" class="demo">鼠標移入</div><script type="text/javascript">var element = document.getElementById('demo')element.addEventListener('transitionend', handle, false)function handle(){alert('transitionend事件觸發')}</script>
</body>
</html>

事件多次觸發問題

當存在多個屬性過渡變化時,結束時會多次觸發transitionend事件。看個例子:
當過渡結束時,width和background-color都發生變化,會觸發兩次transionend事件

<!DOCTYPE html>
<html>
<head><title>transtionend demo</title><style type="text/css">*{margin:0;padding: 0;}.demo{width:100px;height: 100px;background-color: #ddc;transition: all 0.5s ease-out;}.w200{width: 200px;background-color: #fef;}</style>
</head>
<body><div id="demo" class="demo" onmouseover="change()" onmouseout="change()"></div><script type="text/javascript">var element = document.getElementById('demo')element.addEventListener('transitionend', handle, false)function handle(){alert('transitionend事件觸發')}function change() {element.className = element.className === 'demo' ? 'demo w200': 'demo'}</script>
</body>
</html>

事件失效問題及解決方案

1、在transiton動畫完成前設置display:none,事件不會觸發。

<!DOCTYPE html>
<html>
<head><title>transtionend demo</title><style type="text/css">*{margin:0;padding: 0;}.demo{width:100px;height: 100px;background-color: #ddc;transition: all 0.5s ease-out;}.w200{width: 200px;}</style>
</head>
<body><div id="demo" class="demo" onmouseover="change()" onmouseout="change()"></div><script type="text/javascript">var element = document.getElementById('demo')element.addEventListener('transitionend', handle, false)function handle(){alert('transitionend事件觸發')}function change() {element.className = element.className === 'demo' ? 'demo w200': 'demo'// 500ms后設置display:nonesetTimeout(function (){element.style.display = 'none'},400)}</script>
</body>
</html>

2、當transition完成前移除transition一些屬性時,事件也不會觸發,例如:

<!DOCTYPE html>
<html>
<head><title>transtionend demo</title><style type="text/css">*{margin:0;padding: 0;}.demo{width:100px;height: 100px;background-color: #ddc;transition: all 0.5s ease-out;}.noTranstion{width:100px;height: 100px;background-color: #ddc;}.w200{width: 200px;}</style>
</head>
<body><div id="demo" class="demo" onmouseover="change()" onmouseout="change()"></div><script type="text/javascript">var element = document.getElementById('demo')element.addEventListener('transitionend', handle, false)function handle(){alert('transitionend事件觸發')}function change() {element.className = element.className === 'demo' ? 'demo w200': 'demo'setTimeout(function(){element.className = 'noTranstion'},400)}</script>
</body>
</html>

3、元素從display:none到block,不會有過渡,導致無法觸發transitionend事件
例如:元素從display:none 到block opacity從0到1,無法觸發過渡效果。

<!DOCTYPE html>
<html>
<head><title>transtionend demo</title><style type="text/css">*{margin:0;padding: 0;}body{padding: 50px;}.demo{width:100px;height: 100px;background-color: #ddc;transition: all 0.5s ease-out;opacity:0;display: none;}.noTranstion{width:100px;height: 100px;background-color: #ddc;}.opt{display: block;opacity:1}.w200{width: 200px;}button{position: absolute;top: 200px;width: 100px;height: 40px;}</style>
</head>
<body><div id="demo" class="demo" onmouseover="change()" onmouseout="change()"></div><button onclick="change()">Click</button><script type="text/javascript">var element = document.getElementById('demo')element.addEventListener('transitionend', handle, false)function handle(){alert('transitionend事件觸發')}function change() {element.className = element.className === 'demo' ? 'demo opt': 'demo'}</script>
</body>
</html>

無法觸發過渡效果原因:
元素從none到block,剛生成未能即時渲染,導致過渡失效。所以需要主動觸發頁面重繪,刷新DOM。頁面重繪可以通過改變一些CSS屬性來觸發,例如:offsetTop、offsetLeft、offsetWidth、scrollTop等。
觸發過渡效果解決方案:
1、通過定時器延遲渲染

<!DOCTYPE html>
<html>
<head><title>transtionend demo</title><style type="text/css">*{margin:0;padding: 0;}body{padding: 50px;}.demo{width:100px;height: 100px;background-color: #ddc;transition: all 0.5s ease-out;opacity: 0;display: none;}.opt{display: block;}button{position: absolute;top: 200px;width: 100px;height: 40px;}</style>
</head>
<body><div id="demo" class="demo"></div><button id="button" onclick="change()">點擊</button><script type="text/javascript">var element = document.getElementById('demo')var button = document.getElementById('button')element.addEventListener('transitionend', handle, false)function handle(){alert('transitionend事件觸發')}function change() {element.className = element.className === 'demo' ? 'demo opt': 'demo'if(element.className === 'demo'){element.style.opacity = nullbutton.innerHTML = '點擊'}else{setTimeout(function(){element.style.opacity = '1'button.innerHTML = '重置'},10)}}</script>
</body>
</html>

2、強制獲取當前內聯樣式
通過window.getComputedStyle()方法返回應用樣式后的元的所有CSS屬性的值,并解析這些值可能包含的任何基本計算。也就是說返回的屬性值是已計算后的值,即DOM元素的樣式已經更新了。然后再改變對應屬性值觸發過渡效果。例如:

<!DOCTYPE html>
<html>
<head><title>transtionend demo</title><style type="text/css">*{margin:0;padding: 0;}body{padding: 50px;}.demo{width:100px;height: 100px;background-color: #ddc;transition: all 0.5s ease-out;opacity: 0;display: none;}.opt{display: block;}button{position: absolute;top: 200px;width: 100px;height: 40px;}</style>
</head>
<body><div id="demo" class="demo"></div><button id="button" onclick="change()">點擊</button><script type="text/javascript">var element = document.getElementById('demo')var button = document.getElementById('button')element.addEventListener('transitionend', handle, false)function handle(){alert('transitionend事件觸發')}function change() {element.className = element.className === 'demo' ? 'demo opt': 'demo'if(element.className === 'demo'){element.style.opacity = nullbutton.innerHTML = '點擊'}else{// setTimeout(function(){//     element.style.opacity = '1'//     button.innerHTML = '重置'// },10)window.getComputedStyle(element, null).opacityelement.style.opacity = '1'button.innerHTML = '重置'}}</script>
</body>
</html>

3、觸發重繪刷新DOM
通過clientWidth觸發重繪,例如:

<!DOCTYPE html>
<html>
<head><title>transtionend demo</title><style type="text/css">*{margin:0;padding: 0;}body{padding: 50px;}.demo{width:100px;height: 100px;background-color: #ddc;transition: all 0.5s ease-out;opacity: 0;display: none;}.opt{display: block;}button{position: absolute;top: 200px;width: 100px;height: 40px;}</style>
</head>
<body><div id="demo" class="demo"></div><button id="button" onclick="change()">點擊</button><script type="text/javascript">var element = document.getElementById('demo')var button = document.getElementById('button')element.addEventListener('transitionend', handle, false)function handle(){alert('transitionend事件觸發')}function change() {element.className = element.className === 'demo' ? 'demo opt': 'demo'if(element.className === 'demo'){element.style.opacity = nullbutton.innerHTML = '點擊'}else{// setTimeout(function(){//     element.style.opacity = '1'//     button.innerHTML = '重置'// },10)// window.getComputedStyle(element, null).opacityelement.clientWidth;element.style.opacity = '1'button.innerHTML = '重置'}}</script>
</body>
</html>

瀏覽器兼容性

移動端基本支持 android2.1+、webkit3.2+
詳見瀏覽器兼容性

animationEnd事件

與transitonend事件類似,詳見

Zepto中animate結束回調實現

查看了下zepto動畫模塊的源代碼,animate()方法在動畫結束后觸發回調也是通過transitionend、animationend事件來觸發。
另外在一些低版本的Android手機可能無法觸發transitionend事件,需要手動觸發。

$.fx = {off: (eventPrefix === undefined && testEl.style.transitionProperty === undefined),speeds: { _default: 400, fast: 200, slow: 600 },cssPrefix: prefix,transitionEnd: normalizeEvent('TransitionEnd'),animationEnd: normalizeEvent('AnimationEnd')}
// 手動觸發事件
if (duration > 0){this.bind(endEvent, wrappedCallback)// transitionEnd is not always firing on older Android phones// so make sure it gets firedsetTimeout(function(){if (fired) returnwrappedCallback.call(that)}, ((duration + delay) * 1000) + 25)}

參考鏈接

zepto動畫模塊源碼
transitionend事件MDN
transtion屬性詳解MDN
transitionend事件詳解
Window.getComputedStyle() 方法

轉載于:https://www.cnblogs.com/GeniusLyzh/p/8324811.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/252474.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/252474.shtml
英文地址,請注明出處:http://en.pswp.cn/news/252474.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

封裝一個ViewPager真正的實現圖片無限循環滾動帶導航點

效果圖&#xff1a; 大家在寫項目的過程中常常會碰到須要實現Viewpager里面載入幾張圖片來循環自己主動輪播的效果&#xff0c;假設不封裝一下的話代碼分散在activity里面會顯得非常亂。并且也不利于我們下次復用&#xff0c;所以這里我把viewpager的相關代碼抽取出來放在了一個…

畢業論文頁眉頁腳頁碼插入

用word這么多年&#xff0c;第一次完整的操作了一遍頁眉頁腳頁碼的插入過程&#xff0c;其實三者都要要求奇偶頁不同 1.頁面布局-》右下角箭頭-》版式-》奇偶頁不同 因為文章不同的部分需要插入不同的頁眉頁腳頁碼&#xff0c;所以要在不同的部分插入分解符斷開它們的連接 2、…

巴黎市中心降下2019年第一場雪

當地時間1月22日&#xff0c;法國巴黎市中心降下2019年第一場雪&#xff0c;氣溫也隨之下降&#xff0c;街上的行人和車輛均有所減少。中新社記者 李洋 攝一對情侶在埃菲爾鐵塔前合影留念。無家可歸者在長椅上睡覺。游客在盧浮宮前拍照。

Echarts實現隱藏x軸,y軸,刻度線,網格

"yAxis": [{//就是一月份這個顯示為一個線段&#xff0c;而不是數軸那種一個點點"show" : true,"boundaryGap": true,"type": "category","name": "時間","data": ["1月", "2…

Ubuntu16.04 + Matlab2018+ desktop creation

https://blog.csdn.net/m0_37601622/article/details/82731879 https://blog.csdn.net/l18092482025/article/details/78906436 The second blog teaches you how to download a matlab.png when there is no matlab.png in /usr/share/applications/.

Atom插件主題推薦

注意事項 主題和插件這方面,比 Sublime Text 人性化多了..一些比較用心的作者增加了二度設置功能。 何為二度設置,就是不用手寫代碼修改配置文件&#xff0c;點點鼠標&#xff0c;填填輸入框就能生效&#xff0c;主題以 isotope-ui 這個做例子介紹,看圖&#xff1a; 進入二度設…

印尼發生洪災和山體滑坡 致多人死亡數千人撤離

當地時間1月23日&#xff0c;印尼南蘇拉威西省望加錫居民受洪水影像&#xff0c;用竹筏運送摩托車。近日&#xff0c;印尼南蘇拉威西省暴雨連連&#xff0c;造成洪災和山體滑坡。目前&#xff0c;暴雨引發的洪災和山體滑坡至少已造成8人死亡&#xff0c;數千人被迫撤離家園。。…

Django學習筆記第三篇--關于響應返回

一、返回簡單類型&#xff1a; 1 #1、返回簡單字符串 2 #from django.http import HttpResponse 3 return HttpResponse("return string") 4 #2、返回json 5 return HttpResponse(json.dumps(response_data),content_type"application/json") 二、返回文…

HTTP響應狀態碼

1XX:代表提示信息 2XX:代表成功信息 3XX:代表重定向 4XX:代表客戶端錯誤信息 5XX:代表服務器錯誤 信息 500:500 錯誤是服務器內部錯誤 ,而且是程序上錯誤 為多,可能是你的用戶權限的問題導致,或者是數據庫連接出現了錯誤. 501:服務器501服務器501錯誤是服務器是否具有請求功能.…

pycharm中無法import已經安裝的ros中的庫

使用pycharm寫python程序&#xff0c;無法import 已經安裝的ros包&#xff0c;并提示ImportError: No module named sensor_msgs.msg 解決方法如下 1. pycharm->file->settings->project:csvfile->project interpreter-> 點擊右側下三角選擇 show all 2. 在彈…

tcp/ip知識點的總結

知識點搜集于網絡&#xff0c;在加上自己的總結&#xff0c;還有很多不全&#xff0c;希望大家多提意見&#xff0c;共享學習&#xff01; 一、TCP/IP是什么&#xff1f; TCP/IP是一個協議族&#xff0c;而不是單獨的協議。包括arp、ip、icmp、tcp、udp、http、ftp等協議 二、T…

搜索引擎ElasticSearchV5.4.2系列一之ES介紹

相關博文&#xff1a; 搜索引擎ElasticSearchV5.4.2系列一之ES介紹 搜索引擎ElasticSearchV5.4.2系列二之ElasticSearchV5.4.2kibanaV5.4.2x-packV5.4.2安裝 搜索引擎ElasticSearchV5.4.2系列三之ES使用 Elasticsearch 是一個開源的搜索引擎&#xff0c;建立在一個全文搜索引擎…

[譯] 前端組件設計原則

原文地址&#xff1a;Front end component design principles 原文作者&#xff1a;Andrew Dinihan 文中示例代碼&#xff1a;傳送門 限于個人能力&#xff0c;如有錯漏之處&#xff0c;煩請不吝賜教。 前言 我在最近的工作中開始使用 Vue 進行開發&#xff0c;但是我在上一家公…

imu_utils標定imu問題解決

在編譯過程中遇到的一些問題可以參照這個女生的文章 https://blog.csdn.net/fang794735225/article/details/92804030 下面是imu_utils的主頁&#xff0c;可以下載代碼&#xff0c;也有使用步驟 https://github.com/gaowenliang/imu_utils 我下載了imu_utils主頁最后面提供…

術語-服務:PaaS

ylbtech-術語-服務&#xff1a;PaaSPaaS是Platform-as-a-Service的縮寫&#xff0c;意思是平臺即服務。 把服務器平臺作為一種服務提供的商業模式。通過網絡進行程序提供的服務稱之為SaaS(Software as a Service)&#xff0c;而云計算時代相應的服務器平臺或者開發環境作為服務…

PostgreSQL安裝和簡單配置

PostgreSQL安裝與使用 目錄 依賴包的安裝源碼編譯和安裝初始化數據庫集簇簡單配置依賴包安裝 PostgreSQL源碼安裝依賴以下四個軟件包 readline zlib flex bison 在Ubuntu中可是應用以下命令直接進行安裝&#xff1a; sudo apt-get install libreadline6 libreadline6-dev zlib1…

1.App瘦身經驗總結

為什么apk越來越大&#xff1f; 1.項目不斷發展&#xff0c;功能越多&#xff0c;代碼量增加的同時&#xff0c;資源文件也在不斷的增多2.app支持的主流dpi越來越多&#xff0c;如ldpi、mdpi、hdpi、xh xxh xxxh等等&#xff0c;間接導致資源增多3.引入的第三方sdk或開源庫越來…

研究相機和IMU坐標系變換

剛開始錄制的數據時沒有考慮相機和IMU之間的坐標變換&#xff0c;但是后來發現跟蹤效果不好&#xff0c;去查驗imu數據時&#xff0c;發現&#xff0c;我采集保存的imu數據格式沒有和euroc數據集中的imu數據保存格式統一&#xff0c;所以需要研究的是在euroc用于數據采集的設備…

第五天:Swift拖動 item 重排 CollectionView

參考鏈接:https://www.jianshu.com/p/96f956f1479e 1 import UIKit2 3 enum VC: String {4 case ViewController5 case CollectionViewController6 7 func segueIdentifier() -> String {8 switch self {9 case .ViewController:10 …

MIT Kimera閱讀筆記

這兩天在調研SLAM的最新算法&#xff0c;找到了2019CVPR上的一篇文章&#xff0c;出自于MIT&#xff0c;因為要給其他同事講解&#xff0c;所以就把文章的重點內容在我個人理解的情況下翻譯了出來&#xff0c;有理解不到位的還請各位大佬多多批評指正。 最后附上了Delaunay Tri…