Как создать эффект фонарика с помощью PixiJS?
Хотелось бы сделать подобный эффект фонарика как на сайте - https://awwwards-2020.tubikstudio.com/ Судя, по всему, там используется PixiJS.
Смог добиться этого эффекта с помощью CSS/JS, но хотелось бы увидеть решение на PixiJS.
Все, что получилось добиться с помощью PixiJS v6.5.2:
const createBackground = (path) => {
const background = PIXI.Sprite.from(path);
background.width = app.screen.width;
background.height = app.screen.height;
return background;
};
const app = new PIXI.Application({
width: window.innerWidth,
height: window.innerHeight,
backgroundColor: 0x000000
});
document.body.appendChild(app.view);
// Функция для создания затемнённого фона с прозрачным кругом
function createDarkCoverWithHole(x, y) {
const darkCover = new PIXI.Graphics();
darkCover.clear();
darkCover.beginFill(0x000000, 1);
darkCover.drawRect(0, 0, app.screen.width, app.screen.height);
darkCover.beginHole(); // Начинаем создание "дыры"
darkCover.drawCircle(x, y, 300); // Рисуем круг в позиции курсора
darkCover.endHole(); // Заканчиваем создание "дыры"
darkCover.endFill();
return darkCover;
}
app.stage.addChild(createBackground('background.jpg'));
let darkCover = createDarkCoverWithHole(app.screen.width / 2, app.screen.height / 2);
app.stage.addChild(darkCover);
// Обработчик движения мыши
app.renderer.plugins.interaction.on('mousemove', (event) => {
const { x, y } = event.data.global;
app.stage.removeChild(darkCover);
darkCover = createDarkCoverWithHole(x, y);
app.stage.addChild(darkCover);
});
Ответы (1 шт):
Автор решения: Александр
→ Ссылка
Нашел решение (PixiJS v6.5.10):
const app = new PIXI.Application({
width: window.innerWidth,
height: window.innerHeight,
backgroundColor: 0x000000
});
document.body.appendChild(app.view);
const radius = 400;
const blurSize = 32;
app.loader.add('grass', 'background.jpg');
app.loader.load(setup);
let targetX = 0; // Целевая позиция X маски
let targetY = 0; // Целевая позиция Y маски
let currentX = 0; // Текущая позиция X маски
let currentY = 0; // Текущая позиция Y маски
const inertia = 0.1; // Коэффициент инерции (0 - немедленное перемещение, 1 - отсутствие перемещения)
function setup(loader, resources) {
const background = new PIXI.Sprite(resources.grass.texture);
app.stage.addChild(background);
background.width = app.screen.width;
background.height = app.screen.height;
const circle = new PIXI.Graphics()
.beginFill(0xFF0000)
.drawCircle(radius + blurSize, radius + blurSize, radius)
.endFill();
circle.filters = [new PIXI.filters.BlurFilter(blurSize)];
const bounds = new PIXI.Rectangle(0, 0, (radius + blurSize) * 2, (radius + blurSize) * 2);
const texture = app.renderer.generateTexture(circle, PIXI.SCALE_MODES.NEAREST, 1, bounds);
const focus = new PIXI.Sprite(texture);
app.stage.addChild(focus);
background.mask = focus;
app.stage.interactive = true;
app.stage.on('mousemove', pointerMove);
app.ticker.add(() => {
// Плавное обновление позиции маски с учетом инерции
currentX += (targetX - currentX) * inertia;
currentY += (targetY - currentY) * inertia;
focus.position.x = currentX - focus.width / 2;
focus.position.y = currentY - focus.height / 2;
});
function pointerMove(event) {
// Обновляем целевую позицию маски согласно положению курсора
targetX = event.data.global.x;
targetY = event.data.global.y;
}
}