Files
wahyd4.github.com/js/tag-cloud.js
T

87 lines
3.5 KiB
JavaScript

/* =========================================================
Tag Cloud · Nebula color engine (toozhao.com/tags/)
Inject via body-end.njk
- 颜色按真实引用数映射:冷色(冷门) → 暖色(热门) 彩虹渐变
- 大小标签错落漂浮 + 进场 stagger
- 移动端字号自动缩放
========================================================= */
(function () {
'use strict';
function initTagCloud() {
var cloud = document.getElementById('tag-cloud');
if (!cloud) return;
var links = cloud.querySelectorAll('a');
if (!links.length) return;
// 1. 收集每个标签的真实引用数(计数徽章),并做移动端字号缩放
var isMobile = window.innerWidth < 560;
var scale = isMobile ? 0.72 : 1;
var counts = [];
Array.prototype.forEach.call(links, function (a) {
var cEl = a.querySelector('.tag-count');
var c = cEl ? parseInt(cEl.textContent, 10) : 1;
counts.push(c);
});
var minC = Math.min.apply(null, counts);
var maxC = Math.max.apply(null, counts);
var rangeC = (maxC - minC) || 1;
// 2. 混排(riffle):前后两段交错,大小/冷暖标签错落分布成"云"
var arr = Array.prototype.slice.call(links);
var half = Math.ceil(arr.length / 2);
var reordered = [];
for (var k = 0; k < half; k++) {
reordered.push(arr[k]);
if (arr[half + k]) reordered.push(arr[half + k]);
}
var frag = document.createDocumentFragment();
reordered.forEach(function (a) { frag.appendChild(a); });
cloud.appendChild(frag);
links = cloud.querySelectorAll('a');
// 重新收集计数(顺序已变)
counts = [];
Array.prototype.forEach.call(links, function (a) {
var cEl = a.querySelector('.tag-count');
var c = cEl ? parseInt(cEl.textContent, 10) : 1;
counts.push(c);
});
// 3. 逐标签分配颜色与动效
Array.prototype.forEach.call(links, function (a, i) {
var w = (counts[i] - minC) / rangeC; // 0(冷门) ~ 1(热门)
var fs = parseFloat(a.style.fontSize) || 14;
a.style.fontSize = (fs * scale) + 'px';
// 彩虹映射:蓝(222°) → 青 → 绿 → 黄 → 橙 → 红(0°),热门偏暖
var hue = Math.round(222 - w * 222);
// 热门饱和度更高、颜色更深,更有分量
var sat = Math.round(60 + w * 28);
var lig = Math.round(47 - w * 12);
a.style.setProperty('--c', 'hsl(' + hue + ', ' + sat + '%, ' + lig + '%)');
a.style.setProperty('--cb', 'hsl(' + hue + ', ' + sat + '%, ' + Math.min(97, lig + 40) + '%)');
a.style.setProperty('--cb-dark', 'hsl(' + hue + ', ' + (sat - 8) + '%, 18%)');
a.style.setProperty('--i', i);
// 错落起伏:上下偏移 + 微旋转(热门标签更稳,冷门更活泼)
var amp = 14 - w * 8;
a.style.setProperty('--y', (Math.random() * amp * 2 - amp).toFixed(1) + 'px');
a.style.setProperty('--r', (Math.random() * (8 + w * 4) - 4 - w * 2).toFixed(1) + 'deg');
// 漂浮周期:小标签快,大标签慢
a.style.setProperty('--dur', (4.5 + w * 3.5 + Math.random() * 1.5).toFixed(2) + 's');
a.style.setProperty('--fd', (-Math.random() * 6).toFixed(2) + 's');
// 超级热门标签(按真实引用数)加高亮
if (counts[i] >= 25) a.classList.add('hot');
else if (counts[i] >= 10) a.classList.add('warm');
});
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initTagCloud);
} else {
initTagCloud();
}
})();