URL скопирован в буфер обмена!

Как сделать эффект жидкого текста в Zero Block на Tilda?

С помощью этой модификации можно добавить в Zero Block интерактивный эффект: текст ведёт себя как поверхность воды и расходится волнами вслед за курсором. Рябь плавно затухает после того, как курсор уходит, а на гребнях волн появляется лёгкий блик.

Модификация работает с включенным Autoscale в блоках
Модификация работает только c Zero Block
Номер модификации в библиотеке TiCode

Генератор кода

Класс текста
Поддержка на мобилках
Войдите в аккаунт чтобы получить доступ к генератору кода
Этот генератор кода доступен только тем кто оплатил подписку
<!--TICODE--><!-- Библиотека модификаций для Тильда https://ticode.dev --> <!--TCD144--><script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script> <script> (function () { var tcdminwidth = 960; var tcdpad = 120; var tcdsimscale = 0.4; var tcdripple = 20; var tcddamping = 0.98; var tcddistortion = 0.1; var tcdspecular = 0.5; var tcdselector = ".tcd-liquid text"; var tcdinstances = []; var tcdmedia = window.matchMedia("(min-width: " + tcdminwidth + "px)"); function ticodecreateinstance(tcdelem) { if (!tcdelem || tcdelem.dataset.tcdpureenergy === "1") return null; var tcdatom = tcdelem.querySelector(".tn-atom"); if (!tcdatom || !window.THREE) return null; var tcdtext = (tcdatom.innerText || tcdatom.textContent || "").trim(); if (!tcdtext) return null; var tcdrenderer; try { tcdrenderer = new THREE.WebGLRenderer({ alpha: true, antialias: true }); } catch (tcderror) { return null; } tcdelem.dataset.tcdpureenergy = "1"; tcdrenderer.setPixelRatio(1); var tcdglcanvas = tcdrenderer.domElement; tcdglcanvas.style.cssText = "position:absolute;top:" + (-tcdpad) + "px;left:" + (-tcdpad) + "px;pointer-events:none;z-index:5;"; var tcdscene = new THREE.Scene(); var tcdcamera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1); var tcdgeo = new THREE.PlaneGeometry(2, 2); var tcdsimmat = new THREE.ShaderMaterial({ uniforms: { uTexture: { value: null }, uResolution: { value: new THREE.Vector2(1, 1) }, uMouse: { value: new THREE.Vector3(-1, -1, 0) }, uDelta: { value: 1 }, uDamping: { value: tcddamping }, uRippleSize: { value: tcdripple } }, vertexShader: "varying vec2 vUv; void main(){ vUv=uv; gl_Position=vec4(position,1.0); }", fragmentShader: [ "uniform sampler2D uTexture; uniform vec2 uResolution; uniform vec3 uMouse;", "uniform float uDelta; uniform float uDamping; uniform float uRippleSize;", "varying vec2 vUv;", "void main(){", "vec2 texel=1.0/uResolution;", "vec4 data=texture2D(uTexture,vUv);", "float pressure=data.x; float velocity=data.y;", "float pr=texture2D(uTexture,vUv+vec2(texel.x,0.)).x;", "float pl=texture2D(uTexture,vUv-vec2(texel.x,0.)).x;", "float pu=texture2D(uTexture,vUv+vec2(0.,texel.y)).x;", "float pd=texture2D(uTexture,vUv-vec2(0.,texel.y)).x;", "float lap=(pr+pl+pu+pd)*0.25-pressure;", "velocity+=uDelta*lap;", "pressure+=uDelta*velocity;", "velocity*=0.99; pressure*=uDamping;", "if(uMouse.z>0.5){", "float dist=distance(vUv*uResolution,uMouse.xy);", "pressure+=exp(-dist*dist/(uRippleSize*uRippleSize))*0.5;", "}", "gl_FragColor=vec4(pressure,velocity,pr-pl,pu-pd);", "}" ].join("\n") }); var tcddrawmat = new THREE.ShaderMaterial({ transparent: true, uniforms: { uTexture: { value: null }, uContentTexture: { value: null } }, vertexShader: "varying vec2 vUv; void main(){ vUv=uv; gl_Position=vec4(position,1.0); }", fragmentShader: [ "uniform sampler2D uTexture; uniform sampler2D uContentTexture; varying vec2 vUv;", "void main(){", "vec4 data=texture2D(uTexture,vUv);", "vec2 distortion=data.zw*" + tcddistortion.toFixed(3) + ";", "vec4 color=texture2D(uContentTexture,vUv+distortion);", "float spec=pow(max(0.0,data.z+data.w),4.0)*" + tcdspecular.toFixed(3) + ";", "color.rgb+=spec*color.a;", "gl_FragColor=color;", "}" ].join("\n") }); var tcdsimmesh = new THREE.Mesh(tcdgeo, tcdsimmat); var tcddrawmesh = new THREE.Mesh(tcdgeo, tcddrawmat); var tcdrta = null; var tcdrtb = null; var tcdsimw = 1; var tcdsimh = 1; var tcdmouse = new THREE.Vector3(-1, -1, 0); var tcdactive = true; function ticodemaketexture(tcdwidth, tcdheight) { var tcdstyle = getComputedStyle(tcdatom); var tcdcanvas = document.createElement("canvas"); var tcddpr = Math.min(window.devicePixelRatio || 1, 2); tcdcanvas.width = tcdwidth * tcddpr; tcdcanvas.height = tcdheight * tcddpr; var tcdcontext = tcdcanvas.getContext("2d"); tcdcontext.scale(tcddpr, tcddpr); tcdcontext.font = tcdstyle.fontStyle + " " + tcdstyle.fontWeight + " " + tcdstyle.fontSize + " " + tcdstyle.fontFamily; tcdcontext.fillStyle = tcdstyle.color; tcdcontext.textBaseline = "middle"; var tcdlines = tcdtext.split("\n"); var tcdlineheight = parseFloat(tcdstyle.lineHeight) || parseFloat(tcdstyle.fontSize) * 1.2; var tcdalign = tcdstyle.textAlign; tcdcontext.textAlign = tcdalign === "center" ? "center" : tcdalign === "right" || tcdalign === "end" ? "right" : "left"; var tcdx = tcdcontext.textAlign === "center" ? tcdwidth / 2 : tcdcontext.textAlign === "right" ? tcdwidth - tcdpad : tcdpad; for (var tcdindex = 0; tcdindex < tcdlines.length; tcdindex++) { tcdcontext.fillText( tcdlines[tcdindex], tcdx, tcdpad + tcdlineheight / 2 + tcdindex * tcdlineheight ); } var tcdtexture = new THREE.CanvasTexture(tcdcanvas); tcdtexture.minFilter = THREE.LinearFilter; return tcdtexture; } function ticoderebuild() { var tcdwidth = tcdatom.offsetWidth + tcdpad * 2; var tcdheight = tcdatom.offsetHeight + tcdpad * 2; if (tcdwidth <= tcdpad * 2 || tcdheight <= tcdpad * 2) return false; tcdrenderer.setSize(tcdwidth, tcdheight); tcdsimw = Math.max(1, Math.floor(tcdwidth * tcdsimscale)); tcdsimh = Math.max(1, Math.floor(tcdheight * tcdsimscale)); if (tcdrta) tcdrta.dispose(); if (tcdrtb) tcdrtb.dispose(); var tcdoptions = { type: THREE.HalfFloatType, minFilter: THREE.NearestFilter, magFilter: THREE.NearestFilter }; tcdrta = new THREE.WebGLRenderTarget(tcdsimw, tcdsimh, tcdoptions); tcdrtb = new THREE.WebGLRenderTarget(tcdsimw, tcdsimh, tcdoptions); tcdsimmat.uniforms.uResolution.value.set(tcdsimw, tcdsimh); if (tcddrawmat.uniforms.uContentTexture.value) { tcddrawmat.uniforms.uContentTexture.value.dispose(); } tcddrawmat.uniforms.uContentTexture.value = ticodemaketexture( tcdwidth, tcdheight ); return true; } function ticodemousemove(tcdevent) { var tcdrect = tcdglcanvas.getBoundingClientRect(); if ( tcdevent.clientX < tcdrect.left || tcdevent.clientX > tcdrect.right || tcdevent.clientY < tcdrect.top || tcdevent.clientY > tcdrect.bottom ) { return; } tcdmouse.x = ((tcdevent.clientX - tcdrect.left) / tcdrect.width) * tcdsimw; tcdmouse.y = (1 - (tcdevent.clientY - tcdrect.top) / tcdrect.height) * tcdsimh; tcdmouse.z = 1; } function ticodetouchmove(tcdevent) { if (!tcdevent.touches || !tcdevent.touches.length) return; var tcdrect = tcdglcanvas.getBoundingClientRect(); var tcdtouch = tcdevent.touches[0]; if ( tcdtouch.clientX < tcdrect.left || tcdtouch.clientX > tcdrect.right || tcdtouch.clientY < tcdrect.top || tcdtouch.clientY > tcdrect.bottom ) { return; } tcdmouse.x = ((tcdtouch.clientX - tcdrect.left) / tcdrect.width) * tcdsimw; tcdmouse.y = (1 - (tcdtouch.clientY - tcdrect.top) / tcdrect.height) * tcdsimh; tcdmouse.z = 1; } function ticoderesize() { if (!tcdactive) return; try { ticoderebuild(); } catch (tcderror) {} } function ticodeanimate() { if (!tcdactive) return; requestAnimationFrame(ticodeanimate); if (!tcdrta || !tcdrtb) return; tcdsimmat.uniforms.uTexture.value = tcdrtb.texture; tcdsimmat.uniforms.uMouse.value.copy(tcdmouse); tcdrenderer.setRenderTarget(tcdrta); tcdscene.add(tcdsimmesh); tcdrenderer.render(tcdscene, tcdcamera); tcdscene.remove(tcdsimmesh); tcddrawmat.uniforms.uTexture.value = tcdrta.texture; tcdrenderer.setRenderTarget(null); tcdscene.add(tcddrawmesh); tcdrenderer.render(tcdscene, tcdcamera); tcdscene.remove(tcddrawmesh); var tcdtemp = tcdrta; tcdrta = tcdrtb; tcdrtb = tcdtemp; tcdmouse.z *= 0.95; } function ticodestart() { if (!tcdmedia.matches) { ticodeclear(); return; } try { if (!ticoderebuild()) { setTimeout(ticodestart, 300); return; } if (!tcdglcanvas.parentNode) { tcdelem.appendChild(tcdglcanvas); } tcdatom.style.visibility = "hidden"; window.addEventListener("mousemove", ticodemousemove); window.addEventListener("touchmove", ticodetouchmove, { passive: true }); window.addEventListener("resize", ticoderesize); ticodeanimate(); } catch (tcderror) { ticodeclear(); } } function ticodeclear() { tcdactive = false; tcdelem.dataset.tcdpureenergy = ""; tcdatom.style.visibility = ""; window.removeEventListener("mousemove", ticodemousemove); window.removeEventListener("touchmove", ticodetouchmove); window.removeEventListener("resize", ticoderesize); if (tcdglcanvas.parentNode) { tcdglcanvas.parentNode.removeChild(tcdglcanvas); } if (tcdrta) tcdrta.dispose(); if (tcdrtb) tcdrtb.dispose(); if (tcddrawmat.uniforms.uContentTexture.value) { tcddrawmat.uniforms.uContentTexture.value.dispose(); } tcdgeo.dispose(); tcdsimmat.dispose(); tcddrawmat.dispose(); tcdrenderer.dispose(); } if (document.fonts && document.fonts.ready) { document.fonts.ready.then(function () { setTimeout(ticodestart, 100); }); } else { setTimeout(ticodestart, 500); } return { ticodeclear: ticodeclear }; } function ticodeinit() { if (!tcdmedia.matches) return; document.querySelectorAll(tcdselector).forEach(function (tcdelem) { var tcdinstance = ticodecreateinstance(tcdelem); if (tcdinstance) { tcdinstances.push(tcdinstance); } }); } function ticodedestroyall() { tcdinstances.forEach(function (tcdinstance) { if (tcdinstance && typeof tcdinstance.ticodeclear === "function") { tcdinstance.ticodeclear(); } }); tcdinstances = []; } function ticodehandlemedia() { if (tcdmedia.matches) { ticodeinit(); } else { ticodedestroyall(); } } if (document.readyState === "complete") { ticodeinit(); } else { window.addEventListener("load", ticodeinit); } if (typeof tcdmedia.addEventListener === "function") { tcdmedia.addEventListener("change", ticodehandlemedia); } else if (typeof tcdmedia.addListener === "function") { tcdmedia.addListener(ticodehandlemedia); } })(); </script> <script> (function TCDupdType() { const TildahtmlBclok = document.currentScript; if (TildahtmlBclok) { const recordElement = TildahtmlBclok.closest('.r[data-record-type]'); if (recordElement) { recordElement.setAttribute('data-record-type', Math.random().toString(36).substring(2, 12)); }}})(); </script>
КОПИРОВАТЬ КОД
1. Создаем в зеро блок текстовый элемент и присеваем ему класс tcd-liquid text Можно создать несколько таких элементов в разных блоках. Код один для всех, отдельный скрипт для каждого элемента не нужен.

Чтобы добавить класс, нажимаем на элемент правой кнопкой мыши и выбираем из списка "Add CSS Class Name" и далее, справа в настройках указываем класс

2. Указываем дополнительные настройки в генераторе:
Поддержка мобилок - если включено, то на телефонах анимация будет запускается по тапу на текст (так как на мобилках нет курсора).

3. Копируем готовый код и вставляем в HTML блок T123. Блок кода размещаем под зеро блоком.
TICODE