资讯专栏INFORMATION COLUMN

Canvas呈现3D业务逻辑关系

Alliot / 689人阅读

摘要:导言引擎那么火,你让怎么办闲来无事,用实现效果的业务关系,是否也是一种乐趣先睹为快实验天地能绘制效果,的绘图就不能了吗其实不然,也能绘制,只是消耗的都是内存,绘制效率自然收到影响但若场景不大,效果不太真,也不妨试试绘制

导言

3D引擎那么火,你让2D怎么办? 闲来无事,用Canvas实现3D效果的业务关系,是否也是一种乐趣?

先睹为快

实验天地

WebGL能绘制3D效果,Canvas的2D绘图就不能了吗? 其实不然,也能绘制,只是消耗的都是内存,绘制效率自然收到影响;但若场景不大,3D效果不太真,也不妨试试;

Canvas绘制3D Cube



 
 3D cube HTML5 canvas realization
 



 

3D cube HTML5 canvas realization on 2D contex

Features:

  • 3D operations: rotating, moving object center
  • Direct illumination
  • Highlighting edges
  • Optimizations:
    • Skip outputting of invisible polygons
    • Skip processing of duplicated points

效果

封装一个Cube模块

CNode = function(id) {
  CNode.superClass.constructor.call(this, id);
}

twaver.Util.ext("CNode", twaver.Node, {
  _split:1/3,
  _cubeAngle:Math.PI/6,
  getVectorUIClass: function (){
    return CNodeUI;
  },
  setSplit:function(split){
    this._split = split;
  },
  setCubeAngle:function(angle){
    this._cubeAngle = angle;
  }
});

CNodeUI = function(network, element) {
  CNodeUI.superClass.constructor.call(this, network, element);
}

twaver.Util.ext("CNodeUI", twaver.vector.NodeUI, {
  drawVectorBody : function(ctx) {
      // CNodeUI.superClass.drawVectorBody.call(this, ctx);
      var node = this._element;
      var rect = this.getZoomBodyRect();
      // rect.x = rect.x + rect.width /4;
      // rect.y = rect.y + rect.height /4;
      // rect.width /= 2;
      // rect.height /= 2;
      var angleSin = Math.sin(node._cubeAngle);
      var angleCos = Math.cos(node._cubeAngle);
      var angleTan = Math.tan(node._cubeAngle);
      var split = node._split;
      var dash = false;
      var fill = false;
      var fillColor = this.getStyle("vector.fill.color");
      var close = false;

      var cubeDepth = node._width * split/angleCos;
      var cubeWidth = node._width * (1 - split) / angleCos;
      // var cubeHeight = rect.height/3;
      var cubeHeight = rect.height - cubeWidth * angleSin - cubeDepth * angleSin;
      var angle = node.getClient("angle");

      var center = {x:rect.x + rect.width/2,y:rect.y + rect.height/2};
      var p1 = {},p2 = {}, p3 = {}, p4 = {}, p5 = {},p6 = {}, p7 = {}, p8 = {};
      p1.x = rect.x + rect.width * split;
      p1.y = rect.y + rect.height;

      p2.x = rect.x;
      p2.y = rect.y + rect.height - cubeDepth * angleSin;

      p3.x = p2.x;
      p3.y = p2.y - cubeHeight;

      p4.x = p1.x;
      p4.y = p1.y - cubeHeight ;

      p6.x = rect.x + rect.width;
      p6.y = rect.y + rect.height - cubeWidth * angleSin;

      p5.x = p6.x;
      p5.y = p6.y - cubeHeight;

      p7.x = rect.x + rect.width * (1 - split);
      p7.y = rect.y;

      p8.x = p7.x;
      p8.y = p7.y + cubeHeight;

      p1 = this.rotatePoint(center,p1,angle * Math.PI / 180);
      p2 = this.rotatePoint(center,p2,angle * Math.PI / 180);
      p3 = this.rotatePoint(center,p3,angle * Math.PI / 180);
      p4 = this.rotatePoint(center,p4,angle * Math.PI / 180);
      p5 = this.rotatePoint(center,p5,angle * Math.PI / 180);
      p6 = this.rotatePoint(center,p6,angle * Math.PI / 180);
      p7 = this.rotatePoint(center,p7,angle * Math.PI / 180);
      p8 = this.rotatePoint(center,p8,angle * Math.PI / 180);


      close = false;
      dash = true;
      fill = false;
      this.drawPoints(ctx,[p2,p8],close,dash,fill);
      this.drawPoints(ctx,[p7,p8],close,dash,fill);
      this.drawPoints(ctx,[p6,p8],close,dash,fill);

      dash = false;
      close = true;
      fill = true;
      this.drawPoints(ctx,[p1,p2,p3,p4],close,dash,fill,fillColor);
      this.drawPoints(ctx,[p1,p4,p5,p6],close,dash,fill);
      this.drawPoints(ctx,[p3,p4,p5,p7],close,dash,fill);
    },
    drawPoints:function(ctx,points,close,dash,fill,fillColor){
      if(!points || points.length == 0){
        return;
      }
      ctx.beginPath();
      ctx.strokeStyle = "black";
      ctx.lineWidth = 0.5;
      if(fill && fillColor) {
        ctx.fillStyle = fillColor.colorRgb(0.6);
      }
      if(dash){
        ctx.setLineDash([8,8]);
        ctx.strokeStyle = "rgba(0,0,0,0.5)";
      }else{
        ctx.setLineDash([1,0]);
      }
      ctx.moveTo(points[0].x,points[0].y);

      for(var i = 1;i < points.length; i++){
        var p = points[i];
        ctx.lineTo(p.x,p.y);
      }

      if(close){
        ctx.lineTo(points[0].x,points[0].y);
      }

      ctx.closePath();
      ctx.stroke();
      if(fill){
        ctx.fill();
      }
    },
    rotatePoint:function(center,p,angle) {
      var x = (p.x - center.x) * Math.cos(angle) - (p.y - center.y) * Math.sin(angle) + center.x;
      var y = (p.x - center.x) * Math.sin(angle) + (p.y - center.y) * Math.cos(angle) + center.y;
      return {x:x, y:y};
    },
  });

