HTML5绘制一个3D立方体,HTML5/Canvas交互式3D立方体
JavaScript
语言:
JaveScriptBabelCoffeeScript
确定
'use strict';
var CSIZE = 500 /* canvas size */ ,
OFF = .5 * CSIZE /* canvas origin offset */ ,
VPOINT = 2 * CSIZE /* vanishing point */ ,
_c = document.querySelector('canvas'),
ct = _c.getContext('2d'),
/* controls */
_frm = document.querySelector('form'),
_btn = document.querySelector('button'),
_auto = document.getElementById('auto'),
_err = document.querySelector('.err');
var s3d = undefined /* 3D shape */ ,
hue = 5 /* hue for 3D shape faces */ ,
rot = [1, 0, 1] /* default rotate axis */ ,
ang = .005 * Math.PI /* default unit rotation */ ,
rID = null /* request ID */ ,
drag = false /* drag status */ ,
sol = false /* status on lock */ ,
/* coords when starting drag */
x0 = null,
y0 = null;
var Point = function Point() {
var x = arguments.length <= 0 || arguments[0] === undefined ? 0 : arguments[0];
var y = arguments.length <= 1 || arguments[1] === undefined ? 0 : arguments[1];
var z = arguments.length <= 2 || arguments[2] === undefined ? 0 : arguments[2];
var c = [] /* natural set of coords */ ,
/*
* coords flattened to plane,
* taking perspective into account
*/
p = [];
this.setCoords = function(x, y, z) {
var f = z / VPOINT + 1;
c = [x, y, z];
p = [f * x, f * y, z];
};
this.getCoords = function() {
var f = arguments.length <= 0 || arguments[0] === undefined ? 1 : arguments[0];
return f ? c : p;
};
this.setCoords(x, y, z);
};
var Polygon = function Polygon(v) {
var n = v.length /* number of poly vertices */ ,
o = [0, 0, 0] /* central point of poly */ ;
/* recompute central point coordinates */
this.refreshO = function() {
o = [0, 0, 0];
var _loop = function _loop(i) {
o = o.map(function(c, j) {
return c + v[i].getCoords()[j];
});
};
for (var i = 0; i < n; i++) {
_loop(i);
}
};
/* get central point coordinates */
this.getO = function() {
return o;
};
/* draw this polygon */
this.draw = function() {
var _Math;
var
/*
* sign of central point z coord
* + leads to lightening
* - leads to darkening
*/
s = Math.sign(o[2]),
/* fill lightness */
l = 75 + s * (1 - (_Math = Math).hypot.apply(_Math, o.slice(0, 2)) / (.5 * CSIZE)) * 25;
ct.fillStyle = 'hsl(' + hue + ',65%,' + l + '%)';
ct.beginPath();
for (var i = 0; i < n; i++) {
var c = v[i].getCoords(0);
c.splice(2, 1); /* remove the z coord */
ct[(i ? 'line' : 'move') + 'To'].apply(ct, c);
}
ct.closePath();
ct.fill();
ct.stroke();
};
};
var S6hedron = function S6hedron() {
var rc = arguments.length <= 0 || arguments[0] === undefined ? .64 * OFF : arguments[0];
var v = [] /* array to store vertices */ ,
f = [] /* array to store faces */ ,
nf = 6 /* no. of faces */ ,
nv = 8 /* no of vertices */ ;
/*
* rotate the faces in 3D
* a = angle of rotation
* r = vector around which rotation happens
*/
this.rot = function() {
var a = arguments.length <= 0 || arguments[0] === undefined ? ang : arguments[0];
var r = arguments.length <= 1 || arguments[1] === undefined ? rot : arguments[1];
/*
* explanation for variables
* http://stackoverflow.com/a/15208858/1397351
*/
var sc = .5 * Math.sin(a),
db = 1 - Math.cos(a) /* double sq */ ,
sq = .5 * db,
/* get the x*y*sq, y*z*sq, z*x*sq in SO answer */
b = r.map(function(c, i, a) {
return c * a[(i + 1) % 3] * sq;
}),
/* get the x*sc, y*sc, z*sc in SO answer */
c = r.map(function(c) {
return c * sc;
}),
m = [ /* the transform matrix */
[1 - db * (r[1] * r[1] + r[2] * r[2]), 2 * (b[0] - c[2]), 2 * (b[2] + c[1])],
[2 * (b[0] + c[2]), 1 - db * (r[0] * r[0] + r[2] * r[2]), 2 * (b[1] - c[0])],
[2 * (b[2] - c[1]), 2 * (b[1] + c[0]), 1 - db * (r[0] * r[0] + r[1] * r[1])]
];
var _loop2 = function _loop2(i) {
var _v$i;
var /* coords before the rotation */
c0 = v[i].getCoords(),
/*
* multiply matrix m to vector c0
* see https://codepen.io/thebabydino/pen/WoxvPy
* to get coords after the rotation
*/
c1 = m.map(function(c) {
return c.map(function(c, i) {
return c * c0[i];
}).reduce(function(p, c) {
return p + c;
}, 0);
});
(_v$i = v[i]).setCoords.apply(_v$i, c1);
};
for (var i = 0; i < nv; i++) {
_loop2(i);
}
/* compute central point for each face */
/* all convex, so it's enough :P */
for (var i = 0; i < nf; i++) {
f[i].refreshO();
}
sortFaces();
this.draw();
};
this.draw = function() {
ct.clearRect(-OFF, -OFF, CSIZE, CSIZE);
for (var i = 0; i < nf; i++) {
f[i].draw();
}
};
/*
* reorder faces in array based on
* z coord values
* of the faces' central points
*/
function sortFaces() {
f.sort(function(a, b) {
if (a.getO()[2] > b.getO()[2]) return 1;
if (a.getO()[2] < b.getO()[2]) return -1;
return 0;
});
};
/*
* create each face from vertices
* and add each face to f array
*/
function addFaces() {
var /* number of vertices per face */
nvf6 = 4;
f.push(new Polygon(v.slice(0, nvf6)));
f.push(new Polygon(v.slice(nvf6, nv)));
for (var i = 0; i < nvf6; i++) {
f.push(new Polygon([v[i], v[(i + 1) % nvf6], v[nvf6 + (i + 1) % nvf6], v[nvf6 + i]]));
}
};
/*
* compute coords for each vertex
* and add each vertex to v array
*/
(function addVertices() {
var /* cube inradius */
ri6 = rc / Math.sqrt(3),
/* cube face circumradius */
rcf6 = ri6 * Math.SQRT2,
/* number of vertices per face */
nvf6 = 4,
/* face base angle */
baf6 = 2 * Math.PI / nvf6;
/* 2 vertices on top, 2 at the bottom */
for (var i = 0; i < 2; i++) {
/* y coord */
var y = Math.round(Math.pow(-1, i) * ri6);
for (var j = 0; j < nvf6; j++) {
var /* current angle */
ca = j * baf6,
x = Math.round(rcf6 * Math.cos(ca)) /* x coord */ ,
z = Math.round(rcf6 * Math.sin(ca)); /* z coord */
v.push(new Point(x, y, z));
}
}
addFaces();
})();
};
function ani() {
s3d.rot();
rID = requestAnimationFrame(ani);
};
function getE(ev) {
return ev.touches ? ev.touches[0] : ev;
};
/*
* stop cube animation if necessary
* in order to start drag
*/
function lock(ev) {
if (ev.target === _c) {
var e = getE(ev);
drag = true;
x0 = e.clientX;
y0 = e.clientY;
if (rID) {
sol = true;
_auto.checked = false;
cancelAnimationFrame(rID);
rID = null;
}
}
};
/* act on drag, rotate cube */
function act(ev) {
if (drag) {
var e = getE(ev),
x = e.clientX,
y = e.clientY,
dx = x - x0,
dy = y - y0,
d = Math.hypot(dx, dy);
if (d) {
var i = (-dy / d).toFixed(5) /* x comp of rot axis */ ,
j = (dx / d).toFixed(5) /* y comp of rot axis */ ,
a = (.0035 * d).toFixed(2) /* rotation angle in rad */ ;
s3d.rot(a, [i, j, 0]);
}
x0 = x;
y0 = y;
}
};
/*
* stop drag, restart autorotation if necessary
*/
function release() {
if (drag) {
drag = false;
x0 = y0 = null;
if (sol && !rID) {
_auto.checked = true;
sol = false;
ani();
}
}
};
/* what to do when slider values change */
function update(e) {
var _Math2;
var tg = e.target,
d = undefined;
switch (true) {
case tg.id == 'hue':
hue = ~~tg.value;
break;
case tg.id == 'alpha':
ct.globalAlpha = .01 * tg.value;
break;
case tg.id == 'w':
ang = .0005 * tg.value * Math.PI;
break;
case tg.id.indexOf('axis') > -1:
var i = 1 * tg.id.split('axis')[1],
copy = rot.slice();
copy[i] = .01 * tg.value;
d = (_Math2 = Math).hypot.apply(_Math2, copy);
if (d === 0) {
tg.value = 10;
_err.classList.add('show');
} else rot = copy.map(function(c) {
return c / d;
});
break;
}
};
/* fade the "drag me!" info in or out */
function fadeInf() {
document.body.classList.toggle('faded');
};
/* init demo */
(function init() {
/* initially have the "drag me!" info faded */
document.body.classList.add('faded');
/* set canvas dimensions */
_c.width = _c.height = CSIZE;
/* put 0,0 point in the middle of canvas */
ct.translate(OFF, OFF);
/* set global alpha of strokes and fills */
ct.globalAlpha = .87;
/* set rgba value for edges */
ct.strokeStyle = 'rgba(0,0,0,.1)';
/* create cube object */
s3d = new S6hedron();
/* start animation */
ani();
})();
addEventListener('mousedown', lock, false);
addEventListener('touchstart', lock, false);
addEventListener('mousemove', act, false);
addEventListener('touchmove', act, false);
addEventListener('mouseup', release, false);
addEventListener('touchend', release, false);
_auto.addEventListener('change', function(e) {
if (_auto.checked && !rID) ani();
if (!_auto.checked && rID) {
cancelAnimationFrame(rID);
rID = null;
}
}, false);
_btn.addEventListener('click', function(e) {
_frm.classList.toggle('closed');
}, false);
addEventListener('input', update, false);
addEventListener('change', update, false);
_c.addEventListener('mouseover', fadeInf, false);
_c.addEventListener('mouseout', fadeInf, false);
_err.addEventListener('animationend', function(e) {
_err.classList.remove('show');
}, false);
HTML5绘制一个3D立方体,HTML5/Canvas交互式3D立方体相关推荐
- html5绘制运动的图形,html5 canvas高级贝塞尔曲线运动动画
canvas高级贝塞尔曲线运动动画 window.addEventListener('load',eventWindowLoaded,false);functioneventWindowLoaded( ...
- html5绘制节点链接,利用HTML5实现网状结构节点动画特效
特效描述:利用HTML5实现 网状结构 节点动画特效.利用HTML5实现网状结构节点动画特效 代码结构 1. HTML代码 (function() { var canvas, ctx, circ, n ...
- 用java绘制一个光照球体_HTML5 Canvas一个基本光线行进的球体光照效果
JavaScript 语言: JaveScriptBabelCoffeeScript 确定 var TWO_PI = 2 * Math.PI; var canvas; var canvasWidth; ...
- html制作星空,HTML5绘制星空
HTML5绘制一个很丑的星空 canvas{display: block;border:1px dotted skyblue;} HTML5绘制星空 var nimo={}; window.οnlοa ...
- 互交式3d地球仪工具:Earth 3D - World Atlas Mac
Earth 3D - World Atlas for Mac是一款3d地球仪.这个交互式 3D 地球仪以世界奇观.政治和物理地图以及天气为特色.发现许多关于我们星球的有趣事实和有用信息!原始的彩色图形 ...
- html页面画一个矩形,使用HTML5 canvas绘制一个矩形的方法
使用HTML5 canvas绘制一个矩形的方法 发布时间:2020-08-29 11:23:12 来源:亿速云 阅读:102 作者:小新 这篇文章将为大家详细讲解有关使用HTML5 canvas绘制一 ...
- HTML1个像素宽的代码,HTML5 Canvas中绘制一个像素宽的细线实现代码详情
正统的HTML5 Canvas中如下代码ctx.lineWidth = 1; ctx.beginPath(); ctx.moveTo(10, 100); ctx.lineTo(300,100); ct ...
- html5制作一个立方体,CSS3 3D transforms系列教程-立方体
学习制作3D翻转卡片是开始学习3D transform的一个好方法.一旦你掌握了3D翻转卡片的制作方法,是不是迫不及待的想制作更复杂的3D物体?我们在这个教程中将开始学习制作3D立方体. 3D立方体的 ...
- php 3d animation,如何用HTML5的Canvas制作3D动画效果
HTML5的诞生给web前端界带来了不小轰动,像什么动画旋转.图片滑块.图片轮播等等这些3D特效,也引发了不少朋友想要学习HTML5的好奇心.最近我一直在做canvas动画效果,发现canvas这个东 ...
- html5画布画点,在HTML5画布上绘制一个点
6 个答案: 答案 0 :(得分:141) 如果您打算绘制大量像素,使用画布的图像数据进行像素绘制会更有效率. var canvas = document.getElementById("m ...
最新文章
- 在Ubuntu中使用远程桌面
- npm install 原理(node_modules)
- Redis集群CentOS系统配置企业级数据备份方案以及数据恢复的操作(在开启AOF功能下恢复冷备RDB文件数据,保持AOF和RDB双开情况下恢复数据及错误的数据恢复步骤详解)
- 新浪微博客户端(eoe)
- 在MySQL登录时出现Access denied for user ‘root‘@‘localhost‘ (using password: YES)
- 全文搜索!收藏这篇Solr ElasticSearch 长文就可以搞定
- html如何设置滚动条居中,css3内容垂直居中及垂直滚动条例子
- 7 centos 时钟跟物理机同步_centos7上使用chrony自动同步时间
- html5如何绘制饼图,如何在HTML5中创建“饼图”?
- 【Java】浅析Java位移运算符<<、>>、>>>
- RPC的负载均衡策略
- vue 手动挂载组件 手动销毁组件_javascript原生手动分页组件
- TreeMap按照value进行排序
- 机器学习笔记(八):线性回归算法的评测标准 | 凌云时刻
- localtime选择00:00值不回显_配置OSPF的DR选择示例
- 数据结构导论(第一章概论)
- linux7如何改ssid,ssid怎么设置,教您网络ssid怎么设置
- 中台能力是什么?PaaS是什么?微服务是什么?
- cuda学习(5):使用cuda核函数加速warpaffine
- 13种MongoDB的GUI简介