음악, 삶, 개발

Vue 에서 p5.js 사용하기 : p5 의 instance 모드 본문

개발 Web/Vue.js 공부방

Vue 에서 p5.js 사용하기 : p5 의 instance 모드

Lee_____ 2020. 12. 10. 04:55

< 참고 자료 >

 

www.npmjs.com/package/p5

Youtube : Instance mode (a.k.a name spacing) 

Instance container


< p5.js 란? >

 

p5.js 는 HTML5 의 <canvas> 를 엄청나게 확장해주는 그래픽 라이브러리이다.

물론 <canvas> 가 기본적으로 제공하는 함수들만으로도 그려볼수있겠지만

복잡한 도형들을 그려낼려면 엄청난 노가다를 해야한다.

p5.js 가 제공하는 수많은 함수들을 사용하면, 훨씬 더 우아한 그림들을 그려낼수있다.


< 하지만 vue 애서 어떻게 p5.js 를? >

 

구글에서 p5 를 vue 에서 사용하는 것을 검색했을때,

결과가 거의 나오지않았다.

나오더라도 vue 3 의 composition api 를 사용하지않은 예제들이 대부분이었다.

그래서 엄청나게 디깅을 하고, 혼자 이것저것 코드를 해본 결과 방법을 마침내 찾아내었다.

 

다행인것은 p5 가 npm 모듈로도 출시되었다는것이다.

먼저 아래와 같이 설치한다.

npm i p5

그 다음 .vue 를 일단 아래와 같이 작성한다.

<!-- App.vue -->

<template>
    
    <div id="container"></div>

</template>

<script>

    import P5 from 'p5'

</script>

이제 p5 의 instance 를 만드는 코드를 추가해야한다.

function createP5(parentId, w, h, backgroundColor) {

    const sketch = (p) => {

        p.setup = () => { 
            
            p.noLoop()
            p.createCanvas(w, h)
            
        }

        p.draw = () => p.background(backgroundColor)

    }
    
    return new P5(sketch, parentId)

}

위의 함수는 내가 만들었다.

이 함수는 p5 인스턴스를 초기화하고 생성해주는 코드이다.

깊게 이해하려하기보다는 외우는것이 편하다.

p5 의 instance 는 <canvas> 요소를 만들어낸다.

이 <canvas> 요소가 생성되면 들어갈 부모 태그가 필요한데, 이때 사용하는것이 parentId 이다.

그후의 인자인 w, h 는 <canvas> 의 width 와 height 속성이 된다. 

backgroundColor 는 p5 의 background 함수의 인자로 넘겨지게된다.

이 createP5 함수는 p5 인스턴스를 초기화하면서 생성해주는데,

반드시 Vue 의 onMounted() 훅에서 호출되어야한다.

왜냐면 부모 컴포넌트가 먼저 생성되고 <canvas> 요소가 이 안으로 삽입되어야하기때문이다.

import { reactive, onMounted } from 'vue'

export default {

    setup() {

        const state = reactive({ 

            p5 : {}

        })

        onMounted(() => {

            state.p5 = createP5('container', 500, 500, 'green')
            
        })

    }

}

createP5 로 return 된 p5 인스턴스는 반드시 state 로 저장되어야한다.

그래야 추후 이 p5 인스턴스에 접근하여 무언가를 추가적으로 런타임에서 그려낼수있기때문이다.

위와 같이 onMounted 에서 p5 instance 를 생성하였다면,

p5 가 제공하는 모든 함수들을 호출하면서 그림을 그려내면된다.

function mouseDown() {

  state.p5.background('red')
  state.p5.ellipse(0, 0, 100, 100)

}

보이는것처럼, p5 인스턴스에서 무언가를 그리기위해서는

p5.draw() 를 우리가 호출할 필요가없고, 다이렉트로 p5 의 인스턴스에서

ellipse 같이 원하는 함수를 호출해버리면 바로 그려진다.

만약 Vue 의 일반적인 방법처럼 state 안에 데이터와

연동하고싶다면 초기화할때 draw 안에 모든것을 정의한뒤

state 가 변할때 redraw() 함수를 호출하는것이 현명할것이다.


< 모듈로 만들자 >

 

이 p5 인스턴스를 만드는 함수는 매우 자주 사용할것이므로,

따로 .js 파일로 만든뒤 .vue 에서 import 하여 사용하는것이 좋을것이다.

/* p5.js */

import P5 from 'p5'

function createP5(parentId, w, h, backgroundColor) {

    const sketch = p => {

        p.setup = () => {

            p.noLoop()
            p.createCanvas(w, h)

        }

        p.draw = () => p.background(backgroundColor)

    }

    return new P5(sketch, parentId)

}

export default createP5

로 정의후..

<!-- App.vue -->

<template>
    
    <div id="p5-container"></div>

</template>

<script>

    import { onMounted } from 'vue'
    import createP5  from '../library/p5.js'

    export default {

        setup() {

            onMounted(() => {

                createP5('p5-container', 200, 200, 'green')

            })

        }

    }

</script>

<style scoped>

    #p5-container {

        width               : 500px;
        height              : 500px;
        background-color    : black;

    }

</style>

같이 작성하면..