Web/Front - Vue

vue / webpack / three.js

잉_민 2022. 8. 21. 02:38
728x90
반응형

프론트 개발환경을 vue로 정했고.

https://ing-min.tistory.com/31?category=1052709 

 

Vue_시작하기

[작업 환경 만들기] 0.node 설치(14.18.2 버전) https://nodejs.org/ko/download/releases/ 이전 릴리스 | Node.js Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine. nodejs.org 윈도..

ing-min.tistory.com

3d 오브젝트를 mqtt를 활용해 제어하고 싶다.

그러기 위해서 three.js를 사용하기로 했고,

내 obj 파일을 three.js의 obj loader 로 올리려고했다 하지만 obj 파일을 경로에서 읽지 못한다.

-> public 경로를 사용해 axios를 활용해 불러올 수 있지만

경로의 특정 파일을 webpack의 file loader로 쉽게 활용한다 하니 이참에 vue + webpack 환경을 구현해보기로 했다.

  • vue : 우리가 사용할 JS 프레임워크.
  • vue-loader : Vue 파일을 JS로 변환해준다.
  • vue-template-compiler : Vue 파일을 JS로 변환해준다.
  • webpack : 파일을 일부 변형하여 코드를 전달하고 하나로 묶어주는 도구. ⚠️버전주의
  • webpack-cli : webpack 명령을 실행하는 사용하는 cli.  ⚠️버전주의
  • webpack-dev-server : 로컬에서 개발 서버를 실행하기 위해 사용하는 도구.  ⚠️버전주의
  • babel-loader : 우리의 코드를 브라우저에 맞는 코드로 변환해준다. (ES6 => ES5)
  • css-loader : vue에서 구현한 css 파일을 가져와서 해당 파일의 경로로 확인해준다. ⚠️버전주의
  • vue-style-loader : css-loader로 불어온 css 파일을 html에 삽입해준다.
  • sass-loader : vue에서 구현한 sass 파일을 가져와서 해당 파일의 경로로 확인해준다.
  • mini-css-extract-plugin : 자바스크립트 파일에서 css를 별도의 파일로 분리해서 번들링하게 해준다.
  • html-webpack-plugin : index.html을 가져와서 번들된 JS파일을 header에 삽입한다.
  • rimraf : 명령줄에서 파일삭제를 허용해준다. 여러번 프로젝트를 빌드할때 유용하며, 오래된 빌드를 삭제해준다.
  • -D : 하나의 파일로 모든 파일의 종속성을 묶어준다.

https://chb2005.tistory.com/16

 

[Vue] 웹팩 설치 및 사용법

전에 만들었던 더하기 문제 맞추기 예시를 통해 웹팩 개념 정리 ● 웹팩이란? 웹팩 : HTML, CSS, Javascript 등 많은 파일들을 하나의 js 파일로 변환 해주는 도구 코드 관리 용이, 로딩 속도 증가, 버전

chb2005.tistory.com


웹펙 / 뷰 설치

그렇다면 webpack이 도데체 뭘까

웹팩은 HTML,CSS, Javascript 등 많은 파일들을 하나의 js 파일로 변환해주는 도구라고 .. 한다.

코드관리가 용이하고 로딩 속도가 증가하고 버전 관리가 용이하여 다들 사용한다고 한다..

 

후.

일단 설치해보다가 많은 문제가 발생했다.

npm run serve 자체가 안 된다. 뭐가 문제일까 ... -> 버전 문제였다. 으으

 

- 설치 과정

node.js를 설치하여 npm을 사용할 수 있어야한다.

경로 파일을 하나 만든다.

npm init -y

npm install -g @vue/cli@4.5.15
vue create vueproj
#여기 설정은 위의 사이트 경로에서 확인 vue 버전이 2여야 three.js 오류 없다 !!!!주의

npm i webpack@4.10.0 -D
npm i webpack-cli@4.10.0 -D

npm i vue-loader@15.0.0 -D

npm i vue-template-compiler -D

