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);
...