JSFiddle - React, Tailwind, and code Playground

by secretgspot

HTML

<canvas id='world' width='465' height='425'></canvas><br />
視野角:<input type='text' id='f' value='60' onkeyup='fChanged(this);' />

CSS

body {
  background-color: #FFF;
  margin: 0;
  overflow: hidden;
}

JavaScript

/**
 * HTML5で3D
 * カメラを導入
 * マウス位置にカメラXY移動
 * マウスホイールでカメラZ移動
 * 
 */

function Vertex3D(x, y, z) {
  // 3D座標
  this.x = x || 0;
  this.y = y || 0;
  this.z = z || 0;
  
  // 2D座標
  this.screenX = 0;
  this.screenY = 0;
  
  this.project = function(camera) {
    var tx = this.x - camera.x;
    var ty = this.y - camera.y;
    var tz = this.z - camera.z;
    var scale = camera.fov / ( camera.fov - tz );
    this.screenX = tx * scale * canvas.width * 0.5 + canvas.width * 0.5;
    this.screenY = ty * scale * canvas.height * 0.5 + canvas.height * 0.5;
  };
}

function Camera(x, y, z, angle) {
  this._super = Vertex3D;
  this._super(x, y, z);
  this._angle = 0;
  this.fov = 0;
  this.angle = function(value) {
    if(value) {
      this._angle = value;
      this.fov = 1 / Math.tan(this._angle * 0.5 * Math.PI / 180);
    }
    else {
      return this._angle;
    }
  };
  this.angle(angle || 60);
}
Camera.prototype = new Vertex3D;


var canvas = document.getElementById('world');
var cxt = canvas.getContext("2d");

var camera = new Camera(Math.floor(canvas.width / 2), Math.floor(canvas.height / 2), 200);

function render() {
  cxt.clearRect(0, 0, 600, 500);
  
  var cx = Math.floor(canvas.width / 2);
  var cy = Math.floor(canvas.height / 2);
  
  var v1 = new Vertex3D();
  var v2 = new Vertex3D();
  
  var i;
  
  v1.y = v2.y = cy;
  for(i = 0; i <= 400; i+=50) {
    v1.x = v2.x = cx + i - 200;
    v1.z = 0;
    v2.z = -400;
    drawLine(v1, v2);
    
    v1.x = cx - 200;
    v2.x = cx + 200;
    v1.z = v2.z = -i;
    drawLine(v1, v2);
  }
  
  v1.x = v2.x = cx;
  for(i = 0; i <= 400; i+=50) {
    v1.y = v2.y = cy + i - 200;
    v1.z = 0;
    v2.z = -400;
    drawLine(v1, v2);
    
    v1.y = cy - 200;
    v2.y = cy + 200;
    v1.z = v2.z = -i;
    drawLine(v1, v2);
  }
  
  cxt.fillStyle = "#FF0000";
  cxt.fillText("camera (" + camera.x + ", " + camera.y + ", " + camera.z + ")", 10, 20);
}

function drawLine(v1, v2) {
  v1.project(camera);
  v2.project(camera);
 ...