/** * 格式化金额,默认 MYR (RM) * @param {Number|String} amount 金额 * @param {String} currency 币种(ISO 4217),默认 MYR * @param {String} locale 语言地区,默认 "ms-MY" * @returns {String} 格式化后的金额 */ function formatCurrency(amount, currency = "MYR", locale = "ms-MY") { const num = Number(amount); if (isNaN(num)) return String(amount); // 非数字直接返回原值 return new Intl.NumberFormat(locale, { style: "currency", currency, }).format(num); } const sponsorListDiv = document.getElementById("sponsorList"); Promise.all([ fetch("../data/sponsors.json").then((res) => res.json()), fetch("../data/seats.json").then((res) => res.json()), ]).then(([sponsors, seats]) => { const sponsorList = sponsors.map((item) => ({ name: item.name, amount: formatCurrency(item.amount), // 使用 Intl API })); const seatList = seats.map((item) => ({ name: item.name, amount: `${item.seat} 席`, })); [...sponsorList, ...seatList].forEach((entry) => { const card = document.createElement("div"); card.className = "sponsor-item card"; card.innerHTML = `

${entry.name}

${entry.amount}

`; sponsorListDiv.appendChild(card); }); }); // ================= Canvas 背景 ================= const canvas = document.getElementById("background"); const ctx = canvas.getContext("2d"); function resizeCanvas() { canvas.width = window.innerWidth; canvas.height = window.innerHeight; } resizeCanvas(); window.addEventListener("resize", resizeCanvas); class Point { constructor() { this.radius = Math.random() * 4 + 2; this.x = Math.random() * canvas.width; this.y = Math.random() * canvas.height; this.xSpeed = (Math.random() - 0.5) * 60; this.ySpeed = (Math.random() - 0.5) * 60; this.color = `hsl(${Math.random() * 360}, 100%, 50%)`; this.lastDrawTime = null; } draw() { const now = Date.now(); if (this.lastDrawTime) { const dt = (now - this.lastDrawTime) / 1000; this.x += this.xSpeed * dt; this.y += this.ySpeed * dt; } if (this.x < 0 || this.x > canvas.width) this.xSpeed *= -1; if (this.y < 0 || this.y > canvas.height) this.ySpeed *= -1; ctx.beginPath(); ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2); ctx.fillStyle = this.color; ctx.shadowBlur = 15; ctx.shadowColor = this.color; ctx.fill(); this.lastDrawTime = now; } } class Graph { constructor(pointCount = 70, maxDistance = 120) { this.points = Array.from({ length: pointCount }, () => new Point()); this.maxDist = maxDistance; } draw() { requestAnimationFrame(() => this.draw()); ctx.clearRect(0, 0, canvas.width, canvas.height); for (let i = 0; i < this.points.length; i++) { const p1 = this.points[i]; p1.draw(); for (let j = i + 1; j < this.points.length; j++) { const p2 = this.points[j]; const dx = p1.x - p2.x; const dy = p1.y - p2.y; const dist = Math.sqrt(dx * dx + dy * dy); if (dist < this.maxDist) { const alpha = 1 - dist / this.maxDist; ctx.beginPath(); ctx.moveTo(p1.x, p1.y); ctx.lineTo(p2.x, p2.y); ctx.strokeStyle = `rgba(255, 255, 255, ${alpha})`; ctx.lineWidth = 2 * alpha; ctx.stroke(); } } } } } new Graph().draw();