Files
Websites/Profice WebSite/scripts/cursor-simple.js
2026-02-06 09:30:59 +01:00

228 lines
7.3 KiB
JavaScript

// Simple cursor.js - Fixed version with better line effects
document.addEventListener("DOMContentLoaded", function () {
// Check if touch device
if (window.matchMedia("(pointer: coarse)").matches) return;
const toggleBtn = document.getElementById('cursorToggle');
const body = document.body;
// Start with system cursor
let isCustomCursor = false;
function updateCursorState() {
if (isCustomCursor) {
body.classList.remove('system-cursor');
if (toggleBtn) {
toggleBtn.classList.add('active');
}
} else {
body.classList.add('system-cursor');
if (toggleBtn) {
toggleBtn.classList.remove('active');
}
}
}
// Initialize cursor state
updateCursorState();
// Toggle button click handler
if (toggleBtn) {
toggleBtn.addEventListener('click', () => {
isCustomCursor = !isCustomCursor;
localStorage.setItem('customCursor', isCustomCursor);
updateCursorState();
});
}
// Create canvas for custom cursor
const canvas = document.createElement("canvas");
canvas.id = "custom-cursor";
canvas.style.cssText = `
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
z-index: 999999;
display: none;
`;
document.body.appendChild(canvas);
const ctx = canvas.getContext("2d");
const tentacles = [];
const mouse = { x: 0, y: 0 };
const oldMouse = { x: 0, y: 0 };
// Mouse move handler
document.addEventListener("mousemove", (e) => {
mouse.x = e.clientX;
mouse.y = e.clientY;
if (isCustomCursor) {
canvas.style.display = 'block';
} else {
canvas.style.display = 'none';
}
});
// Window resize handler
window.addEventListener("resize", () => {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
});
// Tentacle class with better line effects
class Tentacle {
constructor(x, y, targetX, targetY) {
this.startX = x;
this.startY = y;
this.endX = targetX;
this.endY = targetY;
this.life = 1.0;
this.decay = 0.015;
this.growth = 0;
this.maxLength = 0;
}
update() {
// Grow the tentacle
if (this.growth < 1.0) {
this.growth += 0.1;
}
// Calculate actual end point based on growth
const currentEndX = this.startX + (this.endX - this.startX) * this.growth;
const currentEndY = this.startY + (this.endY - this.startY) * this.growth;
this.currentEndX = currentEndX;
this.currentEndY = currentEndY;
// Decay over time
this.life -= this.decay;
}
draw(ctx) {
if (this.life <= 0) return;
const opacity = this.life * this.growth;
// Draw main line with gradient effect
const gradient = ctx.createLinearGradient(
this.startX, this.startY,
this.currentEndX, this.currentEndY
);
gradient.addColorStop(0, `rgba(20, 20, 20, ${opacity * 0.8})`);
gradient.addColorStop(1, `rgba(20, 20, 20, ${opacity * 0.2})`);
ctx.strokeStyle = gradient;
ctx.lineWidth = 3 * opacity * this.growth;
ctx.lineCap = 'round';
ctx.beginPath();
ctx.moveTo(this.startX, this.startY);
ctx.lineTo(this.currentEndX, this.currentEndY);
ctx.stroke();
// Draw glowing endpoint
const glowSize = 6 * opacity;
const glowGradient = ctx.createRadialGradient(
this.currentEndX, this.currentEndY, 0,
this.currentEndX, this.currentEndY, glowSize
);
glowGradient.addColorStop(0, `rgba(20, 20, 20, ${opacity})`);
glowGradient.addColorStop(1, `rgba(20, 20, 20, 0)`);
ctx.fillStyle = glowGradient;
ctx.beginPath();
ctx.arc(this.currentEndX, this.currentEndY, glowSize, 0, Math.PI * 2);
ctx.fill();
// Draw connection dots along the line
const dotCount = 3;
for (let i = 1; i <= dotCount; i++) {
const t = i / (dotCount + 1);
const dotX = this.startX + (this.currentEndX - this.startX) * t;
const dotY = this.startY + (this.currentEndY - this.startY) * t;
const dotOpacity = opacity * (1 - t) * 0.5;
ctx.fillStyle = `rgba(20, 20, 20, ${dotOpacity})`;
ctx.beginPath();
ctx.arc(dotX, dotY, 2, 0, Math.PI * 2);
ctx.fill();
}
}
}
// Animation loop
function animate() {
if (!isCustomCursor) {
requestAnimationFrame(animate);
return;
}
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Create new tentacles on movement
const dx = mouse.x - oldMouse.x;
const dy = mouse.y - oldMouse.y;
const distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 3) {
// Create multiple tentacles in movement direction
const angle = Math.atan2(dy, dx);
const spread = 0.3;
for (let i = 0; i < 4; i++) {
const spreadAngle = angle + (Math.random() - 0.5) * spread;
const length = 60 + Math.random() * 80;
const targetX = mouse.x + Math.cos(spreadAngle) * length;
const targetY = mouse.y + Math.sin(spreadAngle) * length;
tentacles.push(new Tentacle(mouse.x, mouse.y, targetX, targetY));
}
oldMouse.x = mouse.x;
oldMouse.y = mouse.y;
}
// Update and draw tentacles
for (let i = tentacles.length - 1; i >= 0; i--) {
const tentacle = tentacles[i];
tentacle.update();
if (tentacle.life <= 0) {
tentacles.splice(i, 1);
} else {
tentacle.draw(ctx);
}
}
// Limit tentacle count
if (tentacles.length > 15) {
tentacles.splice(0, tentacles.length - 15);
}
// Draw cursor point with glow
const cursorGradient = ctx.createRadialGradient(
mouse.x, mouse.y, 0,
mouse.x, mouse.y, 8
);
cursorGradient.addColorStop(0, 'rgba(20, 20, 20, 0.8)');
cursorGradient.addColorStop(1, 'rgba(20, 20, 20, 0)');
ctx.fillStyle = cursorGradient;
ctx.beginPath();
ctx.arc(mouse.x, mouse.y, 6, 0, Math.PI * 2);
ctx.fill();
// Add central bright point
ctx.fillStyle = 'rgba(255, 255, 255, 0.9)';
ctx.beginPath();
ctx.arc(mouse.x, mouse.y, 2, 0, Math.PI * 2);
ctx.fill();
requestAnimationFrame(animate);
}
animate();
});