原生JS实现3D彩色标签云(Typecho插件)

2020-02-02T22:54:00

看到emlog的3d彩色标签云后,瞬间觉得typecho标签云不够上档次,于是参考emlog 3d标签云开始修改.
这里以handsome主题为例。

handsome主题彩色效果

对于handsome主题,只要在自定义 CSS 里添加:

#tag_cloud-2>div>a {
    color: #fff;
    text-align: center;
    text-overflow: ellipsis;
    white-space: nowrap;
    padding: 3px 5px;
    border: 0;
    border-radius: 3px;
    display: inline-block;
    line-height: 18px;
}

#tag_cloud-2>div>a:hover {
    background: #d02f53;
}

接着在后台自定义 JS 里加上:

function colorfultags(){
let tags = document.querySelectorAll("#tag_cloud-2 a");
let colorArr = ["#f60", "#45B6F7", "#15a287", "#5cb85c", "#d9534f", "#567e95", "#00a67c", "#b37333"];
let count = 1;
tags.forEach(tag => {
    tagsColor = colorArr[count%8];
    tag.style.backgroundColor = tagsColor;
    count++;
});
}
window.onload=colorfultags();

这样就完成了彩色效果。

3D效果

接下来通过自定义实现3d效果

自定义 CSS :

#tag_cloud-2>div {
    position: relative;
    width: 240px;
    height: 240px;
    border: 2px black;
    margin: 0 10px 15px 0
}
#tag_cloud-2>div>a {
    position: absolute;
}

#tag_cloud-2>div>a:hover {
    display: block
}

自定义 JS(前面的参数可以自己调):

function around3D() {
  var oDiv = document.getElementById('tag_cloud-2').getElementsByTagName('div')[0];
  if (null == oDiv) {
    return
  } else {
    var radius = 80;
    var d = 200;
    var dtr = Math.PI / 180;
    var mcList = [];
    var lasta = 1;
    var lastb = 1;
    var distr = true;
    var tspeed = 11;
    var size = 200;
    var mouseX = 0;
    var mouseY = 10;
    var howElliptical = 1;
    var aA = null;
    var i = 0;
    var oTag = null;
    aA = oDiv.getElementsByTagName('a');
    for (i = 0; i < aA.length; i++) {
      oTag = {};
      aA[i].onmouseover = (function(obj) {
        return function() {
          obj.on = true;
          this.style.zIndex = 9999;
          this.style.color = '#fff';
          this.style.background = '#0099ff';
          this.style.padding = '5px 5px';
          this.style.filter = "alpha(opacity=100)";
          this.style.opacity = 1;
        }
      })(oTag)
      aA[i].onmouseout = (function(obj) {
        return function() {
          obj.on = false;
          this.style.zIndex = obj.zIndex;
          this.style.color = '#fff';
          this.style.background = '#30899B';
          this.style.padding = '5px';
          this.style.filter = "alpha(opacity=" + 100 * obj.alpha + ")";
          this.style.opacity = obj.alpha;
          this.style.zIndex = obj.zIndex;
        }
      })(oTag)
      oTag.offsetWidth = aA[i].offsetWidth;
      oTag.offsetHeight = aA[i].offsetHeight;
      mcList.push(oTag);
    }
    sineCosine(0, 0, 0);
    positionAll();
    (function() {
      update();
      setTimeout(arguments.callee, 40);
    })();

    function update() {
      var a, b, c = 0;
      a = (Math.min(Math.max(-mouseY, -size), size) / radius) * tspeed;
      b = (-Math.min(Math.max(-mouseX, -size), size) / radius) * tspeed;
      lasta = a;
      lastb = b;
      if (Math.abs(a) <= 0.01 && Math.abs(b) <= 0.01) {
        return;
      }
      sineCosine(a, b, c);
      for (var i = 0; i < mcList.length; i++) {
        if (mcList[i].on) {
          continue;
        }
        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;

        per = d / (d + rz3);

        mcList[i].x = (howElliptical * rx3 * per) - (howElliptical * 2);
        mcList[i].y = ry3 * per;
        mcList[i].scale = per;
        var alpha = per;
        alpha = (alpha - 0.6) * (10 / 6);
        mcList[i].alpha = alpha * alpha * alpha - 0.2;
        mcList[i].zIndex = Math.ceil(100 - Math.floor(mcList[i].cz));
      }
      doPosition();
    }

    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;
      for (var i = 0; i < max; i++) {
        if (distr) {
          phi = Math.acos(-1 + (2 * (i + 1) - 1) / max);
          theta = Math.sqrt(max * Math.PI) * phi;
        } else {
          phi = Math.random() * (Math.PI);
          theta = Math.random() * (2 * Math.PI);
        }

        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);

        aA[i].style.left = mcList[i].cx + oDiv.offsetWidth / 2 - mcList[i].offsetWidth / 2 + 'px';
        aA[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++) {
        if (mcList[i].on) {
          continue;
        }
        var aAs = aA[i].style;
        if (mcList[i].alpha > 0.1) {
          if (aAs.display != '')
            aAs.display = '';
        } else {
          if (aAs.display != 'none')
            aAs.display = 'none';
          continue;
        }
        aAs.left = mcList[i].cx + l - mcList[i].offsetWidth / 2 + 'px';
        aAs.top = mcList[i].cy + t - mcList[i].offsetHeight / 2 + 'px';
        
        aAs.filter = "alpha(opacity=" + 100 * mcList[i].alpha + ")";
        aAs.zIndex = mcList[i].zIndex;
        aAs.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);
    }
  }
}
window.onload = around3D();

