A single-serving app that lets you see what it’s like to read at certain speeds
I decided to finally try out Svelte. I recently watched Svelte Origins, a short documentary on the origins of the framework and its creator Rich Harris. That doc got me excited so I decided to take it for a spin.
After going through their intro tutorial and reaching halfway, I built a tiny single-serving app that lets you see what it’s like to read at certain speeds.
Note — If you decide on using Sveltekit as I did, (instead Vite), to bootstrap the app, you might run into issues when trying to build the site if you plan on hosting it with Github Pages.
From the terminal type:
That will create the project with the following folder structure:
The main logic of the app will be written in the index.svelte file in the routes folder. In the index.svelte file remove all the section tags in the markup. Leave the <svelte:head> tag in.
Let’s start first with the paragraph we’re going to use to test our reading speed. I chose about 300 words from Alice and Wonderland, but you can choose any content you want.
Let’s start with a paragraph:
The rabbit-hole went straight on like a tunnel for some way, and then dipped suddenly down, so suddenly, that Alice had not a moment to think about stopping herself, before she found herself falling down what seemed a deep well. Either the well was very deep, or she fell very slowly, for she had plenty of time as she went down to look about her, and to wonder what would happen next. First, she tried to look down and make out what she was coming to, but it was too dark to see anything: then, she looked at the sides of the well, and noticed that they were filled with cupboards and book-shelves: here and there were maps and pictures hung on pegs. She took a jar down off one of the shelves as she passed: it was labelled “Orange Marmalade,” but to her great disappointment it was empty: she did not like to drop the jar, for fear of killing somebody underneath, so managed to put it into one of the cupboards as she fell past it. “Well!” thought Alice to herself, “after such a fall as this, I shall think nothing of tumbling down stairs! How brave they’ll all think me at home! Why, I wouldn’t say anything about it, even if I fell off the top of the house!” (which was most likely true.) Down, down, down. Would the fall never come to an end? “I wonder how many miles I’ve fallen by this time?” she said aloud, “I must be getting somewhere near the centre of the earth. Let me see: that would be four thousand miles down, I think — “ (for you see Alice had learnt several things of this sort in her lessons in the schoolroom, and though this was not a very good opportunity of showing off her knowledge, as there was no one to hear her, still it was good practice to say it over,) “yes that’s the right distance, but then what Longitude or Latitude-line shall I be in?”
Copy and paste the above paragraph, (or any paragraph of your choosing), and save it to a variable called paragraph. Make sure to wrap the paragraph in back ticks “ so you don’t have any weird formatting issues.
After that, we’ll split the paragraph into individual words and save into an array with the .split method. The split method takes a string as an argument. Here we’re using an empty space argument. This method automatically returns an array.
We’re saving the paragraph into the ‘words’ array so we can later traverse through each word.
The first piece of data is the boolean isReading variable. With this variable we will control the starting and stopping of the traversal through the words. We are also using an id to add to each word. And finally, we start with a default readingSpeed which is 150. This number is milliseconds as we’ll see later with the setInterval function.
The other piece of the data is an array of objects that we’re calling words_per_minute. We’re going to use that array to populate the options in the select element.
changeSpeed() handler is super simple. It will be listening to the select element and grabbing the value of the option and updating the speed.
startReading() function is where we have the core logic of how it will work once we click the button to start reading.
The first thing it does is flip the value of the boolean
isReading. Then we’re setting up and saving a
setInterval that will only run if
isReading is true and if the
id is the last word in the array.
In other words, if we have reached the last word the interval will stop. In the else clause we stop the interval(traversal of words basically), we reset the id, and we return is reading to false.
The last value
readingSpeed, which is the milliseconds. This is how fast or slow the interval will be according to which WPM speed was selected.
There’s also some logic in the Svelte component markup. In the paragraph, we are using an #each block. This is looping through the words array, getting the index (i) and generating a <span> tag for each word with a class, an id, or none, depending on some conditions.
The first condition is if isReading is true and if the index is equal to the id, (starting out it will be true because they will both be 0) the span tag will have an id and a class of highlight-text. As you’ll see in the CSS below, the highlight-text class will make each span tag bolder and increase the font-size a bit.
We also want to give spans a class of .fade-text if isReading is true so all the other words get “faded out.” That class just gives the text a lighter gray color.
Finally if the conditions are false we just render the spans with no classes nor ids.
I added some styles for the button, but you can style the app as you like. The important classes are the
.highlight-text classes, but even those you can tweak and customize as you please.
npm run dev and check if it all works.
That concludes my first ever tutorial.