{"id":10970,"date":"2021-03-16T23:18:13","date_gmt":"2021-03-16T14:18:13","guid":{"rendered":"http:\/\/www.gisdeveloper.co.kr\/?p=10970"},"modified":"2022-10-30T08:38:33","modified_gmt":"2022-10-29T23:38:33","slug":"three-js%ec%97%90%ec%84%9c-%ea%b2%bd%eb%a1%9cpath%eb%a5%bc-%eb%94%b0%eb%9d%bc-%ea%b0%9d%ec%b2%b4-%ec%9d%b4%eb%8f%99%ec%8b%9c%ed%82%a4%ea%b8%b0","status":"publish","type":"post","link":"http:\/\/www.gisdeveloper.co.kr\/?p=10970","title":{"rendered":"three.js\uc5d0\uc11c \uacbd\ub85c(Path)\ub97c \ub530\ub77c \uac1d\uccb4 \uc774\ub3d9\uc2dc\ud0a4\uae30"},"content":{"rendered":"<p>\uad6c\ud604\ud558\uace0\uc790 \ud558\ub294 \uacb0\uacfc\ub294 \uc544\ub798\uc758 \uadf8\ub9bc\ucc98\ub7fc \ub178\ub780\uc0c9 \uacbd\ub85c\uac00 \uc788\uace0 \ube68\uac04\uc0c9 \uc9c1\uc721\uba74\uccb4\uac00 \uc774 \uacbd\ub85c\ub97c \ub530\ub77c \uc790\uc5f0\uc2a4\ub7fd\uac8c \uc774\ub3d9\ud558\ub294 \uac83\uc785\ub2c8\ub2e4.<\/p>\n<p><center><video width=\"75%\" controls autoplay loop><source src=\"http:\/\/www.gisdeveloper.co.kr\/wp-content\/uploads\/2021\/03\/three.js.move_.path_.mp4\">\ube44\ub514\uc624\ub97c \uc9c0\uc6d0\ud558\uc9c0 \uc54a\ub294 \uc6f9\ube0c\ub77c\uc6b0\uc838\uc785\ub2c8\ub2e4.<\/video><\/center><\/p>\n<p>\uba3c\uc800 \uc81c\uac00 \uc0ac\uc6a9\ud558\ub294 three.js\uc758 \uad6c\uc131 \uc911 \uac70\uc758 \ubcc0\uacbd\ub418\uc9c0 \uc54a\ub294 HTML\uacfc CSS\ub97c \uc0b4\ud3b4\ubcf4\uaca0\uc2b5\ub2c8\ub2e4. HTML\uc740 \ub2e4\uc74c\uacfc \uac19\uc2b5\ub2c8\ub2e4.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"html\">\r\n&lt;!DOCTYPE html>\r\n&lt;html>\r\n    &lt;head>\r\n        &lt;meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\r\n        &lt;link rel=\"stylesheet\" href=\"style.css\">\r\n        &lt;script type=\"module\" src=\"app.js\" defer><\/script>\r\n    &lt;\/head>\r\n    &lt;body>\r\n    &lt;\/body>\r\n&lt;\/html> \r\n<\/pre>\n<p>CSS\ub294 \ub2e4\uc74c\uacfc \uac19\uad6c\uc694.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"html\">\r\n* {\r\n    outline: none;\r\n    padding: 0;\r\n    margin: 0;\r\n}\r\n<\/pre>\n<p>\uadf8\ub9ac\uace0 \uc774\uc81c app.js\uc5d0 \ub300\ud55c \ucf54\ub4dc\ub97c \uc0b4\ud3b4\ubcf4\uaca0\uc2b5\ub2c8\ub2e4. \uba3c\uc800 \uae30\ucd08 \ucf54\ub4dc\uc785\ub2c8\ub2e4.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\">\r\nimport * as THREE from 'https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/three.js\/r126\/three.module.min.js'\r\n\r\nclass App {\r\n    constructor() {\r\n        this._initialize();\r\n    }\r\n\r\n    _initialize() {\r\n        this.domWebGL = document.createElement('div');\r\n        document.body.appendChild(this.domWebGL);\r\n\r\n        let scene = new THREE.Scene();\r\n        let renderer = new THREE.WebGLRenderer();\r\n\r\n        renderer.setClearColor(0x000000, 1.0);\r\n        this.domWebGL.appendChild(renderer.domElement);  \r\n        window.onresize = this.resize.bind(this); \r\n        \r\n        this.renderer = renderer;\r\n        this.scene = scene;\r\n\r\n        this._setupModel();\r\n        this._setupLights()\r\n        this._setupCamera();\r\n\r\n        this.resize();\r\n    }\r\n\r\n    _setupModel() {\r\n        \/\/ \uacbd\ub85c \ubc0f \uc9c1\uc0ac\uac01\ud615 \ubaa8\ub378 \uad6c\uc131\r\n    }\r\n\r\n    update(time) {\r\n        \/\/ \uc9c1\uc0ac\uac01\ud615 \ubaa8\ub378\uc744 \uacbd\ub85c\uc5d0 \ub530\ub77c \uc774\ub3d9\uc2dc\ud0b4\r\n    }\r\n\r\n    _setupLights() {\r\n        const light = new THREE.DirectionalLight(0xffffff, 1);\r\n        light.position.set(30, 50, 20);\r\n        this.scene.add(light);\r\n    }\r\n\r\n    _setupCamera() {\r\n        const fov = 60;\r\n        const aspect = 1;\r\n        const zNear = 0.1;\r\n        const zFar = 1000;\r\n        \r\n        let camera = new THREE.PerspectiveCamera(fov, aspect, zNear, zFar);\r\n\r\n        camera.position.set(40, 40, 40).multiplyScalar(0.3);\r\n        camera.lookAt(0,-2,0);\r\n        \r\n        this.scene.add(camera);\r\n        this.camera = camera;\r\n    }\r\n\r\n    render(time) {\r\n        requestAnimationFrame(this.render.bind(this));\r\n\r\n        this.update(time);\r\n        this.renderer.render(this.scene, this.camera);\r\n    }\r\n\r\n    resize() {\r\n        let camera = this.camera;\r\n        let renderer = this.renderer;\r\n        \r\n        renderer.setPixelRatio(window.devicePixelRatio);\r\n        renderer.setSize(window.innerWidth, window.innerHeight);\r\n\r\n        camera.aspect = window.innerWidth \/ window.innerHeight;\r\n        camera.updateProjectionMatrix();\r\n    }\r\n}\r\n\r\nwindow.onload = function() {\r\n    (new App()).render(0);\r\n}\r\n<\/pre>\n<p>\uc704\uc758 \ucf54\ub4dc\uc5d0\uc11c \uacbd\ub85c\uc640 \uc815\uc721\uba74\uccb4 \ub9e4\uc26c\ub97c \uad6c\uc131\ud558\ub294 _setupModel\uacfc \ub9e4\uc26c \ubaa8\ub378\uc744 \uc6c0\uc9c1\uc774\ub3c4\ub85d \uc18d\uc131\uac12\uc744 \uc5c5\ub370\uc774\ud2b8\ud558\ub294 update \ud568\uc218\ub294 \uc544\uc9c1 \ube44\uc5b4 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n<p>\ubaa8\ub378\uc744 \uad6c\uc131\ud558\ub294 _setupModel \ud568\uc218\uc758 \ucf54\ub4dc\ub294 \ub2e4\uc74c\uacfc \uac19\uc2b5\ub2c8\ub2e4.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\">\r\n_setupModel() {\r\n    const path = new THREE.SplineCurve( [\r\n        new THREE.Vector2( 10, 5 ),\r\n        new THREE.Vector2( 5, 5 ),\r\n        new THREE.Vector2( 5, 10 ),\r\n        new THREE.Vector2( -5, 10 ),\r\n        new THREE.Vector2( -5, 5 ),\r\n        new THREE.Vector2( -10, 5 ),\r\n        new THREE.Vector2( -10, -5 ),\r\n        new THREE.Vector2( -5, -5 ),\r\n        new THREE.Vector2( -5, -10 ),\r\n        new THREE.Vector2( 5, -10 ),\r\n        new THREE.Vector2( 5, -5 ),\r\n        new THREE.Vector2( 10, -5 ),\r\n        new THREE.Vector2( 10, 5 ),\r\n    ] );\r\n\r\n    this.path = path;\r\n\r\n    const points = path.getPoints( 100 );\r\n    const geometry = new THREE.BufferGeometry().setFromPoints( points );\r\n    const material = new THREE.LineBasicMaterial( { color : 0xffff00 } );\r\n    const pathLine = new THREE.Line( geometry, material );\r\n    pathLine.rotation.x = Math.PI * .5;\r\n    this.scene.add(pathLine);\r\n\r\n    const boxGeometry = new THREE.BoxGeometry(1, 1, 3);\r\n    const boxMaterial = new THREE.MeshPhongMaterial({color: 0xff0000});\r\n    const boxMesh = new THREE.Mesh(boxGeometry, boxMaterial);\r\n    this.scene.add(boxMesh);\r\n\r\n    this.boxMesh = boxMesh;\r\n}\r\n<\/pre>\n<p>\uadf8\ub9ac\uace0 update \ud568\uc218\ub294 \ub2e4\uc74c\uacfc \uac19\uc2b5\ub2c8\ub2e4.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\">\r\nupdate(time) {\r\n    const boxTime = time * .0001;\r\n\r\n    const boxPosition = new THREE.Vector3();\r\n    const boxNextPosition = new THREE.Vector2();\r\n    \r\n    this.path.getPointAt(boxTime % 1, boxPosition);\r\n    this.path.getPointAt((boxTime + 0.01) % 1, boxNextPosition);\r\n    \r\n    this.boxMesh.position.set(boxPosition.x, 0, boxPosition.y);\r\n    this.boxMesh.lookAt(boxNextPosition.x, 0, boxNextPosition.y);\r\n}\r\n<\/pre>\n<p>\uc704\uc758 \ucf54\ub4dc \uc911 7\uacfc 8\ubc88 \ub77c\uc778\uc758 getPointAt\uc740 \uacbd\ub85c\ub97c \uad6c\uc131\ud558\ub294 \uc88c\ud45c\ub97c \uc5bb\uc744 \uc218 \uc788\ub294\ub370, \uc774 \ud568\uc218\uc758 \uccab\ubc88\uc9f8 \uc778\uc790\ub294 0\uc5d0\uc11c 1\uc0ac\uc774\uc758 \uac12\uc744 \uac00\uc9c8 \uc218 \uc788\uace0 0\uc77c\ub54c \uacbd\ub85c\uc758 \uc2dc\uc791\uc810 1\uc77c\ub54c \uacbd\ub85c\uc758 \ub05d\uc810\uc744 \uc5bb\uc744 \uc218 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\uad6c\ud604\ud558\uace0\uc790 \ud558\ub294 \uacb0\uacfc\ub294 \uc544\ub798\uc758 \uadf8\ub9bc\ucc98\ub7fc \ub178\ub780\uc0c9 \uacbd\ub85c\uac00 \uc788\uace0 \ube68\uac04\uc0c9 \uc9c1\uc721\uba74\uccb4\uac00 \uc774 \uacbd\ub85c\ub97c \ub530\ub77c \uc790\uc5f0\uc2a4\ub7fd\uac8c \uc774\ub3d9\ud558\ub294 \uac83\uc785\ub2c8\ub2e4. \ube44\ub514\uc624\ub97c \uc9c0\uc6d0\ud558\uc9c0 \uc54a\ub294 \uc6f9\ube0c\ub77c\uc6b0\uc838\uc785\ub2c8\ub2e4. \uba3c\uc800 \uc81c\uac00 \uc0ac\uc6a9\ud558\ub294 three.js\uc758 \uad6c\uc131 \uc911 \uac70\uc758 \ubcc0\uacbd\ub418\uc9c0 \uc54a\ub294 HTML\uacfc CSS\ub97c \uc0b4\ud3b4\ubcf4\uaca0\uc2b5\ub2c8\ub2e4. HTML\uc740 \ub2e4\uc74c\uacfc \uac19\uc2b5\ub2c8\ub2e4. &lt;!DOCTYPE html> &lt;html> &lt;head> &lt;meta name=&#8221;viewport&#8221; content=&#8221;width=device-width, initial-scale=1&#8243;> &lt;link rel=&#8221;stylesheet&#8221; href=&#8221;style.css&#8221;> &lt;script type=&#8221;module&#8221; src=&#8221;app.js&#8221; defer> &lt;\/head> &lt;body> &lt;\/body> &lt;\/html> CSS\ub294 &hellip; <\/p>\n<p class=\"link-more\"><a href=\"http:\/\/www.gisdeveloper.co.kr\/?p=10970\" class=\"more-link\">\ub354 \ubcf4\uae30<span class=\"screen-reader-text\"> &#8220;three.js\uc5d0\uc11c \uacbd\ub85c(Path)\ub97c \ub530\ub77c \uac1d\uccb4 \uc774\ub3d9\uc2dc\ud0a4\uae30&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[145,139],"tags":[],"class_list":["post-10970","post","type-post","status-publish","format-standard","hentry","category-three-js","category-webgl"],"_links":{"self":[{"href":"http:\/\/www.gisdeveloper.co.kr\/index.php?rest_route=\/wp\/v2\/posts\/10970","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.gisdeveloper.co.kr\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.gisdeveloper.co.kr\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.gisdeveloper.co.kr\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.gisdeveloper.co.kr\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=10970"}],"version-history":[{"count":11,"href":"http:\/\/www.gisdeveloper.co.kr\/index.php?rest_route=\/wp\/v2\/posts\/10970\/revisions"}],"predecessor-version":[{"id":12719,"href":"http:\/\/www.gisdeveloper.co.kr\/index.php?rest_route=\/wp\/v2\/posts\/10970\/revisions\/12719"}],"wp:attachment":[{"href":"http:\/\/www.gisdeveloper.co.kr\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=10970"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.gisdeveloper.co.kr\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=10970"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.gisdeveloper.co.kr\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=10970"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}