|
@@ -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>
|