资讯专栏INFORMATION COLUMN

Canvas呈现3D业务逻辑关系

Alliot / 618人阅读

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

导言

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和WebGL的三维可视立体动态流程图

    摘要:甲方爸爸的企业,部门繁多,流程复杂,为了提升业务流程的效率,同时优化企业自身的管理,提出了一个将其现有业务流程进行三维可视化的需求。利用获取模型数据,然后三行代码便可建造一个流程图系统。 惯例先扯点闲篇 记得15年那会儿,我给人讲WebGL,还得从头科普,三令五申要用Chrome,末了再强调一句,记得启用WebGL功能。今天,但凡懂点儿Web开发的,都会来一句网页3D用WebGL。 怎...

    printempw 评论0 收藏0
  • 数百个 HTML5 例子学习 HT 图形组件 – 拓扑图篇

    摘要:拓扑图组件作为最典型的客户需求应用,自然是首篇登场。入门手册中也有个简单的编辑器例子,教用户如何自定义创建节点连线和多边形的示例教材,学习自定义拓扑图交互可从此例子入手。 HT 是啥:Everything you need to create cutting-edge 2D and 3D visualization. 这口号是当年心目中的产品方向,接着就朝这个方向慢慢打磨,如今 HT ...

    Shonim 评论0 收藏0
  • 打造最美HTML5 3D机房(MONO哥强势归来,第四季惊艳发布)

    摘要:鹰眼上次的小机房功能已经基本完成了,客户对演示效果也非常满意。鹰眼看上去是这样子的上面的界面是同事给客户做的虚拟机开通配置的编辑界面,右下角的这块试图就是鹰眼缩略图。 前言 初次见面的朋友们大家好,简单自我介绍一下:我是Mono哥,性别男,爱好。。。编程,自从一年多前入了HTML5和WebGL的坑,就再也没有爬出来过,目前正在钻研3D机房以及相关的3D应用。这篇文章是打造最美3D机房系...

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

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

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

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

    xiaokai 评论0 收藏0

发表评论

0条评论

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