zoukankan      html  css  js  c++  java
  • rotate 3D [初识篇]

    随着前端技术发展,尤其是html5中canvas和svg的应用,开始让web也可以轻易的渲染出各种绚丽的效果。

    本篇讨论的是基于rotate(旋转)的3d效果的初识。在canvas的getContext('2d')下利用一些变换来模拟。webGL是后话,本篇暂不讨论。

    【简要原理】
    由于仍是在2d下模拟,所以所谓的3d最终还是要降到2d的层面来。
    在坐标上的表现就是,3d的界面应该是有x,y,z三向坐标,2d的就只有x,y二向。
    那么怎么把3d的z向坐标降到和2d的x,y相关联起来,就是关键。

    要在2d的界面上展现3d的z方向的层次感,需要一个视井。
    相信学过绘画的同学应该很清楚,要画透视或者有层次关系的多个物体时。在最开始建模的时候老师都会教先根据观察角度“打格子”,把物体的大小层次关系大概先模拟出来。
    格子打出来其实就是由近及远的“井”字形。

    最直观的感觉就是可以想象一张拍很长走廊的照片,照片里的走廊一定是近处宽,随着距离的拉远,走廊宽度一定是渐窄,看起来就像是两条斜线向远处延伸。

    于是,在编码过程中,根据这个原理,不难想象到原本的z坐标要表现在2d的x,y坐标上,其影响就是会影响xy坐标的偏移。
    同时还有物体大小的变化,透明度(模糊度)的变化,这些应该容易想到。

    【demo1】
    下面就以一个小球来展现改变z坐标的位置对其2d界面下的x,y位置和大小的影响。

    // 创建一个小球    
    var ball = createBall(ballR);
    //添加到舞台
    stage.addChild(ball);
    //取得画布中心位置
    vpx = canvas.width/2;
    vpy = canvas.height/2;

    // 取得当前鼠标相对中心偏移距离 xpos, ypos
    stage.addEventListener('mousemove', function (x, y) {
    xpos
    = x - vpx;
    ypos
    = y - vpy;
    });
    // 用键盘上下键改变z坐标的位置
    document.addEventListener('keydown', function (e) {
    if (e.keyCode == 38) zpos += 5;
    if (e.keyCode == 40) zpos -=5;
    },
    false)

    // 每帧刷新时的改变
    stage.onRefresh = function () {
    // 将z坐标扁平化
    var scale = focalLength/(focalLength + zpos);
    // 将扁平後z坐标对x,y的影响给小球坐标
    ball.x = vpx + xpos*scale;
    ball.y
    = vpy + ypos*scale;
    // 对小球大小的影响
    ball.width = ballR*2*scale;

    document.getElementById(
    'scale').innerHTML = scale;
    }

    stage.start();

    代码很简单,都舔了注释。
     

    【demo2】
    可能上面的demo还太简单,不能看出所谓的3d的效果。按照上面的思路,可以给x方向添加一个旋转的效果,结合z方向对其的影响就可以看出一点所谓3d的效果了。

    // 获取画布中心        
    vpx = canvas.width/2;
    vpy = canvas.height/2;

    // 根据鼠标位置计算选装角度(速度)
    stage.addEventListener('mousemove', function (x, y) {
    angleY
    = (x - vpx) * .001;
    });

    // 主旋转函数
    function rotateY(ball, angleY) {
    // 把角度三角函数化,以便看起来是绕圆旋转
    var cosy = Math.cos(angleY),
    siny
    = Math.sin(angleY),
    // 把 z方向影响算进来
    x1 = ball.xpos * cosy - ball.zpos * siny,
    z1
    = ball.zpos * cosy + ball.xpos * siny;
    ball.xpos
    = x1;
    ball.zpos
    = z1;

    // z坐标扁平化,并赋给小球影响
    var scale = focalLength / (focalLength + ball.zpos);
    ball.x
    = vpx + ball.xpos * scale;
    ball.y
    = vpy + ball.ypos * scale;
    ball.width
    = ballR*2*scale;
    }

    代码实际运行如下:
      

    恩,本来这篇还想多写点的,但是肚子饿了,木办法,先去填肚子了,明天还要上班....

    今天中秋,虽然迟了点,还是祝各位园友佳节快乐吧。

    下篇继续...

  • 相关阅读:
    6种负载均衡算法
    Java中volatile关键字
    剑指offer练习
    linux系统查看IP地址,不显示IP地址或者只显示127.0.0.1
    Nginx负载均衡配置
    集群应用Session一致性实现的三种方案
    rabbitMQ学习
    JDK1.8在LINUX下安装步骤
    ecplise部署gradle web项目
    Kubernetes下的应用监控解决方案
  • 原文地址:https://www.cnblogs.com/hongru/p/2174187.html
Copyright © 2011-2022 走看看