<script type="importmap">
  {
    "imports": {      
      "three": "https://unpkg.com/three@0.159.0/build/three.module.js",
      "three/addons/": "https://unpkg.com/three@0.159.0/examples/jsm/"
    }
  }
</script>
<canvas id="test"></canvas>
html, body{
  margin: 0px;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 100%;
	height: 100%;
	background-color: #000;
}
canvas{
  width: 100%;
	height: 100%;
  color: gray;
}
import * as THREE from "three";
import * as BufferGeometryUtils from 'three/addons/utils/BufferGeometryUtils.js';
import { OrbitControls } from "three/addons/controls/OrbitControls.js";

var camera, scene, mesh, geometry, renderer, material, cube, light, canvas, group

// x= 14, y= 12
const targetImg = new Array(14).fill(new Array(12));
// mirrored Target Image
const colorRowMap ={
  0: ['r', 'r', 'r', 'b', 'r', 'b', 'r', 'r', 'r', 'r', 'r', 'r'],
  1: ['r', 'b', 'b', 'b', 'b', 'b', 'b', 'b', 'b', 'b', 'b', 'r'],
  2: ['r', 'b', 'b', 'b', 'g', 'b', 'b', 'b', 'r', 'r', 'r', 'r'],
  3: ['r', 'b', 'g', 'b', 'g', 'b', 'g', 'b', 'r', 'r', 'r', 'r'],
  4: ['r', 'b', 'g', 'b', 'g', 'b', 'r', 'r', 'r', 'r', 'r', 'r']
}
const kindOfRow = [0,0,1,1,2,3,4,4,3,2,1,1,0,0];
kindOfRow.forEach((el, i)=>{
  targetImg[i] = colorRowMap[el]
})

const setCamera = ()=>{
  const fov = 100;
  const aspect = window.innerWidth / window.innerHeight;
  const near =0.1;
  const far =200;
  camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
  camera.position.set(0, 0, 30);
  
  const controls = new OrbitControls(camera, canvas);
  controls.target.set(0, 2, 0);
  controls.enableZoom = true;
  controls.update();
}

function setLight(){
  const color = 0xFFFFFF;
  const intensity = 3;
  light = new THREE.DirectionalLight(color, intensity);
  light.position.set(-1, 2, 4);
}

function init(){
  canvas= document.getElementById('test');
  renderer = new THREE.WebGLRenderer({antialias: true, canvas});
  renderer.setSize( window.innerWidth, window.innerHeight );
  setCamera();
  setLight();
  scene = new THREE.Scene();
  
  const boxWidth = 2;
  const boxHeight = 2;
  const boxDepth = 2;
  group = new THREE.Group();
  
  const _color = new THREE.Color();
  //x
  targetImg.forEach((xArr, i)=>{
    //y
    xArr.forEach((kind, ii)=>{
      switch(kind){
        case 'r':
          _color.set(0xF74747);
          break;
        case 'g':
          _color.set(0x89F748);
          break;
        case 'b':
          _color.set(0x000000);
          break;
      }
      
      const material = new THREE.MeshLambertMaterial({ color: _color });
      const _geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
      _geometry.translate(i*2,ii*2,0);
      const cube = new THREE.Mesh( _geometry, material );
      group.add(cube);
    })  
  })
  
  scene.background = new THREE.Color( 'gray' );
  scene.add(group, light, camera);
  const axesHelper = new THREE.AxesHelper(5);
  scene.add(axesHelper);
  
  renderer.render(scene, camera);
  
  updateScene()
}

function needResize( renderer ) {
  const canvas = renderer.domElement;
  const width = canvas.clientWidth;
  const height = canvas.clientHeight;
  const needResize = canvas.width !== width || canvas.height !== height;
  if ( needResize ) {
    renderer.setSize( width, height, false );
  }
  return needResize;
}

var t=0

function move(index){
  const cube = group.children[index];
  const translateVar = t + index*0.5;
  cube.translateX(Math.cos(translateVar));
  cube.translateZ(Math.sin(translateVar));
  cube.translateY(Math.cos(translateVar));
  // cube.rotateOnWorldAxis(cube.position, Math.cos(translateVar) * 0.001);
  console.log(cube)
  // cube.rotation.x = Math.cos(translateVar);
  // cube.setRotationFromEuler(new THREE.Euler( Math.cos(translateVar)))
}

function animate(){
  // 움직일 원의 범위
  t+=0.1;
  {
    let index=0;
    
    // y축 기준 대각선으로 위치 변환
    for(index; index<12; index++){
      for(let _i=0; _i<=index; _i++){
        move(index + (_i * 11));
      }
    }
    
    // y축 기준 대각선 위치 변환
    // y축의 0은 이미x=12이므로 계산x
    for(let y =1; y<=14; y++){
      let index = ((y+1) * 12)-1
      const count = 14 - y;
      for(let _y = 0; _y <count; _y++){
        const targetIndex = index + (_y * 11);
        move(targetIndex);
      }
    }
  }
  
  scene.add(group);
}

var startTime=0;

function updateScene(time){
  // animate();
  if(time > startTime + 20){
    startTime +=20;
    animate();
  }
  if ( needResize(renderer)) {
    const canvas = this.renderer.domElement;
    camera.aspect = canvas.clientWidth / canvas.clientHeight;
    camera.updateProjectionMatrix();
  }
  renderer.render(scene, camera);
  
  requestAnimationFrame(updateScene)
}

init();
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.