就是把小学初中所学的几何知识用上就可以了;

再封装一个倾斜平面

var CGroup = function(id){
      CGroup.superClass.constructor.apply(this, arguments);
      this.enlarged = false;
    };

    twaver.Util.ext(CGroup, twaver.Group, {
      _tiltAngle:45,
      getTiltAngleX : function() {
        return this._tiltAngle;
      },
      setTiltAngleX : function(angle) {
        var oldValue = this._tiltAngle;
        this._tiltAngle = angle % 360;
        this.firePropertyChange("tiltAngleX", oldValue, this._tiltAngle);
      },
      getVectorUIClass:function(){
        return CGroupUI;
      },
      isEnlarged:function() {
        return this.enlarged;
      },
      setEnlarged:function(value){
        this.enlarged = value;
        var fillColor;
        if(value === false){
          this.setClient("group.angle",this._tiltAngle);
          this.setClient("group.shape","parallelogram");
          this.setClient("group.deep",10);
          this.setStyle("select.style","none");
          // this.setStyle("group.gradient","linear.northeast");
          this.setStyle("group.gradient","radial.center");
          this.setStyle("group.deep",0);
          this.setStyle("label.position","right.left");
          this.setStyle("label.xoffset",-10);
          this.setStyle("label.yoffset",-30);
          this.setStyle("label.font","italic bold 12px/30px arial,sans-serif");
          fillColor = this.changeHalfOpacity(this.getStyle("group.fill.color"));
          this.setStyle("group.fill.color",fillColor);
          this.setAngle(-20);
        }else{
         this.setAngle(0);
         this.setClient("group.angle",1);
         this.setClient("group.shape","parallelogram");
         this.setClient("group.deep",0);

         this.setStyle("select.style","none");
         this.setStyle("group.gradient","linear.northeast");
         this.setStyle("group.deep",0);
         this.setStyle("label.position","right.right");
         this.setStyle("label.xoffset",0);
         this.setStyle("label.yoffset",0);
         this.setStyle("label.font","italic bold 12px/30px arial,sans-serif");

         fillColor = this.changeOpacity(this.getStyle("group.fill.color"));
         this.setStyle("group.fill.color",fillColor);
       }
     },

     increaseOpacity:function(rgba){
      if(typeof rgba === "string" && rgba.indexOf("rgba(") !== -1 && rgba.indexOf(")") !== -1){
        var rgbaSub = rgba.substring(5, rgba.length-1);
        var rgbaNums = rgbaSub.split(",");
        var returnColor ="rgba(";
        var i;
        for(i=0;i

参考文献

[1].canvas实现简单3D旋转效果

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/82182.html

相关文章

  • 打造最美HTML5 3D机房(第二季)

    摘要:写在前面的前面现在拍电影搞真人秀都流行拍续集,哥今天给大家带来的是打造最美机房的续集,哥的目标是成为机房界的网红。机柜标签机房中最重要的物理资源机柜是机房管理规划监控人员最关注的对象之一。 写在前面的前面 现在拍电影、搞真人秀都流行拍续集,哥今天给大家带来的是打造最美3D机房的续集,哥的目标是成为3D机房界的网红。 -------------------------------我是这个...

    BetaRabbit 评论0 收藏0
  • 打造最美HTML5 3D机房(第二季)

    摘要:写在前面的前面现在拍电影搞真人秀都流行拍续集,哥今天给大家带来的是打造最美机房的续集,哥的目标是成为机房界的网红。机柜标签机房中最重要的物理资源机柜是机房管理规划监控人员最关注的对象之一。 写在前面的前面 现在拍电影、搞真人秀都流行拍续集,哥今天给大家带来的是打造最美3D机房的续集,哥的目标是成为3D机房界的网红。 -------------------------------我是这个...

    xiaokai 评论0 收藏0

发表评论

0条评论

Alliot

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<