Skip to content

Commit

Permalink
Merge pull request #88 from hairyf/application-ref
Browse files Browse the repository at this point in the history
[feat]: optimization of composition-api Based on Injection
  • Loading branch information
hairyf authored Jan 1, 2024
2 parents b0885f5 + f255262 commit 5e928c6
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 16 deletions.
3 changes: 2 additions & 1 deletion docs/.vitepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,13 @@ const themeConfig: DefaultTheme.Config = {
sidebar: {
'/guide/': [
{
text: 'Getting Started',
text: 'Guide',
items: [
{ text: 'Introduction', link: '/guide/introduction' },
{ text: 'Quick Start', link: '/guide/quick-start' },
{ text: 'Usage', link: '/guide/usage' },
{ text: 'Nuxtjs', link: '/guide/nuxtjs' },
{ text: 'Troubleshooting', link: '/guide/troubleshooting' },
],
},
{
Expand Down
51 changes: 51 additions & 0 deletions docs/guide/troubleshooting.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# A guide to common problems and how to solve them

This guide is intended to help you solve the most common issues that you might encounter when using Vue3 PIXI.

## Composition API failure

The Composition API of vue3-pixi is based on dependency injection. If you use the Composition API in a component at the same level as `<Application />`, you will receive the following warning:

![](https://pic.imgdb.cn/item/6592ba28c458853aefc26d55.jpg)

You can resolve this by binding a ref at the same level and providing it to the Composition API you are using in the component at the same level:

```vue
<script lang="ts" setup>
import { Application, useApplication, useRenderer, useScreen, useStage } from 'vue3-pixi'
const app = useApplication()
const screen = useScreen(app)
const renderer = useRenderer(app)
const stage = useStage(app)
</script>
<template>
<Application ref="app">
<!-- ... -->
</Application>
</template>
```

Note that if you use this approach, you cannot immediately access `app`. You need to use it within `onMounted`, similar to the characteristics of ref:

```ts
import { Application, useApplication } from 'vue3-pixi'
const app = useApplication()
const renderer = useRenderer(app)
const stage = useStage(app)

console.log(app.value) // undefined
console.log(stage.value) // undefined
console.log(renderer.value) // undefined
// ...
```

While `useScreen` will create a default empty rectangle if Application is not obtained, so you don't need to worry about screen-related calculations when using ref:

```ts
import { useScreen } from 'vue3-pixi'
const screen = useScreen(app)
screen.value // defaultRectangle
// ...
```
21 changes: 16 additions & 5 deletions packages/vue3-pixi/src/composables/useApplication.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,23 @@
import type { Ref } from 'vue-demi'
import { inject, ref } from 'vue-demi'
import { computed, inject, onMounted, ref } from 'vue-demi'
import type { Application } from 'pixi.js'
import { appInjectKey } from './internal'

export function useApplication<T = Application>(): Ref<T> {
const app = ref(inject(appInjectKey))
if (!app.value)
throw new Error('No PIXI Application found. Make sure to create one before using any other composable.')
return app as any
const app = ref(inject(appInjectKey, undefined))
const appComputed = computed({
get: () => app.value,
set: (value: any) => {
if (value.app)
app.value = value.app
},
})

onMounted(() => {
if (!app.value)
console.warn('not found <Application />, you can use ref for referencing or create a new component to be used as a child element of <Application /> with PIXI composition API.')
})

return appComputed as any
}

8 changes: 4 additions & 4 deletions packages/vue3-pixi/src/composables/useRenderer.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import type { IRenderer } from 'pixi.js'
import type { Application, ICanvas, IRenderer } from 'pixi.js'
import type { Ref } from 'vue-demi'
import { computed, unref } from 'vue-demi'

import { useApplication } from './useApplication'

export function useRenderer(): Ref<IRenderer> {
const useApp = useApplication()
return computed(() => unref(useApp).renderer)
export function useRenderer(app?: Ref<Application<ICanvas>>): Ref<IRenderer> {
const useApp = app || useApplication()
return computed(() => unref(useApp)?.renderer)
}
5 changes: 3 additions & 2 deletions packages/vue3-pixi/src/composables/useScreen.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import type { Ref } from 'vue-demi'
import { computed, unref } from 'vue-demi'

import type { Application, ICanvas } from 'pixi.js'
import { Rectangle } from 'pixi.js'

import { computedWithControl, useResizeObserver } from '@vueuse/core'
import { useApplication } from './useApplication'

export function useScreen(): Ref<Rectangle> {
const useApp = useApplication()
export function useScreen(app?: Ref<Application<ICanvas>>): Ref<Rectangle> {
const useApp = app || useApplication()
const view = computed(() => unref(useApp).view as HTMLCanvasElement)
const defaultRectangle = new Rectangle()

Expand Down
8 changes: 4 additions & 4 deletions packages/vue3-pixi/src/composables/useStage.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import type { Container } from 'pixi.js'
import type { Application, Container, ICanvas } from 'pixi.js'
import type { Ref } from 'vue-demi'
import { computed, unref } from 'vue-demi'

import { useApplication } from './useApplication'

export type StageInst = Container & EventTarget

export function useStage(): Ref<StageInst> {
const useApp = useApplication()
return computed(() => unref(useApp).stage as any)
export function useStage(app?: Ref<Application<ICanvas>>): Ref<StageInst> {
const useApp = app || useApplication()
return computed(() => unref(useApp)?.stage as any)
}

0 comments on commit 5e928c6

Please sign in to comment.