(+ CSS 사용하려면 'npm i css-loader -D', 'npm i vue-sytle-loader -D' 입력)

npm install

 

webpack.config.js 파일 만들기

const path = require("path");
const { VueLoaderPlugin } = require('vue-loader');

module.exports = {
  //진입점
  entry: {
    app: path.join(__dirname, "main.js"), //웹팩으로 빌드할 파일
  },
  // 결과물에 대한 설정
  output: {
    filename: "[name].js", //app.js 결과물을 담은 파일
    path: path.join(__dirname, "dist"), // 결과물이 저장될 디렉토리
  },
   //모듈 rules를 통해 .vue로 끝나는 파일들은 vue-loader를 사용하겠다고 정의 vue->js
   module: {
    rules: [
        {
          test: /\.vue$/,
          loader: 'vue-loader'
        }
    ]
},
//플러그인 vue-loder를 위해 vueloaderplugin 가져옴
plugins: [
    new VueLoaderPlugin()
]
};

const VueLoaderPlugin  불러올 수 없다는 오류 -> const { VueLoaderPlugin } = require('vue-loader'); 대괄호 이렇게 쳐주니 수정됨..

 

package.json(버전 확인 !!!!! webpack 들어간 애들은 다 버전이 같아야한다  하하하)

(버전확인 !!! vue loader 버전 17-> 15로 :cannot find module 'vue/compiler-sfc' 이 오류 뜰 때 ..)

{
  "name": "vuewebpack",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "serve": "webpack-dev-server --mode development",
    "build": "webpack --watch"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "vue-loader": "^15.0.0",
    "vue-template-compiler": "^2.7.9",
    "webpack": "^4.10.0",
    "webpack-cli": "^4.10.0"
  },
  "dependencies": {
    "html-webpack-plugin": "^5.5.0",
    "vue-gl": "^1.0.0",
    "webpack-dev-server": "^4.10.0"
  }
}

scripts 부분  test일 경우 serve로 고쳐주기

  "scripts": {
    "serve": "webpack-dev-server --mode development"
  },

이래야 npm run serve 가능 (웹 띄우는 코드)

build 명령어를 사용하면 계속 껏다켰다 안 하고 수정하는 대로 바로 run 되서 편리함.

 

프로젝트를 배포하기 위해서는 빌드작업을 해줘야한다. webpack-dev-server는 작업을 할때, 진행사항을 눈으로 확인하기위해 사용하는 서버이지 배포용 서버가 아니기 때문이다. package.json에 clean과 build를 스크립트를 추가하자. 한 단계전인 [serve] 추가하기에 있는 이미지를 참고하면 작업이 더욱 쉬울 것이다. 아래내용을 작성하자.

 

"scripts": {
    "clean": "rimraf dist",
    "build": "npm run clean && webpack --mode production",
    "serve": "webpack-dev-server --mode development"
  },

 

빌드를 시작하면 dist라는 폴더가 생기는데  Webpack이 프로젝트를 빌드 할 때 자동으로 생성되는 폴더이니 신경쓰지 말자! 아래 명령어를 사용하면 프로젝트가 빌드된다.

npm run build

참고

https://hj-tilblog.tistory.com/75

 

Vue.js Webpack 초기세팅

 webpack으로 초기세팅을 하자! 사실 해당 글은 예전에도 정리한적이 있는데, 동기분들이 읽고 따라하기에 부족한점이 있는 것같아 내용을 보충하여 새로 정리하고자 한다. 순서대로 따라 진행한

hj-tilblog.tistory.com


.eslintrc.js

module.exports = {
  root: true,
  env: {
    node: true,
  },
  // extends: ["plugin:vue/essential", "eslint:recommended", "@vue/prettier"],
  extends: ["plugin:vue/recommended", "eslint:recommended", "@vue/prettier"],
  parserOptions: {
    parser: "babel-eslint",
  },
  rules: {
    "prettier/prettier": [
      "error", {
        singleQuote: true,
        semi: false,
        useTabs: false,
        tabWidth: 2,
        trailingComma: "none",
        printWidth: 120,
        bracketSpacing: true,
        arrowParens: "avoid",
        endOfLine: "auto",
      }
    ],
    "no-console": process.env.NODE_ENV === "production" ? "warn" : "off",
    "no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off",
    "no-unused-vars": ["warn", { vars: "all", args: "after-used", ignoreRestSiblings: false }],
  },
};

