<!-- Глитч-анимация фона по курсору -->
<!-- Источник: https://inkedx.ru/guides/glitch -->
<style>
#glitch-background-effect {
position: relative;
width: 100%;
height: 100vh;
overflow: hidden;
}
#glitch-canvas-wrapper {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
canvas {
width: 100% !important;
height: 100% !important;
}
</style>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/ogl@0.0.64/dist/ogl.umd.js"></script>
<script type="module">
const imageResolution = [1650, 1200];
const vertShader = `
attribute vec2 position;
attribute vec2 uv;
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = vec4(position, 0, 1);
}
`;
const fragShader = `
precision highp float;
uniform sampler2D tWater;
uniform sampler2D tFlow;
uniform float uTime;
uniform vec4 resolution;
varying vec2 vUv;
void main() {
vec3 flow = texture2D(tFlow, vUv).rgb;
vec2 uvCoord = .5 * gl_FragCoord.xy / resolution.xy;
vec2 baseUV = (uvCoord - 0.5) * resolution.zw + 0.5;
vec3 colorR = texture2D(tWater, baseUV - flow.xy * 0.105).rgb;
vec3 colorG = texture2D(tWater, baseUV - flow.xy * 0.0875).rgb;
vec3 colorB = texture2D(tWater, baseUV - flow.xy * 0.07).rgb;
gl_FragColor = vec4(colorR.r, colorG.g, colorB.b, 1.0);
}
`;
{
const renderer = new ogl.Renderer({ dpr: 2 });
const gl = renderer.gl;
$(gl.canvas).appendTo('#glitch-canvas-wrapper');
const mousePos = new ogl.Vec2(-1);
const velocity = new ogl.Vec2();
let aspectRatio = 1;
function handleResize() {
let scaleX, scaleY;
const imageAspect = imageResolution[1] / imageResolution[0];
if (window.innerHeight / window.innerWidth < imageAspect) {
scaleX = 1;
scaleY = window.innerHeight / window.innerWidth / imageAspect;
} else {
scaleX = (window.innerWidth / window.innerHeight) * imageAspect;
scaleY = 1;
}
shaderProgram.uniforms.resolution.value = new ogl.Vec4(
window.innerWidth,
window.innerHeight,
scaleX,
scaleY
);
renderer.setSize(window.innerWidth, window.innerHeight);
aspectRatio = window.innerWidth / window.innerHeight;
}
const flowmap = new ogl.Flowmap(gl, {
falloff: 1.0,
alpha: 0.25,
dissipation: 0.95
});
const geometry = new ogl.Geometry(gl, {
position: { size: 2, data: new Float32Array([-1, -1, 3, -1, -1, 3]) },
uv: { size: 2, data: new Float32Array([0, 0, 2, 0, 0, 2]) }
});
const backgroundTexture = new ogl.Texture(gl, {
minFilter: gl.LINEAR,
magFilter: gl.LINEAR
});
const bgImage = new Image();
bgImage.onload = () => (backgroundTexture.image = bgImage);
bgImage.crossOrigin = 'anonymous';
bgImage.src = "!МЕСТО ДЛЯ ССЫЛКИ!";
let sX, sY;
const imgAspect = imageResolution[1] / imageResolution[0];
if (window.innerHeight / window.innerWidth < imgAspect) {
sX = 1;
sY = window.innerHeight / window.innerWidth / imgAspect;
} else {
sX = (window.innerWidth / window.innerHeight) * imgAspect;
sY = 1;
}
const shaderProgram = new ogl.Program(gl, {
vertex: vertShader,
fragment: fragShader,
uniforms: {
uTime: { value: 0 },
tWater: { value: backgroundTexture },
tFlow: flowmap.uniform,
resolution: { value: new ogl.Vec4(window.innerWidth, window.innerHeight, sX, sY) }
}
});
const plane = new ogl.Mesh(gl, { geometry, program: shaderProgram });
window.addEventListener('resize', handleResize);
handleResize();
const canvas = gl.canvas;
const isTouch = 'ontouchstart' in window;
if (!isTouch) {
canvas.addEventListener('mousemove', onMouseMove, false);
}
let lastTime;
const lastMouse = new ogl.Vec2();
function onMouseMove(e) {
e.preventDefault();
const x = e.pageX || e.clientX;
const y = e.pageY || e.clientY;
mousePos.set(x / gl.renderer.width, 1.0 - y / gl.renderer.height);
if (!lastTime) {
lastTime = performance.now();
lastMouse.set(x, y);
}
const dx = x - lastMouse.x;
const dy = y - lastMouse.y;
lastMouse.set(x, y);
const now = performance.now();
const delta = Math.max(10.4, now - lastTime);
lastTime = now;
velocity.x = dx / delta;
velocity.y = dy / delta;
velocity.needsUpdate = true;
}
requestAnimationFrame(loop);
function loop(time) {
requestAnimationFrame(loop);
if (!velocity.needsUpdate) {
mousePos.set(-1);
velocity.set(0);
}
velocity.needsUpdate = false;
flowmap.aspect = aspectRatio;
flowmap.mouse.copy(mousePos);
flowmap.velocity.lerp(velocity, velocity.len ? 0.15 : 0.1);
flowmap.update();
shaderProgram.uniforms.uTime.value = time * 0.01;
renderer.render({ scene: plane });
}
}
</script>