Skip to content

Commit c078f6e

Browse files
authored
Merge pull request #1179 from ethereum/morpher
Add Morpher [Fixes #1151]
2 parents 38dc396 + 04b3f59 commit c078f6e

File tree

2 files changed

+173
-3
lines changed

2 files changed

+173
-3
lines changed

src/components/Morpher.js

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
import React, { useState, useEffect } from "react"
2+
3+
const Morpher = () => {
4+
const [state, setState] = useState({
5+
text: "Ethereum",
6+
words: [
7+
"Ethereum",
8+
"以太坊",
9+
"イーサリアム",
10+
"Etérium",
11+
"이더리움",
12+
"اتریوم",
13+
"Αιθέριο",
14+
"Eterijum",
15+
"إثيريوم",
16+
"อีเธอเรียม",
17+
"Эфириум",
18+
"इथीरियम",
19+
"ಇಥೀರಿಯಮ್",
20+
"אתריום",
21+
"Ξ",
22+
"ইথেরিয়াম",
23+
"எதீரியம்",
24+
"ఇథిరియూమ్",
25+
],
26+
counter: 0,
27+
})
28+
29+
// loops over chars to morph a text to another
30+
const morpher = (start, end) => {
31+
// array of chars to randomly morph the text between start and end
32+
const chars = [
33+
"a",
34+
"b",
35+
"c",
36+
"d",
37+
"x",
38+
"y",
39+
"z",
40+
"0",
41+
"1",
42+
"2",
43+
"3",
44+
"4",
45+
"5",
46+
"6",
47+
"7",
48+
"{",
49+
"}",
50+
"%",
51+
"$",
52+
"?",
53+
"!",
54+
]
55+
// duration of the global morph
56+
const duration = 3
57+
// speed of the morph for each letter
58+
const frameRate = 30
59+
60+
// text variables
61+
const string = start.split("")
62+
const result = end.split("")
63+
const slen = string.length
64+
const rlen = result.length
65+
66+
// time variables
67+
let present = new Date()
68+
let past = present.getTime()
69+
let count = 0
70+
let spentTime = 0
71+
// splitTime = milliseconds / letters
72+
let splitTime = (duration * 70) / Math.max(slen, rlen)
73+
74+
function update() {
75+
// Update present date and spent time
76+
present = new Date()
77+
spentTime += present.getTime() - past
78+
79+
// Random letters
80+
for (let i = count; i < Math.max(slen, rlen); i++) {
81+
const random = Math.floor(Math.random() * (chars.length - 1))
82+
// Change letter
83+
string[i] = chars[random]
84+
}
85+
86+
// Morph letters from start to end
87+
if (spentTime >= splitTime) {
88+
// Update count of letters to morph
89+
count += Math.floor(spentTime / splitTime)
90+
// Morphing
91+
for (let j = 0; j < count; j++) {
92+
string[j] = result[j] || null
93+
}
94+
// Reset spent time
95+
spentTime = 0
96+
}
97+
98+
// Update DOM
99+
setState({ ...state, text: string.join("") })
100+
101+
// Save present date
102+
past = present.getTime()
103+
104+
// Loop
105+
if (count < Math.max(slen, rlen)) {
106+
// Only use a setTimeout if the frameRate is lower than 60FPS
107+
// Remove the setTimeout if the frameRate is equal to 60FPS
108+
setTimeout(() => {
109+
window.requestAnimationFrame(update)
110+
}, 1000 / frameRate)
111+
}
112+
}
113+
114+
// Start loop
115+
update()
116+
}
117+
118+
useEffect(() => {
119+
const morphInterval = setInterval(() => {
120+
const start = state.text
121+
const end = state.words[state.counter]
122+
123+
morpher(start, end)
124+
125+
if (state.counter < state.words.length - 1) {
126+
setState({ ...state, counter: state.counter++ })
127+
} else {
128+
// TODO this doesn't work, it doesn't set counter state
129+
setState({ ...state, counter: 0 })
130+
}
131+
}, 3000)
132+
133+
return () => {
134+
clearInterval(morphInterval)
135+
}
136+
})
137+
138+
return <span>{state.text}</span>
139+
}
140+
141+
export default Morpher

src/pages/index.js

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import Img from "gatsby-image"
55
import styled from "styled-components"
66

77
import { getLangContentVersion, getDefaultMessage } from "../utils/translations"
8+
import Morpher from "../components/Morpher"
89
import PageMetadata from "../components/PageMetadata"
910
import Translation from "../components/Translation"
1011
import Link from "../components/Link"
@@ -46,11 +47,19 @@ const OldHeader = styled.header`
4647
margin: 0 auto;
4748
`
4849

50+
const Title = styled.div`
51+
display: flex;
52+
justify-content: space-between;
53+
width: 100%;
54+
max-width: 100%;
55+
`
56+
4957
const H1 = styled.h1`
5058
line-height: 1.4;
5159
font-weight: 400;
5260
font-size: 1.5rem;
5361
margin: 1.5rem 0;
62+
5463
max-width: 80%;
5564
@media (max-width: ${(props) => props.theme.breakpoints.m}) {
5665
max-width: 100%;
@@ -135,6 +144,18 @@ const OldTitle = styled.h3`
135144
}
136145
`
137146

147+
const H3 = styled.h3`
148+
margin-top: 1.5rem;
149+
margin-bottom: 1.5rem;
150+
@media (max-width: ${(props) => props.theme.breakpoints.m}) {
151+
display: none;
152+
}
153+
`
154+
155+
const OldH3 = styled.h3`
156+
margin-top: 2.5rem;
157+
`
158+
138159
const HomePage = ({ data }) => {
139160
const intl = useIntl()
140161
const contentVersion = getLangContentVersion(intl.locale)
@@ -315,9 +336,14 @@ const HomePage = ({ data }) => {
315336
{contentVersion > 1.1 && (
316337
<>
317338
<Header>
318-
<H1>
319-
<Translation id="page-home-title" />
320-
</H1>
339+
<Title>
340+
<H1>
341+
<Translation id="page-home-title" />
342+
</H1>
343+
<H3>
344+
<Morpher />
345+
</H3>
346+
</Title>
321347
<Description>
322348
<Translation id="page-home-subtitle" />
323349
</Description>
@@ -327,6 +353,9 @@ const HomePage = ({ data }) => {
327353
)}
328354
{contentVersion <= 1.1 && (
329355
<OldHeader>
356+
<OldH3>
357+
<Morpher />
358+
</OldH3>
330359
<H1>
331360
<Translation id="page-home-title" />
332361
</H1>

0 commit comments

Comments
 (0)