大屏显示之动态词云组件

先上效果图:
请添加图片描述

<template>
  <div class="wordCloud" ref="wordCloudRef">
  </div>
</template>

<script setup>
import { reactive, ref, onMounted, onUnmounted } from 'vue'
const props = defineProps({
  wordCloud:{
    type:Array,
    required:true
  },
  colorList:{
    type:Array,
    default: [
          '#a18cd1', '#fad0c4', '#ff8177',
          '#fecfef', '#fda085', '#f5576c',
          '#330867', '#30cfd0', '#38f9d7'
          ]
  }
})
// 容器节点ref
let wordCloudRef = ref(null)
// 容器节点的边界坐标
let ContainerSize = reactive({})
// 词云Dom节点
let wordDomList = ref([])
// 定义定时器,组件卸载时销毁
let timer = ref(null)


// 初始化词云DOM位置
function initWordPos () {
			// 计算每个词的真实位置和容器的位置
			wordDomList.forEach((value) => {
				value.local.realPos = {
					minx: value.offsetLeft,
					maxx: value.offsetLeft + value.offsetWidth,
					miny: value.offsetTop,
					maxy: value.offsetTop + value.offsetHeight
				};
			});
			ContainerSize = getContainerSize();
}
// 初始化词云DOM节点
function dealSpan () {
			const wordArr = [];
			props.wordCloud.forEach((value) => {
				// 根据词云数量生成span数量设置字体颜色和大小
				const spanDom = document.createElement('span');
				spanDom.style.position = 'relative';
				spanDom.style.display = 'inline-block';
				spanDom.style.color = randomColor();
				spanDom.style.fontSize = randomNumber(20, 40) + '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()
					},
				};
				wordCloudRef.value.appendChild(spanDom);
				wordArr.push(spanDom);
			});
			wordDomList = wordArr;
}
// 动态词云
function wordFly () {
			wordDomList.forEach((value) => {
				// 设置运动方向 大于边界或者小于边界的时候换方向
				if (value.local.realPos.minx + value.local.position.x < ContainerSize.leftPos.x || value.local.realPos.maxx + value.local.position.x > ContainerSize.rightPos.x) value.local.direction.x = -value.local.direction.x;
				if (value.local.realPos.miny + value.local.position.y < ContainerSize.leftPos.y || value.local.realPos.maxy + value.local.position.y > 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)';
			});
		
    timer = window.requestAnimationFrame(wordFly)
}
// 获取容器位置
function getContainerSize () {
  // 判断容器大小控制词云位置
  const el  = wordCloudRef.value;
  return {
      leftPos: {
              // 容器左侧的位置和顶部位置
              x: el.offsetLeft,
              y: el.offsetTop
      },
      rightPos: {
              // 容器右侧的位置和底部位置
              x: el.offsetLeft + el.offsetWidth,
              y: el.offsetTop + el.offsetHeight
      }
  };
}
// 获得一个包含最小值和最大值之间的随机数。
function randomNumber (lowerInteger, upperInteger) {
  const choices = upperInteger - lowerInteger + 1;
  return Math.floor(Math.random() * choices + lowerInteger);
}

// 获取随机颜色
function randomColor () {
  var colorIndex = Math.floor(props.colorList.length * Math.random());
  return props.colorList[colorIndex];
}

onMounted(() => {
  dealSpan()
  initWordPos()
  timer = window.requestAnimationFrame(wordFly)
})
onUnmounted(() => {
  // 组件销毁,关闭定时执行
  cancelAnimationFrame(timer);
})
</script>

<style lang="scss" scoped>
  .wordCloud{
    width: 400px;
    height: 400px;
    border: 1px darkcyan dashed;
  }
</style>

组件调用


<script setup>
// 词云数据
let wordCloud =reactive([ '闭月羞花','沉鱼落雁','出水芙蓉','明眸皓齿','美如冠玉','倾国倾城','国色天香','鹤发童颜','眉清目秀',
                '张牙舞爪','愁眉苦脸','冰清玉洁','雍容华贵','文质彬彬','威风凛凛',,'心慈面善','弱不禁风','和蔼可亲',
                '老态龙钟','虎背熊腰','如花似玉','容光焕发','落落大方','骨瘦如柴','大腹便便','面黄肌瘦','其貌不扬','蓬头垢面'])
</script>
<template>
	<WordCloud :wordCloud="wordCloud" ></WordCloud>
</template>

小推一个好用的录制gif图的工具—>LICEcap

参考文章:https://juejin.cn/post/7000300247947673630

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值