From 3d181affc5b3ff36567032be034e4188cdc654b6 Mon Sep 17 00:00:00 2001 From: Jasmine Date: Sat, 21 Sep 2024 23:31:14 +0530 Subject: [PATCH] post - svg gradients & text as mask --- .gitignore | 1 + .vscode/tasks.json | 2 +- _includes/sidebar.html | 9 +- .../21/2024-09-21-svg-gradient-animation.md | 330 ++++++++++++++++++ 4 files changed, 336 insertions(+), 6 deletions(-) create mode 100644 _posts/2024/09/21/2024-09-21-svg-gradient-animation.md diff --git a/.gitignore b/.gitignore index 16436fa..281ee10 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ /node_modules/ _site/ +_drafts/ .sass-cache/ .jekyll-cache/ .jekyll-metadata diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 587904d..90f0072 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -6,7 +6,7 @@ { "label": "Run jekyll", "type": "shell", - "command": "bundle exec jekyll serve --livereload", + "command": "bundle exec jekyll serve --livereload --drafts", "problemMatcher": [], "group": { "kind": "build", diff --git a/_includes/sidebar.html b/_includes/sidebar.html index 10fbf8e..0d78559 100644 --- a/_includes/sidebar.html +++ b/_includes/sidebar.html @@ -13,13 +13,12 @@ fill="#fff">Jasmine Hirpara - + - - + + + from="0" to="1" repeatCount="indefinite" dur="5s"/> diff --git a/_posts/2024/09/21/2024-09-21-svg-gradient-animation.md b/_posts/2024/09/21/2024-09-21-svg-gradient-animation.md new file mode 100644 index 0000000..8f7b688 --- /dev/null +++ b/_posts/2024/09/21/2024-09-21-svg-gradient-animation.md @@ -0,0 +1,330 @@ +--- +author: "Jasmine Hirpara" +excerpt: "Animating SVG gradients and masking with text" +tags: [svg gradients, animation] +permalink: /posts/svg-gradient-animation +--- + +i always wondered how could i aninamate gradients. This curiosity led me to explore the SVG gradients and the result is what i used as the backrgound for my name on the left. Lets get started with how i achieved this. + +## SVG Gradients + +Just as we have linear and radial gradients in CSS, we have gradients in SVG as well. i tried to animate css gradients but i could find a way to do it. So i started looking up for SVG linear gradients and found that they can be animated using the animate element. + +Lets start with a simple svg with a `rect` element + +```html + + + + +``` +When rendered, it looks like this: + + + + + +Now lets add a linear gradient to the `rect` element. For this we need to add a `defs` element to the svg and define the gradient in it. Using the id attribute of the gradient, we can refer to it in the `fill` attribute of the `rect` element. + +```html + + + + + + + + + + +``` +{: .snippet} + +When rendered, it looks like this: + + + + + + + + + + + +The `stop` element helps to define the color stops of the gradient. The interpolation or the transition is based on how the `offset` attribute is defined. Its value ranges from 0 to 1 or from 0% to 100%. In the example above, the gradient starts with the color `#fdf1cb` at 0% and ends with the color `#ed73a8` at 100%. This will create a linear gradient from left to right. + +Lets see what happens when we keep the offset of the second stop at 0.5 + +```html +... + + +... +``` +When rendered, it looks like this: + + + + + + + + + + + +As you can see the difference, the interpolation or transition from the first color to the second color completes at 50% and the second color remains solid till the end. + +Now when we have the same values for the offset of the stops, + +```html +... + + +... +``` + +the gradient will be nothing but 2 solid colors placed side by side like this: + + + + + + + + + + + + +## x1, y1, x2, y2 attributes + +The `x1`, `y1`, `x2`, and `y2` attributes on `linearGradient` element are used to define the direction of the gradient. They can have values ranging from 0 to 1 or from 0% to 100%. The default values are `x1="0%"`, `y1="0%"`, `x2="100%"`, and `y2="0%"`. The `x1` and `x2` attributes define the direction of the gradient along the x-axis (left to right) and the `y1` and `y2` attributes define the direction of the gradient along the y-axis (top to bottom). Lets see how we can use these attributes to create a gradient from top to bottom. + +```html + + + + + + + + + + +``` +{: .snippet} +When rendered, it looks like this: + + + + + + + + + + + +Go on and try different values for the `x1`, `y1`, `x2`, and `y2` to create different gradients. One more thing to add is, we can add multiple stops to `linearGradient` element to create more complex gradients. + +## Let's animate + +We now know bare bones of how to create gradients in SVG. i went through the animate element and found that it can be used to animate the gradients. As per the `linearGradient` specification, it can accept an `animate` element as its child. It also lists the attributes that can be animated. Lets see how we can animate the `y1` attribute of the `linearGradient` element to create a transition from top to bottom. + +```html + + + + + + + + + + + +``` +{: .snippet} +When rendered, it looks like this: + + + + + + + + + + + + +The `animate` element animates the `y1` attribute of the `linearGradient` element from 0 to 1 in 3 seconds. The `repeatCount` attribute allows us to set the number of times the animation should repeat. The value `indefinite` makes the animation run indefinitely. Similarly, we can animate the `x1` and `x2` attributes to create a transition from left to right which will look like this: + + + + + + + + + + + + + +So with different combinations of animating the `x1`, `y1`, `x2`, and `y2` attributes, we can create different transitions. i was able to create the background for my name using different combinations of these attributes. Here is what i came up with: + +```html + + + + + + + + + + + + +``` +{: .snippet} +When rendered, it looks like this: + + + + + + + + + + + + + +## Enter the mask + +The `mask` element in SVG is used to clip parts of an element. Lets see how we can use the `mask` element to clip the gradient. We can define a `mask` element in the `defs` element and use the `mask` attribute on the `rect` element to apply the mask. The element declared in mask can be any shape or path. The fill color of the mask element works as opacity for what is visible in the `rect` element. + +```html + + + + + + + + + + + + + + +``` +{: .snippet} +When rendered, it looks like this: + + + + + + + + + + + + + + + +Here the mask is a `rect` element that is 50% wide. Since the fill color of the mask is white, the gradient is visible only on the left side of the masked `rect` element. We can use different shapes or paths in the mask to create different effects. + +This got me thinking what if we could use text as a mask. i straight away headed to the specification and found that it is possible. Lets see how we can use text as a mask. + +```html + + + + + + + + ABCDEFGHIJKLMNOPQRSTUVWXYZ + + + + + +``` +{: .snippet} +When rendered, it looks like this: + + + + + + + + ABCDEFGHIJKLMNOPQRSTUVWXYZ + + + + + + +The text is used as a mask here. The fill color of the text is white, so the gradient is visible only where the text is present. + +## It all comes together + +Now we have a gradient, that is animated. We have a mask that is using text. Now is the time to get this all together. + +```html + + + + + + + + + + ABCDEFGHIJKLMNOPQRSTUVWXYZ + + + + + +``` +{: .snippet} +When rendered, it looks like this: + + + + + + + + + + ABCDEFGHIJKLMNOPQRSTUVWXYZ + + + + + + +Well, well, well. It sure did take some time and effort to get this right. But i am glad i did it. i hope someone finds this useful. Credits where due, i found this really old article that helped me understand the basics of SVG gradients and of course the SVG Working Group for the detailed specifications.