<!--
* @Description:会动的词云
* @Author: Vergil
* @Date: 2021-08-25 14:17:45
* @LastEditTime: 2021-08-25 17:08:15
* @LastEditors: Vergil
-->
<template>
<div class="wordCloud" ref="wordCloud">
</div>
</template>
<script>
export default {
name: 'word-cloud',
data () {
return {
hotWord: ['万事如意', '事事如意 ', '万事亨通', '一帆风顺', '万事大吉', '吉祥如意', '步步高升', '步步登高', '三羊开泰', '得心应手', '财源广进', '陶未媲美',
'阖家安康', '龙马精神', '锦绣前程', '吉祥如意', '生龙活虎', '神采奕奕', '五谷丰登', '马到成功', '飞黄腾达', ' 步步高升', '福禄寿禧'
],
color: [
'#a18cd1', '#fad0c4', '#ff8177',
'#fecfef', '#fda085', '#f5576c',
'#fe9a8b', '#30cfd0', '#38f9d7'
],
wordArr: [],
timer: null,
resetTime: 10,
ContainerSize: ''
}
},
mounted () {
this.init()
},
methods: {
init () {
this.dealSpan()
this.initWordPos()
this.render()
},
dealSpan () {
const wordArr = []
this.hotWord.forEach((value) => {
// 根据词云数量生成span数量设置字体颜色和大小
const spanDom = document.createElement('span')
spanDom.style.position = 'relative'
spanDom.style.display = 'inline-block'
spanDom.style.color = this.randomColor()
spanDom.style.fontSize = this.randomNumber(15, 30) + 'px'
spanDom.innerHTML = value
spanDom.local = {
position: {
// 位置
x: 0,
y: 0
},
direction: {
// 方向 正数往右 负数往左
x: 1,
y: 1
},
velocity: {
// 每次位移初速度
x: -0.5 + Math.random(),
y: -0.5 + Math.random()
}
}
this.$refs.wordCloud.appendChild(spanDom)
wordArr.push(spanDom)
})
this.wordArr = wordArr
},
randomColor () {
// 获取随机颜色
var colorIndex = Math.floor(this.color.length * Math.random())
return this.color[colorIndex]
},
randomNumber (lowerInteger, upperInteger) {
// 获得一个包含最小值和最大值之间的随机数。
const choices = upperInteger - lowerInteger + 1
return Math.floor(Math.random() * choices + lowerInteger)
},
render () {
if (this.resetTime < 100) {
this.resetTime = this.resetTime + 1
this.timer = requestAnimationFrame(this.render.bind(this))
// setInterval(() => {
// console.log(1)
// this.render.bind(this)
// }, 10)
this.resetTime = 0
}
this.wordFly()
},
wordFly () {
this.wordArr.forEach((value) => {
// 设置运动方向 大于边界或者小于边界的时候换方向
if (value.local.realPos.minx + value.local.position.x < this.ContainerSize.leftPos.x || value.local
.realPos.maxx + value.local.position.x > this.ContainerSize.rightPos.x) {
value.local.direction.x = -value
.local.direction.x
}
if (value.local.realPos.miny + value.local.position.y < this.ContainerSize.leftPos.y || value.local
.realPos.maxy + value.local.position.y > this.ContainerSize.rightPos.y) {
value.local.direction.y = -value
.local.direction.y
}
value.local.position.x += value.local.velocity.x * value.local.direction.x
value.local.position.y += value.local.velocity.y * value.local.direction.y
// 给每个词云加动画过渡
value.style.transform = 'translateX(' + value.local.position.x + 'px) translateY(' + value.local.position
.y + 'px)'
})
},
initWordPos () {
// 计算每个词的真实位置和容器的位置
this.wordArr.forEach((value) => {
value.local.realPos = {
minx: value.offsetLeft,
maxx: value.offsetLeft + value.offsetWidth,
miny: value.offsetTop,
maxy: value.offsetTop + value.offsetHeight
}
})
this.ContainerSize = this.getContainerSize()
},
getContainerSize () {
// 判断容器大小控制词云位置
const el = this.$refs.wordCloud
return {
leftPos: {
// 容器左侧的位置和顶部位置
x: el.offsetLeft,
y: el.offsetTop
},
rightPos: {
// 容器右侧的位置和底部位置
x: el.offsetLeft + el.offsetWidth,
y: el.offsetTop + el.offsetHeight
}
}
}
},
destroyed () {
// 组件销毁,关闭定时执行
cancelAnimationFrame(this.timer)
}
}
</script>
<style lang="less" scoped>
.wordCloud {
width: 100%;
// height: 100%;
height: 400px;
}
</style>
在vue项目中操作元素ref案例;
最新推荐文章于 2022-04-14 23:07:32 发布
![](https://img-home.csdnimg.cn/images/20240711042549.png)