SVG / 190

Displacement filter

ノイズで輪郭をゆがめる
ノイズの濃淡を位置のずれに変換して、文字や図形に波打つような輪郭をつくります。

見本の中を操作して変化を試してください。

ラボで詳しく試す ↗

ひとつ試すなら

輪郭をゆがめて素材感を変える

こんなときに

水面や熱、揺らぐ素材を感じさせるビジュアル。

仕組みと使い方

ゆがみを0にすると元の文字に戻ります。feTurbulenceのノイズをfeDisplacementMapに渡します。強すぎる変形は読みにくさにつながります。

SVGフィルターノイズゆがみ質感
実装コードを見る
<!doctype html><html lang="ja"><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><style>body{margin:0;min-height:300px}.sample{box-sizing:border-box;min-height:210px;width:100%;height:100%;display:grid;place-items:center;align-content:center;gap:18px;padding:24px;background:#efeee9;color:#202020;font-family:Arial,Meiryo,sans-serif;overflow:hidden}.sample *{box-sizing:border-box}.sample button{min-height:40px;border:1px solid #777;border-radius:999px;background:transparent;padding:9px 17px;font:12px Arial,Meiryo,sans-serif;color:inherit;cursor:pointer}.sample label{font-size:11px;display:grid;gap:8px;width:min(100%,220px)}.sample input{width:100%;accent-color:#222}.sample small{font-size:10px;line-height:1.6}.sample :focus-visible{outline:2px solid #222;outline-offset:4px}@media(prefers-reduced-motion:reduce){.sample *{animation:none!important;transition:none!important}}.sample svg{width:min(100%,280px);height:130px}</style><div class="sample"><svg viewBox="0 0 280 130" role="img" aria-label="ゆがみが変わるgoodの文字"><defs><filter id="warp" x="-30%" y="-50%" width="160%" height="200%"><feTurbulence baseFrequency=".018 .04" numOctaves="2" seed="4" result="noise"/><feDisplacementMap in="SourceGraphic" in2="noise" scale="16" xChannelSelector="R" yChannelSelector="G"/></filter></defs><text x="140" y="88" text-anchor="middle" font-size="82" font-weight="bold" letter-spacing="-6" filter="url(#warp)">good</text></svg><label>ゆがみの強さ <output>16</output><input type="range" aria-label="ゆがみの強さ" min="0" max="45" value="16" data-target="feDisplacementMap" data-attr="scale"></label></div><script>const controller=(function controls(root){const abort=new AbortController();for(const input of root.querySelectorAll('[data-target]')){const update=()=>{const target=root.querySelector(input.dataset.target);if(input.dataset.attr)target.setAttribute(input.dataset.attr,input.value+(input.dataset.unit||''));else target.style.setProperty(input.dataset.prop,input.value+(input.dataset.unit||''));const output=input.closest('label')?.querySelector('output');if(output)output.textContent=input.value};input.addEventListener('input',update,{signal:abort.signal});update()}for(const button of root.querySelectorAll('[data-toggle]'))button.addEventListener('click',()=>{const target=root.querySelector(button.dataset.toggle),on=target.classList.toggle('changed');button.setAttribute('aria-pressed',String(on));},{signal:abort.signal});return {destroy(){abort.abort()},setAuto(){}}})(document);addEventListener('pagehide',()=>controller.destroy(),{once:true});</script></html>