Skip to content

Commit 93925bd

Browse files
committed
add challenge 23
1 parent 8e850f1 commit 93925bd

File tree

2 files changed

+171
-0
lines changed

2 files changed

+171
-0
lines changed

23 - Speech Synthesis/index.html

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<title>Speech Synthesis</title>
6+
<link href='https://fonts.googleapis.com/css?family=Pacifico' rel='stylesheet' type='text/css'>
7+
<link rel="stylesheet" href="style.css">
8+
</head>
9+
<body>
10+
11+
<div class="voiceinator">
12+
13+
<h1>The Voiceinator 5000</h1>
14+
15+
<select name="voice" id="voices">
16+
<option value="">Select A Voice</option>
17+
</select>
18+
19+
<label for="rate">Rate:</label>
20+
<input name="rate" type="range" min="0" max="3" value="1" step="0.1">
21+
22+
<label for="pitch">Pitch:</label>
23+
24+
<input name="pitch" type="range" min="0" max="2" step="0.1">
25+
<textarea name="text">Hello! I love JavaScript 👍</textarea>
26+
<button id="stop">Stop!</button>
27+
<button id="speak">Speak</button>
28+
29+
</div>
30+
31+
<script>
32+
const msg = new SpeechSynthesisUtterance();
33+
let voices = [];
34+
const voicesDropdown = document.querySelector('[name="voice"]');
35+
const options = document.querySelectorAll('[type="range"], [name="text"]');
36+
const speakButton = document.querySelector('#speak');
37+
const stopButton = document.querySelector('#stop');
38+
msg.text = document.querySelector('[name="text"]').value;
39+
40+
function populateVoices() {
41+
voices = this.getVoices();
42+
voicesDropdown.innerHTML = voices
43+
.filter(voice => voice.lang.includes('en'))
44+
.map(voice => `<option value="${voice.name}">${voice.name} (${voice.lang})</option>`)
45+
.join('');
46+
}
47+
48+
function setVoice() {
49+
msg.voice = voices.find(voice => voice.name === this.value);
50+
toggle();
51+
}
52+
53+
function toggle(startOver = true) {
54+
speechSynthesis.cancel();
55+
if (startOver) {
56+
speechSynthesis.speak(msg);
57+
}
58+
}
59+
60+
function setOption() {
61+
console.log(this.name, this.value);
62+
msg[this.name] = this.value;
63+
toggle();
64+
}
65+
66+
speechSynthesis.addEventListener('voiceschanged', populateVoices);
67+
voicesDropdown.addEventListener('change', setVoice);
68+
options.forEach(option => option.addEventListener('change', setOption));
69+
speakButton.addEventListener('click', toggle);
70+
stopButton.addEventListener('click', () => toggle(false));
71+
72+
</script>
73+
74+
</body>
75+
</html>

23 - Speech Synthesis/style.css

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
html {
2+
font-size: 10px;
3+
box-sizing: border-box;
4+
}
5+
6+
*, *:before, *:after {
7+
box-sizing: inherit;
8+
}
9+
10+
body {
11+
margin: 0;
12+
padding: 0;
13+
font-family: sans-serif;
14+
background-color:#3BC1AC;
15+
display:flex;
16+
min-height: 100vh;
17+
align-items: center;
18+
19+
background-image:
20+
radial-gradient(circle at 100% 150%, #3BC1AC 24%, #42D2BB 25%, #42D2BB 28%, #3BC1AC 29%, #3BC1AC 36%, #42D2BB 36%, #42D2BB 40%, transparent 40%, transparent),
21+
radial-gradient(circle at 0 150%, #3BC1AC 24%, #42D2BB 25%, #42D2BB 28%, #3BC1AC 29%, #3BC1AC 36%, #42D2BB 36%, #42D2BB 40%, transparent 40%, transparent),
22+
radial-gradient(circle at 50% 100%, #42D2BB 10%, #3BC1AC 11%, #3BC1AC 23%, #42D2BB 24%, #42D2BB 30%, #3BC1AC 31%, #3BC1AC 43%, #42D2BB 44%, #42D2BB 50%, #3BC1AC 51%, #3BC1AC 63%, #42D2BB 64%, #42D2BB 71%, transparent 71%, transparent),
23+
radial-gradient(circle at 100% 50%, #42D2BB 5%, #3BC1AC 6%, #3BC1AC 15%, #42D2BB 16%, #42D2BB 20%, #3BC1AC 21%, #3BC1AC 30%, #42D2BB 31%, #42D2BB 35%, #3BC1AC 36%, #3BC1AC 45%, #42D2BB 46%, #42D2BB 49%, transparent 50%, transparent),
24+
radial-gradient(circle at 0 50%, #42D2BB 5%, #3BC1AC 6%, #3BC1AC 15%, #42D2BB 16%, #42D2BB 20%, #3BC1AC 21%, #3BC1AC 30%, #42D2BB 31%, #42D2BB 35%, #3BC1AC 36%, #3BC1AC 45%, #42D2BB 46%, #42D2BB 49%, transparent 50%, transparent);
25+
background-size:100px 50px;
26+
}
27+
28+
29+
.voiceinator {
30+
padding:2rem;
31+
width:50rem;
32+
margin:0 auto;
33+
border-radius:1rem;
34+
position: relative;
35+
background:white;
36+
overflow: hidden;
37+
z-index: 1;
38+
box-shadow:0 0 5px 5px rgba(0,0,0,0.1);
39+
}
40+
41+
h1 {
42+
width:calc(100% + 4rem);
43+
margin: -2rem 0 2rem -2rem;
44+
padding:.5rem;
45+
background: #ffc600;
46+
border-bottom: 5px solid #F3C010;
47+
text-align: center;
48+
font-size: 5rem;
49+
font-weight: 100;
50+
font-family: 'Pacifico', cursive;
51+
text-shadow:3px 3px 0 #F3C010;
52+
53+
}
54+
55+
.voiceinator input,
56+
.voiceinator button,
57+
.voiceinator select,
58+
.voiceinator textarea {
59+
width: 100%;
60+
display: block;
61+
margin:10px 0;
62+
padding:10px;
63+
border:0;
64+
font-size: 2rem;
65+
background:#F7F7F7;
66+
outline:0;
67+
}
68+
69+
textarea {
70+
height: 20rem;
71+
}
72+
73+
input[type="select"] {
74+
75+
}
76+
77+
.voiceinator button {
78+
background:#ffc600;
79+
border:0;
80+
width: 49%;
81+
float:left;
82+
font-family: 'Pacifico', cursive;
83+
margin-bottom: 0;
84+
font-size: 2rem;
85+
border-bottom: 5px solid #F3C010;
86+
cursor:pointer;
87+
position: relative;
88+
}
89+
90+
.voiceinator button:active {
91+
top:2px;
92+
}
93+
94+
.voiceinator button:nth-of-type(1) {
95+
margin-right: 2%;
96+
}

0 commit comments

Comments
 (0)