摘要:標點處理根據(jù)傳入的字符來判斷下一個字符出現(xiàn)的延遲時間,即方法的第二個參數(shù)。年初的時候試著重寫了這個項目,感覺已是沒有什么難度了,不過也是面向過程,一頓操作罷了。
先看效果
請戳這里看預覽
這里是代碼
針對移動端優(yōu)化了體驗
支持動畫跳過
支持多段動畫
標點字符特殊處理,停留時間略長于字符時間
typescript 編寫
對功能進行了封裝處理,可以直接引入使用
基本準備 字符逐個彈出效果的實現(xiàn)原理很簡單,一個閉包,逐一截取字符串,setTimeout 渲染在頁面上即可
/** * @param {HTMLElement} container - 渲染字符的容器 * @param {string} text - 需要渲染的字符串 */ function loadItem(container, text) { let num = 0 let sum = text.length let interval = 16 const startLoad = () => { setTimeout(() => { num += 1 if (num <= sum) { let str = text.substr(0, num) container.scrollTop = 100000 container.innerHTML = str setTimeout(() => { startLoad() }, interval) } }, interval) } startLoad() }html 上的 CSS 字符自動生效
只要在字符串開始渲染時,在 html 中添加一個 style 標簽,將渲染的 CSS 代碼寫入到標簽中即可
創(chuàng)建一個 style 標簽
function getStyleEl() { let newStyle = document.createElement("style") let head = document.querySelector("head") head.appendChild(newStyle) let allStyle = document.querySelectorAll("style") return allStyle[allStyle.length - 1] }
將 CSS 代碼寫入
/** * * @param {string} style - CSS 代碼 * @param {HTMLElement} el - 創(chuàng)建的 style 標簽 */ function handleStyle(style, el) { el.innerHTML = style }CSS 代碼高亮,markdown 自動轉(zhuǎn)換
這里需要借助 prismjs 和 marked 兩個代碼處理庫(當然也可以用其他的)
需要在上述的 loadTtem 函數(shù)中添加判斷
let code switch (type) { case "css": handleStyle(str, styleEl) code = Prism.highlight(str, Prism.languages.css) break case "md": code = marked(str) break }進階處理 分析
基本的核心功能已經(jīng)準備好了
下面我們開始分析過程,開始編寫代碼
需求如下:
支持多段動畫加載
支持動畫跳過(直接加載完成)
移動端特殊處理
基于上述需求,我們需要先對接口進行定義
我們設想函數(shù)是這樣使用的
/** * @param {HTMLElement} container - 字符渲染的容器 * @param {Object} options - 動畫參數(shù) * * @param {string} options.content.load - 需要渲染的字符串 * @param {"css" | "md"} options.content.type - 渲染后高亮的方式,當前僅支持 "css" | "md" 兩個參數(shù) * @param {string} options.content.id - 渲染容器的 id * @param {boolean} options.content.rewrite - 是否需要重寫 * * @param {Object}? options.mobileAnimate - 移動端需要特殊處理 * @param {string} options.mobileAnimate.styleID - css 加載的容器 ,id 應與 content 中 css 容器的 id 相同 * @param {string} options.mobileAnimate.string - markdown 加載的容器,id 應與 content 中 md 容器的 id 相同 */ let ar = new AnimateResume(container, { content:[ { load:"", type:"css", id:"", rewrite:"", }, ... ], mobileAnimate:{ styleID:"", resumeID:"" } }) ar.animate() ar.skip()
使用前需要實例化一個并傳入?yún)?shù),通過 animate 方法開始動畫,skip 方法跳過動畫
根據(jù)上述參數(shù)設想,我們可以寫出如下的 typescript 接口,不了解 typescript 的同學可以直接跳過,只看上面代碼的注釋即可
interface Core { container: Element options: CoreOptions isSkip: boolean animate: () => void skip: () => void } interface CoreOptions { content: Array實現(xiàn)mobileAnimate?: { styleID: string resumeID: string } } interface LoadParams { load: string type: "css" | "md" id: string rewrite?: boolean }
基本的架構(gòu)已經(jīng)分析好了,現(xiàn)在可以開始實現(xiàn)了
逐一加載首先,因為動畫是多段完成的,所以我們通過參數(shù) content 傳入的是一個二維數(shù)組,其中每個 item 存放著我們想要加載的內(nèi)容和對應要求,如何讓動畫一段一段的完成呢?很自然的能想到 Promise 方法,通過 Promise.then() 來實現(xiàn)。
所以我們可以將這個需求抽象為:一個未知長度的數(shù)組,需要逐一的在未知時間后加載下一項。
實現(xiàn)也很簡單,代碼如下:
function load(contents) { if (contents.length) { this.loadItem(contents[0]) .then(() => this.load(contents.slice(1))) } }
可以想到,上述中的 loadItem 方法應該返回一個 new Promise ,內(nèi)部當字符串加載完成后返回 resolve(),然后繼續(xù)執(zhí)行下一段 load 方法
支持跳過如何才能中斷當前的動畫,直接加載完成呢?
最初我嘗試直接暴力的通過在 loadItem 時檢查加載字數(shù)和一個全局變量來判斷是否 setTimeout,
但很明顯這么做及其不優(yōu)雅,而且有 bug(但我忘了是什么 bug 了...)。
優(yōu)雅實現(xiàn):在類中聲明 this.isSkip = false(相當于全局變量),在 skip() 方法調(diào)用時,將其改變?yōu)?true,在 loadItem 中 setTimeout 前檢查該變量,如果為 true 則拋出 reject()
所以上述的 load 方法需要添加變?yōu)椋?/p>
function load(contents) { if (contents.length) { this.loadItem(contents[0]) .then(() => this.load(contents.slice(1))) .catch(() => this.skipAnimate()) } }
skipAnimate 即為對應的跳過動畫方法
移動端處理沒有動圖…… 請點擊預覽在手機或者谷歌調(diào)試中自行查看
展示樣式我們可以直接在渲染的 CSS 代碼動畫中自定義,所以不過多解釋
這里只說一下兩個頁面上下滑動的效果實現(xiàn)
我們需要借助 better-scroll 插件來幫助優(yōu)化,分別設置上部分頁面上拉刷新事件和下部分頁面的下拉刷新事件,在對應事件觸發(fā)時,通過 transform:translateY(x) 來實現(xiàn)頁面的整體滑動,代碼如下
let styleScroll = new BScroll(styleContainer, { pullUpLoad: { threshold: 20 } }) let mdScroll = new BScroll(mdContainer, { pullDownRefresh: { threshold: 20, } }) styleScroll.on("pullingUp", function () { mdContainer.style.transform = "translateY(calc(-100% - 4rem))" styleContainer.style.transform = "translateY(calc(-100% - 1rem))" styleScroll.finishPullUp() }) mdScroll.on("pullingDown", function () { mdContainer.style.transform = "translateY(0)" styleContainer.style.transform = "translateY(0)" mdScroll.finishPullDown() })
需要注意的是如果下方簡歷內(nèi)容長度不夠,不會觸發(fā) better-scroll 的滑動檢測,導致無法出現(xiàn)預想的滑動效果。
標點處理根據(jù)傳入的字符來判斷下一個字符出現(xiàn)的延遲時間,即 setTimeout 方法的第二個參數(shù)。
function getInterval(str: string, interval = 16): number { if (/D[,]s$/.test(str)) return interval * 20 if (/[^/] $/.test(str)) return interval * 40 if (/[.?!]s$/.test(str)) return interval * 60 return 0 }
參考自 https://github.com/STRML/strm... ,算是拾人牙慧了。
結(jié)束基本的實現(xiàn)思路已經(jīng)說完,具體的代碼貼上來實在是篇幅太長,請查看源碼。
不了解 typescript 的同學可以看這里,這是我年初時用 js 寫的,不過算是面向過程編寫,沒有做過多的封裝處理。
寫在最后第一次見到http://strml.net/ 時,是在初學前端大概三四個月的樣子,當時看到這樣的展現(xiàn)形式著實是被驚艷到了,那時還是個小白,連 highlight 這樣的插件都不知道,更不知道還能在style里自定義東西,更更更不知道網(wǎng)站下面就放著View Source這么個大字,只是一心想的要自己也寫一個,就那么硬生生自己寫正則,通過不同的特殊符號加載對應的標簽處理變色,再通過 `dom.style....=..." 設置樣式,然后居然還寫的有模有樣,第一次找工作時還居然敢拿出來給面試官看了(笑)。
年初的時候試著重寫了這個項目,感覺已是沒有什么難度了,不過也是面向過程,一頓操作罷了。這些天初學 typescript 想著拿個什么東西練個手,所以又把這個項目用 ts 重構(gòu)了,并且進一步的進行了封裝。感覺可以出來溜溜了,所以寫下了這篇文章。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/53452.html
摘要:標點處理根據(jù)傳入的字符來判斷下一個字符出現(xiàn)的延遲時間,即方法的第二個參數(shù)。年初的時候試著重寫了這個項目,感覺已是沒有什么難度了,不過也是面向過程,一頓操作罷了。 先看效果 請戳這里看預覽這里是代碼 見過了?別走,這是與眾不同的地方 針對移動端優(yōu)化了體驗 支持動畫跳過 支持多段動畫 標點字符特殊處理,停留時間略長于字符時間 typescript 編寫 對功能進行了封裝處理,可以直接引入...
摘要:標點處理根據(jù)傳入的字符來判斷下一個字符出現(xiàn)的延遲時間,即方法的第二個參數(shù)。年初的時候試著重寫了這個項目,感覺已是沒有什么難度了,不過也是面向過程,一頓操作罷了。 先看效果 請戳這里看預覽這里是代碼 見過了?別走,這是與眾不同的地方 針對移動端優(yōu)化了體驗 支持動畫跳過 支持多段動畫 標點字符特殊處理,停留時間略長于字符時間 typescript 編寫 對功能進行了封裝處理,可以直接引入...
閱讀 968·2023-04-26 02:49
閱讀 1180·2021-11-25 09:43
閱讀 2551·2021-11-18 10:02
閱讀 2926·2021-10-18 13:32
閱讀 1288·2019-08-30 13:54
閱讀 2084·2019-08-30 12:58
閱讀 3017·2019-08-29 14:06
閱讀 2159·2019-08-28 18:10