制作嘈杂的 SVG
Making noisy SVGs

原始链接: https://daniel.do/article/making-noisy-svgs/

近年来,设计师通过应用颗粒状或嘈杂的纹理,在插图中融入了纹理。 虽然这种趋势提供了独特的风格,但由于传统图像格式可用的选项有限,用代码添加纹理仍然具有挑战性。 然而,SVG 提供了通过基本形状、渐变、滤镜和 fe 复合元素的组合来生成更有效的带有噪声纹理的矢量图像的机会。 一种方法包括定义主要形状(例如圆形),应用线性渐变,然后利用馈送湍流噪声滤波器和与源 Alpha 模式混合的 Fe 颜色矩阵来覆盖人造纹理。 通过以 CSS Trick 的方式利用这些工具,人们可以在嘈杂的设计组合中实现嘈杂的阴影和其他所需的效果。 尽管这种技术有其局限性,但它为数字艺术的持续创新提供了机会。 要查看完整的演示,请参阅上面提供的存储库链接或访问作者的网站 DanielImmke.com。 *其他资源: - MDN 的 SVG 过滤器指南 (https://developer.mozilla.org/en-US/docs/Web/SVG/Element/filter) - 2021 年在 CSS Tricks 上发表的相关文章 (https://css-tricks.com/add-grain-vector-graphics/) 注:作者未在原帖中引用来源; 然而,添加了来源以确保正确的归属。

然而,由于与某些网站的潜在兼容性问题,通过浏览器内置的“深色模式”功能为整个网页激活相同的模式似乎会产生不太理想的结果。 因此,作者建议创建专门针对各个网站的可定制暗模式,而不是在整个系统范围内应用通用的暗模式。 通过这样做,用户可以在较低的光照条件下享受舒适的观看体验,同时避免因通用暗模式实施不当而造成的干扰。 此外,值得注意的是,在网站本身不提供合适的暗模式变体的情况下,存在允许用户创建自己的自定义解决方案的工具,有效地充当开发人员提供自己的替代方案之前的权宜之计。 最终,尽管这种方法需要开发人员社区付出额外的努力,但它会为每个参与者带来更好的结果。
相关文章

原文

Making noisy SVGs

Adding noise texture with only code

Addendum Dec 7, 2023

One of my ongoing fixations with the web is how improvements in technology inform web design. In an earlier post this year I wrote about my theory that the increasing pixel density of displays galvanized the shift from photography to vector illustrations in the early to mid 2010s.

In recent years there has been a design trend that runs counter to this. Illustrations still rule in web design, but instead of clean, flat shapes there has been an emergence of texture, usually as part of a design’s lighting or shading and usually a “noisy” or grainy texture.

Studio Vellekoop & León

I’m not hip enough to know if this style has been assigned a pithy label, but I do enjoy it. At the same time, I find it frustrating — because as far as I can tell (the lack of examples I have seen in the wild supports this theory) there isn’t an easy way to replicate these illustrations with SVGs. They can probably be exported as such from illustration programs but it’s likely these applied textures are raster or if they are vector, quite large in size.

SVGs are an interesting subject to me, because the specification for them is dense and there are usually multiple ways to accomplish an effect. Most SVGs are simply exported directly from a graphics program and have a lot of inefficiencies etc… which has led to the emergence of tools like SVGO.

I’m not an expert on the subject (I feel like the older I get, the less I feel like I can claim that about anything) but in recent years have taken to hand tuning and occasionally writing my own SVGs from scratch so I am not a complete novice either.

I decided to give creating an SVG using this illustration style a shot. My goal was to use the regular SVG specification to write a simple illustration that had this noisy, textured shadow effect. An additional goal was for this illustration to be moderately flexible, something that could easily be turned into a component in Svelte or React and changed for different shapes and colors. For more direct inspiration, I looked to the designer Josh Warren who has experimented a lot with using this style and simple geometry to nice effect:

Josh Warren

Basic shape and gradient

Drawing a circle or square in an SVG is really easy. There are primitives for them.

svg viewbox="0 0 100 100">
	circle cx="50" cy="50" r="50" />
svg>

The tricky part is everything else. If you want to apply a gradient, you can specify that as the fill - but what if you want a gradient that changes with the base color you specify? So you don’t have to define a custom gradient with specific colors if you want to reuse the component. Then you’ve entered mask territory. The way masks work in SVGs is that you use the “colors” black and white to how you want a mask to work. It’s a little confusing, but I’ve tried to keep the code example simple.

(As an aside, I have to give huge kudos to MDN’s excellent documentation, this project could not have been done without it!)

This can actually be optimized a little more. We know we’re going to use the same circle shape multiple times, so we can define it once in , assign it an id and simply reference it with the use element. This makes the code a little more DRY:

svg viewbox="0 0 100 100">
   defs>
 	circle id="shape" cx="50" cy="50" r="50" />
   	mask id="gradient">
   		linearGradient id="fade">
   			stop offset="0%" stop-color="black" stop-opacity="0.5" />
   			stop offset="75%" stop-color="white" stop-opacity="1" />
   		linearGradient>
   		use href="#shape" fill="url('#fade')" />
   	mask>
   defs>
 use href="#shape" mask="url(#gradient)" />
svg>

So we’ve got the shape and a gradient going, but how do we add a texture to that gradient? The answer is with a filter. MDN’s documentation on SVG Filters goes into better detail on the nuts and bolts of how filters work. I also found this excellent article that goes into great detail about creating textures for SVGs.

To create noise, I used the filter which is explicitly for generating artificial textures but required quite a bit of fiddling to get to my liking. Then, I had to use other filter effects to eliminate color variance and blend naturally with the fill color selected, and finally apply the filter to the circle.

Result

svg viewbox="0 0 100 100">
	defs>
		circle id="shape" cx="50" cy="50" r="50" />
		filter id="noise">
			feTurbulence
				type="fractalNoise"
				baseFrequency="19.5"
				numOctaves="10"
				result="turbulence"
			/>
			feComposite operator="in" in="turbulence" in2="SourceAlpha" result="composite"/>
			feColorMatrix in="composite" type="luminanceToAlpha" />
			feBlend in="SourceGraphic" in2="composite" mode="color-burn" />
		filter>
		mask id="gradient">
			linearGradient id="fade">
				stop offset="0%" stop-color="black" stop-opacity="0.6" />
				stop offset="65%" stop-color="white" stop-opacity="0.9" />
				stop offset="75%" stop-color="white" stop-opacity="1" />
			linearGradient>
			use href="#shape" fill="url('#fade')" />
		mask>
	defs>
	use href="#shape" fill="hsl(337, 92%, 69%)" mask="url(#gradient)" filter="url('#noise')" />
svg>

Full Demo Link

Adding a nice fill color and making the gradient a little more subtle and there we go!

With some additional playing around I was able to create an illustration I was quite happy with. It’s not perfect, and notably renders differently in Safari than other browsers but it achieves what I set out to accomplish.

You can also check out the code in the repository.

This method could certainly be improved with additional experimenting. It’s still a far cry from the complexity of some of the illustrations I linked, but I think it could potentially be refined to be usable in more situations.

Addendum Dec 7, 2023

I submitted this post to Hacker News where it received some reception, and was pointed out that CSS Tricks posted a great article written by Jimmy Chion about this subject in 2021. It’s a great article, and the techniques we arrive at are similar.

I was not aware of this post at the time of this writing but am now linking to it here for supplementary reading.

Hey — My name is Daniel Immke. I’m a designer & developer who travels the world.

If you liked my writing, check out more posts or subscribe.

联系我们 contact @ memedata.com