Upload files to "js"
This commit is contained in:
parent
6892e556f3
commit
5e45870d5b
3 changed files with 1437 additions and 0 deletions
1142
js/create-circle.js
Normal file
1142
js/create-circle.js
Normal file
File diff suppressed because it is too large
Load diff
279
js/image.js
Normal file
279
js/image.js
Normal file
|
@ -0,0 +1,279 @@
|
|||
// Configuration
|
||||
// ---------------------------------------------------------------------------------
|
||||
const config = {
|
||||
logoSrc: 'img/logo.png', // Path to the logo image
|
||||
logoHeight: 50, // Logo height
|
||||
backgroundColor: '#090909', // Canvas background color
|
||||
lineColor: '#159262', // Default dashed line color
|
||||
lineThickness: 3, // Dashed line thickness
|
||||
randomizeYellowLines: true, // Enable or disable random yellow lines
|
||||
yellowLineColor: '#9d921d', // Yellow line color
|
||||
avatarBackgroundColor: '#090909', // Background color behind the avatar
|
||||
borderThickness: 5, // Border thickness around avatars
|
||||
borderColor: '#1bec99', // Border color around avatars
|
||||
urlText: '[ Create your own at ccc.cyber.to ]', // Text to display on the canvas
|
||||
urlFont: '16px monospace', // Font for URL text
|
||||
urlColor: '#159262', // URL text color
|
||||
avatarScale: 75, // Avatar scale percentage
|
||||
drawMazeBackground: true, // Whether to draw a random maze background
|
||||
mazeColor: '#05130f', // Color of the maze lines
|
||||
mazeThickness: 2, // Thickness of the maze lines
|
||||
drawRedLine: true, // Enable or disable the red line
|
||||
redLineColor: '#FB2735', // Red line color
|
||||
consoleLogging: false, // Enable or disable console logging
|
||||
};
|
||||
// ---------------------------------------------------------------------------------
|
||||
|
||||
// Converts degrees to radians
|
||||
const toRad = (x) => {
|
||||
if (config.consoleLogging) console.log('Function call: toRad');
|
||||
return x * (Math.PI / 180);
|
||||
};
|
||||
|
||||
const dist = [200, 330, 450]; // Distance of each user layer from the center
|
||||
const numb = [8, 15, 26]; // Number of users in each layer
|
||||
const radius = [64, 58, 50]; // Radius of avatars in each layer
|
||||
let userNum = 0; // Counter for the number of users rendered
|
||||
let remainingImg = 0; // Counter for remaining images to load
|
||||
let totalImg = 0; // Total images to load
|
||||
|
||||
function render(users, selfUser) {
|
||||
if (config.consoleLogging) console.log('Function call: render');
|
||||
userNum = 0;
|
||||
remainingImg = 0;
|
||||
|
||||
// Get canvas element
|
||||
const canvas = document.getElementById("canvas");
|
||||
if (!canvas) return;
|
||||
const ctx = canvas.getContext("2d"); // Get canvas context
|
||||
|
||||
const width = canvas.width;
|
||||
const height = canvas.height;
|
||||
|
||||
// Draw maze if enabled
|
||||
if (config.drawMazeBackground) {
|
||||
drawMazeBackground(ctx, width, height);
|
||||
}
|
||||
|
||||
// Configure canvas background
|
||||
ctx.fillStyle = config.backgroundColor;
|
||||
ctx.globalCompositeOperation = 'destination-over';
|
||||
ctx.fillRect(0, 0, width, height);
|
||||
ctx.globalCompositeOperation = 'source-over';
|
||||
|
||||
const userPositions = [];
|
||||
const tasks = [];
|
||||
const mainAvatarRadius = 110 * (config.avatarScale / 100); // Scale main avatar
|
||||
|
||||
totalImg += 1;
|
||||
remainingImg += 1;
|
||||
loadImage(
|
||||
ctx,
|
||||
selfUser.avatar,
|
||||
(width / 2) - mainAvatarRadius,
|
||||
(height / 2) - mainAvatarRadius,
|
||||
mainAvatarRadius,
|
||||
null,
|
||||
tasks
|
||||
);
|
||||
|
||||
// Position and render user avatars
|
||||
for (let layerIndex = 0; layerIndex < 3; layerIndex++) {
|
||||
const angleSize = 360 / numb[layerIndex];
|
||||
|
||||
for (let i = 0; i < numb[layerIndex]; i++) {
|
||||
if (userNum >= users.length) break;
|
||||
|
||||
totalImg += 1;
|
||||
remainingImg += 1;
|
||||
|
||||
const offset = layerIndex * 30;
|
||||
const r = toRad(i * angleSize + offset);
|
||||
|
||||
const centerX = Math.cos(r) * dist[layerIndex] + width / 2;
|
||||
const centerY = Math.sin(r) * dist[layerIndex] + height / 2;
|
||||
userPositions.push({ x: centerX, y: centerY });
|
||||
|
||||
// Render connecting lines
|
||||
ctx.beginPath();
|
||||
ctx.setLineDash([10, 3]);
|
||||
ctx.moveTo(width / 2, height / 2);
|
||||
ctx.lineTo(centerX, centerY);
|
||||
ctx.strokeStyle = config.lineColor;
|
||||
ctx.lineWidth = config.lineThickness;
|
||||
ctx.stroke();
|
||||
ctx.setLineDash([]);
|
||||
|
||||
loadImage(
|
||||
ctx,
|
||||
users[userNum].avatar,
|
||||
centerX - radius[layerIndex] * (config.avatarScale / 100),
|
||||
centerY - radius[layerIndex] * (config.avatarScale / 100),
|
||||
radius[layerIndex] * (config.avatarScale / 100),
|
||||
null,
|
||||
tasks
|
||||
);
|
||||
|
||||
userNum++;
|
||||
}
|
||||
}
|
||||
|
||||
// Draw random yellow lines if enabled
|
||||
if (config.randomizeYellowLines) {
|
||||
randomizeYellowLines(ctx, userPositions, 10);
|
||||
}
|
||||
|
||||
// Draw red line if enabled
|
||||
if (config.drawRedLine) {
|
||||
drawRedLine(ctx, width, height, userPositions);
|
||||
}
|
||||
|
||||
const logo = new Image();
|
||||
logo.onload = function () {
|
||||
// Load and draw logo
|
||||
const aspectRatio = logo.width / logo.height;
|
||||
const logoWidth = config.logoHeight * aspectRatio;
|
||||
ctx.drawImage(logo, 10, 10, logoWidth, config.logoHeight);
|
||||
};
|
||||
logo.src = config.logoSrc;
|
||||
|
||||
// Draw URL text
|
||||
ctx.font = config.urlFont;
|
||||
ctx.fillStyle = config.urlColor;
|
||||
const textWidth = ctx.measureText(config.urlText).width;
|
||||
const textXPosition = width - textWidth - 10;
|
||||
const textYPosition = height - 10;
|
||||
|
||||
ctx.fillText(config.urlText, textXPosition, textYPosition);
|
||||
}
|
||||
|
||||
// Draws a maze background
|
||||
function drawMazeBackground(ctx, width, height) {
|
||||
if (config.consoleLogging) console.log('Function call: drawMazeBackground');
|
||||
const cellSize = 20;
|
||||
ctx.strokeStyle = config.mazeColor;
|
||||
ctx.lineWidth = config.mazeThickness;
|
||||
for (let y = 0; y < height; y += cellSize) {
|
||||
for (let x = 0; x < width; x += cellSize) {
|
||||
if (Math.random() > 0.5) {
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(x, y);
|
||||
ctx.lineTo(x + cellSize, y + cellSize);
|
||||
ctx.stroke();
|
||||
} else {
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(x + cellSize, y);
|
||||
ctx.lineTo(x, y + cellSize);
|
||||
ctx.stroke();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Draw random yellow lines
|
||||
function randomizeYellowLines(ctx, userPositions, maxLines) {
|
||||
if (config.consoleLogging) console.log('Function call: randomizeYellowLines');
|
||||
const numberOfLines = Math.min(maxLines, Math.floor(Math.random() * userPositions.length));
|
||||
|
||||
for (let i = 0; i < numberOfLines; i++) {
|
||||
const index1 = Math.floor(Math.random() * userPositions.length);
|
||||
let index2;
|
||||
do {
|
||||
index2 = Math.floor(Math.random() * userPositions.length);
|
||||
} while (index2 === index1);
|
||||
|
||||
const startPos = userPositions[index1];
|
||||
const endPos = userPositions[index2];
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.setLineDash([10, 3]);
|
||||
ctx.moveTo(startPos.x, startPos.y);
|
||||
ctx.lineTo(endPos.x, endPos.y);
|
||||
ctx.strokeStyle = config.yellowLineColor;
|
||||
ctx.lineWidth = config.lineThickness;
|
||||
ctx.stroke();
|
||||
ctx.setLineDash([]);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw a random red line
|
||||
function drawRedLine(ctx, width, height, userPositions) {
|
||||
if (config.consoleLogging) console.log('Function call: drawRedLine');
|
||||
if (userPositions.length === 0) return;
|
||||
|
||||
const selectedPosition = userPositions[Math.floor(Math.random() * userPositions.length)];
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.setLineDash([10, 3]);
|
||||
ctx.moveTo(width / 2, height / 2);
|
||||
ctx.lineTo(selectedPosition.x, selectedPosition.y);
|
||||
ctx.strokeStyle = config.redLineColor;
|
||||
ctx.lineWidth = config.lineThickness;
|
||||
ctx.stroke();
|
||||
ctx.setLineDash([]);
|
||||
}
|
||||
|
||||
// Load and draw user images
|
||||
function loadImage(ctx, url, x, y, r, name, tasks) {
|
||||
if (config.consoleLogging) console.log('Function call: loadImage');
|
||||
let progress = document.getElementById("outInfo");
|
||||
if (!progress) return;
|
||||
|
||||
tasks.push(() => { /* No text addition here */ });
|
||||
|
||||
// Decrement image counter
|
||||
const decrementRemaining = () => {
|
||||
remainingImg -= 1;
|
||||
progress.innerText = `Loading avatars: ${totalImg - remainingImg}/${totalImg}`;
|
||||
|
||||
if (remainingImg <= 0) {
|
||||
progress.innerText = "";
|
||||
tasks.forEach((task) => task());
|
||||
}
|
||||
};
|
||||
|
||||
const img = new Image();
|
||||
|
||||
// Handle image loading errors
|
||||
const drawImageWithFallback = (imageSrc) => {
|
||||
img.onload = function() {
|
||||
ctx.save();
|
||||
ctx.beginPath();
|
||||
ctx.arc(x + r, y + r, r, 0, Math.PI * 2, true);
|
||||
ctx.closePath();
|
||||
ctx.clip();
|
||||
|
||||
ctx.fillStyle = config.avatarBackgroundColor;
|
||||
ctx.beginPath();
|
||||
ctx.arc(x + r, y + r, r, 0, Math.PI * 2, true);
|
||||
ctx.fill();
|
||||
ctx.closePath();
|
||||
|
||||
ctx.drawImage(img, x, y, r * 2, r * 2);
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.arc(x + r, y + r, r, 0, Math.PI * 2, true);
|
||||
ctx.lineWidth = config.borderThickness;
|
||||
ctx.strokeStyle = config.borderColor;
|
||||
ctx.stroke();
|
||||
ctx.closePath();
|
||||
|
||||
ctx.restore();
|
||||
|
||||
decrementRemaining();
|
||||
};
|
||||
|
||||
img.onerror = function() {
|
||||
console.error(`IMG Error: ${imageSrc}`);
|
||||
if (imageSrc !== 'img/placeholder.png') {
|
||||
drawImageWithFallback('img/placeholder.png');
|
||||
} else {
|
||||
decrementRemaining();
|
||||
}
|
||||
};
|
||||
|
||||
img.src = imageSrc;
|
||||
};
|
||||
|
||||
drawImageWithFallback(url);
|
||||
}
|
16
js/url.js
Normal file
16
js/url.js
Normal file
|
@ -0,0 +1,16 @@
|
|||
document.addEventListener("DOMContentLoaded", function() {
|
||||
function getFediverseHandle() {
|
||||
const url = window.location.href;
|
||||
const prefix = "?@";
|
||||
const index = url.indexOf(prefix);
|
||||
if(index !== -1) {
|
||||
return decodeURIComponent(url.substring(index + prefix.length));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
var fediverseHandle = getFediverseHandle();
|
||||
if(fediverseHandle) {
|
||||
document.getElementById('txt_mastodon_handle').value = fediverseHandle;
|
||||
(async() => await circleMain())();
|
||||
}
|
||||
});
|
Loading…
Reference in a new issue