前言
22年暑假时,我把博客首页的打字机特效换成了类似于现在这种,但是当时也是随便做出来玩玩的,不仅功能单一,结构臃肿,用了530行js也只能达到让主页有两句循环的轮播,实在太不优雅。
今年十月初我决定重制这个功能将其从530行压缩到370行,并在原有的基础上加入了跳过空格、自定义速度、快捷引用目标等功能,并将其封装为函数,现在想要使用只需一句:
virgule(target,context,speed)
项目现已开源。@Github:RavelloH/virgule.js
效果
升级前后对比
升级前
升级后
即时体验
使用
直接引入JavaScript脚本
<script src="https://ravelloh.github.io/virgule.js/virgule.js"></script>
手动复制源代码
// Author:RavelloH // LICENCE: MIT // Repo src: github.com/RavelloH/virgule.js randArrMin = ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","0","1","2","3","4","5","6","7","8","9"]; randArr = ["あ","ぃ","い","ぅ","う","ぇ","え","ぉ","お","か","が","き","ぎ","く","ぐ","け","げ","こ","ご","さ","ざ","し","じ","す","ず","せ","ぜ","そ","ぞ","た","だ","ち","ぢ","っ","つ","づ","て","で","と","ど","な","に","ぬ","ね","の","は","ば","ぱ","ひ","び","ぴ","ふ","ぶ","ぷ","へ","べ","ぺ","ほ","ぼ","ぽ","ま","み","む","め","も","ゃ","や","ゅ","ゆ","ょ","よ","ら","り","る","れ","ろ","ゎ","わ","ゐ","ゑ","を","ん","ゔ","ゕ","ゖ","ァ","ア","ィ","イ","ゥ","ウ","ェ","エ","ォ","オ","カ","ガ","キ","ギ","ク","グ","ケ","ゲ","コ","ゴ","サ","ザ","シ","ジ","ス","ズ","セ","ゼ","ソ","ゾ","タ","ダ","チ","ヂ","ッ","ツ","ヅ","テ","デ","ト","ド","ナ","ニ","ヌ","ネ","ノ","ハ","バ","パ","ヒ","ビ","ピ","フ","ブ","プ","ヘ","ベ","ペ","ホ","ボ","ポ","マ","ミ","ム","メ","モ","ャ","ヤ","ュ","ユ","ョ","ヨ","ラ","リ","ル","レ","ロ","ヮ","ワ","ヰ","ヱ","ヲ","ン","ヴ","ヵ","ヶ","ヷ","ヸ","ヹ","ヺ","ー","ヾ","ㄅ","ㄆ","ㄇ","ㄈ","ㄉ","ㄊ","ㄋ","ㄌ","ㄍ","ㄎ","ㄏ","ㄐ","ㄑ","ㄒ","ㄓ","ㄔ","ㄕ","ㄖ","ㄗ","ㄘ","ㄙ","ㄝ","ㄞ","ㄟ","ㄠ","ㄡ","ㄢ","ㄣ","ㄤ","ㄥ","ㄦ","ㄧ","ㄨ","ㄩ","〇","口","甲","乙","丙","丁","戊","己","庚","辛","壬","癸",]; function virgule(target, context, speed = 100) { //context重组 contextArr = []; for (var i = 0; i < context.length; i++) { contextArr.push(context[i]) } // 添加/ target.innerHTML = ""; numVirgule = 0 var virgulegenerate = setInterval( function() { // 字符划分 if (escape(contextArr[numVirgule]).indexOf("%u") < 0) { if (contextArr[numVirgule] == ' ') { target.innerHTML += ' ' } else { target.innerHTML += '/' } } else { target.innerHTML += '//' } numVirgule += 1 if (numVirgule > context.length) { clearInterval(virgulegenerate); target.innerHTML = target.innerHTML.slice(0, target.innerHTML.length-1) setTimeout(function() { textIn()}, 100) } }, 1000/speed) // 文字进入 numIn = 0; numCharacter = 0; function textIn() { originText = target.innerHTML; var virgulereplace = setInterval( function() { numIn += 1 if (numIn >= contextArr.length) { clearInterval(virgulereplace) textwrite() } cacheText = '' numCharacter = 0 for (i = 0; i < numIn; i++) { if (escape(contextArr[i]).indexOf("%u") < 0) { if (contextArr[i] == ' ') { cacheText += ' ' numCharacter += 1 } else { //单字符 var rand = Math.floor(Math.random() * randArrMin.length); cacheText += randArrMin[rand] numCharacter += 1 } } else { // 双字符 var rand = Math.floor(Math.random() * randArr.length); cacheText += randArr[rand] numCharacter += 2 } } target.innerHTML = cacheText + originText.slice(numCharacter, originText.length) }, 2000/speed) // 原始文字写入 numWrite = 0 function textwrite() { originText = target.innerHTML; var virgulewrite = setInterval( function() { numWrite += 1 if (numWrite >= contextArr.length) { clearInterval(virgulewrite) } cacheText = '' numCharacter = 0 for (i = 0; i < numIn; i++) { if (escape(contextArr[i]).indexOf("%u") < 0) { if (contextArr[i] == ' ') { cacheText += ' ' numCharacter += 1 } else { //单字符 var rand = Math.floor(Math.random() * randArrMin.length); cacheText += randArrMin[rand] numCharacter += 1 } } else { // 双字符 var rand = Math.floor(Math.random() * randArr.length); cacheText += randArr[rand] numCharacter += 2 } } target.innerHTML = context.slice(0, numWrite) + cacheText.slice(numWrite, cacheText.length) + originText.slice(numCharacter, originText.length) }, 2000/speed) } } }
用以上任意一种方法,获取到JS即可。接下来就是如何使用,也十分方便:
virgule(target,context,speed) //target context必填,speed可选填,默认100 //example: virgule(document.getElementById('jumping'), 'Place the text you want as the result here',100) //对文档中一个id为jumping的元素使用virgule效果,目标文字是"Place the text you want as the result here",速度为100
这里推荐Microsoft Yahei Mono和SF Mono SC。
实现方法
注:下方行数表示以上Js代码所处行数。
4-5:定义了两个列表randArrMin
以及randArr
,前者用于一个英文字符宽的字符的替换,后者用于一个中文字符宽的替换。
7:定义了virgule的主函数,默认参数中target
context
必填,speed
选填,默认100。
8-12:将context中的内容转换到contextArr中储存。
14-15:重置目标
16-36:创建延迟循环virgulegenerate,间隔1000/speed毫秒。
41-109:textIn()主函数,用于将生成的斜杠替换为context文字。
关键分析
其实整个过程中最复杂的是三个插入过程的顺序。这简单来说,分为以下三个阶段:
1.用斜杠覆盖文本。
2.逐渐将斜杠替换为随机文字。这一过程中,每将一个斜杠组替换一个新字符,就会重新将它前面的随机字符再随机化。
3.用target中的文字替换随机文字。这一过程大体与2相反,没将一个随机字符替换为目标字符,就会刷新其后的随机字符。
以上三个过程顺次进行,每个过程完成后唤起下一个过程。如果还不理解,可以在#效果章节的在线体验中,选择较低的速度运行,以理解这三个过程。
后言
上述就是virgule.js现有的功能介绍和使用方法,顺带着也写了大体的实现方法。
本来打算把virgule效果应用给整个博客的,但碍于实在找不到什么地方再去添加,先鸽了。