vue词云(vue + TagCanvas)

1、引入tagcanvas.js
官网地址: https://www.goat1000.com/tagcanvas.php#links
2、全部代码

点击查看代码
<template>
  <div id="superviseCon" ref="superviseCon" class="content-info">
    <!-- 词云容器 -->
    <div class="word-cloud-container">
      <canvas
        id="world-cloud-canvas"
        width="800"
        height="800"
        style="width: 100%; height: 100%"
        aria-label="企业标签云图"
      ></canvas>
    </div>
    <!-- 标签容器(隐藏)用于存储标签数据 -->
    <div id="weightTags" class="hidden-tags"></div>
  </div>
</template>
<script>
// 导入标签云库
import '@/views/adminIndex/tagcanvas.js'

// 防抖函数,用于窗口大小改变时优化性能
const debounce = (func, wait) => {
  let timeout
  return function() {
    const context = this
    const args = arguments
    clearTimeout(timeout)
    timeout = setTimeout(() => {
      func.apply(context, args)
    }, wait)
  }
}

// 词云标签数据
const WORD_CLOUD_DATA = [
  { name: '公共交通集团有限公司', light: 1 },
  { name: '永信财税服务有限公司', light: 2 },
  { name: '薪火传承数字科技有限公司', light: 3 },
  { name: '智谷天厨科技有限公司', light: 4 },
  { name: '麟才教育咨询有限公司', light: 5 },
  { name: '九策有限公司', light: 1 },
  { name: '大疆有限公司', light: 2 },
  { name: '云基华海信息技术', light: 3 },
  { name: '公共交通集团有限公司', light: 4 },
  { name: '永信财税服务有限公司', light: 5 },
  { name: '薪火传承数字科技有限公司', light: 1 },
  { name: '智谷天厨科技有限公司', light: 2 },
  { name: '麟才教育咨询有限公司', light: 3 },
  { name: '九策有限公司', light: 4 },
  { name: '大疆有限公司', light: 5 },
  { name: '云基华海信息技术', light: 1 },
  { name: '公共交通集团有限公司', light: 2 },
  { name: '永信财税服务有限公司', light: 3 },
  { name: '薪火传承数字科技有限公司', light: 4 },
  { name: '智谷天厨科技有限公司', light: 5 },
  { name: '麟才教育咨询有限公司', light: 1 },
  { name: '九策有限公司', light: 2 },
  { name: '大疆有限公司', light: 3 },
  { name: '云基华海信息技术', light: 4 },
  { name: '公共交通集团有限公司', light: 5 },
  { name: '永信财税服务有限公司', light: 1 },
  { name: '薪火传承数字科技有限公司', light: 2 },
  { name: '智谷天厨科技有限公司', light: 3 },
  { name: '麟才教育咨询有限公司', light: 4 },
  { name: '九策有限公司', light: 5 },
  { name: '大疆有限公司', light: 1 },
  { name: '云基华海信息技术', light: 2 }
]

// 标签样式映射
const TAG_CLASS_MAP = {
  1: 'huge',
  2: 'medium',
  3: 'small',
  4: 'mini',
  5: 'large'
}

