Jelajahi Sumber

feat: add tag-cloud component

Sendya 6 tahun lalu
induk
melakukan
9025539c38

+ 113 - 0
src/components/Charts/TagCloud.vue

@@ -0,0 +1,113 @@
+<template>
+  <v-chart :width="width" :height="height" :padding="[0]" :data="data" :scale="scale">
+    <v-tooltip :show-title="false" />
+    <v-coord type="rect" direction="TL" />
+    <v-point position="x*y" color="category" shape="cloud" tooltip="value*category" />
+  </v-chart>
+</template>
+
+<script>
+import { registerShape } from 'viser-vue'
+const DataSet = require('@antv/data-set')
+
+const imgUrl = 'https://gw.alipayobjects.com/zos/rmsportal/gWyeGLCdFFRavBGIDzWk.png'
+
+const scale = [
+  { dataKey: 'x', nice: false },
+  { dataKey: 'y', nice: false }
+]
+
+registerShape('point', 'cloud', {
+  draw (cfg, container) {
+    return container.addShape('text', {
+      attrs: {
+        fillOpacity: cfg.opacity,
+        fontSize: cfg.origin._origin.size,
+        rotate: cfg.origin._origin.rotate,
+        text: cfg.origin._origin.text,
+        textAlign: 'center',
+        fontFamily: cfg.origin._origin.font,
+        fill: cfg.color,
+        textBaseline: 'Alphabetic',
+        ...cfg.style,
+        x: cfg.x,
+        y: cfg.y
+      }
+    })
+  }
+})
+
+export default {
+  name: 'TagCloud',
+  props: {
+    tagList: {
+      type: Array,
+      required: true
+    },
+    height: {
+      type: Number,
+      default: 400
+    },
+    width: {
+      type: Number,
+      default: 640
+    }
+  },
+  data () {
+    return {
+      data: [],
+      scale
+    }
+  },
+  watch: {
+    tagList: function (val) {
+      if (val.length > 0) {
+        this.initTagCloud(val)
+      }
+    }
+  },
+  mounted () {
+    if (this.tagList.length > 0) {
+      this.initTagCloud(this.tagList)
+    }
+  },
+  methods: {
+    initTagCloud (dataSource) {
+      const { height, width } = this
+
+      const dv = new DataSet.View().source(dataSource)
+      const range = dv.range('value')
+      const min = range[0]
+      const max = range[1]
+      const imageMask = new Image()
+      imageMask.crossOrigin = ''
+      imageMask.src = imgUrl
+      imageMask.onload = () => {
+        dv.transform({
+          type: 'tag-cloud',
+          fields: ['name', 'value'],
+          size: [width, height],
+          imageMask,
+          font: 'Verdana',
+          padding: 0,
+          timeInterval: 5000, // max execute time
+          rotate () {
+            let random = ~~(Math.random() * 4) % 4
+            if (random === 2) {
+              random = 0
+            }
+            return random * 90 // 0, 90, 270
+          },
+          fontSize (d) {
+            if (d.value) {
+              return ((d.value - min) / (max - min)) * (32 - 8) + 8
+            }
+            return 0
+          }
+        })
+        this.data = dv.rows
+      }
+    }
+  }
+}
+</script>

+ 2 - 0
src/components/index.js

@@ -9,6 +9,7 @@ import MiniProgress from '@/components/Charts/MiniProgress'
 import Radar from '@/components/Charts/Radar'
 import RankList from '@/components/Charts/RankList'
 import TransferBar from '@/components/Charts/TransferBar'
+import TagCloud from '@/components/Charts/TagCloud'
 
 // pro components
 import AvatarList from '@/components/AvatarList'
@@ -35,6 +36,7 @@ export {
   MiniBar,
   MiniProgress,
   Radar,
+  TagCloud,
   RankList,
   TransferBar,
   Trend,

+ 1 - 0
src/mock/index.js

@@ -9,6 +9,7 @@ if (process.env.NODE_ENV !== 'production' || process.env.VUE_APP_PREVIEW === 'tr
   require('./services/user')
   require('./services/manage')
   require('./services/other')
+  require('./services/tagCloud')
 
   Mock.setup({
     timeout: 800 // setter delay time

File diff ditekan karena terlalu besar
+ 5 - 0
src/mock/services/tagCloud.js


+ 17 - 2
src/views/Home.vue

@@ -134,6 +134,11 @@
         <description-list-item term="描述">这段描述很长很长很长很长很长很长很长很长很长很长很长很长很长很长...</description-list-item>
       </description-list>
     </a-card>
+
+    <a-divider> TagCloud </a-divider>
+    <a-card style="margin-bottom: 3rem">
+      <tag-cloud :tag-list="tagCloudData"></tag-cloud>
+    </a-card>
   </div>
 </template>
 
@@ -146,7 +151,7 @@ import CountDown from '@/components/CountDown/CountDown'
 import Ellipsis from '@/components/Ellipsis'
 import NumberInfo from '@/components/NumberInfo'
 import TagSelect from '@/components/TagSelect'
-import { DescriptionList } from '@/components/'
+import { DescriptionList, TagCloud } from '@/components/'
 
 const AvatarListItem = AvatarList.AvatarItem
 const TagSelectOption = TagSelect.Option
@@ -164,14 +169,19 @@ export default {
     AvatarListItem,
     TagSelect,
     TagSelectOption,
+    TagCloud,
     DescriptionList,
     DescriptionListItem
   },
   data () {
     return {
-      targetTime: new Date().getTime() + 3900000
+      targetTime: new Date().getTime() + 3900000,
+      tagCloudData: []
     }
   },
+  created () {
+    this.getTagCloudData()
+  },
   methods: {
     onEndHandle () {
       this.$message.success('CountDown callback!!!')
@@ -181,6 +191,11 @@ export default {
         message: 'Notification Title',
         description: 'This is the content of the notification. This is the content of the notification. This is the content of the notification.'
       })
+    },
+    getTagCloudData () {
+      this.$http.get('/data/antv/tag-cloud').then(res => {
+        this.tagCloudData = res.result
+      })
     }
   }
 }

Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini