Skip to content

Commit

Permalink
feat: replace wordcloud component with wordcloud2.js
Browse files Browse the repository at this point in the history
  • Loading branch information
ltchou committed Aug 1, 2024
1 parent 5f13b91 commit 2249f9f
Show file tree
Hide file tree
Showing 7 changed files with 135 additions and 102 deletions.
3 changes: 2 additions & 1 deletion nuxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ const config = {

elementPlus: {
importStyle: false // using css @import for custom
}
},
plugins: ['~/plugins/wordcloud.client.js']
}

// https://nuxt.com/docs/api/configuration/nuxt-config
Expand Down
15 changes: 6 additions & 9 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"@pinia/nuxt": "^0.5.1",
"chart.js": "^4.4.0",
"pinia": "^2.1.7",
"vuewordcloud": "^19.0.0"
"wordcloud": "^1.2.2"
},
"engines": {
"node": ">=18.0.0"
Expand Down
95 changes: 64 additions & 31 deletions pages/high_value_datasets/[id].vue
Original file line number Diff line number Diff line change
Expand Up @@ -268,27 +268,7 @@
<div class="left">
<div class="title-with-line">文字雲</div>
<div class="cloud-box">
<vue-word-cloud
style="width: 80%; height: 360px; margin: 0 auto"
:words="[
['政府統計', 1000],
['政府支出', 700],
['政府預算', 300],
['主計', 3]
]"
:spacing="2"
:font-size-ratio="2"
>
<template #default="{ text }">
<button
:class="['btn-cloud']"
:title="`前往搜尋有關關鍵字 ${text} 的資料集`"
@click="onWordClick(text)"
>
<span>{{ text }}</span>
</button>
</template>
</vue-word-cloud>
<div id="word_cloud" ref="canvas" class="statistics-wordcloud"></div>
</div>
</div>
<div class="right">
Expand All @@ -307,13 +287,15 @@
</template>

