好玩的液态玻璃

156 阅读1分钟

blog 原文: www.yysuni.com/blog/liquid…

早上看到一篇文章:《浏览器中液态玻璃》,文章我只能明白玻璃折射率,置换,其它的看不懂。

代码上很简单,在这个blog 仓库目录的 components/liquid-grass 目录。

实现

逻辑是,两个置换,组合一个边缘。嫌麻烦可以不要边缘效果。

const width = 210
const height = 150

<div
	style={{ width, height }}
			className='fixed top-0 left-0 z-90 select-none'
			whileTap={{
				scale: 1.1
			}}>
	<svg colorInterpolationFilters='sRGB' style={{ display: 'none' }}>
			<defs>
				<filter id='magnifying-glass-filter'>
					<feImage href={displacement1.src} x='0' y='0' width={width} height={height} result='magnifying_displacement_map' />
					<feDisplacementMap in='SourceGraphic' in2='magnifying_displacement_map' scale='24' xChannelSelector='R' yChannelSelector='G' result='magnified_source' />
					<feGaussianBlur in='magnified_source' stdDeviation='0' result='blurred_source' />
					<feImage href={displacement2.src} x='0' y='0' width={width} height={height} result='displacement_map' />
					<feDisplacementMap in='blurred_source' in2='displacement_map' scale='98.24713343067756' xChannelSelector='R' yChannelSelector='G' result='displaced' />
					<feColorMatrix in='displaced' type='saturate' result='displaced_saturated' values='9'></feColorMatrix>
					<feImage href={borderImg.src} x='0' y='0' width={width} height={height} result='specular_layer'></feImage>
					<feComposite in='displaced_saturated' in2='specular_layer' operator='in' result='specular_saturated'></feComposite>
					<feComponentTransfer in='specular_layer' result='specular_faded'>
						<feFuncA type='linear' slope='0.5'></feFuncA>
					</feComponentTransfer>
				<feBlend in='specular_saturated' in2='displaced' mode='normal' result='withSaturation'></feBlend>
				<feBlend in='specular_faded' in2='withSaturation' mode='normal'></feBlend>
			</filter>
		</defs>
	</svg>

	<div
		onClick={() => setIsTouched(true)}
		className='absolute inset-0 flex items-center justify-center rounded-full font-mono'
		style={{
			backdropFilter: 'url(#magnifying-glass-filter)',
			boxShadow: 'rgba(0, 0, 0, 0.05) 0px 4px 9px, rgba(0, 0, 0, 0.05) 0px 2px 24px inset, rgba(255, 255, 255, 0.2) 0px -2px 24px inset'
		}}>
		{isTouched ? null : 'Liquid Grass'}
	</div>
</div>

原理

最开始以为它只能在 svg 中实现,意味着需要把网址内容刻入到 svg,结果它并不需要,二是直接能在文档流使用,这就太方便了。

只需要 svg 内容写好,backdropFilter 引出来用就行,虽然限制在 chrome 中使用,但是光是自己玩就够够的了。

图片素材

图片被掘金加了水印,所以需求去 参考文章,或者我的 public blog 去取

displacement-1.png

displacement-2.png

border.png