feat: 初步添加词云组件

This commit is contained in:
tnt group 2022-09-22 01:01:54 +08:00
parent ad60b7b44c
commit 20f720bf27
10 changed files with 358 additions and 26 deletions

View File

@ -19,6 +19,7 @@
"crypto-js": "^4.1.1",
"echarts-liquidfill": "^3.1.0",
"echarts-stat": "^1.2.0",
"echarts-wordcloud": "^2.0.0",
"highlight.js": "^11.5.0",
"html2canvas": "^1.4.1",
"keymaster": "^1.6.2",

View File

@ -25,6 +25,7 @@ specifiers:
echarts: ^5.3.2
echarts-liquidfill: ^3.1.0
echarts-stat: ^1.2.0
echarts-wordcloud: ^2.0.0
eslint: ^8.12.0
eslint-config-prettier: ^8.5.0
eslint-plugin-import: ^2.26.0
@ -71,6 +72,7 @@ dependencies:
crypto-js: 4.1.1
echarts-liquidfill: 3.1.0_echarts@5.3.3
echarts-stat: registry.npmmirror.com/echarts-stat/1.2.0
echarts-wordcloud: registry.npmmirror.com/echarts-wordcloud/2.0.0_echarts@5.3.3
highlight.js: 11.5.1
html2canvas: 1.4.1
keymaster: 1.6.2
@ -5396,6 +5398,17 @@ packages:
version: 1.2.0
dev: false
registry.npmmirror.com/echarts-wordcloud/2.0.0_echarts@5.3.3:
resolution: {integrity: sha512-K7l6pTklqdW7ZWzT/1CS0KhBSINr/cd7c5N1fVMzZMwLQHEwT7x+nivK7g5hkVh7WNcAv4Dn6/ZS5zMKRozC1g==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/echarts-wordcloud/-/echarts-wordcloud-2.0.0.tgz}
id: registry.npmmirror.com/echarts-wordcloud/2.0.0
name: echarts-wordcloud
version: 2.0.0
peerDependencies:
echarts: ^5.0.1
dependencies:
echarts: 5.3.3
dev: false
registry.npmmirror.com/esbuild-android-64/0.14.43:
resolution: {integrity: sha512-kqFXAS72K6cNrB6RiM7YJ5lNvmWRDSlpi7ZuRZ1hu1S3w0zlwcoCxWAyM23LQUyZSs1PbjHgdbbfYAN8IGh6xg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/esbuild-android-64/-/esbuild-android-64-0.14.43.tgz}
name: esbuild-android-64

View File

@ -1,6 +0,0 @@
<template>
</template>
<script setup lang="ts">
</script>

View File

@ -1,13 +0,0 @@
<template>
<div>
词云
</div>
</template>
<script setup lang="ts">
</script>
<style lang="scss" scoped>
</style>

View File

