Javascript: wordCloud

5 minute read

Today, I add a TagCloud function in my blog, here is the code:

tagCloud

html

<div id="tagsList">
    
          <a href="#bubble-sort " class = "word">
            <strong>Bubble sort</strong> 
          </a>
    
          <a href="#selection-sort " class = "word">
            <strong>Selection sort</strong> 
          </a>
    
          <a href="#insertion-sort " class = "word">
            <strong>Insertion sort</strong> 
          </a>
    
          <a href="#merge-sort " class = "word">
            <strong>Merge sort</strong> 
          </a>
    
          <a href="#quick-sort " class = "word">
            <strong>Quick sort</strong> 
          </a>
    
          <a href="#counting-sort " class = "word">
            <strong>Counting sort</strong> 
          </a>
    
          <a href="#radix-sort " class = "word">
            <strong>Radix sort</strong> 
          </a>
    
          <a href="#bucket-sort " class = "word">
            <strong>Bucket sort</strong> 
          </a>
    
          <a href="#array-sort " class = "word">
            <strong>Array sort</strong> 
          </a>
    
          <a href="#list-sort " class = "word">
            <strong>List sort</strong> 
          </a>
    
          <a href="#image-url " class = "word">
            <strong>Image Url</strong> 
          </a>
    
          <a href="#flipping " class = "word">
            <strong>Flipping</strong> 
          </a>
    
          <a href="#reverse " class = "word">
            <strong>Reverse</strong> 
          </a>
    
          <a href="#move-zero " class = "word">
            <strong>Move zero</strong> 
          </a>
    
          <a href="#odd " class = "word">
            <strong>Odd</strong> 
          </a>
    
          <a href="#even " class = "word">
            <strong>Even</strong> 
          </a>
    
          <a href="#chrome " class = "word">
            <strong>Chrome</strong> 
          </a>
    
          <a href="#devtools " class = "word">
            <strong>DevTools</strong> 
          </a>
    
          <a href="#wordcloud " class = "word">
            <strong>Wordcloud</strong> 
          </a>
    
          <a href="#script " class = "word">
            <strong>Script</strong> 
          </a>
    
          <a href="#popup " class = "word">
            <strong>Popup</strong> 
          </a>
    
          <a href="#error-handling " class = "word">
            <strong>error-handling</strong> 
          </a>
    
          <a href="#comfirmation-email " class = "word">
            <strong>comfirmation-email</strong> 
          </a>
    
          <a href="#recover-email " class = "word">
            <strong>recover-email</strong> 
          </a>
    
          <a href="#carousel " class = "word">
            <strong>carousel</strong> 
          </a>
    
          <a href="#video " class = "word">
            <strong>video</strong> 
          </a>
    
          <a href="#callback " class = "word">
            <strong>Callback</strong> 
          </a>
    
          <a href="#call-stack " class = "word">
            <strong>Call_stack</strong> 
          </a>
    
          <a href="#web-apis " class = "word">
            <strong>Web_APIs</strong> 
          </a>
    
          <a href="#callback-queue " class = "word">
            <strong>Callback_Queue</strong> 
          </a>
    
          <a href="#cli " class = "word">
            <strong>CLI</strong> 
          </a>
    
          <a href="#card " class = "word">
            <strong>Card</strong> 
          </a>
    
          <a href="#map " class = "word">
            <strong>Map</strong> 
          </a>
    
</div>

css

Notice: I had set transition for every element in my blog website, so I need to set transition to none, otherwise, it may not show correctly.

#tagsList {
    position: relative;
    width: 450px;
    height: 450px;
    margin: 150px 150px 150px;
  }
   
  #tagsList a {
    position: absolute;
    top: 0px ;
    left: 0px;
    font-family: Microsoft YaHei;
    color: lightgreen;
    font-weight: bold;
    text-decoration: none;
    padding: 3px 6px;
    -webkit-transition: none !important; 
    transition: none !important;
  }
  #tagsList a:hover {
    color: #FF0000;
    letter-spacing: 2px;
  }

  @media screen and (max-width: 864px){
    #tagsList {
        display: none;
    }
}

JS

var radius = 120;
var dtr = Math.PI / 180;
var d = 300;
var mcList = [];
var active = false;
var lasta = 1;
var lastb = 1;
var distr = true;
var tspeed = 10;
var size = 250;
 
