将SVG多边形转换为svg而非canvas中的3d多边形

时间:2017-06-07 14:29:50

标签: javascript svg

我有JSON数据来生成一些SVG(2D)多边形。我正在寻找一种在三维中在SVG中绘制这些多边形的方法。我发现很多库在画布中绘制3D路径和多边形,但是我需要SVG来访问我的多边形作为DOM对象。 为了更好地理解,我想要这样的东西,但我想要SVG中的输出: JSModeler

2D polygin in SVG 3D polygon in SVG

2 个答案:

答案 0 :(得分:1)

从未创建SVG来制作3D,但您可以通过为多边形面提供多个多边形来模拟3D:

var Polygon = (function() {
  function Polygon(lines, fill) {
    if (lines === void 0) {
      lines = [];
    }
    if (fill === void 0) {
      fill = "rgba(" + (Math.round(Math.random() * 255)) + "," + (Math.round(Math.random() * 255)) + "," + (Math.round(Math.random() * 255)) + ",0.15)";
    }
    this.lines = lines;
    this.fill = fill;
    this.svgshape = document.createElementNS('http://www.w3.org/2000/svg', "polygon");
    this.svgshape.style.stroke = 'black';
  }
  Polygon.prototype.render = function(position) {
    if (position === void 0) {
      position = {
        x: 0,
        y: 0
      };
    }
    this.svgshape.style.fill = this.fill;
    var points = [];
    for (var lineIndex = 0; lineIndex < this.lines.length; lineIndex++) {
      var line = this.lines[lineIndex];
      points.push((line.x + 0.3 * line.z + position.x) + "," + (line.y + 0.3 * line.z + position.y));
    }
    this.svgshape.setAttribute("points", points.join(" "));
  };
  return Polygon;
}());
var PolygonSet = (function() {
  function PolygonSet(polygons, position) {
    if (polygons === void 0) {
      polygons = [];
    }
    if (position === void 0) {
      position = {
        x: 0,
        y: 0
      };
    }
    this.polygons = polygons;
    this.position = position;
  }
  PolygonSet.prototype.render = function(svg) {
    if (svg === void 0) {
      svg = null;
    }
    for (var pIndex = 0; pIndex < this.polygons.length; pIndex++) {
      var polygon = this.polygons[pIndex];
      polygon.render(this.position);
      if (svg != null) {
        svg.appendChild(polygon.svgshape);
      }
    }
  };
  return PolygonSet;
}());
//TEST
var svg = document.createElementNS('http://www.w3.org/2000/svg', "svg");
svg.setAttribute("width", "200");
svg.setAttribute("height", "200");
svg.setAttribute("xmlns", 'http://www.w3.org/2000/svg');
var box = new PolygonSet([
  //Floor
  /* */
  new Polygon([{
      x: 0,
      y: 100,
      z: 100
    },
    {
      x: 100,
      y: 100,
      z: 100
    },
    {
      x: 100,
      y: 100,
      z: 0
    },
    {
      x: 0,
      y: 100,
      z: 0
    }
  ]),
  //Wall 1 - right
  /* */
  new Polygon([{
      x: 100,
      y: 0,
      z: 0
    },
    {
      x: 100,
      y: 100,
      z: 0
    },
    {
      x: 100,
      y: 100,
      z: 100
    },
    {
      x: 100,
      y: 0,
      z: 100
    },
  ]),
  //Wall 2
  /* */
  new Polygon([{
      x: 0,
      y: 0,
      z: 0
    },
    {
      x: 100,
      y: 0,
      z: 0
    },
    {
      x: 100,
      y: 100,
      z: 0
    },
    {
      x: 0,
      y: 100,
      z: 0
    },
  ]),
  //Wall 3 - left
  /* */
  new Polygon([{
      x: 0,
      y: 0,
      z: 0
    },
    {
      x: 0,
      y: 100,
      z: 0
    },
    {
      x: 0,
      y: 100,
      z: 100
    },
    {
      x: 0,
      y: 0,
      z: 100
    },
  ]),
  //Wall 4
  /* */
  new Polygon([{
      x: 0,
      y: 0,
      z: 100
    },
    {
      x: 100,
      y: 0,
      z: 100
    },
    {
      x: 100,
      y: 100,
      z: 100
    },
    {
      x: 0,
      y: 100,
      z: 100
    },
  ]),
  //Roof
  /* */
  new Polygon([{
      x: 0,
      y: 0,
      z: 0
    },
    {
      x: 100,
      y: 0,
      z: 0
    },
    {
      x: 100,
      y: 0,
      z: 100
    },
    {
      x: 0,
      y: 0,
      z: 100
    }
  ]),
], {
  x: 10,
  y: 10
});
box.render(svg);
document.body.appendChild(svg);
setInterval(function() {
  var polygon = box.polygons[Math.round((box.polygons.length - 1) * Math.random())];
  polygon.fill = "rgba(" + (Math.round(Math.random() * 255)) + "," + (Math.round(Math.random() * 255)) + "," + (Math.round(Math.random() * 255)) + ",0.5)";
  box.render();
}, 1000 / 4);