@ -0,0 +1,95 @@
import { echartOptionProfixHandle, PublicConfigClass } from '@/packages/public'
import { WordCloudConfig } from './index'
import { CreateComponentType } from '@/packages/index.d'
import cloneDeep from 'lodash/cloneDeep'
import dataJson from './data.json'
export const includes = []
export const ShapeEnumList = [
{ label: '圆形', value: 'circle' },
{ label: '心形', value: 'cardioid' },
{ label: '钻石', value: 'diamond' },
{ label: '右三角形', value: 'triangle-forward' },
{ label: '三角形', value: 'triangle' },
{ label: '五边形', value: 'pentagon' },
{ label: '星星', value: 'star' }
]
export const option = {
dataset: [...dataJson],
tooltip: {},
series: [
{
type: 'wordCloud',
// “云”绘制的形状,可以是表示为回调函数,也可以是固定关键字。
// 可用值有circle|cardioid|diamond|triangle-forward|triangle|pentagon|star
shape: 'circle',
// 白色区域将被排除在绘制文本之外的剪影图像。
// 随着云的形状生长,形状选项将继续应用。
// maskImage: maskImage,
// Folllowing left/top/width/height/right/bottom are used for positioning the word cloud
// Default to be put in the center and has 75% x 80% size.
left: 'center',
top: 'center',
width: '70%',
height: '80%',
right: null,
bottom: null,
// 文本大小范围,默认 [12,60]
sizeRange: [12, 60],
// 文本旋转范围和程度的步骤。 文本将通过旋转步骤45在[-9090]中随机旋转
rotationRange: [0, 0],
rotationStep: 45,
// size of the grid in pixels for marking the availability of the canvas
// 网格大小越大,单词之间的差距就越大。
gridSize: 8,
// 设置为true以允许单词在画布之外部分地绘制。允许绘制大于画布的大小
drawOutOfBound: false,
// If perform layout animation.
// NOTE disable it will lead to UI blocking when there is lots of words.
layoutAnimation: true,
// Global text style
textStyle: {
fontFamily: 'sans-serif',
fontWeight: 'bold'
// 颜色可以是回调功能或颜色字符串
// color: function () {
// // 随机颜色
// return (
// 'rgb(' +
// [Math.round(Math.random() * 160), Math.round(Math.random() * 160), Math.round(Math.random() * 160)].join(
// ','
// ) +
// ')'
// )
// }
},
emphasis: {
focus: 'self',
textStyle: {
shadowBlur: 10,
shadowColor: '#333'
}
},
data: [...dataJson]
}
]
}
export default class Config extends PublicConfigClass implements CreateComponentType {
public key = WordCloudConfig.key
public chartConfig = cloneDeep(WordCloudConfig)
// 图表配置项
public option = echartOptionProfixHandle(option, includes)
}

View File

