Preview: Code: <template> <div class="tagcloud-all" ref="tagcloudall"> <a v-for="item in tagList" :href="item.url" rel="external nofollow" :style="'color:' + item.color + ';top: 0;left: 0;filter:none;'">{{item.name}}</a> </div> </template> CSS part: // Tag cloud.tagcloud-all { position: relative; a { position: absolute; top: 0px; left: 0px; color: #fff; font-weight: bold; text-decoration: none; padding: 3px 6px; &:hover { color: #FF0000; letter-spacing: 2px; } } } JS part: export default { name: "tagcloud", data() { return { tagList: [], radius: 120, dtr: Math.PI / 180, d: 300, mcList: [], active: false, lasta: 1, lastb: 1, distr: true, tspeed: 10, size: 250, mouseX: 0, mouseY: 0, howElliptical: 1, oList: null, oA: null, sa: 0, ca: 0, sb: 0, cb: 0, sc: 0, cc: 0 } }, methods: { // Generate a random number getRandomNum() { return Math.floor(Math.random() * (255 + 1)); }, // Trigonometric function angle calculation sineCosine(a, b, c) { this.sa = Math.sin(a * this.dtr); this.ca = Math.cos(a * this.dtr); this.sb = Math.sin(b * this.dtr); this.cb = Math.cos(b * this.dtr); this.sc = Math.sin(c * this.dtr); this.cc = Math.cos(c * this.dtr); }, // Set the initial position positionAll() { this.$nextTick(() => { // Note: All methods executed in the onReady method require $nextTick to ensure that all labels have been rendered var phi = 0; var theta = 0; var max = this.mcList.length; var aTmp = []; var oFragment = document.createDocumentFragment(); // Random sort for (let i = 0; i < this.tagList.length; i++) { aTmp.push(this.oA[i]); } aTmp.sort(() => { return Math.random() < 0.5 ? 1 : -1; }); for (let i = 0; i < aTmp.length; i++) { oFragment.appendChild(aTmp[i]); } this.oList.appendChild(oFragment); for (let i = 1; i < max + 1; i++) { if (this.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); } // Coordinate transformation this.mcList[i - 1].cx = this.radius * Math.cos(theta) * Math.sin(phi); this.mcList[i - 1].cy = this.radius * Math.sin(theta) * Math.sin(phi); this.mcList[i - 1].cz = this.radius * Math.cos(phi); this.oA[i - 1].style.left = this.mcList[i - 1].cx + this.oList.offsetWidth / 2 - this.mcList[i - 1].offsetWidth / 2 + 'px'; this.oA[i - 1].style.top = this.mcList[i - 1].cy + this.oList.offsetHeight / 2 - this.mcList[i - 1].offsetHeight / 2 + 'px'; } }) }, // Update the coordinates to make the label move update() { this.$nextTick(() => { // Note: All methods executed in the onReady method require $nextTick to ensure that all labels have been rendered var a; var b; if (this.active) { a = (-Math.min(Math.max(-this.mouseY, -this.size), this.size) / this.radius) * this.tspeed; b = (Math.min(Math.max(-this.mouseX, -this.size), this.size) / this.radius) * this.tspeed; } else { a = this.lasta * 0.98; b = this.lastb * 0.98; } this.lasta = a; this.lastb = b; if (Math.abs(a) <= 0.01 && Math.abs(b) <= 0.01) { return } var c = 0; this.sineCosine(a, b, c); for (var j = 0; j < this.mcList.length; j++) { var rx1 = this.mcList[j].cx; var ry1 = this.mcList[j].cy * this.ca + this.mcList[j].cz * (-this.sa); var rz1 = this.mcList[j].cy * this.sa + this.mcList[j].cz * this.ca; var rx2 = rx1 * this.cb + rz1 * this.sb; var ry2 = ry1; var rz2 = rx1 * (-this.sb) + rz1 * this.cb; var rx3 = rx2 * this.cc + ry2 * (-this.sc); var ry3 = rx2 * this.sc + ry2 * this.cc; var rz3 = rz2; this.mcList[j].cx = rx3; this.mcList[j].cy = ry3; this.mcList[j].cz = rz3; var per = this.d / (this.d + rz3); this.mcList[j].x = (this.howElliptical * rx3 * per) - (this.howElliptical * 2); this.mcList[j].y = ry3 * per; this.mcList[j].scale = per; this.mcList[j].alpha = per; this.mcList[j].alpha = (this.mcList[j].alpha - 0.6) * (10 / 6); } this.doPosition(); this.depthSort(); }) }, // doPosition() { this.$nextTick(() => { // Note: All methods executed in the onReady method require $nextTick to ensure that all labels have been rendered var l = this.oList.offsetWidth / 2; var t = this.oList.offsetHeight / 2; for (var i = 0; i < this.mcList.length; i++) { this.oA[i].style.left = this.mcList[i].cx + l - this.mcList[i].offsetWidth / 2 + 'px'; this.oA[i].style.top = this.mcList[i].cy + t - this.mcList[i].offsetHeight / 2 + 'px'; this.oA[i].style.fontSize = Math.ceil(12 * this.mcList[i].scale / 2) + 8 + 'px'; // this.oA[i].style.filter = "alpha(opacity=" + 100 * this.mcList[i].alpha + ")"; this.oA[i].style.opacity = this.mcList[i].alpha; } }) }, // depthSort() { this.$nextTick(() => { // Note: All methods executed in the onReady method require $nextTick to ensure that all labels have been rendered var aTmp = []; for (let i = 0; i < this.oA.length; i++) { aTmp.push(this.oA[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 (let i = 0; i < aTmp.length; i++) { aTmp[i].style.zIndex = i; } }) }, // Network request to get tagList query() { // Pretend to get the data from the interface let tagListOrg = [ { name: 'Label 1', url: 'www.baidu.com' }, { name: 'Label 2', url: 'www.baidu.com' }, { name: 'Tag 3', url: 'www.baidu.com' }, { name: 'Label 4', url: 'www.baidu.com' }, { name: 'Tag 5', url: 'www.baidu.com' }, { name: 'Tag 6', url: 'www.baidu.com' }, { name: 'Tag 7', url: 'www.baidu.com' }, { name: 'Label 8', url: 'www.baidu.com' }, { name: 'Tag 9', url: 'www.baidu.com' }, { name: 'Label 10', url: 'www.baidu.com' }, { name: 'Label 11', url: 'www.baidu.com' }, { name: 'Label 12', url: 'www.baidu.com' }, { name: 'Tag 13', url: 'www.baidu.com' }, { name: 'Tag 14', url: 'www.baidu.com' }, { name: 'Tag 15', url: 'www.baidu.com' }, { name: 'Tag 16', url: 'www.baidu.com' }, { name: 'Tag 16', url: 'www.baidu.com' }, { name: 'Tag 16', url: 'www.baidu.com' }, { name: 'Tag 16', url: 'www.baidu.com' }, { name: 'Tag 16', url: 'www.baidu.com' }, { name: 'Tag 16', url: 'www.baidu.com' }, { name: 'Tag 16', url: 'www.baidu.com' }, { name: 'Tag 16', url: 'www.baidu.com' }, { name: 'Tag 16', url: 'www.baidu.com' }, { name: 'Tag 16', url: 'www.baidu.com' }, { name: 'Tag 16', url: 'www.baidu.com' }, { name: 'Tag 16', url: 'www.baidu.com' }, { name: 'Tag 16', url: 'www.baidu.com' }, { name: 'Tag 16', url: 'www.baidu.com' }, { name: 'Tag 17', url: 'www.baidu.com' } ]; // Add random colors to tagListtagListOrg.forEach(item => { item.color = "rgb(" + this.getRandomNum() + "," + this.getRandomNum() + "," + this.getRandomNum() + ")"; }) this.tagList = tagListOrg; this.onReady(); }, // Generate tag cloud onReady() { this.$nextTick(() => { this.oList = this.$refs.tagcloudall; this.oA = this.oList.getElementsByTagName('a') var oTag = null; for (var i = 0; i < this.oA.length; i++) { oTag = {}; oTag.offsetWidth = this.oA[i].offsetWidth; oTag.offsetHeight = this.oA[i].offsetHeight; this.mcList.push(oTag); } this.sineCosine(0, 0, 0); this.positionAll(); this.oList.onmouseover = () => { this.active = true; } this.oList.onmouseout = () => { this.active = false; } this.oList.onmousemove = (event) => { var oEvent = window.event || event; this.mouseX = oEvent.clientX - (this.oList.offsetLeft + this.oList.offsetWidth / 2); this.mouseY = oEvent.clientY - (this.oList.offsetTop + this.oList.offsetHeight / 2); this.mouseX /= 5; this.mouseY /= 5; } setInterval(() => { this.update() }, 30); // Timer execution cannot write setInterval(this.update(), 30) }) } }, created() { this.$nextTick(() => { this.query(); }) } } This is the end of this article about implementing 3D tag cloud in Vue. For more relevant Vue 3D tag cloud content, please search 123WORDPRESS.COM's previous articles or continue to browse the following related articles. I hope everyone will support 123WORDPRESS.COM in the future! You may also be interested in:
|
<<: How to install MySQL 8.0 in Docker
>>: Optimization analysis of Limit query in MySQL optimization techniques
This article shares the specific code of JavaScri...
Prelude We all know that nginx is an excellent re...
By default, the MyISAM table will generate three ...
Preface We all know that the import and export of...
Nginx is now one of the most popular load balance...
<br />Structure and hierarchy reduce complex...
Table of contents 1. Use the uuid function to gen...
Overview There are many form requirements in the ...
Preface: I have often heard about database paradi...
This week has been as busy as a war. I feel like ...
sftp is the abbreviation of Secure File Transfer ...
Effect If you use it, please optimize the code an...
Flex Layout Flex is the abbreviation of Flexible ...
1. Introduction By enabling the slow query log, M...
Table of contents Install Tomcat Download Tomcat ...