<script setup lang="ts">
import { useNuxtApp } from '#app'
import zhTW from 'element-plus/es/locale/lang/zh-tw'
import { Chart, registerables } from 'chart.js'
const runtimeConfig = useRuntimeConfig()
const pageTitle = ref('')
const pageDescription = ref('')
const route = useRoute()
const { VueWordCloud } = useWordCloud()
const { $wordcloud }: any = useNuxtApp()
const canvas = ref(null)
useHead({
title: computed(() => '高應用價值主題專區:' + pageTitle.value),
Expand Down Expand Up @@ -358,7 +340,7 @@ useHead({
Chart.register(...registerables)
const valueChart = ref<HTMLCanvasElement | null>(null)
const { isRadio, addThScope } = useJSAccessibility()
onMounted(() => {
if (valueChart.value) {
const ctx = valueChart.value.getContext('2d') as CanvasRenderingContext2D
Expand Down Expand Up @@ -404,6 +386,21 @@ onMounted(() => {
}
})
}
document.getElementById('word_cloud')!.addEventListener('wordcloudstop', () => {
const word = document.getElementsByClassName('custom-class')
for (let i = 0; i < word.length; i++) {
word[i].setAttribute('tabindex', '0')
word[i].addEventListener('keyup', (event: any) => {
if (event.keyCode === 13) {
const text = word[i].textContent
navigateTo('/datasets/search?rtt=' + text)
}
})
}
})
render()
isRadio()
addThScope()
})
const pageData = ref([
Expand Down Expand Up @@ -711,13 +708,49 @@ const relApp = ref([
imgPath: '/images/logo-icon.png'
}
])
const onWordClick = (text: string) => {
navigateTo('/datasets/search?q=' + text)
const tags = [
['政府統計', 10],
['政府支出', 4],
['政府預算', 6],
['主計', 3]
]
const render = (wordSize: number = 10) => {
$wordcloud(document.getElementById('word_cloud'), {
list: tags,
gridSize: 24,
weightFactor: wordSize,
fontFamily: 'Noto Sans TC',
rotateRatio: 0,
classes: 'custom-class',
color: () => {
const ind = customCrypt()
return ['#E51010', '#A26A15', '#0079B7', '#068415'][ind]
},
click: (item: any) => {
navigateTo('/datasets/search?rtt=' + item[0])
},
hover: (item: any) => {
if (item !== undefined) {
document.body.style.cursor = 'pointer'
document.getElementById('word_cloud')!.title = `移至資料集列表,關鍵字: ${item[0]}`
} else {
document.body.style.cursor = 'default'
}
}
})
}
const customCrypt = () => {
const crypto = window.crypto || (window as any).msCrypto
const array = new Uint32Array(1)
crypto.getRandomValues(array) // Compliant for security-sensitive use cases
return array[0] % 4
}
const { isRadio, addThScope } = useJSAccessibility()
onMounted(() => {
isRadio()
addThScope()
})
</script>
<style>
.statistics-wordcloud {
width: 80%;
height: 360px;
margin: 0 auto;
background-color: #e9edf2 !important;
}
</style>
95 changes: 57 additions & 38 deletions pages/statistics/wordcloud.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,53 +5,22 @@
<h2>{{ pageTitle }}</h2>
<el-divider />
<section>
<div class="cloud-box">
<vue-word-cloud
style="width: 80%; height: 360px; margin: 0 auto"
:words="[
['政府統計', 1000],
['政府支出', 700],
['政府預算', 300],
['主計', 3]
]"
:spacing="2"
:font-size-ratio="2"
>
<template #default="{ text, weight, word }">
<button
:class="[
'btn-cloud',
weight >= 800
? 'level1'
: weight >= 600 && weight < 800
? 'level2'
: weight >= 400 && weight < 600
? 'level3'
: weight >= 200 && weight < 400
? 'level4'
: weight < 200
? 'level5'
: ''
]"
:title="`前往搜尋有關關鍵字 ${text} 的資料集`"
@click="onWordClick(text)"
>
<span>{{ text }}</span>
</button>
</template>
</vue-word-cloud>
<div id="word_cloud__box" class="cloud-box">
<div id="word_cloud" ref="canvas" style="width: 80%; height: 360px; margin: 0 auto"></div>
</div>
</section>
</div>
</main>
</template>

<script setup lang="ts">
import { useNuxtApp } from '#app'
const runtimeConfig = useRuntimeConfig()
const pageTitle = ref('標籤雲')
const pageDescription = ref('標籤雲')
const route = useRoute()
const { VueWordCloud } = useWordCloud()
const { $wordcloud }: any = useNuxtApp()
const canvas = ref(null)
useHead({
title: pageTitle,
Expand Down Expand Up @@ -90,7 +59,57 @@ useHead({
]
})
const onWordClick = (text: string) => {
navigateTo('/datasets/search?q=' + text)
const tags = [
['政府統計', 12],
['政府支出', 6],
['政府預算', 8],
['主計', 3]
]
onMounted(() => {
document.getElementById('word_cloud')!.addEventListener('wordcloudstop', () => {
const word = document.getElementsByClassName('custom-class')
for (let i = 0; i < word.length; i++) {
word[i].setAttribute('tabindex', '0')
word[i].addEventListener('keyup', (event: any) => {
if (event.keyCode === 13) {
const text = word[i].textContent
navigateTo('/datasets/search?rtt=' + text)
}
})
}
})
render()
})
const render = (wordSize: number = 10) => {
$wordcloud(document.getElementById('word_cloud'), {
list: tags,
gridSize: 24,
weightFactor: wordSize,
fontFamily: 'Noto Sans TC',
rotateRatio: 0,
classes: 'custom-class',
color: () => {
const ind = customCrypt()
return ['#E51010', '#A26A15', '#0079B7', '#068415'][ind]
},
click: (item: any) => {
navigateTo('/datasets/search?rtt=' + item[0])
},
hover: (item: any) => {
if (item !== undefined) {
document.body.style.cursor = 'pointer'
document.getElementById('word_cloud')!.title = `移至資料集列表,關鍵字: ${item[0]}`
} else {
document.body.style.cursor = 'default'
}
}
})
}
const customCrypt = () => {
const crypto = window.crypto || (window as any).msCrypto
const array = new Uint32Array(1)
crypto.getRandomValues(array) // Compliant for security-sensitive use cases
return array[0] % 4
}
</script>
22 changes: 0 additions & 22 deletions pages/word-cloud.vue

This file was deleted.

5 changes: 5 additions & 0 deletions plugins/wordcloud.client.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// plugins/wordcloud.js
export default defineNuxtPlugin(async (nuxtApp) => {
const WordCloud = await import('wordcloud')
nuxtApp.provide('wordcloud', WordCloud.default)
})

0 comments on commit 2249f9f

Please sign in to comment.