export default {
  name: 'WordCloud',

  data() {
    return {
      wordArr: [...WORD_CLOUD_DATA], // 标签数据
      resizeHandler: null, // 窗口大小改变事件处理器
      tagCanvas: null // TagCanvas实例引用
    }
  },
  created() {
    // 初始化时设置rem基准值
    this.setRem()

    // 添加防抖的窗口大小改变事件监听
    this.resizeHandler = debounce(() => {
      this.setRem()
      // 窗口大小改变时重新计算词云位置
      if (this.tagCanvas) {
        this.tagCanvas.Resume()
      }
    }, 300)

    window.addEventListener('resize', this.resizeHandler)
  },

  mounted() {
     // 初始化词云
     this.initializeWordCloud()
  },

  watch: {
    // 监听词云数据变化,重新渲染
    wordArr: {
      deep: true, // 深度监听数组变化
      handler() {
        this.updateWordCloud()
      }
    }
  },

  beforeDestroy() {
    // 清理词云实例
    if (this.tagCanvas) {
      this.tagCanvas.Stop()
      this.tagCanvas = null
    }
  },
  methods: {
    /**
     * 初始化词云
     */
    initializeWordCloud() {
      this.createTagListDom()
      this.startWordCloud()
    },

    /**
     * 启动或更新词云
     * @param {boolean} isUpdate - 是否为更新操作
     */
    startWordCloud(isUpdate = false) {
      try {
        const options = this.getWordCloudOptions()

        if (!isUpdate) {
          // 初始化词云
          // eslint-disable-next-line no-undef
          this.tagCanvas = TagCanvas
          this.tagCanvas.Start('world-cloud-canvas', 'weightTags', options)
        } else {
          // 更新词云
          this.tagCanvas.Reload('world-cloud-canvas')
        }
      } catch (error) {
        console.error('词云初始化失败:', error)
      }
    },

    /**
     * 获取词云配置选项
     * @returns {Object} 词云配置对象
     */
    getWordCloudOptions() {
      return {
        maxSpeed: 0.01,        // 最大运动速度
        minSpeed: 0.01,        // 最小运动速度,保持持续运动
        textHeight: 25,        // 文本高度
        outlineMethod: 'colour', // 悬停轮廓效果
        fadeIn: 800,           // 淡入动画时间(ms)
        outlineColour: '#fff',  // 轮廓颜色
        outlineOffset: 0,       // 轮廓偏移量
        depth: 0.97,           // 3D深度
        minBrightness: 0.2,     // 最小亮度
        wheelZoom: false,       // 禁用滚轮缩放
        reverse: true,          // 反向运动
        shadowBlur: 1,          // 阴影模糊度
        shuffleTags: true,      // 随机排序标签
        shadowOffset: [1, 1],   // 阴影偏移
        stretchX: 1,            // 水平拉伸
        initial: [-0.1, 0.1],   // 初始运动方向
        shape: 'Sphere',        // 形状:球体
        zoom: 1,                // 缩放级别
        zoomStep: 0.05,         // 缩放步长
        zoomMax: 3,             // 最大缩放
        zoomMin: 0.3,           // 最小缩放
        textAlign: 'center',    // 文本水平对齐
        textVAlign: 'middle',   // 文本垂直对齐
        textFont: null,         // 使用标签字体
        textColour: null,       // 使用标签颜色
        weight: true,           // 启用权重
        weightMode: 'size',     // 权重模式:大小
        weightSize: 0.5         // 权重大小
      }
    },

    /**
     * 更新词云
     */
    updateWordCloud() {
      this.createTagListDom()
      this.startWordCloud(true)
    },

    /**
     * 创建标签DOM元素
     */
    createTagListDom() {
      const fragment = document.createDocumentFragment()

      this.wordArr.forEach(item => {
        const link = document.createElement('a')
        link.textContent = item.name
        link.href = 'javascript:void(0)'
        link.className = TAG_CLASS_MAP[item.light] || 'small' // 默认使用small样式

        // 添加无障碍属性
        link.setAttribute('role', 'button')
        link.setAttribute('tabindex', '0')
        link.setAttribute('aria-label', `企业: ${item.name}`)

        fragment.appendChild(link)
      })

      // 更新标签容器
      const container = document.getElementById('weightTags')
      if (container) {
        container.innerHTML = ''
        container.appendChild(fragment)
      }
    },
  }
}
</script>
<style scoped lang="scss">
// 主容器样式
.content-info {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: #f5f7fa; // 添加背景色
  padding: 20px;
  box-sizing: border-box;
  overflow: hidden;

  // 词云容器
  .word-cloud-container {
    width: 800px;
    height: 800px;
    max-width: 100%;
    max-height: 100%;
    display: flex;
    justify-content: center;
    align-items: center;
  }

  // 隐藏的标签容器
  .hidden-tags {
    position: absolute;
    opacity: 0;
    pointer-events: none;
  }
}

// 响应式调整
@media screen and (max-width: 768px) {
  .content-info {
    padding: 10px;

    .word-cloud-container {
      height: 80vh;
    }
  }
}
</style>

<style lang="scss">
// 标签样式
#weightTags {
  // 基础标签样式
  a {
    font-family: 'Microsoft YaHei', '微软雅黑', Arial, sans-serif;
    font-weight: 500;
    text-decoration: none;
    transition: all 0.3s ease;
    display: inline-block;
    margin: 2px;
    cursor: pointer;

    // 添加悬停效果
    &:hover {
      transform: scale(1.05);
      opacity: 0.9;
    }

    // 添加焦点样式,提升可访问性
    &:focus {
      outline: 2px solid #3a86ff;
      outline-offset: 2px;
    }
  }

  // 不同权重的标签样式
  .huge {
    font-size: 36px;
    color: #FF6B6B;
  }

  .large {
    font-size: 36px;
    color: #8E24AA;
  }

  .medium {
    font-size: 36px;
    color: #FFA000;
  }

  .small {
    font-size: 36px;
    color: #00ACC1;
  }

  .mini {
    font-size: 36px;
    color: #009688;
    opacity: 0.8;
  }
}
</style>
3、实现样式

PixPin_2025-11-03_18-47-13

posted @ 2025-11-03 18:48  _seven7  阅读(9)  评论(0)    收藏  举报