Closed3
GitHubの草をNuxtでThree.jsを使って生やしたい
GitHub GraphQL APIをNuxtからurqlを使って叩く
こちらの記事を見るとgraphql-request が軽量で良さそうだが、エラーが出て使えなかったのでurqlというライブラリを使う
urqlのドキュメントはとても丁寧なのでこれ見れば大丈夫
- urql導入
yarn add @urql/vue graphql
# or
npm install --save @urql/vue graphql
最小構成
クライアント側にGitHubのトークンを渡したくないので、サーバー側でGitHubのAPIを叩く仕様にする
plugins/github.server.ts
import { Client, cacheExchange, fetchExchange } from "@urql/core"
export default defineNuxtPlugin(async () => {
const urql = new Client({
url: "https://api.github.com/graphql",
exchanges: [cacheExchange, fetchExchange],
fetchOptions: () => {
const token = process.env.GITHUB_TOKEN
return {
headers: { authorization: token ? `Bearer ${token}` : "" },
}
}
})
const { data } = await urql.query(`
query {
viewer {
login
}
}
`, {}).toPromise()
return {
provide: {
github: data
},
}
})
composables/github.ts
export const useGitHub = () => {
const { $github } = useNuxtApp()
const github = useState('github', () => $github)
return github
}
pages/kusa.vue
<template>
<ClientOnly>
{{ kusa }}
</ClientOnly>
</template>
<script setup lang="ts">
const kusa = useGitHub()
</script>
実行結果
あとはクエリを草を取得するものに変えれば良い。
これを自分で設定するのが面倒なら、このパッケージ使うのもありかも(Nuxt3には対応してないっぽい…?)
(余談)graphql-request使おうとしたら起こったエラーはこれ↓https://github.com/jasonkuhrt/graphql-request
raphql-request:GitHub APIの仕様について
- トークンはClasicの方を使う
注: GraphQL API の認証には personal access token (classic)、GitHub App、または OAuth App を作成する必要があります。 GraphQL API は fine-grained personal access token を使った認証をサポートしていません。
https://docs.github.com/ja/enterprise-cloud@latest/graphql/guides/forming-calls-with-graphql
- ここにAPIのクエリの例が乗ってる
https://zenn.dev/gentamura/scraps/3718406d2c9316 - エクスプローラで色々試しながら欲しいデータを見つけるのが良さげ
https://docs.github.com/ja/graphql/overview/explorer
NuxtサイトにThree.jsを導入する
この記事を参考にして進めてみる。composables
にthree.jsのコードを置いて、.vue
から呼び出して使う方針らしい。
- three.js導入
yarn add @types/three three
参考記事をめちゃめちゃ参考にさせてもらいながら、こんな感じに
types/GitHub.ts
// 命名もうちょっと良いのあったやろ…
export type KusaWeek = {
contributionDays: {
date: string,
weekDay: number,
color: string,
contributionCount: number,
}[]
}
pages/kusa.vue
<template>
<div ref="container" class="w-full h-80">
<ClientOnly>
<GitHubKusa
:weeks="kusa.user.contributionsCollection.contributionCalendar.weeks"
:clientWidth="clientWidth"
:clientHeight="clientHeight"
/>
</ClientOnly>
</div>
</template>
<script setup lang="ts">
const kusa = useGitHub()
const container = ref<HTMLElement | null>(null)
const { clientHeight, clientWidth } = useWindowSize(container)
</script>
components/GitHubKusa.vue
<template>
<div ref="container"></div>
</template>
<script setup lang="ts">
import { KusaWeek } from "~/types/GitHub"
const props = defineProps<{
weeks: KusaWeek[]
clientWidth: number
clientHeight: number
}>()
const container: Ref<HTMLElement | null> = ref(null)
onMounted(() => {
if(!props.weeks) return
const { init } = useKusa(
container,
props.clientWidth,
props.clientHeight,
props.weeks
)
init()
})
</script>
composables/kusa.tsのkusa生成部分
const kusaMesh = (week: KusaWeek) => {
const group = new Group()
for (let i = 0; i < week.contributionDays.length; i++) {
const height = week.contributionDays[i].contributionCount
const geometry = new BoxGeometry(10, height, 10)
const material = new MeshBasicMaterial({ color: week.contributionDays[i].color})
const cube = new Mesh(geometry, material)
cube.position.set(i * 15, height / 2, 0)
group.add(cube)
}
return group
}
composables/kusa.tsのkusa作成部分2
// 草作成
const kusa = new Group()
for (let i = 0; i < weeks.length; i++) {
const weekMesh = kusaMesh(weeks[i])
weekMesh.position.set(0, 0, i * 21)
kusa.add(weekMesh)
}
kusa.position.set(-5, 0, -(weeks.length * 21 / 2))
こんな感じ
開発環境
% node -v
v16.19.1
% yarn -v
1.22.19
% lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 22.04.2 LTS
Release: 22.04
Codename: jammy
このスクラップは2023/05/07にクローズされました