MediaWiki:Common.js
Appearance
Note: After publishing, you may have to bypass your browser's cache to see the changes.
- Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
- Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
- Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5.
/* 3D Tag Cloud Interactive Animation */
(function() {
if (typeof window.TagCloudInitialized !== 'undefined') return;
window.TagCloudInitialized = true;
function initTagCloud() {
var container = document.getElementById('tagcloud-sphere');
if (!container) return;
var tags = container.getElementsByClassName('tag-item');
if (tags.length === 0) return;
var radius = 180;
var dtr = Math.PI / 180;
var mcList = [];
var active = false;
var lasta = 1;
var lastb = 1;
var distr = true;
var tspeed = 2;
var size = 250;
var mouseX = 0;
var mouseY = 0;
var howElliptical = 1;
var aA = null;
var oDiv = container;
// Position tags in 3D sphere
var i = 0;
var oTag = null;
for (i = 0; i < tags.length; i++) {
oTag = {};
oTag.offsetWidth = tags[i].offsetWidth;
oTag.offsetHeight = tags[i].offsetHeight;
mcList.push(oTag);
}
sineCosine(0, 0, 0);
positionAll();
// Auto-rotate
var autoRotateTimer = setInterval(update, 30);
function update() {
var a;
var b;
if (active) {
a = (-Math.min(Math.max(-mouseY, -size), size) / radius) * tspeed;
b = (Math.min(Math.max(-mouseX, -size), size) / radius) * tspeed;
} else {
a = lasta * 0.98;
b = lastb * 0.98;
}
lasta = a;
lastb = b;
if (Math.abs(a) <= 0.01 && Math.abs(b) <= 0.01 && !active) {
// Gentle auto-rotation when idle
a = 0.3;
b = 0.3;
}
var c = 0;
sineCosine(a, b, c);
for (var i = 0; i < mcList.length; i++) {
var rx1 = mcList[i].cx;
var ry1 = mcList[i].cy * ca + mcList[i].cz * (-sa);
var rz1 = mcList[i].cy * sa + mcList[i].cz * ca;
var rx2 = rx1 * cb + rz1 * sb;
var ry2 = ry1;
var rz2 = rx1 * (-sb) + rz1 * cb;
var rx3 = rx2 * cc + ry2 * (-sc);
var ry3 = rx2 * sc + ry2 * cc;
var rz3 = rz2;
mcList[i].cx = rx3;
mcList[i].cy = ry3;
mcList[i].cz = rz3;
var per = 350 / (350 + rz3);
mcList[i].x = rx3 * per;
mcList[i].y = ry3 * per;
mcList[i].scale = per;
mcList[i].alpha = per;
mcList[i].alpha = (mcList[i].alpha - 0.6) * (10 / 6);
}
doPosition();
depthSort();
}
function depthSort() {
var i = 0;
var aTmp = [];
for (i = 0; i < tags.length; i++) {
aTmp.push(tags[i]);
}
aTmp.sort(function(vItem1, vItem2) {
if (vItem1.cz > vItem2.cz) {
return -1;
} else if (vItem1.cz < vItem2.cz) {
return 1;
} else {
return 0;
}
});
for (i = 0; i < aTmp.length; i++) {
aTmp[i].style.zIndex = i;
}
}
function positionAll() {
var phi = 0;
var theta = 0;
var max = mcList.length;
var aTmp = [];
var oFragment = document.createDocumentFragment();
for (var i = 0; i < max; i++) {
phi = Math.acos(-1 + (2 * i) / max);
theta = Math.sqrt(max * Math.PI) * phi;
mcList[i].cx = radius * Math.cos(theta) * Math.sin(phi);
mcList[i].cy = radius * Math.sin(theta) * Math.sin(phi);
mcList[i].cz = radius * Math.cos(phi);
tags[i].style.left = mcList[i].cx + oDiv.offsetWidth / 2 - mcList[i].offsetWidth / 2 + 'px';
tags[i].style.top = mcList[i].cy + oDiv.offsetHeight / 2 - mcList[i].offsetHeight / 2 + 'px';
}
}
function doPosition() {
var l = oDiv.offsetWidth / 2;
var t = oDiv.offsetHeight / 2;
for (var i = 0; i < mcList.length; i++) {
var item = tags[i];
var mc = mcList[i];
item.style.left = mc.x + l - mc.offsetWidth / 2 + 'px';
item.style.top = mc.y + t - mc.offsetHeight / 2 + 'px';
item.style.fontSize = Math.ceil(12 * mc.scale / 2) + 8 + 'px';
item.style.filter = 'alpha(opacity=' + 100 * mc.alpha + ')';
item.style.opacity = mc.alpha;
}
}
function sineCosine(a, b, c) {
sa = Math.sin(a * dtr);
ca = Math.cos(a * dtr);
sb = Math.sin(b * dtr);
cb = Math.cos(b * dtr);
sc = Math.sin(c * dtr);
cc = Math.cos(c * dtr);
}
// Mouse/Touch interaction
var containerElement = document.getElementById('tagcloud-container');
containerElement.addEventListener('mouseover', function() {
active = true;
});
containerElement.addEventListener('mouseout', function() {
active = false;
});
containerElement.addEventListener('mousemove', function(ev) {
var rect = containerElement.getBoundingClientRect();
mouseX = ev.clientX - rect.left - containerElement.offsetWidth / 2;
mouseY = ev.clientY - rect.top - containerElement.offsetHeight / 2;
});
// Touch support
containerElement.addEventListener('touchstart', function() {
active = true;
});
containerElement.addEventListener('touchend', function() {
active = false;
});
containerElement.addEventListener('touchmove', function(ev) {
ev.preventDefault();
var rect = containerElement.getBoundingClientRect();
var touch = ev.touches[0];
mouseX = touch.clientX - rect.left - containerElement.offsetWidth / 2;
mouseY = touch.clientY - rect.top - containerElement.offsetHeight / 2;
});
}
// Initialize when DOM is ready
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initTagCloud);
} else {
initTagCloud();
}
})();