Как добавить картинкам на сайте зернистость и искажение при наведении?
Из названия уже понятна суть: есть простые картинки на сайте, добавляемые при помощи <img>. При наведении на любую картинку срабатывает анимация искажения. Искажение должно выглядеть в точности, как на примере, в котором это всё реализовано. Также я ещё хочу добавить второй эффект, который всегда будет показываться: зернистость. Тоже, как в примере.
Именно такое чудо я и хочу придать картинкам и на своей странице. Существует ли подходящая для этой задачи библиотека и как это грамотно реализовывают?
Ответы (1 шт):
Автор решения: Max Watson
→ Ссылка
Я бы сделал так
'use strict';
console.clear();
//настройки шума, тут покрутишь найдешь нужное.
class Grain {
constructor (el) {
this.patternSize = 150;
this.patternScaleX = 1;
this.patternScaleY = 1;
this.patternRefreshInterval = 1;
this.patternAlpha = 35;
this.canvas = el;
this.ctx = this.canvas.getContext('2d');
this.ctx.scale(this.patternScaleX, this.patternScaleY);
this.patternCanvas = document.createElement('canvas');
this.patternCanvas.width = this.patternSize;
this.patternCanvas.height = this.patternSize;
this.patternCtx = this.patternCanvas.getContext('2d');
this.patternData = this.patternCtx.createImageData(this.patternSize, this.patternSize);
this.patternPixelDataLength = this.patternSize * this.patternSize * 4; // rgba = 4
this.resize = this.resize.bind(this);
this.loop = this.loop.bind(this);
this.frame = 0;
window.addEventListener('resize', this.resize);
this.resize();
window.requestAnimationFrame(this.loop);
}
resize () {
this.canvas.width = window.innerWidth * devicePixelRatio;
this.canvas.height = window.innerHeight * devicePixelRatio;
}
update () {
const {patternPixelDataLength, patternData, patternAlpha, patternCtx} = this;
for (let i = 0; i < patternPixelDataLength; i += 4) {
const value = Math.random() * 255;
patternData.data[i] = value;
patternData.data[i + 1] = value;
patternData.data[i + 2] = value;
patternData.data[i + 3] = patternAlpha;
}
patternCtx.putImageData(patternData, 0, 0);
}
draw () {
const {ctx, patternCanvas, canvas, viewHeight} = this;
const {width, height} = canvas;
ctx.clearRect(0, 0, width, height);
ctx.fillStyle = ctx.createPattern(patternCanvas, 'repeat');
ctx.fillRect(0, 0, width, height);
}
loop () {
const shouldDraw = ++this.frame % this.patternRefreshInterval === 0;
if (shouldDraw) {
this.update();
this.draw();
}
window.requestAnimationFrame(this.loop);
}
}
const el = document.querySelector('.grain');
const grain = new Grain(el);
body {
background-image: urL('https://klike.net/uploads/posts/2019-06/1560838551_1.jpg');
background-position: center center;
background-size: cover;
background-repeat: no-repeat;
}
.grain {
width: 100%;
height: 100%;
z-index: 1;
}
<canvas class="grain">
