-
Notifications
You must be signed in to change notification settings - Fork 0
/
animatedText.js
147 lines (138 loc) · 3.87 KB
/
animatedText.js
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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
class AnimaText {
constructor(word, x, y, size = 150, gap = 10, types = []) {
this.x = x;
this.y = y;
this.size = size;
this.types = types;
this.size = size;
this.gap = gap;
this.letters = this.formLetters(word);
}
/**
* Renders each letter to canvas
*/
render() {
for (let letter of this.letters) {
letter.show();
}
}
/**
* Forms an array of animated letters from an input string
* @param {String} letterSet String of characters to animate
* @return {Array} Array of animated letters
*/
formLetters(letterSet) {
let animatedLetters = [];
let xPos = this.x
for (let i = 0; i < letterSet.length; i++) {
let l;
if (this.types.length > 0) {
let randomIndex = Math.floor(random(0, this.types.length));
l = new this.types[randomIndex](letterSet[i].toUpperCase(), xPos, this.y, this.size);
} else {
let allTypes = [RainbowLetter, DotsLetter, LinesLetter, GlitchLetter,
PerlinLetter, WaveLetter, NeonLetter
];
let randomIndex = Math.floor(random(0, allTypes.length));
l = new allTypes[randomIndex](letterSet[i].toUpperCase(), xPos, this.y, this.size);
}
animatedLetters.push(l);
xPos += l.w + this.gap;
}
return animatedLetters;
}
setSize(size) {
this.size = size;
}
}
class Letter {
constructor(letter, x, y, size) {
this.letter = letter;
this.size = size;
this.x = x;
this.y = y;
this.w = this.letterWidth();
}
/**
* Renders generic letter to canvas. Concrete letter classes override this method.
*/
show() {
noStroke();
fill(255);
textFont(font);
textSize(this.size);
text(this.letter, this.x, this.y);
}
/**
* Calculates the width of a letter using limits of textToPoints
* @return {Number} Width of the letter in pixels
*/
letterWidth() {
if (this.letter == ' ') {
return this.size / 2;
}
let leftPos = 5;
let rightPos = 0;
let pts = font.textToPoints(this.letter, 0, 0, this.size);
for (let p of pts) {
if (p.x < leftPos) {
leftPos = p.x;
}
if (p.x > rightPos) {
rightPos = p.x;
}
}
return rightPos - leftPos;
}
/**
* Calculates the centre of mass of a letter using the averages of textToPoints
* @return {Array} Two element array of [xCOM, yCOM]
*/
com() {
let sumX = 0;
let sumY = 0;
let pts = font.textToPoints(this.letter, 0, 0, this.size);
for (let p of pts) {
sumX += p.x;
sumY += p.y;
}
return [(sumX / pts.length) + this.x, (sumY / pts.length) + this.y];
}
/**
* Splits the points returned from textToPoints into separate arrays if there
* is a discontinuity in the letter, e.g. "B" has three distinct curves that
* define the letter stroke: one outer and two inner curves.
* Note: this method ensures the first array constains the most points i.e.
* is the outer edge of the letter.
* @return {Array} Array of array of points
*/
splitPts() {
let arrOfPts = [
[]
];
if (this.pts.length == 0) {
return arrOfPts
}
let expectedDist = dist(this.pts[1].x, this.pts[1].y, this.pts[0].x, this.pts[0].y);
for (let i = 0; i < this.pts.length; i++) {
let p = this.pts[i];
let q = this.pts[(i + 1) % this.pts.length];
if (dist(p.x, p.y, q.x, q.y) > expectedDist * 1.5) {
arrOfPts.push([]);
} else {
arrOfPts[arrOfPts.length - 1].push(p);
}
}
// Rearrange array so that the longest path is the first element
let mostPtsIndex = 0;
let mostPts = 0;
for (let i = 0; i < arrOfPts.length; i++) {
if (mostPts < arrOfPts[i].length) {
mostPts = arrOfPts[i].length;
mostPtsIndex = i;
}
}
[arrOfPts[0], arrOfPts[mostPtsIndex]] = [arrOfPts[mostPtsIndex], arrOfPts[0]];
return arrOfPts;
}
}