当前位置:   article > 正文

vue实现标签云,让你的标签动起来_vue tagcloud

vue tagcloud

一起探讨学习

欢迎大家进群,一起讨论学习

每天给大家提供技术干货

在这里插入图片描述

博主技术笔记 https://notes.xiyankt.com


博主开源微服架构前后端分离技术博客项目源码地址,欢迎各位star https://gitee.com/bright-boy/xiyan-blog


vue实现标签云,让你的标签动起来

npm包地址 https://www.npmjs.com/package/bright-tag

项目介绍

Vue标签云UI组件

安装教程
  1. npm i bright-tag
  2. 在main.js中
import tagCloud from 'bright-tag'
Vue.use(tagCloud)
  • 1
  • 2
使用说明

props

  1. data

Object数组。name属性是显示的标签名,其他自行扩展。

  1. config

Object对象,配置项。有下面几个参数:

参数默认值说明
radius120滚动半径,Number,单位px
maxFont24最大字体大小
colornull字体颜色。为null时随机
rotateAngleXbase600X方向旋转速度基数,数越小速度越快
rotateAngleYbase600Y方向旋转速度基数,数越小速度越快

方法

方法名参数说明
clickTagtag点击标签的方法。返回整个标签

调用用例

<!-- template -->
<tag-cloud :data="hotTag" @clickTag="clickTagItem"></tag-cloud>
  • 1
  • 2
