--- layout: post title: Blog Function Update 2025 (1) date: 2025-01-26 00:10:01 +0800 category: tech thumb: ARTICLEPICTURES_PATH/update.jpg tags: [技术, 骑行, update] --- 由于郑州最近的雨夹雪天气,已经一周没有骑行了,实在憋得不行,给自己找点事做,今天中午下班时更新了一下博客 ## Update details - **修复了柱形图显示错位** - **移除了骑行页面的活动天数** - **新增了全年骑行总时长、全年骑行总公里数** - **柱形图的宽度**不再由骑行时长来计算,而是由骑行公里数来计算显示 - **新增春节快乐红灯笼**(移动端不支持) - **移除 `node-sass` 包,由 `sass` 代替** ## Fix Bugs:柱形图显示错位 当前的柱形图仅为有骑行数据的周生成柱形图,导致柱形图与日历中的周对齐错位,所以即某周没有骑行数据时,柱形图也要生成一根柱子 ```js function generateBarChart() { const barChartElement = document.getElementById('barChart'); // 清空柱形图内容 barChartElement.innerHTML = ''; const today = getChinaTime(); const startDate = getStartDate(today, 21); // 创建所有周的时间范围 const weeklyData = {}; let currentWeekStart = new Date(startDate); currentWeekStart.setUTCHours(0, 0, 0, 0); // 按周计算未来 4 周的日期范围 for (let i = 0; i < 4; i++) { const weekStart = new Date(currentWeekStart); const weekEnd = new Date(weekStart); // 一周结束日期为开始日期 +6 天 weekEnd.setUTCDate(weekStart.getUTCDate() + 6); const weekKey = `${weekStart.toISOString().split('T')[0]} - ${weekEnd.toISOString().split('T')[0]}`; // 初始化每周骑行数据为 0 weeklyData[weekKey] = 0; // 移动到下一周 currentWeekStart.setUTCDate(currentWeekStart.getUTCDate() + 7); } // 累加每周的骑行距离 processedActivities.forEach(activity => { const activityDate = new Date(activity.activity_time); // 活动所在周的开始日期 const weekStart = getWeekStartDate(activityDate); const weekEnd = new Date(weekStart); weekEnd.setUTCDate(weekStart.getUTCDate() + 6); const weekKey = `${weekStart.toISOString().split('T')[0]} - ${weekEnd.toISOString().split('T')[0]}`; if (weeklyData[weekKey] !== undefined) { weeklyData[weekKey] += parseFloat(activity.riding_distance); } }); // 获取最大骑行距离(用于柱形图比例) const maxDistance = Math.max(...Object.values(weeklyData), 0); // 创建并显示每周的柱形图 Object.keys(weeklyData).forEach(week => { // 当前周的骑行距离 const distance = weeklyData[week]; const barContainer = document.createElement('div'); barContainer.className = 'bar-container'; const bar = document.createElement('div'); bar.className = 'bar'; // 计算柱形图的宽度 const width = maxDistance > 0 ? (distance / maxDistance) * 190 : 0; bar.style.setProperty('--bar-width', `${width}px`); const distanceText = document.createElement('div'); distanceText.className = 'cycling-kilometer'; distanceText.innerText = '0 km'; const messageBox = createMessageBox(); const clickMessageBox = createMessageBox(); barContainer.style.position = 'relative'; bar.appendChild(distanceText); barContainer.appendChild(bar); barContainer.appendChild(messageBox); barContainer.appendChild(clickMessageBox); barChartElement.appendChild(barContainer); // 动画效果:逐渐显示柱形图宽度 bar.style.width = '0'; bar.offsetHeight; bar.style.transition = 'width 1s ease-out'; bar.style.width = `${width}px`; distanceText.style.opacity = '1'; // 动态更新柱形图的数值 animateText(distanceText, 0, distance, 1000, true); setupBarInteractions(bar, messageBox, clickMessageBox, distance); }); } // 动态文本显示 function animateText(element, startValue, endValue, duration, isDistance = false) { const startTime = performance.now(); function update() { const elapsed = performance.now() - startTime; const progress = Math.min(elapsed / duration, 1); const currentValue = (progress * endValue).toFixed(2); element.innerText = isDistance ? `${currentValue} km` : `${currentValue}h`; if (progress < 1) { requestAnimationFrame(update); } else { element.innerText = isDistance ? `${endValue.toFixed(2)} km` : `${endValue.toFixed(2)}h`; } } update(); } ``` ## New:全年骑行总时长、全年骑行总公里数 ```js // 显示总活动数和总公里数 function displayTotalActivities(activities) { // 全年骑行时长 const ridingTimeThisYear = document.getElementById('totalCount'); // 全年骑行公里数 const milesRiddenThisYear = document.getElementById('milesRiddenThisYear'); // 动态年标题《2025 骑行总时长》 const totalTitleElement = document.getElementById('totalTitle'); if (!ridingTimeThisYear || !milesRiddenThisYear || !totalTitleElement) return; const ridingTimeThisYearValue = ridingTimeThisYear.querySelector('#ridingTimeThisYearValue'); const milesRiddenThisYearValue = milesRiddenThisYear.querySelector('#milesRiddenThisYearValue'); const totalCountSpinner = ridingTimeThisYear.querySelector('.loading-spinner'); const milesRiddenThisYearSpinner = milesRiddenThisYear.querySelector('.loading-spinner'); totalCountSpinner.classList.add('active'); milesRiddenThisYearSpinner.classList.add('active'); const currentYear = new Date().getFullYear(); totalTitleElement.textContent = `${currentYear} 骑行总时长`; // 筛选全年活动数据 const filteredActivities = activities.filter(activity => { const activityYear = new Date(activity.activity_time).getFullYear(); return activityYear === currentYear; }); // 计算全年活动时间的总和(单位:小时) const totalMovingTime = filteredActivities.reduce((total, activity) => { return total + parseFloat(activity.moving_time) || 0; }, 0); // 计算全年总公里数 const totalKilometers = calculateTotalKilometers(filteredActivities); // 动画效果 animateCount(ridingTimeThisYearValue, totalMovingTime, 1000, 50, false); animateCount(milesRiddenThisYearValue, totalKilometers, 1000, 50, true); setTimeout(() => { console.log(totalKilometers.toFixed(2)); ridingTimeThisYearValue.textContent = `${totalMovingTime.toFixed(2)} h`; milesRiddenThisYearValue.textContent = `${totalKilometers.toFixed(2)} km`; totalCountSpinner.classList.remove('active'); milesRiddenThisYearSpinner.classList.remove('active'); }, 1000); } // 加载数据并生成日历 (async function() { const today = getChinaTime(); const startDate = getStartDate(today, 21); const activities = await loadActivityData(); // 显示4周的日历 generateCalendar(activities, startDate, 4); // 显示全年骑行时长和公里数 displayTotalActivities(activities); })(); ``` ## New:春节快乐红灯笼 两年前在冲浪时下载的,已经是第二次用了: ```css // default.html include lantern.html // main.scss @use 'lantern' ``` ## Fix Bugs:移除 node-sass 包 node-sass 是基于 LibSass 库构建的,而 LibSass 从 2019 年就停止了更新。所以,Sass 团队放弃了这个项目,重构了 sass(Dart 编写) ### sass 相对 node-sass 的优点 1. 原生支持 Dart sass 是由 Dart 编写,它不再依赖 C++ 编译器,安装和构建速度更快 2. 不再依赖编译 node-sass 需要本地编译,会遇到编译问题,尤其是 Windows 系统上。而 sass 是纯 JavaScript 实现,跨平台时不会有编译问题 ```json { "devDependencies": { "sass": "^1.83.4", } } ``` ![Show][p1]{:.small} [p1]: {{ site.ARTICLEPICTURES_PATH }}/89ffc8f51982841a4f04ce590446b07.png