import * as PIXI from 'pixi.js';
const app = new PIXI.Application({ background: '#1099bb', resizeTo: window });
document.body.appendChild(app.view);
const generateSpinner1 = (position) =>
{
const container = new PIXI.Container();
container.position = position;
app.stage.addChild(container);
const base = PIXI.Sprite.from('https://pixijs.com/assets/bg_scene_rotate.jpg');
const size = 100;
base.width = size;
base.height = size;
const bottom = PIXI.Sprite.from('https://pixijs.com/assets/bg_rotate.jpg');
bottom.width = size;
bottom.height = size;
const mask = new PIXI.Graphics();
mask.position.set(size / 2, size / 2);
base.mask = mask;
window.mask = mask;
container.addChild(bottom);
container.addChild(base);
container.addChild(mask);
let phase = 0;
return (delta) =>
{
phase += delta / 60;
phase %= (Math.PI * 2);
const x = Math.cos(phase - Math.PI / 2) * size;
const y = Math.sin(phase - Math.PI / 2) * size;
const segments = [
[-size / 2, -size / 2, size / 2, -size / 2],
[size / 2, -size / 2, size / 2, size / 2],
[-size / 2, size / 2, size / 2, size / 2],
[-size / 2, -size / 2, -size / 2, size / 2],
];
let intersection = null;
let winding = 0;
for (let i = 0; i < segments.length; i++)
{
const segment = segments[i];
const hit = intersect(0, 0, x, y, segment[0], segment[1], segment[2], segment[3]);
if (hit)
{
intersection = hit;
if (i === 0) winding = hit.x > 0 ? 0 : 4;
else winding = i;
break;
}
}
const corners = [
size / 2, -size / 2,
size / 2, size / 2,
-size / 2, size / 2,
-size / 2, -size / 2,
0, -size / 2,
];
mask.clear();
mask.lineStyle(2, 0xff0000, 1);
mask.beginFill(0xff0000, 1);
mask.moveTo(0, -size / 2);
mask.lineTo(0, 0);
mask.lineTo(intersection.x, intersection.y);
for (let i = winding; i < corners.length / 2; i++)
{
mask.lineTo(corners[i * 2], corners[i * 2 + 1]);
}
mask.endFill();
};
};
const generateSpinner2 = (position) =>
{
const container = new PIXI.Container();
container.position = position;
app.stage.addChild(container);
const size = 100;
const ballAmount = 7;
const balls = [];
for (let i = 0; i < ballAmount; i++)
{
const ball = PIXI.Sprite.from('https://pixijs.com/assets/circle.png');
ball.anchor.set(0.5);
container.addChild(ball);
ball.position.set(
size / 2 + Math.cos(i / ballAmount * Math.PI * 2) * size / 3,
size / 2 + Math.sin(i / ballAmount * Math.PI * 2) * size / 3,
);
balls.push(ball);
}
let phase = 0;
return (delta) =>
{
phase += delta / 60;
phase %= (Math.PI * 2);
balls.forEach((b, i) =>
{
const sin = Math.sin(i / ballAmount * Math.PI - phase);
b.scale.set(Math.abs(sin * sin * sin * 0.5) + 0.5);
});
};
};
const generateSpinner3 = (position) =>
{
const container = new PIXI.Container();
container.position = position;
app.stage.addChild(container);
const base = PIXI.Sprite.from('https://pixijs.com/assets/bg_scene_rotate.jpg');
const size = 100;
base.width = size;
base.height = size;
const mask = new PIXI.Graphics();
mask.position.set(size / 2, size / 2);
base.mask = mask;
window.mask = mask;
container.addChild(base);
container.addChild(mask);
let phase = 0;
return (delta) =>
{
phase += delta / 60;
phase %= (Math.PI * 2);
const angleStart = 0 - Math.PI / 2;
const angle = phase + angleStart;
const radius = 50;
const x1 = Math.cos(angleStart) * radius;
const y1 = Math.sin(angleStart) * radius;
mask.clear();
mask.lineStyle(2, 0xff0000, 1);
mask.beginFill(0xff0000, 1);
mask.moveTo(0, 0);
mask.lineTo(x1, y1);
mask.arc(0, 0, radius, angleStart, angle, false);
mask.lineTo(0, 0);
mask.endFill();
};
};
const generateSpinner4 = (position) =>
{
const container = new PIXI.Container();
container.position = position;
app.stage.addChild(container);
const size = 100;
const arcRadius = 15;
const base = PIXI.Sprite.from('https://pixijs.com/assets/bg_scene_rotate.jpg');
base.width = size;
base.height = size;
const roundingMask = new PIXI.Graphics();
roundingMask.beginFill(0, 1);
roundingMask.lineStyle(1, 0xff0000, 1);
roundingMask.drawRoundedRect(0, 0, size, size, arcRadius);
roundingMask.endFill();
base.mask = roundingMask;
const lineSize = 5;
const edge = new PIXI.Graphics();
edge.lineStyle(lineSize, 0xff0000, 1);
edge.drawRoundedRect(0, 0, size, size, arcRadius);
edge.endFill();
const mask = new PIXI.Graphics();
mask.position.set(size / 2, size / 2);
edge.mask = mask;
container.addChild(base);
container.addChild(roundingMask);
container.addChild(edge);
container.addChild(mask);
let phase = 0;
return (delta) =>
{
phase += delta / 160;
phase %= (Math.PI * 2);
const x = Math.cos(phase - Math.PI / 2) * size;
const y = Math.sin(phase - Math.PI / 2) * size;
const segments = [
[-size / 2 + lineSize, -size / 2 + lineSize, size / 2 - lineSize, -size / 2 + lineSize],
[size / 2 - lineSize, -size / 2 + lineSize, size / 2 - lineSize, size / 2 - lineSize],
[-size / 2 + lineSize, size / 2 - lineSize, size / 2 - lineSize, size / 2 - lineSize],
[-size / 2 + lineSize, -size / 2 + lineSize, -size / 2 + lineSize, size / 2 - lineSize],
];
let outDir = [
[0, -1],
[1, 0],
[0, 1],
[-1, 0],
];
let intersection = null;
let winding = 0;
for (let i = 0; i < segments.length; i++)
{
const segment = segments[i];
const hit = intersect(0, 0, x, y, segment[0], segment[1], segment[2], segment[3]);
if (hit)
{
intersection = hit;
if (i === 0) winding = hit.x < 0 ? 0 : 4;
else winding = 4 - i;
outDir = outDir[i];
break;
}
}
const corners = [
-size / 2 - lineSize, -size / 2 - lineSize,
-size / 2 - lineSize, size / 2 + lineSize,
size / 2 + lineSize, size / 2 + lineSize,
size / 2 + lineSize, -size / 2 - lineSize,
];
mask.clear();
mask.lineStyle(2, 0x00ff00, 1);
mask.beginFill(0xff0000, 1);
mask.moveTo(0, 0);
mask.moveTo(0, -size / 2 - lineSize);
for (let i = 0; i < winding; i++)
{
mask.lineTo(corners[i * 2], corners[i * 2 + 1]);
}
mask.lineTo(intersection.x + outDir[0] * lineSize * 2, intersection.y + outDir[1] * lineSize * 2);
mask.lineTo(intersection.x, intersection.y);
mask.lineTo(0, 0);
mask.endFill();
};
};
const generateSpinner5 = (position) =>
{
const container = new PIXI.Container();
container.position = position;
app.stage.addChild(container);
const halfCircle = new PIXI.Graphics();
halfCircle.beginFill(0xff0000);
halfCircle.lineStyle(2, 0xffffff);
halfCircle.arc(0, 0, 100, 0, Math.PI);
halfCircle.endFill();
halfCircle.position.set(50, 50);
const rectangle = new PIXI.Graphics();
rectangle.lineStyle(2, 0xffffff, 1);
rectangle.drawRoundedRect(0, 0, 100, 100, 16);
rectangle.endFill();
rectangle.mask = halfCircle;
container.addChild(rectangle);
container.addChild(halfCircle);
let phase = 0;
return (delta) =>
{
phase += delta / 6;
phase %= (Math.PI * 2);
halfCircle.rotation = phase;
};
};
const onTick = [
generateSpinner1(new PIXI.Point(50, 50)),
generateSpinner2(new PIXI.Point(160, 50)),
generateSpinner3(new PIXI.Point(270, 50)),
generateSpinner4(new PIXI.Point(380, 50)),
generateSpinner5(new PIXI.Point(490, 50)),
];
app.ticker.add((delta) =>
{
onTick.forEach((cb) =>
{
cb(delta);
});
});
function intersect(x1, y1, x2, y2, x3, y3, x4, y4)
{
if ((x1 === x2 && y1 === y2) || (x3 === x4 && y3 === y4))
{
return false;
}
const denominator = ((y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1));
if (denominator === 0)
{
return false;
}
const ua = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / denominator;
const ub = ((x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3)) / denominator;
if (ua < 0 || ua > 1 || ub < 0 || ub > 1)
{
return false;
}
const x = x1 + ua * (x2 - x1);
const y = y1 + ua * (y2 - y1);
return { x, y };
}