// Vue实例
export default {
  data () {
    return {
      hotTag: [{"id":"05023f8da31c4b4187cc6899e2a3aec2","name":"镇远县"},{"id":"0ef028e5278f4f5ca31f99f1bd22b1cc","name":"剑河县"},{"id":"1a32ef04d3c548eaa6777abb46da32f2","name":"台江县"},{"id":"2c26488325bd493687d16315fe0e5fdd","name":"岑巩县"},{"id":"3a786111828a4b9f89ae9da25753eedd","name":"黎平"},{"id":"4ed593eed91b4244969995237f5c96c5","name":"丹寨县"},{"id":"615d2c178f1a47cb8d473823e74f5386","name":"凯里市"},{"id":"76f652df03db43349272a9aff492b065","name":"榕江县"},{"id":"8ff29d0d35e548feb945063b34ed9c9b","name":"黄平县"},{"id":"a8ac2170008746fdadc05ea461bc5e37","name":"雷山县"}]
    }
  },
  methods: {
    clickTagItem (tag) {
      // TODO
    }
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

在这里插入图片描述

以下是源码解析

<template>
  <div class="tag-wall"        <div class="tag-cloud" ref="wrapper">
          <p
            v-for="(item, index) in data"
            :key="index"
            ref="tag"
            @click="clickTag(item)"
            @dblclick="dbclickTag(item)"
          >
            {{ item.name }}
          </p>
      </div>
  </div>
</template>

<script>

export default {
  data() {
    return {
      data: [
        { id: "05023f8da31c4b4187cc6899e2a3aec2", name: "镇远县" },
        { id: "0ef028e5278f4f5ca31f99f1bd22b1cc", name: "剑河县" },
        { id: "1a32ef04d3c548eaa6777abb46da32f2", name: "台江县" },
        { id: "2c26488325bd493687d16315fe0e5fdd", name: "岑巩县" },
        { id: "3a786111828a4b9f89ae9da25753eedd", name: "黎平" },
        { id: "4ed593eed91b4244969995237f5c96c5", name: "丹寨县" },
        { id: "615d2c178f1a47cb8d473823e74f5386", name: "凯里市" },
        { id: "76f652df03db43349272a9aff492b065", name: "榕江县" },
        { id: "8ff29d0d35e548feb945063b34ed9c9b", name: "黄平县" },
        { id: "a8ac2170008746fdadc05ea461bc5e37", name: "雷山县" },
      ],
      option: {
        radius: 140, // 滚动半径,单位px
        maxFont: 24, // 最大字体大小
        color: null, // 字体颜色。为空时随机
        rotateAngleXbase: 600, // 默认旋转速度基数,数越小速度越快
        rotateAngleYbase: 600,
      },
      tagList: [],
    };
  },
  beforeDestroy() {
    if (this.timer) {
      clearInterval(this.timer);
      this.timer = null;
    }
  },
  watch: {
    data() {
      this.$nextTick(() => {
        this._initTags();
      });
    },
  },
  mounted() {
    this._initTags();
  },
  created() {
    this.listTag();
    if (this.config != null) {
      this.option = Object.assign({}, this.option, this.config);
    }
  },
  methods: {
    _initTags() {
      this.rotateAngleX = Math.PI / this.option.rotateAngleXbase;
      this.rotateAngleY = Math.PI / this.option.rotateAngleYbase;

      for (var i = 0, length = this.data.length; i < length; i++) {
        // 获取球面上均匀的点的经纬度 θ = arccos( ((2*num)-1)/all - 1); Φ = θ*sqrt(all * π);
        let angleX = Math.acos((2 * (i + 1) - 1) / length - 1);
        let angleY = angleX * Math.sqrt(length * Math.PI);
        // 根据经纬度获取点的坐标,球中心的点坐标是 (0,0,0) x=r*sinθ*cosΦ   y=r*sinθ*sinΦ   z=r*cosθ;
        const x = this.option.radius * Math.sin(angleX) * Math.cos(angleY);
        const y = this.option.radius * Math.sin(angleX) * Math.sin(angleY);
        const z = this.option.radius * Math.cos(angleX);
        if (this.option.color) {
          this.$refs.tag[i].style.color = this.option.color;
        } else {
          // 随机颜色
          this.$refs.tag[i].style.color =
            "rgb(" +
            Math.round(255 * Math.random()) +
            "," +
            Math.round(255 * Math.random()) +
            "," +
            Math.round(255 * Math.random()) +
            ")";
        }
        // 每个标签对象都有四对值
        var tag = {
          x: x,
          y: y,
          z: z,
          ele: this.$refs.tag[i],
        };
        this.tagList.push(tag);
      }
      const _self = this;
      const datas = _self.tagList;
      this.timer = setInterval(function () {
        for (var i = 0; i < datas.length; i++) {
          _self.rotateX(datas[i]);
          _self.rotateY(datas[i]);
          _self.setPosition(
            datas[i],
            _self.option.radius,
            _self.option.maxFont
          );
        }
      }, 20);
    },
    setPosition(tag, r, maxFont) {
      // 设置每个标签的坐标位置和字体大小以及透明度
      if (this.$refs.wrapper) {
        tag.ele.style.transform =
          "translate(" +
          (tag.x +
            this.$refs.wrapper.offsetWidth / 2 -
            tag.ele.offsetWidth / 2) +
          "px," +
          (tag.y +
            this.$refs.wrapper.offsetHeight / 2 -
            tag.ele.offsetHeight / 2) +
          "px)";
        tag.ele.style.opacity = tag.z / r / 2 + 0.7;
        tag.ele.style.fontSize = (tag.z / r / 2 + 0.5) * maxFont + "px";
      }
    },
    rotateX(tag) {
      var cos = Math.cos(this.rotateAngleX);
      var sin = Math.sin(this.rotateAngleX);
      var y1 = tag.y * cos - tag.z * sin;
      var z1 = tag.y * sin + tag.z * cos;
      tag.y = y1;
      tag.z = z1;
    },
    rotateY(tag) {
      var cos = Math.cos(this.rotateAngleY);
      var sin = Math.sin(this.rotateAngleY);
      var x1 = tag.z * sin + tag.x * cos;
      var z1 = tag.z * cos - tag.x * sin;
      tag.x = x1;
      tag.z = z1;
    },
    dbclickTag() {
      if (this.timer) {
        clearInterval(this.timer);
        this.timer = null;
      } else {
        const _self = this;
        this.timer = setInterval(function () {
          for (var i = 0; i < _self.tagList.length; i++) {
            _self.rotateX(_self.tagList[i]);
            _self.rotateY(_self.tagList[i]);
            _self.setPosition(
              _self.tagList[i],
              _self.option.radius,
              _self.option.maxFont
            );
          }
        }, 20);
      }
    },
    clickTag(item) {
      this.$emit("clickTag", item);
    },
  },
};
</script>

<style scoped>
.tag-cloud {
  width: 300px;
  height: 300px;
  position: relative;
  color: #333;
  margin: 0 auto;
  text-align: center;
}

.tag-cloud p {
  position: absolute;
  top: 0px;
  left: 0px;
  color: #333;
  font-family: Arial;
  text-decoration: none;
  margin: 0 10px 15px 0;
  line-height: 18px;
  text-align: center;
  font-size: 16px;
  padding: 4px 9px;
  display: inline-block;
  border-radius: 3px;
}
.tag-cloud p:hover {
  cursor: pointer;
}
</style>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202

各位老板关注下

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/132334
推荐阅读
相关标签