1/** 2 * Utilidades para crear mapas de desplazamiento y filtros 3 * Convertido desde TypeScript a JavaScript vanilla 4 */ 5 6/** 7 * Crear el mapa de desplazamiento que usa el filtro feDisplacementMap. 8 * Los gradientes toman en cuenta el radio del elemento. 9 */ 10function getDisplacementMap({ height, width, radius, depth }) { 11 const svg = `<svg height="${height}" width="${width}" viewBox="0 0 ${width} ${height}" xmlns="http://www.w3.org/2000/svg"> 12 <style> 13 .mix { mix-blend-mode: screen; } 14 </style> 15 <defs> 16 <linearGradient 17 id="Y" 18 x1="0" 19 x2="0" 20 y1="${Math.ceil((radius / height) * 15)}%" 21 y2="${Math.floor(100 - (radius / height) * 15)}%"> 22 <stop offset="0%" stop-color="#0F0" /> 23 <stop offset="100%" stop-color="#000" /> 24 </linearGradient> 25 <linearGradient 26 id="X" 27 x1="${Math.ceil((radius / width) * 15)}%" 28 x2="${Math.floor(100 - (radius / width) * 15)}%" 29 y1="0" 30 y2="0"> 31 <stop offset="0%" stop-color="#F00" /> 32 <stop offset="100%" stop-color="#000" /> 33 </linearGradient> 34 </defs> 35 36 <rect x="0" y="0" height="${height}" width="${width}" fill="#808080" /> 37 <g filter="blur(2px)"> 38 <rect x="0" y="0" height="${height}" width="${width}" fill="#000080" /> 39 <rect 40 x="0" 41 y="0" 42 height="${height}" 43 width="${width}" 44 fill="url(#Y)" 45 class="mix" 46 /> 47 <rect 48 x="0" 49 y="0" 50 height="${height}" 51 width="${width}" 52 fill="url(#X)" 53 class="mix" 54 /> 55 <rect 56 x="${depth}" 57 y="${depth}" 58 height="${height - 2 * depth}" 59 width="${width - 2 * depth}" 60 fill="#808080" 61 rx="${radius}" 62 ry="${radius}" 63 filter="blur(${depth}px)" 64 /> 65 </g> 66 </svg>`; 67 68 return "data:image/svg+xml;utf8," + encodeURIComponent(svg); 69} 70 71/** 72 * Crear el filtro de desplazamiento. 73 * La complejidad del archivo se debe al efecto experimental de "aberración cromática"; 74 * los filtros desde el primer `feColorMatrix` hasta el último `feBlend` pueden eliminarse 75 * si el efecto no es necesario. 76 */ 77function getDisplacementFilter({ 78 height, 79 width, 80 radius, 81 depth, 82 strength = 100, 83 chromaticAberration = 0 84}) { 85 const displacementMapUrl = getDisplacementMap({ height, width, radius, depth }); 86 87 const svg = `<svg height="${height}" width="${width}" viewBox="0 0 ${width} ${height}" xmlns="http://www.w3.org/2000/svg"> 88 <defs> 89 <filter id="displace" color-interpolation-filters="sRGB"> 90 <feImage x="0" y="0" height="${height}" width="${width}" href="${displacementMapUrl}" result="displacementMap" /> 91 <feDisplacementMap 92 transform-origin="center" 93 in="SourceGraphic" 94 in2="displacementMap" 95 scale="${strength + chromaticAberration * 2}" 96 xChannelSelector="R" 97 yChannelSelector="G" 98 /> 99 <feColorMatrix 100 type="matrix" 101 values="1 0 0 0 0 102 0 0 0 0 0 103 0 0 0 0 0 104 0 0 0 1 0" 105 result="displacedR" 106 /> 107 <feDisplacementMap 108 in="SourceGraphic" 109 in2="displacementMap" 110 scale="${strength + chromaticAberration}" 111 xChannelSelector="R" 112 yChannelSelector="G" 113 /> 114 <feColorMatrix 115 type="matrix" 116 values="0 0 0 0 0 117 0 1 0 0 0 118 0 0 0 0 0 119 0 0 0 1 0" 120 result="displacedG" 121 /> 122 <feDisplacementMap 123 in="SourceGraphic" 124 in2="displacementMap" 125 scale="${strength}" 126 xChannelSelector="R" 127 yChannelSelector="G" 128 /> 129 <feColorMatrix 130 type="matrix" 131 values="0 0 0 0 0 132 0 0 0 0 0 133 0 0 1 0 0 134 0 0 0 1 0" 135 result="displacedB" 136 /> 137 <feBlend in="displacedR" in2="displacedG" mode="screen"/> 138 <feBlend in2="displacedB" mode="screen"/> 139 </filter> 140 </defs> 141 </svg>`; 142 143 return "data:image/svg+xml;
143utf8," + encodeURIComponent(svg) + "#displace"; 144} 145 146// Exportar las funciones para uso global 147window.DisplacementUtils = { 148 getDisplacementMap, 149 getDisplacementFilter 150};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.