var mouseX = 0;
var mouseY = 0;
 
var howElliptical = 1;
 
var aA = null;
var oDiv = null;
 
window.onload = function () {
  var i = 0;
  var oTag = null;
 
  oDiv = document.getElementById('tagsList');
  aA = oDiv.getElementsByClassName('word');
 
  for (i = 0; i < aA.length; i++) {
    oTag = {};
    oTag.offsetWidth = aA[i].offsetWidth;
    oTag.offsetHeight = aA[i].offsetHeight;
    mcList.push(oTag);
  }
 
  sineCosine(0, 0, 0);
 
  positionAll();
 
  oDiv.onmouseover = function () {
    active = true;
  };
 
  oDiv.onmouseout = function () {
    active = false;
  };
 
  oDiv.onmousemove = function (ev) {
    var oEvent = window.event || ev;
    mouseX = oEvent.clientX - (oDiv.offsetLeft + oDiv.offsetWidth / 2);
    mouseY = oEvent.clientY - (oDiv.offsetTop + oDiv.offsetHeight / 2);
    //console.log("event: "+oDiv.offsetTop+" mouse:"+oDiv.offsetHeight);
    mouseX /= 5;
    mouseY /= 5;
  };
  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) {
    return;
  }
 
  var c = 0;
  sineCosine(a, b, c);
  for (var j = 0; j < mcList.length; j++) {
    var rx1 = mcList[j].cx;
    var ry1 = mcList[j].cy * ca + mcList[j].cz * (-sa);
    var rz1 = mcList[j].cy * sa + mcList[j].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[j].cx = rx3;
    mcList[j].cy = ry3;
    mcList[j].cz = rz3;
 
    per = d / (d + rz3);
 
    mcList[j].x = (howElliptical * rx3 * per) - (howElliptical * 2);
    mcList[j].y = ry3 * per;
    mcList[j].scale = per;
    mcList[j].alpha = per;
 
    mcList[j].alpha = (mcList[j].alpha - 0.6) * (10 / 6);
  }
 
  doPosition();
  depthSort();
}
 
function depthSort() {
  var i = 0;
  var aTmp = [];
 
  for (i = 0; i < aA.length; i++) {
    aTmp.push(aA[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 i = 0;
 
  var aTmp = [];
  var oFragment = document.createDocumentFragment();
 
  //sort order
  for (i = 0; i < aA.length; i++) {
    aTmp.push(aA[i]);
  }
 
  aTmp.sort(function () {
    return Math.random() < 0.5 ? 1 : -1;
  });
  for (i = 0; i < aTmp.length; i++) {
    oFragment.appendChild(aTmp[i]);
  }
  oDiv.appendChild(oFragment);
  for (var i = 1; i < max + 1; i++) {
    if (distr) {
      phi = Math.acos(-1 + (2 * i - 1) / max);
      theta = Math.sqrt(max * Math.PI) * phi;
    }
    else {
      phi = Math.random() * (Math.PI);
      theta = Math.random() * (2 * Math.PI);
    }
    //change position
    mcList[i - 1].cx = radius * Math.cos(theta) * Math.sin(phi);
    mcList[i - 1].cy = radius * Math.sin(theta) * Math.sin(phi);
    mcList[i - 1].cz = radius * Math.cos(phi);
 
    aA[i - 1].style.left=mcList[i - 1].cx+oDiv.offsetWidth /2-mcList[i - 1].offsetWidth/2+'px';
    aA[i - 1].style.top=mcList[i - 1].cy+oDiv.offsetHeight/2-mcList[i - 1].offsetHeight/2+'px';
  }
}
function doPosition() {
  var l = oDiv.offsetWidth / 2;
  var t = oDiv.offsetHeight / 2;
  for (var i = 0; i < mcList.length; i++) {
    aA[i].style.left = mcList[i].cx + l - mcList[i].offsetWidth / 2 + 'px';
    aA[i].style.top = mcList[i].cy + t - mcList[i].offsetHeight / 2 + 'px';
 
    aA[i].style.fontSize = Math.ceil(12 * mcList[i].scale / 2) + 8 + 'px';
 
    aA[i].style.filter = "alpha(opacity=" + 100 * mcList[i].alpha + ")";
    aA[i].style.opacity = mcList[i].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);
}