class Animate {

  frc = 60 // 帧率
  fTime = 1 / 60 * 1000 // 频率
  timeoutKey = null // 定时器序列号

  update () {
    // ... transform 逻辑
  }

  running () {
    timeoutKey = setTimeout(() => {
      this.update()
      this.running()
    }, this.fTime)
  }

  // 启动
  start () {
    this.running()
  }

  // 停机
  stop () { 
    clearTimeout(this.timeoutKey)
  }

}



class Animate {

  frcKey = null // 执行 key

  update () {
    // ... transform 逻辑
  }

  running () {
    this.update()
    this.frcKey = requestAnimationFrame(this.running)
  }

  // 启动
  start () {
    this.running()
  }

  // 停机
  stop () { 
    cancelAnimationFrame(this.frcKey)
  }

}

import * as THREE from 'three'
import { OrbitControls } from 'three/addons/controls/OrbitControls.js'


// 几何体创建
const createCube = () => {
  const geometry = new THREE.BoxGeometry(1, 1, 1)
  const material = new THREE.MeshBasicMaterial(0xffffff)
  return new THREE.Mesh(geometry, material)
}

const createContext = (canvasEl) => {

  // 创建场景
  const scene = new THREE.Scene()

  // 创建摄像机
  const { clientWidth: w, clientHeight: h } = canvasEl
  const camera = newCamera(75,  w / h, 0.1, 10000)
  scene.add(camera) // 添加

  // 创建渲染器
  const renderer = new THREE.WebGLRenderer({ antialias: true })
  canvasEl.appendChild(renderer.domElement)

  // 轨道控制器
  const controls = new OrbitControls(camera, renderer.domElement)

  // 环境光
  const enviroment = new THREE.AmbientLight(0xffffff, 1, 0, 0)
  scene.add(enviroment)

  // 立方几何体
  const cube = createCube()

  return {
    scene,
    camera,
    renderer,
    controls,
    cube
  }

}


const start = () => {

  const context = createContext(document.querySelector('canvas'))

  // 内容变更
  const frcChange = () => {
    context.cube.rotation.x += 0.01
    context.cube.rotation.y += 0.01
    // ...
  }

  const running = () => {

    frcChange()

    // 控制器状态更新
    context.controls.update()

    // 场景渲染更新
    context.renderer.render(context.scene, context.camera)

    requestAnimationFrame(running)
  }

}

