Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion layouts/partials/section/community.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<section class="community-section">
<div class="community-header cursors-container" data-cursors="0,1">
<div class="community-header cursors-container" data-cursors="4,1">
<span class="community-badge"><span class="dot"></span> Get Involved <span class="dot"></span></span>
<h2 class="community-title">Join the Community</h2>
<p class="capabilities-subtitle">Kanvas is open source and community-driven. Connect with fellow cloud native enthusiasts.</p>
Expand Down
4 changes: 2 additions & 2 deletions layouts/partials/section/hero-glass.html
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,11 @@ <h1>Infrastructure as Design</h1>

<div class="hero-visual">
<div class="canvas-preview glass--dark" data-float>
<div class="cursor-layer" data-cursors="0,1,2,3"
<div class="cursor-layer" data-cursors="0,1,2,3,4"
style="position:absolute; inset:0; z-index:15; pointer-events:none;"></div>
<div class="canvas-header">
<span>Production</span>
<span class="status">Syncing</span>
<span class="status">Collaboration</span>
</div>
<div class="canvas-grid">
<div class="connector connector--one"></div>
Expand Down
6 changes: 3 additions & 3 deletions static/images/cursors/cursor-1.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions static/images/cursors/cursor-5.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
72 changes: 42 additions & 30 deletions static/scripts/multi-player-cursors.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,19 @@

// Configuration
const CURSORS = [
{ src: '/images/cursors/cursor-1.svg', name: 'Sarah' },
{ src: '/images/cursors/cursor-1.svg', name: 'Aditya' },
{ src: '/images/cursors/cursor-2.svg', name: 'Jorge' },
{ src: '/images/cursors/cursor-3.svg', name: 'Suzan' },
{ src: '/images/cursors/cursor-4.svg', name: 'Ryan' }
{ src: '/images/cursors/cursor-4.svg', name: 'Ryan' },
{ src: '/images/cursors/cursor-5.svg', name: 'Sara Lin' }
];

const ANIMATION_DURATION = 3000; // 3 seconds
const ANIMATION_INTERVAL = 6000; // 6 seconds between movements
const CURSOR_SIZE = 50; // Default cursor size in pixels
const EDGE_PADDING = 50; // Padding from container edges
const EDGE_PADDING = 20; // Padding from container edges
const MIN_INTERVAL_FACTOR = 0.6;
const MAX_INTERVAL_FACTOR = 1.4;

/**
* Initialize cursors in a container
Expand All @@ -27,7 +30,7 @@

const cursors = [];

cursorIndices.forEach((index, i) => {
cursorIndices.forEach((index) => {
if (index >= CURSORS.length) return;

const cursorData = CURSORS[index];
Expand All @@ -38,29 +41,12 @@
// Set initial random position
setInitialRandomPosition(container, cursorElement);

// Start animation with stagger
// Start animation loop on an independent timer
const initialDelay = getRandomInterval();
setTimeout(() => {
animateCursor(container, cursorElement);
}, i * ANIMATION_DURATION);
scheduleCursorMovement(container, cursorElement);
}, initialDelay);
});

// Continue animation loop
const intervalId = setInterval(() => {
// Check if container still exists in DOM
if (!document.body.contains(container)) {
clearInterval(intervalId);
return;
}

cursors.forEach((cursor, i) => {
// Check if cursor still exists
if (!document.body.contains(cursor)) return;

setTimeout(() => {
animateCursor(container, cursor);
}, i * ANIMATION_DURATION);
});
}, ANIMATION_INTERVAL);
}

/**
Expand All @@ -80,22 +66,33 @@
}

/**
* Get random position within container bounds
* Get random position within container bounds with equal padding on all sides
*/
function getRandomPosition(container) {
const rect = container.getBoundingClientRect();
const width = rect.width;
const height = rect.height;

const maxX = Math.max(10, width - CURSOR_SIZE - EDGE_PADDING);
const maxY = Math.max(10, height - CURSOR_SIZE - EDGE_PADDING);
const minX = EDGE_PADDING;
const minY = EDGE_PADDING;
const maxX = Math.max(minX, width - CURSOR_SIZE - EDGE_PADDING);
const maxY = Math.max(minY, height - CURSOR_SIZE - EDGE_PADDING);

const randomX = Math.floor(Math.random() * maxX);
const randomY = Math.floor(Math.random() * maxY);
const randomX = Math.floor(Math.random() * (maxX - minX + 1)) + minX;
const randomY = Math.floor(Math.random() * (maxY - minY + 1)) + minY;

return { x: randomX, y: randomY };
}

/**
* Get randomized interval for independent movement
*/
function getRandomInterval() {
const min = ANIMATION_INTERVAL * MIN_INTERVAL_FACTOR;
const max = ANIMATION_INTERVAL * MAX_INTERVAL_FACTOR;
return Math.floor(Math.random() * (max - min + 1)) + min;
}

/**
* Set initial random position for cursor
*/
Expand All @@ -119,6 +116,21 @@
}, ANIMATION_DURATION);
}

/**
* Schedule cursor movement on its own timer
*/
function scheduleCursorMovement(container, element) {
// Check if container and cursor still exist
if (!document.body.contains(container) || !document.body.contains(element)) return;

animateCursor(container, element);

const nextDelay = getRandomInterval();
setTimeout(() => {
scheduleCursorMovement(container, element);
}, nextDelay);
}

/**
* Initialize all cursor containers on page load
*/
Expand Down