效果图:
highcharts也提供了类似的词云的效果(但效果是静态的),附上链接: www.hcharts.cn/demo/highch…
vue代码:
<div class="helix-tag-cloud">
<!-- 绘制螺旋线 -->
<div id="helix-wrap">
<canvas id="myCanvas" width="700" height="700"></canvas>
</div>
<!-- 绘制词云 -->
<div class="tagBall" ref="tagBall">
<p v-for="(item, index) in tagList" :key="index" class="tag">
{{ item }}
</p>
</div>
</div>
js代码:
<script>
export default {
components: {},
props: {},
data() {
return {
// 螺旋线
canvas: '',
context: {},
// 词云
tagEle: '',
paper: '',
RADIUS: 150,
fallLength: 500,
tags: [],
angleX: Math.PI / 500,
angleY: Math.PI / 500,
CX: '',
CY: '',
EX: '',
EY: '',
timing: null,
tagList: [
'11111',
'222',
'33333',
'444444444444',
'55',
'666',
'777',
'ggg',
'55353',
'hhgs',
'jjj',
'jsnn',
'i77kdt',
'2htsjnn',
'kddf67',
'kl888888osv',
'aqvvsr',
'wgnre55',
'667utgh',
'k56e4rgg',
],
};
},
computed: {},
watch: {},
created() {},
mounted() {
// 螺旋线
this.canvas = document.getElementById('myCanvas');
this.context = this.canvas.getContext('2d');
this.initCanvas();
// 词云
this.tagEle = this.$refs.tagBall.children;
this.paper = this.$refs.tagBall;
this.CX = this.paper.offsetWidth / 2;
this.CY = this.paper.offsetHeight / 2;
this.EX =
this.paper.offsetLeft +
document.body.scrollLeft +
document.documentElement.scrollLeft;
this.EY =
this.paper.offsetTop +
document.body.scrollTop +
document.documentElement.scrollTop;
this.innit();
this.animate();
},
methods: {
initCanvas() {
let radius = 0;
let angle = 0;
this.context.lineWidth = 3;
this.context.strokeStyle = 'rgba(0, 150, 255,0.2)';
this.context.beginPath();
this.context.moveTo(this.canvas.width / 2, this.canvas.height / 2);
for (var n = 0; n < 150; n++) {
radius += 2.15;
angle += (Math.PI * 2) / 50;
var x = this.canvas.width / 2 + radius * Math.cos(angle);
var y = this.canvas.height / 2 + radius * Math.sin(angle);
this.context.lineTo(x, y);
}
this.context.stroke();
},
innit() {
for (var i = 0; i < this.tagEle.length; i++) {
var a, b;
var k = (2 * (i + 1) - 1) / this.tagEle.length - 1;
var a = Math.acos(k);
var b = a * Math.sqrt(this.tagEle.length * Math.PI);
var x = this.RADIUS * Math.sin(a) * Math.cos(b);
var y = this.RADIUS * Math.sin(a) * Math.sin(b);
var z = this.RADIUS * Math.cos(a);
// var t = this.tag({ ele: this.tagEle[i], x, y, z });
this.tagEle[i].style.color =
'rgb(' +
parseInt(Math.random() * 255) +
',' +
parseInt(Math.random() * 255) +
',' +
parseInt(Math.random() * 255) +
')';
this.tags.push({ ele: this.tagEle[i], x, y, z });
}
},
tag({ ele, x, y, z }) {
var scale = this.fallLength / (this.fallLength - z);
var alpha = (z + this.RADIUS) / (2 * this.RADIUS);
ele.style.fontSize = 20 * scale + 'px';
ele.style.opacity = alpha + 0.5;
ele.style.filter = 'alpha(opacity = ' + (alpha + 0.5) * 100 + ')';
ele.style.zIndex = parseInt(scale * 100);
ele.style.left = x + this.CX - ele.offsetWidth / 2 + 'px';
ele.style.top = y + this.CY - ele.offsetHeight / 2 + 'px';
},
animate() {
this.timing = setInterval(() => {
this.rotateX();
this.rotateY();
this.tags.forEach((item) => {
this.tag(item);
});
}, 20);
},
rotateX() {
var cos = Math.cos(this.angleX);
var sin = Math.sin(this.angleX);
this.tags.forEach((item) => {
var y1 = item.y * cos - item.z * sin;
var z1 = item.z * cos + item.y * sin;
item.y = y1;
item.z = z1;
});
},
rotateY() {
var cos = Math.cos(this.angleY);
var sin = Math.sin(this.angleY);
this.tags.forEach((item) => {
var x1 = item.x * cos - item.z * sin;
var z1 = item.z * cos + item.x * sin;
item.x = x1;
item.z = z1;
});
},
mouseOver(event) {
var x = event.clientX - this.EX - this.CX;
var y = event.clientY - this.EY - this.CY;
this.angleY = x * 0.0001;
this.angleX = y * 0.0001;
if (!this.timing) this.animate();
},
mouseLeave(event) {
var x = event.clientX - this.EX - this.CX;
var y = event.clientY - this.EY - this.CY;
this.angleY = x * 0.0001;
this.angleX = y * 0.0001;
},
cheMouseOver() {
clearInterval(this.timing);
this.timing = null;
},
},
};
</script>
<style scoped lang="less">
.helix-tag-cloud {
width: 70rem;
height: 70rem;
border: 1px solid;
margin: 0 auto;
display: flex;
justify-content: center;
align-items: center;
position: relative;
.tagBall {
width: 70rem;
height: 70rem;
position: absolute;
top: -5rem;
.tag {
display: block;
position: absolute;
left: 0px;
top: 0px;
color: #000;
text-decoration: none;
font-size: 1.5rem;
font-family: '微软雅黑';
font-weight: bold;
}
}
}
</style>
方法源于百度,这里记录仅供个人学习使用;如有侵权,请联系删除
2023.7.4补充: 想要实现鼠标悬浮到词云上会显示对应的气泡内容,在这里刚好又找到一篇符合该需求的文章: www.jianshu.com/p/97fd52f27… 附上git地址: github.com/zhaowhY/sam…