Effect of highlighting text with pen
Julia Shlykova
Posted on July 16, 2024
This codepen is inspired by work by Sten Hougaard
Preparations
Let's create two containers for different implementations of animation:
<div class="container">
<h1>Animated text
<svg viewbox="0 0 235 40" xmlns="http://www.w3.org/2000/svg" id="animated-svg">
<path d="..."/>
</svg>
</h1>
</div>
<div class="container">
<h1 id="clickable-header">Click on me!
<svg viewbox="0 0 235 40" xmlns="http://www.w3.org/2000/svg" id="clickable-svg">
<path d="..."/>
</svg>
</h1>
</div>
I've created svg using Adobe illustrator, the main feature for it must be small height and big width.
It's important to mention thatsvg
is a child of a header element since we will positionsvg
relative to it.
CSS
We transform our containers to flexboxes to gracefully position everything in the center.
.container {
display: flex;
place-content: center;
}
h1 {
display: inline;
position: relative;
}
inline
is used to simply reduce width of the element to its content sincesvg
will rely on it
Next, we should position svg relative to a header:
svg {
min-width: 110%;
min-height: 100%;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
}
We use standard method to position relative element in the center of the parent. To adjust svg to the text, we should apply
min-width
andmin-height
.
Animation logic with javascript
To animate elements in javascript we can use wonderful animate(keyframes, options)
method.
Keyframes
Let's dissect the getDrawingParameters
function, that gives properties to iterate over:
const getDrawingParameters = (path) => {
const length = path.getTotalLength();
path.style.strokeDasharray = length;
const drawingProperties = [
{ strokeDashoffset: length, easing: "ease-in" },
{ strokeDashoffset: 0, offset: 0.15 }
];
return drawingProperties;
};
First, we need to know how long our path actually is, by using svg method getTotalLength:
const length = path.getTotalLength();
Now, we should use our computed length to simulate drawing. Let's define our starting point. We need attribute strokeDasharray:
path.style.strokeDasharray = length;
Here, we tell this attribute to draw path with alternation of one dash (size=length) and one gap (size=length).
The next attribute, where we need length
is stroke-dashoffset:
path.style.strokeDashoffset = length;
This value tells that the dash array computation is pulled by length value. And since, we set our dash array to 'dash-length gap-length dash-length gap-length ...', the starting path will be empty (gap).
So, we define our iterable properties in array:
const drawingProperties = [
{ strokeDashoffset: length, easing: "ease-in" },
{ strokeDashoffset: 0, offset: 0.15 }
];
We use
offset
to define relative time at which this property must be reached. It was made to imitate delay at each iteration.
Options
The second argument of the animate
method is options:
animatedPath.animate(
getDrawingParameters(animatedPath),
{duration: 10000, iterations: Infinity}
);
We set our animation to infinite iterations and 10 seconds duration. Remember
offset
? our "active" animation takes only 1.5 seconds.
Posted on July 16, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.