vue:
<!DOCTYPE html>
<html>
<head>
<title>svg3D标签云</title>
<script src="https://cdn.bootcss.com/vue/2.2.0/vue.min.js"></script>
</head>
<body>
<div id='app' >
<svg :width='width' :height='height' @mousemove='listener($event)'>
<a :href="tag.href" v-for='tag in tags'>
<text :x='tag.x' :y='tag.y' :font-size='20 * (600/(600-tag.z))' :fill-opacity='((400+tag.z)/600)'>{{tag.text}}</text>
</a>
</svg>
</div>
<script>
var app = new Vue({
el: '#app',
data: {
width:700,
height:700,
tagsNum:20,
RADIUS:200,
speedX:Math.PI/360,
speedY:Math.PI/360,
tags: [],
colors:[],
},
computed:{
CX(){
return this.width/2;
},
CY(){
return this.height/2;
}
},
created(){
this.changeColors();
//初始化标签位置
let tags=[];
for(let i = 0; i < this.tagsNum; i++){
let tag = {};
let k = -1 + (2 * (i + 1) - 1) / this.tagsNum;
let a = Math.acos(k);
let b = a * Math.sqrt(this.tagsNum * Math.PI)
tag.text = i + 'tag';
tag.x = this.CX + this.RADIUS * Math.sin(a) * Math.cos(b);
tag.y = this.CY + this.RADIUS * Math.sin(a) * Math.sin(b);
tag.z = this.RADIUS * Math.cos(a);
tag.href = 'https://imgss.github.io'
tags.push(tag)
}
this.tags = tags;
},
mounted(){//使球开始旋转
setInterval(()=>{
this.rotateX(this.speedX);
this.rotateY(this.speedY);
}, 17)
},
methods:{
rotateX(speedX){
var cos = Math.cos(speedX);
var sin = Math.sin(speedX);
for(let tag of this.tags){
var y1 = (tag.y- this.CY) * cos - tag.z * sin + this.CY;
var z1 = tag.z * cos + (tag.y- this.CY) * sin;
tag.y = y1;
tag.z = z1;
}
},
rotateY(speedY){
var cos = Math.cos(speedY);
var sin = Math.sin(speedY);
for(let tag of this.tags){
var x1 = (tag.x - this.CX) * cos - tag.z * sin + this.CX;
var z1 = tag.z * cos + (tag.x - this.CX) * sin;
tag.x = x1;
tag.z = z1;
}
},
listener(event){//响应鼠标移动
var x = event.clientX - this.CX;
var y = event.clientY - this.CY;
this.speedX = x*0.0001>0 ? Math.min(this.RADIUS*0.00002, x*0.0001) : Math.max(-this.RADIUS*0.00002, x*0.0001);
this.speedY = y*0.0001>0 ? Math.min(this.RADIUS*0.00002, y*0.0001) : Math.max(-this.RADIUS*0.00002, y*0.0001);
},
changeColors(){
for(var i = 0;i<30;i++){
var r = Math.floor(Math.random() * 256);
var g = Math.floor(Math.random() * 256);
var b = Math.floor(Math.random() * 256);
this.colors[i] = "rgb(" + r + ',' + g + ',' + b + ")";
}
},
}
})
</script>
</body>
</html>
no vue:
<!DOCTYPE html>
<html>
<head>
<title>svg3D标签云</title>
</head>
<body>
<svg width='700' height='700'>
<a href="https://www.baidu.com">
<text x='10' y='12'>1222</text>
</a>
<text x='100' y='120'>weed</text>
<text x='120' y='152'>sdcc</text>
<text x='160' y='222'>dfdf</text>
<text x='60' y='92'>vbbb</text>
<text x='160' y='300'>evvv</text>
<text x='290' y='400'>hhhh</text>
<text x='633' y='300'>wrgg</text>
<text x='400' y='500'>ohhh</text>
<text x='320' y='400'>qvbn</text>
<text x='480' y='200'>rvbj</text>
<text x='303' y='120'>eghj</text>
<text x='100' y='120'>weed</text>
<text x='120' y='152'>sdcc</text>
<text x='160' y='222'>dfdf</text>
<text x='60' y='92'>vbbb</text>
<text x='160' y='300'>evvv</text>
<text x='290' y='400'>hhhh</text>
<text x='633' y='300'>wrgg</text>
<text x='400' y='500'>ohhh</text>
<text x='320' y='400'>qvbn</text>
<text x='480' y='200'>rvbj</text>
<text x='303' y='120'>eghj</text>
</svg>
<script>
var paper = document.querySelector("svg");//svg
tags = document.querySelectorAll('svg text');
RADIUS =200,
FONTSIZE = RADIUS*0.1,
fallLength = 600,//焦距
tagArr=[],
angleX = Math.PI/300,
angleY = Math.PI/300,
CX = paper.getAttribute('width')/2,//球心坐标
CY = paper.getAttribute('height')/2;//球心坐标
function Tag(ele , x , y , z){
this.ele = ele;
this.x = x;
this.y = y;
this.z = z;
}
function init(){
var len = tags.length
for(var i=0;i<len;i++){
var a , b;
var k = -1+(2*(i+1)-1)/len;
var a = Math.acos(k);
var b = a*Math.sqrt(len*Math.PI);
// var a = Math.random()*2*Math.PI;
// var b = Math.random()*2*Math.PI;
var x =CX + RADIUS * Math.sin(a) * Math.cos(b);
var y =CY + RADIUS * Math.sin(a) * Math.sin(b);
var z = RADIUS * Math.cos(a);
var t = new Tag(tags[i] , x , y , z);
tags[i].setAttribute('x',x);
tags[i].setAttribute('y',y);
tags[i].setAttribute('font-size', FONTSIZE * (fallLength/(fallLength-this.z)));
tags[i].setAttribute('fill', "rgb("+parseInt(Math.random()*255)+","+parseInt(Math.random()*255)+","+parseInt(Math.random()*255)+")")
tagArr.push(t);
}
}
Array.prototype.forEach = function(callback){
for(var i=0;i<this.length;i++){
callback.call(this[i]);
}
}
function animate(){
setInterval(function(){
// angleY += Math.PI/300;
// angleY = angleX>Math.PI? 0 : angleX
rotateX();
rotateY();
} , 17);
}
function rotateX(){
var cos = Math.cos(angleX);
var sin = Math.sin(angleX);
tagArr.forEach(function(){
var y1 = (this.y-CY) * cos - this.z * sin +CY;
var z1 = this.z * cos + (this.y-CY) * sin;
this.y = y1;
this.z = z1;
this.ele.setAttribute('y',this.y)
this.ele.setAttribute('font-size', FONTSIZE * (fallLength/(fallLength-this.z)));
})
}
function rotateY(){
var cos = Math.cos(angleY);
var sin = Math.sin(angleY);
tagArr.forEach(function(){
var x1 = (this.x-CX) * cos - this.z * sin +CX;
var z1 = this.z * cos + (this.x-CX) * sin;
this.x = x1;
this.z = z1;
this.ele.setAttribute('x',this.x)
this.ele.setAttribute('font-size', FONTSIZE * (fallLength/(fallLength-this.z)));
})
}
paper.addEventListener("mousemove" , function(event){
var x = event.clientX - CX;
var y = event.clientY - CY;
// angleY = -x* (Math.sqrt(Math.pow(x , 2) + Math.pow(y , 2)) > RADIUS/4 ? 0.0002 : 0.0001);
// angleX = -y* (Math.sqrt(Math.pow(x , 2) + Math.pow(y , 2)) > RADIUS/4 ? 0.0002 : 0.0001);
angleY = x*0.0001>0 ? Math.min(RADIUS*0.00002,x*0.0001) : Math.max(-RADIUS*0.00002,x*0.0001);
angleX = y*0.0001>0 ? Math.min(RADIUS*0.00002,y*0.0001) : Math.max(-RADIUS*0.00002,y*0.0001);
});
init();
animate();
</script>
</body>
</html>
canvas:
https://github.com/goat1000/TagCanvas
原理:
https://www.cnblogs.com/axes/p/3501424.html
参考:
https://github.com/imgss/imgss.github.io/tree/master/demo/svg