setting.js

{
  "eslint.validate": ["vue", "javascript", "html"],
  "eslint.alwaysShowStatus": true,
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true
  },
  "eslint.workingDirectories": [{ "mode": "auto" }],
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "editor.formatOnSave": false,
  "prettier.trailingComma": "all"
}

부트스트랩 설치\

npm install bootstrap@4.5.3 bootstrap-vue@2.21.2 --save

 

https://archijude.tistory.com/487

 

Vue.js) global(전역) 함수 만들어서 콘솔 로고 사용하기

개발중에 console.log를 사용했던것 들을 개발이 끝난뒤 일일히 지우기가 매우 번거로워 처음부터 전역 함수로 만들어서 사용하기로 하였습니다. 생성 방벙에 대해 적어보겠습니다. - 개발환경 (vue

archijude.tistory.com

main.js 에 use 추가하기 : 글로벌로 선언하여 모든 파일에서 쓸수 있게한다 !.

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'

Vue.config.productionTip = false
// bootstrap
import { BootstrapVue } from 'bootstrap-vue'
import 'bootstrap/dist/css/bootstrap.css'
import 'bootstrap-vue/dist/bootstrap-vue.css'

Vue.use(BootstrapVue)

new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')

이제 three.js!!!!!!!

npm install --save three

 

main.js

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import * as Three from 'three'

Vue.config.productionTip = false
// bootstrap
import { BootstrapVue } from 'bootstrap-vue'
import 'bootstrap/dist/css/bootstrap.css'
import 'bootstrap-vue/dist/bootstrap-vue.css'

Vue.use(BootstrapVue)
Vue.use(Three)

new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')

views/Three.vue

<template>
  <div id="container"></div>
</template>
<script>
import * as THREE from 'three'

export default {
  name: 'ThreeTest',
  data() {
    return {
      cube: null,
      renderer: null,
      scene: null,
      camera: null
    }
  },
  mounted() {
    this.init()
    this.animate()
  },
  methods: {
    init: function () {
      this.scene = new THREE.Scene()
      this.camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000)

      this.renderer = new THREE.WebGLRenderer()
      this.renderer.setSize(window.innerWidth, window.innerHeight)
      document.body.appendChild(this.renderer.domElement)

      const geometry = new THREE.BoxGeometry(1, 1, 1)
      const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 })
      this.cube = new THREE.Mesh(geometry, material)
      this.scene.add(this.cube)

      this.camera.position.z = 5

      const animate = function () {}
    },
    animate: function () {
      requestAnimationFrame(this.animate)

      this.cube.rotation.x += 0.01
      this.cube.rotation.y += 0.01

      this.renderer.render(this.scene, this.camera)
    }
  }
}
</script>

 

router 설정

index.js

import { createRouter, createWebHistory } from 'vue-router'
import Home from '../views/Home.vue'

const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home
  },
  {
    path: '/three',
    name: 'Three',
    // route level code-splitting
    // this generates a separate chunk (about.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    component: () => import(/* webpackChunkName: "three", webpackPrefetch:ture */ '../views/Three.vue')
  }
]

const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),
  routes
})

export default router

 

home 에서 three로 경로 이동하게 만들기

App.vue

<template>
  <div>
    <div id="nav">
      <router-link to="/">Home</router-link> |
      <router-link to="/three">Three</router-link>
    </div>
    <router-view />
  </div>
</template>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
}

#nav {
  padding: 30px;
}

#nav a {
  font-weight: bold;
  color: #2c3e50;
}

#nav a.router-link-exact-active {
  color: #42b983;
}
</style>

이렇게 오류없이 출력가능 ..