这里我把emlog的js复制下来,然后修改了下元素定位并进行了简单的封装。同样只要把这段js加到自定义js里就行了。

pjax版(以handsome主题为例)

css 部分不变
自定义 js:

function colorfultags(){
let tags = document.querySelectorAll("#tag_cloud-2 a");
let colorArr = ["#f60", "#45B6F7", "#15a287", "#5cb85c", "#d9534f", "#567e95", "#00a67c", "#b37333"];
let count = 1;
tags.forEach(tag => {
    tagsColor = colorArr[count%8];
    tag.style.backgroundColor = tagsColor;
    count++;
});
}
function around3D() {
  var oDiv = document.getElementById('tag_cloud-2').getElementsByTagName('div')[0];
  if (null == oDiv) {
    return
  } else {
    var radius = 80;
    var d = 200;
    var dtr = Math.PI / 180;
    var mcList = [];
    var lasta = 1;
    var lastb = 1;
    var distr = true;
    var tspeed = 11;
    var size = 200;
    var mouseX = 0;
    var mouseY = 10;
    var howElliptical = 1;
    var aA = null;
    var i = 0;
    var oTag = null;
    aA = oDiv.getElementsByTagName('a');
    for (i = 0; i < aA.length; i++) {
      oTag = {};
      aA[i].onmouseover = (function(obj) {
        return function() {
          obj.on = true;
          this.style.zIndex = 9999;
          this.style.color = '#fff';
          this.style.background = '#0099ff';
          this.style.padding = '5px 5px';
          this.style.filter = "alpha(opacity=100)";
          this.style.opacity = 1;
        }
      })(oTag)
      aA[i].onmouseout = (function(obj) {
        return function() {
          obj.on = false;
          this.style.zIndex = obj.zIndex;
          this.style.color = '#fff';
          this.style.background = '#30899B';
          this.style.padding = '5px';
          this.style.filter = "alpha(opacity=" + 100 * obj.alpha + ")";
          this.style.opacity = obj.alpha;
          this.style.zIndex = obj.zIndex;
        }
      })(oTag)
      oTag.offsetWidth = aA[i].offsetWidth;
      oTag.offsetHeight = aA[i].offsetHeight;
      mcList.push(oTag);
    }
    sineCosine(0, 0, 0);
    positionAll();
    (function() {
      update();
      setTimeout(arguments.callee, 40);
    })();

    function update() {
      var a, b, c = 0;
      a = (Math.min(Math.max(-mouseY, -size), size) / radius) * tspeed;
      b = (-Math.min(Math.max(-mouseX, -size), size) / radius) * tspeed;
      lasta = a;
      lastb = b;
      if (Math.abs(a) <= 0.01 && Math.abs(b) <= 0.01) {
        return;
      }
      sineCosine(a, b, c);
      for (var i = 0; i < mcList.length; i++) {
        if (mcList[i].on) {
          continue;
        }
        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;

        per = d / (d + rz3);

        mcList[i].x = (howElliptical * rx3 * per) - (howElliptical * 2);
        mcList[i].y = ry3 * per;
        mcList[i].scale = per;
        var alpha = per;
        alpha = (alpha - 0.6) * (10 / 6);
        mcList[i].alpha = alpha * alpha * alpha - 0.2;
        mcList[i].zIndex = Math.ceil(100 - Math.floor(mcList[i].cz));
      }
      doPosition();
    }

    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;
      for (var i = 0; i < max; i++) {
        if (distr) {
          phi = Math.acos(-1 + (2 * (i + 1) - 1) / max);
          theta = Math.sqrt(max * Math.PI) * phi;
        } else {
          phi = Math.random() * (Math.PI);
          theta = Math.random() * (2 * Math.PI);
        }

        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);

        aA[i].style.left = mcList[i].cx + oDiv.offsetWidth / 2 - mcList[i].offsetWidth / 2 + 'px';
        aA[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++) {
        if (mcList[i].on) {
          continue;
        }
        var aAs = aA[i].style;
        if (mcList[i].alpha > 0.1) {
          if (aAs.display != '')
            aAs.display = '';
        } else {
          if (aAs.display != 'none')
            aAs.display = 'none';
          continue;
        }
        aAs.left = mcList[i].cx + l - mcList[i].offsetWidth / 2 + 'px';
        aAs.top = mcList[i].cy + t - mcList[i].offsetHeight / 2 + 'px';

        aAs.filter = "alpha(opacity=" + 100 * mcList[i].alpha + ")";
        aAs.zIndex = mcList[i].zIndex;
        aAs.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);
    }
  }
}

在pjax回调函数里添加

colorfultags();
around3D();

食用方法

[tabs]
[tab name="通用版本" active="true"]
1.解压后重命名为ColorfulTags文件
2.在插件设置中设置标签云容器CSS选择器

[/tab]
[tab name="HandSame版本"]
1.解压后重命名为ColorfulTags文件,到后台根据需要完成设置即可

[/tab]
[/tabs]

[scode type='yellow']如果主题开启了pjax(即页面跳转时插件失效),请在后台插件设置中将是否开启pjax改为是。[/scode]

插件地址

[tabs]
[tab name="通用版本" active="true"]
Github地址:
https://github.com/invelop/Typecho-ColorfulTags

码云地址:
https://gitee.com/ETAS/Typecho-ColorfulTags
[/tab]
[tab name="Handsome专用"]
Github地址:
https://github.com/invelop/Typecho-ColorfulTags-For-Handsome

码云地址:
https://gitee.com/ETAS/Typecho-ColorfulTags-For-Handsome
[/tab]
[/tabs]

当前页面是本站的「Baidu MIP」版。发表评论请点击:完整版 »