摘要:本項目將制作一個交互動畫效果,令其在單詞原詞和數略詞之間切換。二擴展應用到多個單詞數略詞有很多,為了能夠一次展示多個單詞,我們將對現有的程序進行擴展。
效果預覽
按下右側的“點擊預覽”按鈕可以在當前頁面預覽,點擊鏈接可以全屏預覽。
https://codepen.io/comehope/pen/byvRxB
可交互視頻此視頻是可以交互的,你可以隨時暫停視頻,編輯視頻中的代碼。
請用 chrome, safari, edge 打開觀看。
視頻1: https://scrimba.com/p/pEgDAM/cR4gpGsa
視頻2: https://scrimba.com/p/pEgDAM/czNp3MUZ
每日前端實戰系列的全部源代碼請從 github 下載:
https://github.com/comehope/front-end-daily-challenges
代碼解讀大家是否見過 “i18n”、“a11y” 這樣的英文單詞?它們其實是一些單詞的縮寫,“i18n” 代表的是 “internationalization”(國際化),“a11y” 代表的是 “accessibility”(可訪問性),因為包含的字母太多了,所以縮寫時只保留頭尾的字母,再把余下的字符個數寫在中間,這種寫法稱為“Numeronym”,我把它翻譯成“數略詞”。據說最長的單詞是 “pneumonoultramicroscopicsilicovolcanoconiosis”,由 45 個字母組成,意思是一種肺部疾病。
本項目將制作一個交互動畫效果,令其在單詞原詞和“數略詞”之間切換。整個項目分成二個步驟開發,第一步先實現一個固定單詞的交互動畫,第二步改寫為能自動處理任意的單詞,然后擴展應用到多個單詞上。
一、一個固定單詞的交互動畫dom 結構如下,最外側的容器名為 .container,其中包含一個名為 .word 的 元素,分別代表單詞的第1個字母、中間字符的個數(.middle.short)、中間的若干字符(.middle.long)、單詞的最后1個字母。因為動畫時將交替顯示“中間字符的個數”和“中間的若干字符”,所以為它們設置了特殊類名,以便在隨后的 css 代碼中引用它們,當要同時選擇它們時,就用它們共同的類名 middle,當要分別選擇時,就指定它們各自的類名 short 和 long: i
18
nternationalizatio
n 令容器居于頁面正中: 讓 4 個 標簽包含的文字橫向排列在容器中部: 把 2 個中間的 元素的文字上色,突出顯示它們: 接下來制作交互動畫效果。 先把中間的若干字符隱藏起來,只顯示中間字符的個數,在 html 代碼中找到 .middle.long 元素,為它增加一個 hide 樣式類: 在 css 中將 .middle.hide 元素的寬度設置為 0,并且不顯示超出容器的部分: 令鼠標懸停在單詞上時,鼠標指針變成一只手,提示用戶此時可以點擊: 為 .word 元素增加鼠標點擊事件,當單詞被點擊時,2 個中間元素分別切換 hide 類,交替顯示兩者中的一個元素,這些代碼寫在一個名為 initWordElement() 的方法中。在頁面載入時將執行 init() 方法,再在其中調用 initWordElement() 方法。沒有讓 window.onload 直接執行 initWordElement() 方法,而是通過 init() 來調用,是因為在頁面初始化階段還會要做一些其他操作,后面還會逐漸充實 init() 方法: 現在,在頁面上多次點擊單詞,能看到單詞的中間部分不斷切換了,不過這時還沒有動畫效果,接下來為切換增加緩動效果。 先為中間的 2 個元素設置寬度,這 2 個值是手工測量得到的,這不是最終的寫法,后面我們會改成用腳本自動測量得到元素的寬度,不過因為現在我們要解決的是動畫效果,所以先臨時硬編碼一下: 加緩動: 設置緩時長為 1 秒: 現在,點擊單詞時的切換效果,已經有了動畫過程,接下來細化動畫效果。 切換可以理解由 2 個動作組成:一個中間元素消失,另一個中間元素出現,通過增加緩動延時來實現這個效果: 現在,當改變元素寬度時,是以元素的左側為起點改變寬度的,不夠漂亮,我們把它改成以中間為中點改變寬度,這樣當元素變寬時,就向兩側延伸,當元素變窄時,就向中間收縮: 接下來修改緩動時長,由 1s 縮短為 0.5s,也就是令動畫速度加快一倍。為了能方便調試和維護,我們把時長的值定義為變量 --t: 至此,動畫效果制作完成。 “數略詞”有很多,為了能夠一次展示多個單詞,我們將對現有的程序進行擴展。 先引入 lodash 庫,我們將利用它提供的一個模板函數來處理 html 模板: 擴展 dom 結構,.container 容器中將包含不止一個 .word 元素,而是多個 .word 元素了。 創建一個 html 模板,它的內容是 .word 元素的代碼,其中的第一個字母、中間字符個數、中間的若干字符、最后一個字母,這些內容在模板中分別用變量 first、middleLength、middle、last 表示: 而原 .container 元素中的內容都要刪除掉,以便動態填充: 寫一個名為 getWordObject() 的獲取單詞對象的函數,輸入是一個單詞,如“internationalization”,輸出是一個對象,這個對象的屬性與 html 模板中的變量相對應: 接下來寫一個名為 createWordElement() 的方法,用于創建一個 .word 元素,在這個方法中使用了 lodash 的 _.template() 模板函數。該方法的輸入是一個單詞,將傳遞給 getWordObject() 函數: 在負責頁面初始化的 init() 方法中調用 createWordElement() 方法,整個流程改為先創建一個元素,然后把該元素添加到 .container 容器中,再初始化這個元素: 現在,運行一下頁面,雖然運行效果沒有任何變化,但是 css 的屬性、頁面元素都已經變成動態生成的了。如果把 init() 方法中的 word 變量值改為其他單詞,如 “accessibility”,頁面中就會顯示 “a11y” 不過,在單詞變為 “a11y” 之后,中間元素占據的寬度就不正確了,這是因為此前中間元素的寬度是硬編碼的,需要把它們改為用腳本賦值。先刪除掉 css 中的這 2 行代碼: 然后為 .middle 元素設置寬度屬性,屬性值是名為 --w 的變量: 然后在 initWordElement() 方法中增加一行,為變量 --w 賦值: 好了,現在不論把單詞換成什么,都能合適地展現了,至此,單個單詞的動態改造就完成了。 接下來請孫大圣拔下幾根毫毛,幫我們把一個單詞變成多個單詞吧。 修改 init() 方法,刪除掉 word 變量,定義一個名為 WORDS 的數組,遍歷這個數組,為數組中的每個單詞創建一個 .word 元素: 現在,頁面上已經有 5 個單詞了,點擊那個 “p43s” 看看世界上最長的單詞吧。 最后,因為 元素的外邊距較大,把它調整得小一點,讓縱向的幾個單詞排列得緊湊一點: 大功告成! 文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。 轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/54020.htmlbody {
margin: 0;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
background-image: linear-gradient(bisque, lightcyan);
}
.container {
width: 100%;
}
.word {
font-size: 35px;
font-family: monospace;
display: flex;
justify-content: center;
}
.middle {
color: tomato;
}
.middle {
overflow: hidden;
}
.middle.hide {
width: 0;
}
.word:hover {
cursor: pointer;
}
window.onload = init
function init() {
let el = document.querySelector(".word")
initWordElement(el)
}
function initWordElement(el) {
let middles = el.querySelectorAll(".middle")
el.onclick = () => middles.forEach(m => m.classList.toggle("hide"))
}
.middle {
transition: 1s;
}
.middle.short {width: 42px;}
.middle.long {width: 378px;}
.middle {
transition: 1s;
}
.middle {
transition: 1s;
transition-delay: 1s;
}
.middle.hide {
transition: 1s;
}
.middle {
position: relative;
}
.middle span {
position: absolute;
transform: translateX(0);
transition: 1s;
transition-delay: 1s;
}
.middle.hide span {
transform: translateX(-50%);
transition: 1s;
}
.word {
--t: 0.5s;
}
.middle {
transition: var(--t);
transition-delay: var(--t);
}
.middle span {
transition: var(--t);
transition-delay: var(--t);
}
.middle.hide {
transition: var(--t);
}
.middle.hide span {
transition: var(--t);
}
function getWordObject(w) {
return {
first: w.slice(0, 1),
last: w.slice(-1),
middle: w.slice(1, -1),
middleLength: w.slice(1, -1).length,
}
}
function createWordElement(word) {
const TEMPLATE = document.querySelector("#template").innerHTML
let el = document.createElement("div")
el.className = "word"
el.innerHTML = _.template(TEMPLATE)(getWordObject(word))
return el
}
function init() {
let word = "internationalization"
let el = createWordElement(word)
document.querySelector(".container").appendChild(el)
initWordElement(el)
}
了。/* .middle.short {width: 42px;}
.middle.long {width: 378px;} */
.middle {
width: var(--w);
}
function initWordElement(el) {
let middles = el.querySelectorAll(".middle")
middles.forEach(m =>
m.style.setProperty("--w",
window.getComputedStyle(m.querySelector("span")).width))
el.onclick = () => middles.forEach(m => m.classList.toggle("hide"))
}
function init() {
const WORDS = [
"localization",
"accessibility",
"internationalization",
"supercalifragilisticexpialidocious",
"pneumonoultramicroscopicsilicovolcanoconiosis"
]
WORDS.forEach(word => {
let el = createWordElement(word)
document.querySelector(".container").appendChild(el)
initWordElement(el)
})
}
.word p {
margin: 0.3em 0;
}
摘要:本項目將制作一個交互動畫效果,令其在單詞原詞和數略詞之間切換。二擴展應用到多個單詞數略詞有很多,為了能夠一次展示多個單詞,我們將對現有的程序進行擴展。 showImg(https://segmentfault.com/img/bVbtPjm?w=400&h=401); 效果預覽 按下右側的點擊預覽按鈕可以在當前頁面預覽,點擊鏈接可以全屏預覽。 https://codepen.io/co...
摘要:本項目將制作一個交互動畫效果,令其在單詞原詞和數略詞之間切換。二擴展應用到多個單詞數略詞有很多,為了能夠一次展示多個單詞,我們將對現有的程序進行擴展。 showImg(https://segmentfault.com/img/bVbtPjm?w=400&h=401); 效果預覽 按下右側的點擊預覽按鈕可以在當前頁面預覽,點擊鏈接可以全屏預覽。 https://codepen.io/co...
摘要:過往項目年月份項目匯總共個項目年月份項目匯總共個項目年月份項目匯總共個項目年月份項目匯總共個項目年月份項目匯總共個項目年月份項目匯總共個項目年月至年月發布的項目前端每日實戰專欄每天分解一個前端項目,用視頻記錄編碼過程,再配合詳細的代碼解讀, 過往項目 2018 年 9 月份項目匯總(共 26 個項目) 2018 年 8 月份項目匯總(共 29 個項目) 2018 年 7 月份項目匯總(...
閱讀 1074·2021-11-16 11:45
閱讀 2708·2021-09-27 13:59
閱讀 1315·2021-08-31 09:38
閱讀 3143·2019-08-30 15:52
閱讀 1315·2019-08-29 13:46
閱讀 2085·2019-08-29 11:23
閱讀 1631·2019-08-26 13:47
閱讀 2476·2019-08-26 11:54