Javascript HTML5画布生成等距图块

Javascript HTML5画布生成等距图块,javascript,html,canvas,isometric,axonometric,Javascript,Html,Canvas,Isometric,Axonometric,我试图在HTML5画布中生成基本的瓷砖和楼梯,而不使用图像 以下是我到目前为止所做的: 但我正试图重现这一点: 我不知道该怎么做 这是我当前的代码: 类等轴测图{ 构造器(画布、厚度){ 这个.Canvas=Canvas; this.Context=canvas.getContext(“2d”); if(厚度){ 这个。厚度=厚度; }否则{ 该厚度=2; } } LeftPanelWide(x、y、fillStyle){ this.Context.fillStyle=fillStyle

我试图在HTML5画布中生成基本的瓷砖和楼梯,而不使用图像

以下是我到目前为止所做的:

但我正试图重现这一点:

我不知道该怎么做



这是我当前的代码:

类等轴测图{
构造器(画布、厚度){
这个.Canvas=Canvas;
this.Context=canvas.getContext(“2d”);
if(厚度){
这个。厚度=厚度;
}否则{
该厚度=2;
}
}
LeftPanelWide(x、y、fillStyle){
this.Context.fillStyle=fillStyle;
对于(变量i=0;i<16;i++){
this.Context.fillRect(x+i*2,y+i*1,2,this.this*4);
}
}
右面板宽(x、y、fillStyle){
this.Context.fillStyle=fillStyle;
对于(变量i=0;i<16;i++){
this.Context.fillRect(x+(i*2),y+15-(i*1),2,this.this*4);
}
}
上面板宽(x、y、圆角样式){
this.Context.fillStyle=fillStyle;
对于(变量i=0;i<17;i++){
this.Context.fillRect(x+16+16-(i*2),y+i-2,i*4,1);
}
对于(变量i=0;i<16;i++){
this.Context.fillRect(x+i*2,y+(32/2)-1+i,((32/2)-i)*4,1);
}
}
上面板宽边框(x、y、fillStyle){
this.Context.fillStyle=fillStyle;
变量y=y+2;
对于(变量i=0;i<17;i++){
this.Context.fillRect(x+17+16-(i*2)-2,y+i-2,(i==17)?1:2,1);
this.Context.fillRect(x+17+16+(i*2)-2,y+i-2,(i==17)?1:2,1);
}
对于(变量i=0;i<32/2;i++){
this.Context.fillRect(x+i*2,y+16-1+i,2,1);
this.Context.fillRect(x+62-i*2,y+16-1+i,2,1);
}
}
右上面板小(x、y、fillStyle){
this.Context.fillStyle=fillStyle;
对于(变量i=0;i<32/2+4;i++){
这个.Context.fillRect(x+(i*2),(i>=4)?(i-1)+y:3-i+3+y,2,(i>=4)?(i=16)?y+(i-16):16+y-(i*1)-1,2,(i>=4)?(i>=16)?(i>=8-(i-16)-(i-16)-1:8:8*i-(i*6)+1);
}
}
LeftPanelSmall(x、y、fillStyle){
this.Context.fillStyle=fillStyle;
对于(变量i=0;i<8/2;i++){
this.Context.fillRect(x+i*2,y+i*1,2,this.this*4);
}
}
右面板小(x、y、fillStyle){
this.Context.fillStyle=fillStyle;
对于(变量i=0;i<8/2;i++){
this.Context.fillRect(x+(i*2),y+3-(i*1),2,this.this*4);
}
}
}
类等值线发生器{
构造函数(){
var Canvas=document.querySelector(“Canvas”);
var Context=Canvas.getContext(“2d”);
//背景。量表(5,5);
this.Context=Context;
this.IsometricGraphics=新的IsometricGraphics(画布,2);
}
StairLeft(x,y,Color1,Color2,Color3){
对于(变量i=0;i<4;i++){
这个.等距图.RightPanelWide((x+8)+(i*8),(y+4)+(i*12),Color1);
这个。等距图。左上面板小(x+(i*8),y+(i*12),彩色2);
等轴测图.左面板小((i*8)+x,(16+(i*12))+y,彩色3);
}
}
StairRight(x、y、Color1、Color2、Color3){
对于(变量i=0;i<4;i++){
这个.等距图.左面板宽(x+24-(i*8),(4+(i*12))+y,颜色1);
这。等距图。右上面板小(x+24-(i*8),y+(i*12)-3,彩色2);
此图。等距图。右面板小(x+56-(i*8),(16+(i*12))+y,彩色3);
}
}
瓷砖(x、y、颜色1、颜色2、颜色3、边框){
这个.等距图.左面板宽(x,18+y,彩色1);
这是等距图。右面板宽(x+32,18+y,彩色2);
这。等距图。上面板宽(x,2+y,彩色3);
如果(边界){
等轴测图.上面板宽边框(x,y,边框);
}
}
}
var Canvas=document.querySelector(“Canvas”);
var Context=Canvas.getContext(“2d”);
背景量表(3,3);
新的IsoGenerator().Tile(0,0,“#B3E5FC”、“#2196F3”、“#03A9F4”)
新的IsoGenerator().StairLeft(70,0,“#B3E5FC”、“#2196F3”、“#03A9F4”)
新的IsoGenerator().StairRight(70*2,0,“#B3E5FC”、“#2196F3”、“#03A9F4”)
//我想复制的是:http://i.imgur.com/YF4xyz9.png
轴测渲染 处理轴测(通常称为等轴测)渲染的最佳方法是在三维中建模对象,然后在所需的特定轴测投影中渲染模型

作为网格的三维对象 最简单的对象(在本例中)是一个长方体。长方体有6条边和8个顶点,可以通过其顶点和表示边的多边形来描述,这些边是顶点的一组索引

例如,x从左到右,y从上到下,z向上的3D框

首先创建构成长方体的顶点

更新根据评论中的要求,我已将框更改为其x、y、z维度

// function creates a 3D point (vertex)
function vertex(x,y,z){ return {x,y,z} };
// an array of vertices
const vertices = []; // an array of vertices

// create the 8 vertices that make up a box

const boxSizeX = 10;   // size of the box x axis
const boxSizeY = 50;   // size of the box y axis
const boxSizeZ = 8;   // size of the box z axis
const hx = boxSizeX / 2; // half size shorthand for easier typing
const hy = boxSizeY / 2; 
const hz = boxSizeZ / 2; 

vertices.push(vertex(-hx,-hy,-hz)); // lower top left  index 0
vertices.push(vertex( hx,-hy,-hz)); // lower top right
vertices.push(vertex( hx, hy,-hz)); // lower bottom right
vertices.push(vertex(-hx, hy,-hz)); // lower bottom left
vertices.push(vertex(-hx,-hy, hz)); // upper top left  index 4
vertices.push(vertex( hx,-hy, hz)); // upper top right
vertices.push(vertex( hx, hy, hz)); // upper bottom right
vertices.push(vertex(-hx, hy, hz)); // upper  bottom left index 7
然后为长方体上的每个面创建多边形

const colours = {
    dark : "#444",
    shade : "#666",
    light : "#aaa",
    bright : "#eee",
}
function createPoly(indexes,colour){ return { indexes, colour} }
const polygons = [];
// always make the polygon vertices indexes in a clockwise direction
// when looking at the polygon from the outside of the object
polygons.push(createPoly([3,2,1,0],colours.dark)); // bottom face
polygons.push(createPoly([0,1,5,4],colours.dark)); // back face
polygons.push(createPoly([1,2,6,5],colours.shade)); // right face
polygons.push(createPoly([2,3,7,6],colours.light)); // front face
polygons.push(createPoly([3,0,4,7],colours.dark)); // left face
polygons.push(createPoly([4,5,6,7],colours.bright)); // top face
现在您有了一个包含6个多边形的长方体的三维模型

投影 投影描述如何将三维对象转换为二维投影。这是通过为每个3D坐标提供2D轴来实现的

  // From here in I use P2,P3 to create 2D and 3D points
  const P3 = (x=0, y=0, z=0) => ({x,y,z});
  const P2 = (x=0, y=0) => ({x, y});

  // an object to handle the projection
  const isoProjMat = {
      xAxis : P2(1 , 0.5) ,  // 3D x axis for every 1 pixel in x go down half a pixel in y
      yAxis :  P2(-1 , 0.5) , // 3D y axis for every -1 pixel in x go down half a pixel in y
      zAxis :  P2(0 , -1) , // 3D z axis go up 1 pixels
      origin : P2(100,100),  // where on the screen 3D coordinate (0,0,0) will be
// create a new array of 2D projected verts
const projVerts = vertices.map(vert => isoProjMat.project(vert));
在本例中,您使用的是双度量投影的修改

因此,让我们为3个三维坐标中的每一个定义该二维轴

  // From here in I use P2,P3 to create 2D and 3D points
  const P3 = (x=0, y=0, z=0) => ({x,y,z});
  const P2 = (x=0, y=0) => ({x, y});

  // an object to handle the projection
  const isoProjMat = {
      xAxis : P2(1 , 0.5) ,  // 3D x axis for every 1 pixel in x go down half a pixel in y
      yAxis :  P2(-1 , 0.5) , // 3D y axis for every -1 pixel in x go down half a pixel in y
      zAxis :  P2(0 , -1) , // 3D z axis go up 1 pixels
      origin : P2(100,100),  // where on the screen 3D coordinate (0,0,0) will be
// create a new array of 2D projected verts
const projVerts = vertices.map(vert => isoProjMat.project(vert));
现在,通过将x、y、z(3d)坐标转换为x、y(2d)坐标来定义进行投影的函数

翻译 现在可以渲染模型了。首先,必须将每个顶点投影到二维屏幕坐标中

  // From here in I use P2,P3 to create 2D and 3D points
  const P3 = (x=0, y=0, z=0) => ({x,y,z});
  const P2 = (x=0, y=0) => ({x, y});

  // an object to handle the projection
  const isoProjMat = {
      xAxis : P2(1 , 0.5) ,  // 3D x axis for every 1 pixel in x go down half a pixel in y
      yAxis :  P2(-1 , 0.5) , // 3D y axis for every -1 pixel in x go down half a pixel in y
      zAxis :  P2(0 , -1) , // 3D z axis go up 1 pixels
      origin : P2(100,100),  // where on the screen 3D coordinate (0,0,0) will be
// create a new array of 2D projected verts
const projVerts = vertices.map(vert => isoProjMat.project(vert));
然后,只需通过索引将每个多边形渲染到
projVe中即可