-
Notifications
You must be signed in to change notification settings - Fork 1
/
index.ts
129 lines (118 loc) · 3.91 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
import {
createTextNode,
sleep,
createLineFeed,
createTextElement,
} from "./src/utils/index"
import {
handingText,
createCursor,
createTypeContainer,
getCurrentChildNodes,
} from "./src/heplers"
import { INSERT, MOVE, REMOVE } from "./src/heplers"
import "./src/css/animate.css"
export type TypeNetInstance = TypeEffect
export type TypeNetOptions = { speed?: number; style?: string }
export type Callback = () => void
export const defaultTypeNetOptions = { speed: 100 }
export default class TypeEffect {
typeContainer: HTMLElement = document.body // 打字区域 初始化为body
root: HTMLElement | null // 根标签
callbacks: Array<Callback> = [] // 处理链式调用callbacks
cursorPosition = 0
constructor(
private el: string,
public options: TypeNetOptions = defaultTypeNetOptions
) {
this.root = document.querySelector(el)
if (!this.root) {
console.error("please give the correct container.")
return
}
}
type(text: string, options?: TypeNetOptions) {
this.callbacks.push(async () => {
for (let i = 0, n = text.length; i < n; i++) {
const textNode = options?.style
? createTextElement(text[i], options?.style)
: createTextNode(text[i])
// 使用延迟时间
const speed = options?.speed || this.options.speed
await handingText(this.typeContainer, textNode, speed, INSERT)
this.cursorPosition++
}
})
return this
}
remove(characters = 1, options?: TypeNetOptions) {
// 获取到当前的容器元素 执行删除
this.callbacks.push(async () => {
// 获取当前所有子节点
const childNodes = getCurrentChildNodes(this.typeContainer)
// 能删除的节点为光标左侧的节点
let actualCharactersLength = Math.min(characters, this.cursorPosition)
// 防止越界 取用户与实际字符数量的最小值
while (actualCharactersLength--) {
const lastChildNode = childNodes[--this.cursorPosition]
const speed = options?.speed || this.options.speed
await handingText(this.typeContainer, lastChildNode, speed, REMOVE)
}
})
return this
}
move(characters = 1, options?: TypeNetOptions) {
// 获取到当前的容器元素 执行删除
this.callbacks.push(async () => {
const childNodes = getCurrentChildNodes(this.typeContainer),
direction = characters > 0 ? "forward" : "backward"
const dict = {
// 还剩下多少个字符可以往前 (往前移动同时不能超过字符右端点)
forward: {
actualCharactersLength: Math.min(
characters,
childNodes.length - this.cursorPosition
),
add: 1,
},
// 还剩下多少个字符可以往后 (往后移动同时不能超过字符左端点)
backward: {
actualCharactersLength: Math.min(-characters, this.cursorPosition),
add: -1,
},
}
while (dict[direction].actualCharactersLength--) {
const siblingNode = childNodes[(this.cursorPosition += dict[direction].add)]
const speed = options?.speed || this.options.speed
await handingText(this.typeContainer, siblingNode, speed, MOVE)
}
})
return this
}
sleep(time: number) {
this.callbacks.push(async () => await sleep(time))
return this
}
line() {
this.callbacks.push(async () => {
const br = createLineFeed()
this.typeContainer.insertBefore(
br,
this.typeContainer.childNodes[this.cursorPosition++]
)
})
return this
}
// code(codeSnippet: string, options?: TypeNetOptions) {
// // 默认将代码解析成JS
// this.callbacks.push(async () => {
// console.log(codeSnippet, options)
// })
// return this
// }
async start() {
createTypeContainer(this)
createCursor(this)
for (const cb of this.callbacks) await cb.apply(this) // 处理内容callbacks
}
}