@ -0,0 +1,89 @@
<!-- eslint-disable vue/multi-word-component-names -->
<!-- eslint-disable vue/no-mutating-props -->
<template>
<collapse-item name="词云" expanded>
<setting-item-box name="形状">
<setting-item>
<n-select v-model:value="optionData.series[0].shape" size="small" :options="ShapeEnumList" />
</setting-item>
<setting-item>
<n-checkbox v-model:checked="optionData.series[0].drawOutOfBound" size="small">允许出边</n-checkbox>
</setting-item>
</setting-item-box>
<setting-item-box name="布局">
<setting-item name="宽度">
<n-slider
v-model:value="customProps.width"
:min="0"
:max="100"
:format-tooltip="sliderFormatTooltip"
@update:value="updateWidth"
></n-slider>
</setting-item>
<setting-item name="高度">
<n-slider
v-model:value="customProps.height"
:min="0"
:max="100"
:format-tooltip="sliderFormatTooltip"
@update:value="updateHeight"
></n-slider>
</setting-item>
</setting-item-box>
<setting-item-box name="样式" alone>
<setting-item name="字体区间(最小/最大字体)">
<n-slider v-model:value="optionData.series[0].sizeRange" range :step="1" :min="6" :max="100" />
</setting-item>
<setting-item name="旋转角度">
<n-slider
v-model:value="customProps.rotationStep"
:step="15"
:min="0"
:max="45"
@update:value="updateRotation"
/>
</setting-item>
</setting-item-box>
</collapse-item>
</template>
<script setup lang="ts">
import { PropType, reactive } from 'vue'
import { option, ShapeEnumList } from './config'
// eslint-disable-next-line no-unused-vars
import { CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
const props = defineProps({
optionData: {
type: Object as PropType<typeof option>,
required: true
}
})
const sliderFormatTooltip = (v: number) => {
return `${v}%`
}
const customProps = reactive({
width: 70,
height: 80,
rotationStep: 0 //
})
const updateWidth = (value: number) => {
// eslint-disable-next-line vue/no-mutating-props
props.optionData.series[0].width = `${value}%`
}
const updateHeight = (value: number) => {
// eslint-disable-next-line vue/no-mutating-props
props.optionData.series[0].height = `${value}%`
}
const updateRotation = (value: number) => {
// eslint-disable-next-line vue/no-mutating-props
props.optionData.series[0].rotationStep = value
// eslint-disable-next-line vue/no-mutating-props
props.optionData.series[0].rotationRange = value === 0 ? [0, 0] : [-90, 90]
}
</script>

View File

@ -0,0 +1,90 @@
[
{
"name": "数据可视化",
"value": 8000,
"textStyle": {
"color": "#78fbb2"
},
"emphasis": {
"textStyle": {
"color": "red"
}
}
},
{
"name": "GO VIEW",
"value": 6181
},
{
"name": "低代码",
"value": 4386
},
{
"name": "Vue3",
"value": 4055
},
{
"name": "TypeScript4",
"value": 2467
},
{
"name": "Vite2",
"value": 2244
},
{
"name": "NaiveUI",
"value": 1898
},
{
"name": "ECharts5",
"value": 1484
},
{
"name": "Axios",
"value": 1112
},
{
"name": "Pinia2",
"value": 965
},
{
"name": "PlopJS",
"value": 847
},
{
"name": "sfc",
"value": 582
},
{
"name": "SCSS",
"value": 555
},
{
"name": "pnpm",
"value": 550
},
{
"name": "eslint",
"value": 462
},
{
"name": "json",
"value": 366
},
{
"name": "图表",
"value": 360
},
{
"name": "地图",
"value": 282
},
{
"name": "时钟",
"value": 273
},
{
"name": "标题",
"value": 265
}
]

View File

@ -1,11 +1,11 @@
import image from '@/assets/images/chart/informations/words_cloud.png'
import { ConfigType, PackagesCategoryEnum } from '@/packages/index.d'
import { ChatCategoryEnum,ChatCategoryEnumName } from '../../index.d'
import { ChatCategoryEnum, ChatCategoryEnumName } from '../../index.d'
export const TextCloudConfig: ConfigType = {
key: 'TextCloud',
chartKey: 'VTextCloud',
conKey: 'VCTextCloud',
export const WordCloudConfig: ConfigType = {
key: 'WordCloud',
chartKey: 'VWordCloud',
conKey: 'VCWordCloud',
title: '词云',
category: ChatCategoryEnum.MORE,
categoryName: ChatCategoryEnumName.MORE,

View File

@ -0,0 +1,63 @@
<!-- eslint-disable vue/multi-word-component-names -->
<template>
<v-chart
ref="vChartRef"
:theme="themeColor"
:option="option"
:manual-update="isPreview()"
:update-options="{ replaceMerge: replaceMergeArr }"
autoresize
></v-chart>
</template>
<script setup lang="ts">
import { ref, computed, watch, PropType } from 'vue'
import VChart from 'vue-echarts'
import 'echarts-wordcloud'
import { use } from 'echarts/core'
import { CanvasRenderer } from 'echarts/renderers'
import { BarChart } from 'echarts/charts'
import config, { includes } from './config'
import { mergeTheme } from '@/packages/public/chart'
import { useChartDataFetch } from '@/hooks'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { isPreview } from '@/utils'
import { DatasetComponent, GridComponent, TooltipComponent, LegendComponent } from 'echarts/components'
const props = defineProps({
themeSetting: {
type: Object,
required: true
},
themeColor: {
type: Object,
required: true
},
chartConfig: {
type: Object as PropType<config>,
required: true
}
})
use([DatasetComponent, CanvasRenderer, BarChart, GridComponent, TooltipComponent, LegendComponent])
const replaceMergeArr = ref<string[]>()
const option = computed(() => {
return mergeTheme(props.chartConfig.option, props.themeSetting, includes)
})
// dataset
watch(
() => props.chartConfig.option.dataset,
newData => {
// eslint-disable-next-line vue/no-mutating-props
props.chartConfig.option.series[0].data = newData
},
{
deep: false
}
)
const { vChartRef } = useChartDataFetch(props.chartConfig, useChartEditStore)
</script>

View File

@ -1,4 +1,4 @@
import { TextCloudConfig } from './TextCloud/index'
import { ImageConfig } from './Image/index'
import { WordCloudConfig } from './WordCloud/index'
export default [ImageConfig, TextCloudConfig]
export default [ImageConfig, WordCloudConfig]