我正在從頭開始構建一個練習專案。這是一個香草 javascript 插件,可讓您創建“影片打字效果”。
到目前為止帶有演示的代碼筆:https ://codepen.io/juan-sebasti-n-bonnett/pen/oNoVGad
const TypingEffect = {
options: {
parallel: false,
showCursor: true,
removeOtherCursors: true,
removeCursorAfter: 0,
cursorColor: '#000',
cursorBG: '#000',
cursorWeight: '0px',
cursorInterval: 400,
typingSpeed: 80,
cursorChar: '|',
eraseSpeed: 50,
showcaseEraseDelay: 3000,
},
type: function(_elem, _str) {
let elem;
if (typeof(_elem) != 'string' && typeof(_elem) != 'object') return;
if (typeof(_elem) == 'string') {
console.log('we have to query a selector');
elem = document.querySelector(_elem);
console.log(elem);
}
if (this.options.showCursor) elem = this.cursor(elem);
let typingSpeed = parseInt(this.options.typingSpeed);
let str = _str || elem.innerHTML;
let strArray = str.split('');
let currentString = '';
let i = 0;
return new Promise((resolve, reject) => {
let typing = setInterval(() => {
if (i < strArray.length) {
currentString = currentString strArray[i];
elem.innerHTML = currentString;
i ;
} else {
clearInterval(typing);
resolve(elem);
}
}, typingSpeed);
});
},
typeMultiple: function(elements) {
let promise = Promise.resolve();
elements.forEach(element => {
promise = promise.then(() => {
return this.type(element);
});
});
promise.then(() => {
if (parseInt(this.options.removeCursorAfter) > 0) {
setTimeout(() => {
this.removeCursor();
}, this.options.removeCursorAfter);
}
});
return promise;
},
typeSelector: function(selector) {
let elements = document.querySelectorAll(selector);
if (this.options.parallel) {
elements.forEach(element => {
this.type(element);
});;
} else {
return this.typeMultiple(elements);
}
},
erase: function(elem) {
if (typeof(elem) != 'string' && typeof(elem) != 'object') return;
if (typeof(elem) == 'string') {
elem = document.querySelector(elem);
}
let str = elem.innerHTML;
return new Promise((resolve, reject) => {
let erasing = setInterval(() => {
if (str.length > 0) {
str = str.slice(0, -1);
elem.innerHTML = str;
} else {
clearInterval(erasing);
resolve(elem);
}
}, parseInt(this.options.eraseSpeed));
});
},
cursor: function(elem) {
if (this.options.removeOtherCursors) this.removeCursor();
let string = elem.innerHTML;
let cursorInterval = parseInt(this.options.cursorInterval);
let cursorVisible = true;
const cursorNode = document.createElement('span');
const cursor = document.createTextNode(this.options.cursorChar);
const stringNode = document.createElement('span');
const stringContent = document.createTextNode(string);
elem.innerHTML = '';
stringNode.appendChild(stringContent);
elem.appendChild(stringNode);
stringNode.id = 'typing-string-content';
cursorNode.appendChild(cursor);
elem.appendChild(cursorNode);
cursorNode.id = 'typing-cursor';
cursorNode.style.paddingLeft = this.options.cursorWeight;
cursorNode.style.backgroundColor = this.options.cursorBG;
cursorNode.style.color = this.options.cursorColor;
setInterval(() => {
if (cursorVisible) {
cursorNode.style.opacity = 0;
cursorVisible = false;
} else {
cursorNode.style.opacity = 1;
cursorVisible = true;
}
}, cursorInterval);
return stringNode;
},
removeCursor: function(_cursor) {
let cursor = _cursor || document.getElementById('typing-cursor');
if (cursor) cursor.remove();
},
init: function(_options) {
if (_options) Object.assign(this.options, _options);
},
}
/*
Typing Effect usage
*/
let newOptions = {
typingSpeed: 120,
eraseSpeed: 120,
cursorColor: 'rgb(14, 231, 32)',
}
TypingEffect.init(newOptions);
let string = `Hello! I'm using the type() function`;
let done = TypingEffect.type('#type-here', string);
done.then((elem) => {
if (elem) {
let notice = document.getElementById('notice');
notice.innerHTML = `Done Typing! But I will be erased after 6 seconds`;
setTimeout(() => {
let doneErasing = TypingEffect.erase(elem);
doneErasing.then((elem) => {
notice.innerHTML = `Done erasing!`;
});
}, 6000);
}
});
* {
box-sizing: border-box;
}
body {
background-color: #000;
}
.container {
width: 100%;
/*display: flex;
align-items: center;
justify-content: center;*/
}
.typing-effect {
font-family: 'Consolas';
color: rgb(14, 231, 32);
font-size: 22px;
}
#notice {
color: white;
font-size: 22px;
font-family: sans-serif;
padding-top: 54px;
}
<div class="container">
<p id="type-here" class="typing-effect"></p>
</div>
<div id="notice"></div>
我已經有了一種機制,可以讓我在 HTML 元素中鍵入一個字串,而另一種機制可以讓我洗掉它。但是我現在的目標是能夠創建第三個函式,它接收一組句子并開始輸入一個句子,然后稍等片刻,洗掉它,然后輸入另一個句子,直到陣列結束,然后從索引 0。
代碼現在使用 Promises,邏輯如下:
function type(selector, string) {
// returns a promise that resolves
// when we're done typing the string
// and returns the element that contains the text (the selector)
}
function erase(selector) {
// returns a promise that resolves when
// we're done erasing the whole node's content
// and returns the element that is now empty (the selector)
}
Now, I'm still new to this concept of promises, and although they're easy to understand when they're explained with APIs and so, it gets hard to manipulate them in chain, mostly when you need something like this:
function typeMultipleSentences(selector, arrayOfSentences) {
// LOOP:
// types the first sentence of the array
// when its done typing, waits for a couple seconds and then erases it
// when it's done erasing, does the same with the next sentence in the array
}
//Usage
typeMultipleSentences('#type-here', ['Hello World', 'Hola Mundo', 'Hallo Welt']);
Other functions inside the object I shared are just helpers and they do other kind of stuff with this effect, like adding the cursor to the end, typing paragraphs one after the other, etc. But those are not important, I only need to know how to achieve this kind of "Promise Chaining Delaying thing"
uj5u.com熱心網友回復:
聽起來你需要一個延遲函式,你可以通過回傳一個在設定時間后解決的承諾來做到這一點,然后使用async/await它來簡化代碼,這樣你就不會“鏈接”任何東西,只是等待。
function delay(time) {
return new Promise(res => {
setTimeout(() => res(), time);
});
}
async function main(data) {
for (const el of data) {
console.log(`Writing ${el}`);
await delay(2000);
console.log(`Erasing ${el}`);
await delay(2000);
}
console.log('Done!');
}
const data = ['Hello World', 'Hola Mundo', 'Hallo Welt'];
main(data);
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/440238.html