答案 1 :(得分:1)

好的,所以我读了二维形状的3D操作,并发现了{Canuss'动画的this excellent tutorial,我设法制作了SVG版本:

&#13;
&#13;
/**
 * Point holds data for a "point-in-space" and handles any manipulations of said point, like rotation
 *
 * @class Point
 */
var Point = (function() {
  function Point(x, y, z) {
    this.x = x;
    this.y = y;
    this.z = z;
  }
  /**
   * Rotates on all axis
   *
   * @param {ICoord} angle
   * @returns
   *
   * @memberOf Point
   */
  Point.prototype.rotate = function(angle) {
    return this
      .rotateX(angle.x)
      .rotateY(angle.y)
      .rotateZ(angle.y);
  };
  /**
   * Rotate on x axis
   *
   * @param {number} angle
   * @returns
   *
   * @memberOf Point
   */
  Point.prototype.rotateX = function(angle) {
    var rad, cosa, sina, y, z;
    rad = angle * Math.PI / 180;
    cosa = Math.cos(rad);
    sina = Math.sin(rad);
    y = this.y * cosa - this.z * sina;
    z = this.y * sina + this.z * cosa;
    return new Point(this.x, y, z);
  };
  /**
   * Rotate on y axis
   *
   * @param {number} angle
   * @returns
   *
   * @memberOf Point
   */
  Point.prototype.rotateY = function(angle) {
    var rad, cosa, sina, x, z;
    rad = angle * Math.PI / 180;
    cosa = Math.cos(rad);
    sina = Math.sin(rad);
    z = this.z * cosa - this.x * sina;
    x = this.z * sina + this.x * cosa;
    return new Point(x, this.y, z);
  };
  /**
   * Rotate on z axis
   *
   * @param {number} angle
   * @returns
   *
   * @memberOf Point
   */
  Point.prototype.rotateZ = function(angle) {
    var rad, cosa, sina, x, y;
    rad = angle * Math.PI / 180;
    cosa = Math.cos(rad);
    sina = Math.sin(rad);
    x = this.x * cosa - this.y * sina;
    y = this.x * sina + this.y * cosa;
    return new Point(x, y, this.z);
  };
  return Point;
}());
/**
 * Face is a collection of point that produces a surface
 * A face should have at least 3 points(vertices)
 *
 *
 * @class Face
 */
var Face = (function() {
  function Face(name, vertices, color, svgElement) {
    if (vertices === void 0) {
      vertices = [];
    }
    if (color === void 0) {
      color = "rgba(0,0,255,0.5)";
    }
    if (svgElement === void 0) {
      svgElement = document.createElementNS('http://www.w3.org/2000/svg', "polygon");
    }
    this.name = name;
    this.vertices = vertices;
    this.color = color;
    this.svgElement = svgElement;
  }
  /**
   * Calculate all vertices positions and rebuild SVG polygon
   *
   * @param {ICoord} [angle={ x: 0, y: 0, z: 0 }]
   * @returns
   *
   * @memberOf Face
   */
  Face.prototype.render = function(angle) {
    if (angle === void 0) {
      angle = {
        x: 0,
        y: 0,
        z: 0
      };
    }
    this.svgElement.setAttribute("face-name", this.name);
    var points = [];
    for (var i = 0; i < this.vertices.length; i++) {
      var vert = this.vertices[i].rotate(angle);
      points.push(vert.x + ',' + vert.y);
    }
    this.svgElement.setAttribute("stroke", this.color);
    this.svgElement.setAttribute("fill", this.color);
    this.svgElement.setAttribute("points", points.join(" "));
    return this;
  };
  return Face;
}());
/**
 * Polygon is a collection of Faces that make up a shape, like a Box
 * Polygon manages 2D translation across the canvas and maintains shape-level data like the current angle
 *
 * @class Polygon
 */
var Polygon = (function() {
  function Polygon(faces, position, angle, svgElement) {
    if (faces === void 0) {
      faces = [];
    }
    if (position === void 0) {
      position = {
        x: 0,
        y: 0
      };
    }
    if (angle === void 0) {
      angle = {
        x: 0,
        y: 0,
        z: 0
      };
    }
    if (svgElement === void 0) {
      svgElement = document.createElementNS('http://www.w3.org/2000/svg', "g");
    }
    this.faces = faces;
    this.position = position;
    this.angle = angle;
    this.svgElement = svgElement;
  }
  /**
   * Renders all faces and translate across viewport
   *
   * @param {ICoord} [angle=this.angle]
   * @returns
   *
   * @memberOf Polygon
   */
  Polygon.prototype.render = function(angle) {
    if (angle === void 0) {
      angle = this.angle;
    }
    this.svgElement.innerHTML = '';
    for (var index = 0; index < this.faces.length; index++) {
      var face = this.faces[index];
      face.render(angle);
      this.svgElement.appendChild(face.svgElement);
    }
    this.svgElement.setAttribute("transform", "translate(" + this.position.x + "," + this.position.y + ")");
    return this;
  };
  return Polygon;
}());
/**
 * Box is a utility function that creates a cube Polygon
 *
 * @param {ICoord} [dimensions={ x: 100, y: 100, z: 100 }]
 * @param {ISimpleCoord} [position={ x: 0, y: 0 }]
 * @param {ICoord} [angle={ x: 0, y: 0, z: 0 }]
 * @returns
 */
function Box(dimensions, position, angle) {
  if (dimensions === void 0) {
    dimensions = {
      x: 100,
      y: 100,
      z: 100
    };
  }
  if (position === void 0) {
    position = {
      x: 0,
      y: 0
    };
  }
  if (angle === void 0) {
    angle = {
      x: 0,
      y: 0,
      z: 0
    };
  }
  return new Polygon([
    new Face("Back", [
      new Point(-1 * dimensions.x, -1 * dimensions.y, -1 * dimensions.z),
      new Point(1 * dimensions.x, -1 * dimensions.y, -1 * dimensions.z),
      new Point(1 * dimensions.x, 1 * dimensions.y, -1 * dimensions.z),
      new Point(-1 * dimensions.x, 1 * dimensions.y, -1 * dimensions.z),
    ]),
    new Face("Left", [
      new Point(-1 * dimensions.x, -1 * dimensions.y, -1 * dimensions.z),
      new Point(-1 * dimensions.x, -1 * dimensions.y, 1 * dimensions.z),
      new Point(-1 * dimensions.x, 1 * dimensions.y, 1 * dimensions.z),
      new Point(-1 * dimensions.x, 1 * dimensions.y, -1 * dimensions.z),
    ]),
    new Face("Right", [
      new Point(1 * dimensions.x, -1 * dimensions.y, -1 * dimensions.z),
      new Point(1 * dimensions.x, -1 * dimensions.y, 1 * dimensions.z),
      new Point(1 * dimensions.x, 1 * dimensions.y, 1 * dimensions.z),
      new Point(1 * dimensions.x, 1 * dimensions.y, -1 * dimensions.z),
    ]),
    new Face("Front", [
      new Point(-1 * dimensions.x, -1 * dimensions.y, 1 * dimensions.z),
      new Point(1 * dimensions.x, -1 * dimensions.y, 1 * dimensions.z),
      new Point(1 * dimensions.x, 1 * dimensions.y, 1 * dimensions.z),
      new Point(-1 * dimensions.x, 1 * dimensions.y, 1 * dimensions.z),
    ]),
    new Face("Top", [
      new Point(-1 * dimensions.x, -1 * dimensions.y, -1 * dimensions.z),
      new Point(1 * dimensions.x, -1 * dimensions.y, -1 * dimensions.z),
      new Point(1 * dimensions.x, -1 * dimensions.y, 1 * dimensions.z),
      new Point(-1 * dimensions.x, -1 * dimensions.y, 1 * dimensions.z),
    ]),
    new Face("Bottom", [
      new Point(-1 * dimensions.x, 1 * dimensions.y, -1 * dimensions.z),
      new Point(1 * dimensions.x, 1 * dimensions.y, -1 * dimensions.z),
      new Point(1 * dimensions.x, 1 * dimensions.y, 1 * dimensions.z),
      new Point(-1 * dimensions.x, 1 * dimensions.y, 1 * dimensions.z),
    ]),
  ], position, angle);
}
/**
 * Like Box this returns a Polygon shape, this one in a Pyramid shape
 *
 * @param {ICoord} [dimensions={ x: 100, y: 100, z: 100 }]
 * @param {ISimpleCoord} [position={ x: 0, y: 0 }]
 * @param {ICoord} [angle={ x: 0, y: 0, z: 0 }]
 * @returns
 */
function Pyramid(dimensions, position, angle) {
  if (dimensions === void 0) {
    dimensions = {
      x: 100,
      y: 100,
      z: 100
    };
  }
  if (position === void 0) {
    position = {
      x: 0,
      y: 0
    };
  }
  if (angle === void 0) {
    angle = {
      x: 0,
      y: 0,
      z: 0
    };
  }
  return new Polygon([
    new Face("Top", [
      new Point(-1 * dimensions.x, -1 * dimensions.y, -1 * dimensions.z),
      new Point(1 * dimensions.x, -1 * dimensions.y, -1 * dimensions.z),
      new Point(1 * dimensions.x, -1 * dimensions.y, 1 * dimensions.z),
      new Point(-1 * dimensions.x, -1 * dimensions.y, 1 * dimensions.z),
    ]),
    new Face("Back", [
      new Point(-1 * dimensions.x, -1 * dimensions.y, -1 * dimensions.z),
      new Point(1 * dimensions.x, -1 * dimensions.y, -1 * dimensions.z),
      new Point(0, 1 * dimensions.y, 0),
    ]),
    new Face("Left", [
      new Point(-1 * dimensions.x, -1 * dimensions.y, -1 * dimensions.z),
      new Point(-1 * dimensions.x, -1 * dimensions.y, 1 * dimensions.z),
      new Point(0, 1 * dimensions.y, 0),
    ]),
    new Face("Right", [
      new Point(1 * dimensions.x, -1 * dimensions.y, -1 * dimensions.z),
      new Point(1 * dimensions.x, -1 * dimensions.y, 1 * dimensions.z),
      new Point(0, 1 * dimensions.y, 0),
    ]),
    new Face("Front", [
      new Point(-1 * dimensions.x, -1 * dimensions.y, 1 * dimensions.z),
      new Point(1 * dimensions.x, -1 * dimensions.y, 1 * dimensions.z),
      new Point(0, 1 * dimensions.y, 0),
    ]),
  ], position, angle);
}
/**
 * Viewport is the svg-layer where all polygons are drawn
 *
 * @class Viewport
 */
var Viewport = (function() {
  function Viewport(dimensions, polygons, svgElement) {
    if (dimensions === void 0) {
      dimensions = {
        x: 100,
        y: 100
      };
    }
    if (polygons === void 0) {
      polygons = [];
    }
    if (svgElement === void 0) {
      svgElement = document.createElementNS('http://www.w3.org/2000/svg', "svg");
    }
    this.dimensions = dimensions;
    this.polygons = polygons;
    this.svgElement = svgElement;
    this.svgElement.setAttribute("width", this.dimensions.x.toString());
    this.svgElement.setAttribute("height", this.dimensions.y.toString());
    this.svgElement.setAttribute("xmlns", 'http://www.w3.org/2000/svg');
  }
  return Viewport;
}());
//TEST
var view = new Viewport({
  x: 700,
  y: 400
});
var box = Box({
    x: 100,
    y: 100,
    z: 100
  }, {
    x: 200,
    y: 200
  })
  .render();
var pyramid = Pyramid({
    x: 100,
    y: 100,
    z: 100
  }, {
    x: 500,
    y: 200
  }, {
    x: 180,
    y: 0,
    z: 0
  })
  .render();
//append to DOM
document.body.appendChild(view.svgElement);
view.svgElement.appendChild(box.svgElement);
view.svgElement.appendChild(pyramid.svgElement);
//Animate
setInterval(function() {
  box.angle.x++;
  box.angle.y++;
  box.angle.z++;
  box.render();
  pyramid.angle.x++;
  pyramid.angle.y++;
  pyramid.angle.z++;
  pyramid.render();
}, 1000 / 24);
&#13;
&#13;
&#13;

从这里你应该能够自己在3D空间中制作出任何形状。