@sarthak03dot/romantic-animations 1.2.10 → 1.2.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,113 +0,0 @@
1
- import { mergeOptions } from '../core/engine.js';
2
-
3
- const DEFAULTS = {
4
- count: 20, // hearts per burst
5
- minSize: 8,
6
- maxSize: 20,
7
- minSpeed: 2,
8
- maxSpeed: 7,
9
- gravity: 0.08,
10
- decay: 0.018,
11
- colors: ['#ff0a54', '#ff477e', '#ff7096', '#ff85a1', '#fbb1bd', '#ff4d6d'],
12
- glow: true,
13
- symbols: ['heart'], // 'heart' | 'star' | 'sparkle'
14
- };
15
-
16
- function drawSymbol(ctx, type, cx, cy, r, color, alpha, glow) {
17
- ctx.save();
18
- ctx.globalAlpha = Math.max(0, alpha);
19
- if (glow) { ctx.shadowColor = color; ctx.shadowBlur = r * 2; }
20
- ctx.fillStyle = color;
21
-
22
- if (type === 'star') {
23
- // 5-point star
24
- ctx.beginPath();
25
- for (let i = 0; i < 5; i++) {
26
- const outer = (Math.PI / 2) + (i * 2 * Math.PI) / 5;
27
- const inner = outer + Math.PI / 5;
28
- if (i === 0) ctx.moveTo(cx + r * Math.cos(outer), cy - r * Math.sin(outer));
29
- else ctx.lineTo(cx + r * Math.cos(outer), cy - r * Math.sin(outer));
30
- ctx.lineTo(cx + (r * 0.4) * Math.cos(inner), cy - (r * 0.4) * Math.sin(inner));
31
- }
32
- ctx.closePath();
33
- ctx.fill();
34
- } else if (type === 'sparkle') {
35
- // 4-point sparkle
36
- for (let i = 0; i < 4; i++) {
37
- const a = (i * Math.PI) / 2;
38
- ctx.beginPath();
39
- ctx.ellipse(cx + Math.cos(a) * r * 0.5, cy + Math.sin(a) * r * 0.5, r * 0.18, r * 0.7, a, 0, Math.PI * 2);
40
- ctx.fill();
41
- }
42
- } else {
43
- // heart
44
- ctx.beginPath();
45
- ctx.moveTo(cx, cy + r * 0.3);
46
- ctx.bezierCurveTo(cx - r * 1.1, cy - r * 0.5, cx - r * 1.6, cy + r * 0.5, cx, cy + r * 1.4);
47
- ctx.bezierCurveTo(cx + r * 1.6, cy + r * 0.5, cx + r * 1.1, cy - r * 0.5, cx, cy + r * 0.3);
48
- ctx.fill();
49
- }
50
- ctx.restore();
51
- }
52
-
53
- export function heartBurst(canvas, userOptions = {}) {
54
- const opts = mergeOptions(DEFAULTS, userOptions);
55
- const ctx = canvas.getContext('2d');
56
- const particles = [];
57
- let running = true;
58
-
59
- function spawnBurst(x, y) {
60
- for (let i = 0; i < opts.count; i++) {
61
- const angle = Math.random() * Math.PI * 2;
62
- const speed = opts.minSpeed + Math.random() * (opts.maxSpeed - opts.minSpeed);
63
- particles.push({
64
- x, y,
65
- size: opts.minSize + Math.random() * (opts.maxSize - opts.minSize),
66
- vx: Math.cos(angle) * speed,
67
- vy: Math.sin(angle) * speed,
68
- alpha: 1,
69
- decay: opts.decay * (0.8 + Math.random() * 0.4),
70
- color: opts.colors[Math.floor(Math.random() * opts.colors.length)],
71
- symbol: opts.symbols[Math.floor(Math.random() * opts.symbols.length)],
72
- });
73
- }
74
- }
75
-
76
- const onClick = (e) => {
77
- const rect = canvas.getBoundingClientRect();
78
- spawnBurst(e.clientX - rect.left, e.clientY - rect.top);
79
- };
80
- const onTouch = (e) => {
81
- const rect = canvas.getBoundingClientRect();
82
- Array.from(e.changedTouches).forEach((t) => spawnBurst(t.clientX - rect.left, t.clientY - rect.top));
83
- };
84
-
85
- window.addEventListener('click', onClick);
86
- window.addEventListener('touchend', onTouch, { passive: true });
87
-
88
- function animate() {
89
- if (!running) return;
90
- ctx.clearRect(0, 0, canvas.width, canvas.height);
91
-
92
- for (let i = particles.length - 1; i >= 0; i--) {
93
- const p = particles[i];
94
- p.x += p.vx;
95
- p.y += p.vy;
96
- p.vy += opts.gravity; // gravity
97
- p.alpha -= p.decay;
98
- drawSymbol(ctx, p.symbol, p.x, p.y, p.size, p.color, p.alpha, opts.glow);
99
- if (p.alpha <= 0) particles.splice(i, 1);
100
- }
101
-
102
- requestAnimationFrame(animate);
103
- }
104
-
105
- animate();
106
-
107
- return function stop() {
108
- running = false;
109
- window.removeEventListener('click', onClick);
110
- window.removeEventListener('touchend', onTouch);
111
- ctx.clearRect(0, 0, canvas.width, canvas.height);
112
- };
113
- }
@@ -1,85 +0,0 @@
1
- import { mergeOptions } from '../core/engine.js';
2
-
3
- const DEFAULTS = {
4
- minSize: 6,
5
- maxSize: 16,
6
- decay: 0.025,
7
- colors: ['#ff6b8a', '#ff4d6d', '#ff85a1', '#ffc2d1', '#c9184a'],
8
- glow: true,
9
- };
10
-
11
- function drawHeart(ctx, cx, cy, r, color, alpha, glow) {
12
- ctx.save();
13
- ctx.globalAlpha = Math.max(0, alpha);
14
- if (glow) {
15
- ctx.shadowColor = color;
16
- ctx.shadowBlur = r * 2;
17
- }
18
- ctx.fillStyle = color;
19
- ctx.beginPath();
20
- ctx.moveTo(cx, cy + r * 0.3);
21
- ctx.bezierCurveTo(cx - r * 1.1, cy - r * 0.5, cx - r * 1.6, cy + r * 0.5, cx, cy + r * 1.4);
22
- ctx.bezierCurveTo(cx + r * 1.6, cy + r * 0.5, cx + r * 1.1, cy - r * 0.5, cx, cy + r * 0.3);
23
- ctx.fill();
24
- ctx.restore();
25
- }
26
-
27
- export function heartTrail(canvas, userOptions = {}) {
28
- const opts = mergeOptions(DEFAULTS, userOptions);
29
- const ctx = canvas.getContext('2d');
30
- const hearts = [];
31
- let running = true;
32
-
33
- function addHeart(x, y) {
34
- hearts.push({
35
- x,
36
- y,
37
- size: opts.minSize + Math.random() * (opts.maxSize - opts.minSize),
38
- alpha: 0.9 + Math.random() * 0.1,
39
- decay: opts.decay * (0.8 + Math.random() * 0.4),
40
- color: opts.colors[Math.floor(Math.random() * opts.colors.length)],
41
- vy: -(0.3 + Math.random() * 0.6), // drift upward
42
- });
43
- }
44
-
45
- // Mouse support
46
- const onMouseMove = (e) => {
47
- const rect = canvas.getBoundingClientRect();
48
- addHeart(e.clientX - rect.left, e.clientY - rect.top);
49
- };
50
-
51
- // Touch support
52
- const onTouchMove = (e) => {
53
- const rect = canvas.getBoundingClientRect();
54
- Array.from(e.touches).forEach((t) => {
55
- addHeart(t.clientX - rect.left, t.clientY - rect.top);
56
- });
57
- };
58
-
59
- window.addEventListener('mousemove', onMouseMove);
60
- window.addEventListener('touchmove', onTouchMove, { passive: true });
61
-
62
- function animate() {
63
- if (!running) return;
64
- ctx.clearRect(0, 0, canvas.width, canvas.height);
65
-
66
- for (let i = hearts.length - 1; i >= 0; i--) {
67
- const h = hearts[i];
68
- h.y += h.vy;
69
- drawHeart(ctx, h.x, h.y, h.size, h.color, h.alpha, opts.glow);
70
- h.alpha -= h.decay;
71
- if (h.alpha <= 0) hearts.splice(i, 1);
72
- }
73
-
74
- requestAnimationFrame(animate);
75
- }
76
-
77
- animate();
78
-
79
- return function stop() {
80
- running = false;
81
- window.removeEventListener('mousemove', onMouseMove);
82
- window.removeEventListener('touchmove', onTouchMove);
83
- ctx.clearRect(0, 0, canvas.width, canvas.height);
84
- };
85
- }
@@ -1,71 +0,0 @@
1
- import { mergeOptions } from '../core/engine.js';
2
-
3
- const DEFAULTS = {
4
- density: 0.15, // probability of a new drop per frame
5
- symbols: ['❤', '💕', '✨', '💖', '💗', '⭐', '×'],
6
- minSize: 12,
7
- maxSize: 28,
8
- minSpeed: 1,
9
- maxSpeed: 3.5,
10
- colors: ['#ff6b8a', '#ff4d6d', '#ffc2d1', '#ff85a1', '#ff0a54', '#a2d2ff'],
11
- opacity: 0.85,
12
- glow: true,
13
- };
14
-
15
- export function loveRain(canvas, userOptions = {}) {
16
- const opts = mergeOptions(DEFAULTS, userOptions);
17
- const ctx = canvas.getContext('2d');
18
- const drops = [];
19
- let running = true;
20
-
21
- function createDrop() {
22
- const size = opts.minSize + Math.random() * (opts.maxSize - opts.minSize);
23
- return {
24
- x: Math.random() * canvas.width,
25
- y: -size * 2,
26
- size,
27
- speed: opts.minSpeed + Math.random() * (opts.maxSpeed - opts.minSpeed),
28
- symbol: opts.symbols[Math.floor(Math.random() * opts.symbols.length)],
29
- color: opts.colors[Math.floor(Math.random() * opts.colors.length)],
30
- alpha: 0.4 + Math.random() * 0.6,
31
- angle: (Math.random() - 0.5) * 0.4, // slight tilt
32
- wobble: Math.random() * Math.PI * 2,
33
- wobbleSpeed: 0.02 + Math.random() * 0.02,
34
- };
35
- }
36
-
37
- function animate() {
38
- if (!running) return;
39
- ctx.clearRect(0, 0, canvas.width, canvas.height);
40
-
41
- if (Math.random() < opts.density) drops.push(createDrop());
42
-
43
- for (let i = drops.length - 1; i >= 0; i--) {
44
- const d = drops[i];
45
- d.y += d.speed;
46
- d.wobble += d.wobbleSpeed;
47
- const xOff = Math.sin(d.wobble) * d.size * 0.3;
48
-
49
- ctx.save();
50
- ctx.globalAlpha = d.alpha * opts.opacity;
51
- ctx.font = `${d.size}px serif`;
52
- ctx.fillStyle = d.color;
53
- if (opts.glow) { ctx.shadowColor = d.color; ctx.shadowBlur = d.size * 0.8; }
54
- ctx.translate(d.x + xOff, d.y);
55
- ctx.rotate(d.angle);
56
- ctx.fillText(d.symbol, 0, 0);
57
- ctx.restore();
58
-
59
- if (d.y > canvas.height + d.size * 2) drops.splice(i, 1);
60
- }
61
-
62
- requestAnimationFrame(animate);
63
- }
64
-
65
- animate();
66
-
67
- return function stop() {
68
- running = false;
69
- ctx.clearRect(0, 0, canvas.width, canvas.height);
70
- };
71
- }
@@ -1,87 +0,0 @@
1
- import { mergeOptions } from '../core/engine.js';
2
-
3
- const DEFAULTS = {
4
- particleCount: 150,
5
- minSize: 1,
6
- maxSize: 4,
7
- colors: ['#ffd6ff', '#e7c6ff', '#c77dff', '#ffb3c1', '#ffffff'],
8
- speed: 0.8,
9
- glow: true,
10
- };
11
-
12
- export function magicDust(canvas, userOptions = {}) {
13
- const opts = mergeOptions(DEFAULTS, userOptions);
14
- const ctx = canvas.getContext('2d');
15
- const dusts = [];
16
- let running = true;
17
- let time = 0;
18
-
19
- function createDust() {
20
- return {
21
- x: Math.random() * canvas.width,
22
- y: Math.random() * canvas.height,
23
- size: opts.minSize + Math.random() * (opts.maxSize - opts.minSize),
24
- color: opts.colors[Math.floor(Math.random() * opts.colors.length)],
25
- angle: Math.random() * Math.PI * 2,
26
- orbitRadius: 20 + Math.random() * 80,
27
- orbitSpeed: (0.01 + Math.random() * 0.03) * (Math.random() > 0.5 ? 1 : -1),
28
- centerX: Math.random() * canvas.width,
29
- centerY: canvas.height + 50, // Start below and move up
30
- upwardSpeed: opts.speed + Math.random() * 1.5,
31
- alpha: 0,
32
- };
33
- }
34
-
35
- for (let i = 0; i < opts.particleCount; i++) {
36
- dusts.push(createDust());
37
- // Scatter initial positions so they aren't all at the bottom
38
- dusts[i].centerY = Math.random() * canvas.height;
39
- dusts[i].alpha = Math.random();
40
- }
41
-
42
- function animate() {
43
- if (!running) return;
44
- time++;
45
- ctx.clearRect(0, 0, canvas.width, canvas.height);
46
-
47
- for (let i = 0; i < dusts.length; i++) {
48
- const d = dusts[i];
49
- d.angle += d.orbitSpeed;
50
- d.centerY -= d.upwardSpeed;
51
-
52
- // Swirling calculation
53
- d.x = d.centerX + Math.cos(d.angle) * d.orbitRadius + Math.sin(time * 0.01 + d.angle) * 30;
54
- d.y = d.centerY + Math.sin(d.angle) * (d.orbitRadius * 0.5);
55
-
56
- if (d.alpha < 1 && d.centerY > 0) d.alpha += 0.01;
57
-
58
- // Reset when they reach top
59
- if (d.y < -50) {
60
- Object.assign(d, createDust());
61
- d.centerY = canvas.height + 50;
62
- d.centerX = Math.random() * canvas.width;
63
- }
64
-
65
- ctx.save();
66
- ctx.globalAlpha = d.alpha;
67
- if (opts.glow) {
68
- ctx.shadowColor = d.color;
69
- ctx.shadowBlur = d.size * 3;
70
- }
71
- ctx.fillStyle = d.color;
72
- ctx.beginPath();
73
- ctx.arc(d.x, d.y, d.size, 0, Math.PI * 2);
74
- ctx.fill();
75
- ctx.restore();
76
- }
77
-
78
- requestAnimationFrame(animate);
79
- }
80
-
81
- animate();
82
-
83
- return function stop() {
84
- running = false;
85
- ctx.clearRect(0, 0, canvas.width, canvas.height);
86
- };
87
- }
@@ -1,82 +0,0 @@
1
- import { mergeOptions } from '../core/engine.js';
2
-
3
- const DEFAULTS = {
4
- density: 0.02,
5
- minSpeed: 10,
6
- maxSpeed: 25,
7
- colors: ['#ffffff', '#e7c6ff', '#48cae4', '#ffe66d'],
8
- glow: true,
9
- };
10
-
11
- export function shootingStars(canvas, userOptions = {}) {
12
- const opts = mergeOptions(DEFAULTS, userOptions);
13
- const ctx = canvas.getContext('2d');
14
- const stars = [];
15
- let running = true;
16
-
17
- function createStar() {
18
- return {
19
- x: Math.random() * canvas.width * 1.5,
20
- y: -50,
21
- length: 50 + Math.random() * 100,
22
- thickness: 1 + Math.random() * 2,
23
- speed: opts.minSpeed + Math.random() * (opts.maxSpeed - opts.minSpeed),
24
- color: opts.colors[Math.floor(Math.random() * opts.colors.length)],
25
- angle: (Math.PI / 4) + (Math.random() * 0.2 - 0.1), // Roughly 45 degrees
26
- opacity: 1,
27
- };
28
- }
29
-
30
- function animate() {
31
- if (!running) return;
32
- ctx.clearRect(0, 0, canvas.width, canvas.height);
33
-
34
- if (Math.random() < opts.density) {
35
- stars.push(createStar());
36
- }
37
-
38
- for (let i = stars.length - 1; i >= 0; i--) {
39
- const s = stars[i];
40
- const vx = -Math.cos(s.angle) * s.speed;
41
- const vy = Math.sin(s.angle) * s.speed;
42
-
43
- s.x += vx;
44
- s.y += vy;
45
- s.opacity -= 0.01;
46
-
47
- ctx.save();
48
- ctx.globalAlpha = Math.max(0, s.opacity);
49
- if (opts.glow) {
50
- ctx.shadowColor = s.color;
51
- ctx.shadowBlur = s.thickness * 4;
52
- }
53
-
54
- const grad = ctx.createLinearGradient(s.x, s.y, s.x - vx * (s.length / s.speed), s.y - vy * (s.length / s.speed));
55
- grad.addColorStop(0, s.color);
56
- grad.addColorStop(1, 'rgba(255,255,255,0)');
57
-
58
- ctx.strokeStyle = grad;
59
- ctx.lineWidth = s.thickness;
60
- ctx.lineCap = 'round';
61
-
62
- ctx.beginPath();
63
- ctx.moveTo(s.x, s.y);
64
- ctx.lineTo(s.x - vx * (s.length / s.speed), s.y - vy * (s.length / s.speed));
65
- ctx.stroke();
66
- ctx.restore();
67
-
68
- if (s.opacity <= 0 || s.x < -100 || s.y > canvas.height + 100) {
69
- stars.splice(i, 1);
70
- }
71
- }
72
-
73
- requestAnimationFrame(animate);
74
- }
75
-
76
- animate();
77
-
78
- return function stop() {
79
- running = false;
80
- ctx.clearRect(0, 0, canvas.width, canvas.height);
81
- };
82
- }
@@ -1,93 +0,0 @@
1
- import { mergeOptions } from '../core/engine.js';
2
-
3
- const DEFAULTS = {
4
- count: 80, // number of sparkles alive at once
5
- minSize: 2,
6
- maxSize: 6,
7
- speed: 0.5,
8
- twinkleSpeed: 0.04,
9
- colors: ['#fff', '#ffe4e8', '#ffb3c1', '#ff85a1', '#ffd6ff', '#e7c6ff'],
10
- glow: true,
11
- };
12
-
13
- export function sparkles(canvas, userOptions = {}) {
14
- const opts = mergeOptions(DEFAULTS, userOptions);
15
- const ctx = canvas.getContext('2d');
16
- const stars = [];
17
- let running = true;
18
-
19
- function createStar() {
20
- return {
21
- x: Math.random() * canvas.width,
22
- y: Math.random() * canvas.height,
23
- size: opts.minSize + Math.random() * (opts.maxSize - opts.minSize),
24
- alpha: Math.random(),
25
- alphaDir: Math.random() > 0.5 ? 1 : -1,
26
- twinkleSpeed: opts.twinkleSpeed * (0.5 + Math.random()),
27
- color: opts.colors[Math.floor(Math.random() * opts.colors.length)],
28
- vx: (Math.random() - 0.5) * opts.speed,
29
- vy: (Math.random() - 0.5) * opts.speed,
30
- };
31
- }
32
-
33
- // Populate initial stars
34
- for (let i = 0; i < opts.count; i++) stars.push(createStar());
35
-
36
- function drawStar(s) {
37
- ctx.save();
38
- ctx.globalAlpha = Math.max(0, Math.min(1, s.alpha));
39
- if (opts.glow) { ctx.shadowColor = s.color; ctx.shadowBlur = s.size * 3; }
40
- ctx.fillStyle = s.color;
41
-
42
- // Cross / sparkle shape
43
- const r = s.size;
44
- ctx.beginPath();
45
- for (let i = 0; i < 4; i++) {
46
- const a = (i * Math.PI) / 2;
47
- ctx.ellipse(
48
- s.x + Math.cos(a) * r * 0.35,
49
- s.y + Math.sin(a) * r * 0.35,
50
- r * 0.15, r * 0.7, a, 0, Math.PI * 2
51
- );
52
- }
53
- ctx.fill();
54
-
55
- // Tiny centre dot
56
- ctx.beginPath();
57
- ctx.arc(s.x, s.y, r * 0.2, 0, Math.PI * 2);
58
- ctx.fill();
59
- ctx.restore();
60
- }
61
-
62
- function animate() {
63
- if (!running) return;
64
- ctx.clearRect(0, 0, canvas.width, canvas.height);
65
-
66
- for (let i = 0; i < stars.length; i++) {
67
- const s = stars[i];
68
- s.x += s.vx;
69
- s.y += s.vy;
70
- s.alpha += s.alphaDir * s.twinkleSpeed;
71
-
72
- if (s.alpha >= 1) { s.alpha = 1; s.alphaDir = -1; }
73
- else if (s.alpha <= 0) { s.alpha = 0; s.alphaDir = 1; }
74
-
75
- // Wrap edges
76
- if (s.x < -10) s.x = canvas.width + 10;
77
- if (s.x > canvas.width + 10) s.x = -10;
78
- if (s.y < -10) s.y = canvas.height + 10;
79
- if (s.y > canvas.height + 10) s.y = -10;
80
-
81
- drawStar(s);
82
- }
83
-
84
- requestAnimationFrame(animate);
85
- }
86
-
87
- animate();
88
-
89
- return function stop() {
90
- running = false;
91
- ctx.clearRect(0, 0, canvas.width, canvas.height);
92
- };
93
- }
@@ -1,100 +0,0 @@
1
- import { mergeOptions } from '../core/engine.js';
2
-
3
- const DEFAULTS = {
4
- starCount: 120,
5
- speed: 0.4,
6
- colors: ['#ffffff', '#ffe4e8', '#ffc2d1', '#e7c6ff', '#a2d2ff'],
7
- minSize: 1,
8
- maxSize: 3.5,
9
- twinkle: true,
10
- connectDist: 100, // draw faint lines between close stars
11
- connectOpacity: 0.08,
12
- };
13
-
14
- export function starField(canvas, userOptions = {}) {
15
- const opts = mergeOptions(DEFAULTS, userOptions);
16
- const ctx = canvas.getContext('2d');
17
- const stars = [];
18
- let running = true;
19
-
20
- function createStar(randomY = false) {
21
- return {
22
- x: Math.random() * canvas.width,
23
- y: randomY ? Math.random() * canvas.height : Math.random() * canvas.height,
24
- size: opts.minSize + Math.random() * (opts.maxSize - opts.minSize),
25
- alpha: 0.3 + Math.random() * 0.7,
26
- alphaDir: Math.random() > 0.5 ? 1 : -1,
27
- twinkleSpeed: 0.008 + Math.random() * 0.015,
28
- vx: (Math.random() - 0.5) * opts.speed,
29
- vy: (Math.random() - 0.5) * opts.speed,
30
- color: opts.colors[Math.floor(Math.random() * opts.colors.length)],
31
- };
32
- }
33
-
34
- for (let i = 0; i < opts.starCount; i++) stars.push(createStar(true));
35
-
36
- function animate() {
37
- if (!running) return;
38
- ctx.clearRect(0, 0, canvas.width, canvas.height);
39
-
40
- // Draw connections
41
- if (opts.connectDist > 0) {
42
- for (let i = 0; i < stars.length; i++) {
43
- for (let j = i + 1; j < stars.length; j++) {
44
- const dx = stars[i].x - stars[j].x;
45
- const dy = stars[i].y - stars[j].y;
46
- const dist = Math.sqrt(dx * dx + dy * dy);
47
- if (dist < opts.connectDist) {
48
- ctx.save();
49
- ctx.globalAlpha = opts.connectOpacity * (1 - dist / opts.connectDist);
50
- ctx.strokeStyle = '#ffffff';
51
- ctx.lineWidth = 0.5;
52
- ctx.beginPath();
53
- ctx.moveTo(stars[i].x, stars[i].y);
54
- ctx.lineTo(stars[j].x, stars[j].y);
55
- ctx.stroke();
56
- ctx.restore();
57
- }
58
- }
59
- }
60
- }
61
-
62
- // Draw stars
63
- for (let i = 0; i < stars.length; i++) {
64
- const s = stars[i];
65
- s.x += s.vx;
66
- s.y += s.vy;
67
-
68
- if (opts.twinkle) {
69
- s.alpha += s.alphaDir * s.twinkleSpeed;
70
- if (s.alpha >= 1) { s.alpha = 1; s.alphaDir = -1; }
71
- if (s.alpha <= 0.1) { s.alpha = 0.1; s.alphaDir = 1; }
72
- }
73
-
74
- // Wrap
75
- if (s.x < -5) s.x = canvas.width + 5;
76
- if (s.x > canvas.width + 5) s.x = -5;
77
- if (s.y < -5) s.y = canvas.height + 5;
78
- if (s.y > canvas.height + 5) s.y = -5;
79
-
80
- ctx.save();
81
- ctx.globalAlpha = s.alpha;
82
- ctx.shadowColor = s.color;
83
- ctx.shadowBlur = s.size * 3;
84
- ctx.fillStyle = s.color;
85
- ctx.beginPath();
86
- ctx.arc(s.x, s.y, s.size, 0, Math.PI * 2);
87
- ctx.fill();
88
- ctx.restore();
89
- }
90
-
91
- requestAnimationFrame(animate);
92
- }
93
-
94
- animate();
95
-
96
- return function stop() {
97
- running = false;
98
- ctx.clearRect(0, 0, canvas.width, canvas.height);
99
- };
100
- }