이제 원하는 obj를 띄워보자 ...


[three.js obj loader]

https://github.com/fritx/vue-threejs

 

GitHub - fritx/vue-threejs: Vue bindings for Three.js

Vue bindings for Three.js. Contribute to fritx/vue-threejs development by creating an account on GitHub.

github.com

obj 경로 꼭 public / static에 넣어야한다 !

example / SF03 

<template>
  <object3d :position="pos" base-url="static/threex/spaceships/">
    <mesh>
      <m-obj-mtl obj-url="SpaceFighter03.obj"
          mtl-url="SpaceFighter03.mtl"
          :process="getBody">
      </m-obj-mtl>
    </mesh>

    <mesh v-for="n in 2" :key="`1-${n}`" :scale="4"
        :position="{ x: 5 * Math.sign(n - 1.5), z: 0.8 }">
      <geometry type="Plane" :args="[1, 1]"></geometry>
      <material type="MeshBasic" :options="detonation.matOpts">
        <texture url="lensflare0_alpha.png"></texture>
      </material>
    </mesh>

    <object3d v-for="n in 2" :key="`2-${n}`"
        :rotation="{ y: Math.PI / 2 }" :scale="4"
        :position="{ x: 5 * Math.sign(n - 1.5), z: 2.6 }">
      <mesh v-for="n1 in 4" :key="n1"
          :rotation="{ x: (n1 - 1) * Math.PI / 4 }">
        <geometry type="Plane" :args="[1, 1]"></geometry>
        <material type="MeshBasic" :options="shoot.matOpts">
          <texture :canvas="shoot.txtCanvas"></texture>
        </material>
      </mesh>
    </object3d>

    <animation :fn="animate"></animation>
  </object3d>
</template>

<script>
import * as THREE from 'three'
import { Object3D } from '@'

export default {
  name: 'SF03',
  mixins: [Object3D],

  data () {
    return {
      detonation: {
        matOpts: {
          color: 0x00ffff,
          side: THREE.DoubleSide,
          blending: THREE.AdditiveBlending,
          opacity: 2,
          depthWrite: false,
          transparent: true
        }
      },
      shoot: {
        matOpts: {
          color: 0xffaacc,
          side: THREE.DoubleSide,
          blending: THREE.AdditiveBlending,
          depthWrite: false,
          transparent: true
        },
        txtCanvas: this.generateShootCanvas()
      },
      pos: null
    }
  },

  methods: {
    animate (tt) {
      this.pos = { y: Math.sin(tt) }
    },

    getBody (group) {
      let body = group.children[0]
      body.material.color.set(0xffffff)
      return body
    },

    /* eslint-disable semi, space-in-parens */
    generateShootCanvas () {
      // init canvas
      var canvas = document.createElement( 'canvas' );
      var context = canvas.getContext( '2d' );
      canvas.width = 16;
      canvas.height = 64;
      // set gradient
      var gradient = context.createRadialGradient(
        canvas.width / 2, canvas.height / 2, 0,
        canvas.width / 2, canvas.height / 2, canvas.width / 2
      );
      gradient.addColorStop( 0, 'rgba(255,255,255,1)' );
      gradient.addColorStop( 0.5, 'rgba(192,192,192,1)' );
      gradient.addColorStop( 0.8, 'rgba(128,128,128,0.7)' );
      gradient.addColorStop( 1, 'rgba(0,0,0,0)' );

      // fill the rectangle
      context.fillStyle = gradient;
      context.fillRect(0, 0, canvas.width, canvas.height);
      // return the just built canvas
      return canvas;
    }
  }
}
</script>

여기 코드를 바꿔서 썼다.

잘 로드되긴하는데..

회전..페어런트 가능한지 알아봐야한다,-> 그룹 가능 : 회전 순거 정하기 가능 diamond.eulerOrder = 'ZYX';

Three.js Editor

https://threejs.org/editor/

 

three.js editor

 

threejs.org

http://benchung.com/using-three-js-editor/

 

728x90
반응형