2015-10-21 130 views
0

我正在试图让如何绘制在HTML5对象时,但在信息的多个不同来源找到了不同的解释已经引起了一些混乱做矩阵变换的理解。我发现信息说,为了在html5中创建绘制对象的动画,如here所示,同时我也看到可以通过转换绘制的点将变换应用于页面上的单个对象,但我不确定它是如何实现的作品。功能HTML5矩阵变换

我发现,实现腿的动画(两行)代码示例,但它确实动画不施加转换到帆布,使用用于在某些其他文件中定义的变换矩阵的功能对象。该代码提供了自己的实现moveTo()lineTo()(通常与画布对象一起使用),在该实现中,它转换传入的点,根据视口重新调整其位置,然后调用画布的移动版本以传递转化点。

所以这里有几点困惑: 1.当setTransform()只能在画布上使用时,在变换矩阵对象上实现新的变换函数的目的是什么? 2.方法如rotate()translate()在矩阵对象上被调用而没有传入点,所以这些操作如何实际应用? 3.什么时候应该将转换应用于整个画布(如所提供的链接所做的那样),而不是绘制特定的对象,因为它们似乎都可以工作?

我一般只是寻找相关的一般概述,我相当困惑是如何工作的。从该示例中的代码是下面供参考:

<head> 
<script src=g.js></script> 
<script src=matrix4x4.js></script> 
</head> 
<body onload=g_start()> 
<canvas id=myCanvas1 width=480 height=480></canvas> 
<script> 
    var w, h, g; 

    function viewport(p) { 
     return [ w/2 * p[0] + w/2, h/2 - p[1] * w/2 ]; 
    } 

    function moveTo(p) { 
     var q = m.transform(p); // APPLY 3D MATRIX TRANFORMATION 
     var xy = viewport(q); // APPLY VIEWPORT TRANSFORM 
     g.moveTo(xy[0], xy[1]); 
    } 

    function lineTo(p) { 
     var q = m.transform(p); // APPLY 3D MATRIX TRANFORMATION 
     var xy = viewport(q); // APPLY VIEWPORT TRANSFORM 
     g.lineTo(xy[0], xy[1]); 
    } 

    myCanvas1.animate = function(_g) { 
     g = _g; 
     w = g.canvas.width; 
     h = g.canvas.height; 

     g.fillStyle = 'rgb(200,140,255)'; 
     g.beginPath(); 
     g.moveTo(0, 0); 
     g.lineTo(w, 0); 
     g.lineTo(w, h); 
     g.lineTo(0, h); 
     g.lineTo(0, 0); 
     g.stroke(); 

     g.fillStyle = 'rgb(128,0,0)'; 
     g.strokeStyle = 'rgb(0,0,0)'; 

     var legBend = .4; 

     var t = 3 * time; 

     for (var leg = 0 ; leg < 2 ; leg++) { 
    var angle = -Math.PI/2 * (1 + Math.sin(time)); 
    console.log(angle); 
     var sign = (leg == 0) == (angle < -Math.PI/2) ? -1 : 1; 

     m.identity(); 
     m.rotateY(-Math.PI/2 * (1 + Math.sin(time))); 

     g.beginPath(); 

     m.translate(0, .5, .1 * sign); 
     moveTo([0,0,0]);    // HIP 

     m.rotateZ(-.5 * legBend + sign * legBend * Math.cos(t)); 

     m.translate(0, -.5, 0); 

     lineTo([0,0,0]);    // HIP 

     m.rotateZ(2 * legBend + 2 * legBend * sign * Math.sin(t)); 
     m.translate(0, -.5, 0); 
     lineTo([0,0,0]);    // KNEE 

     m.translate(-.1, 0, 0); 
     lineTo([0,0,0]);    // KNEE 

     g.strokeStyle = 'rgb(0,0,0)'; 
     g.lineWidth = 30; 
     g.stroke(); 

     g.strokeStyle = 'rgb(255,0,0)'; 
     g.lineWidth = 20; 
     g.stroke(); 
     } 
    } 

</script> 
</body> 
+2

它让我在身体上感到痛苦,因为看不到'src = g.js'的引号。 –

回答

1

重要HTML5画布变换概念:

  • 所有画布的转化方法(以及.transform)操作相对于当前画布起源和该原点给出坐标[0,0]。起始原点位于画布的左上角。 .setTransform将重置当前画布原点,然后进行相对于该重置原点的转换。

  • 转换不影响现有图纸。所以fillRect(0,0)跟随translate(5,0)不会移动已经绘制的矩形。现有的矩形仍将显示在画布的左上角。

  • 转换会影响新的图纸。

  • translate方法由指定的x,y的距离移动至原点。因此,translate(5,0)将使画布绘制原点[0,0]从画布左侧起5个像素。因此,translate(5,0)后跟fillRect(0,0)会导致新的矩形在画布左侧显示5个像素。

  • 变换实际平移(移动),旋转,缩放整个画布绘制表面。所以新图纸不会单独移动,旋转或缩放。 由于整个画布绘图表面已被移动,旋转或缩放,所以新绘图出现移动,旋转或缩放。

  • 转型是累积的。所以如果你翻译(5,0)然后翻译(0,50),画布原点[0,0]将在左边5像素和顶部50像素。所以fillRect(0,0)将会从左边算起5个像素,从顶部算起50个像素。

因此,要回答你的问题:因为变革是累积

  1. 顺序转换是有用的。因此,为了使人形象“移动”,您可以使用转换的累积效果,而不必记住他们的最后位置或不必计算他们的新位置。

    // the person image will move across the canvas in 5px increments over time 
    // No need to remember its last location 
    // No need to calculate its new position 
    // That's because the canvas internally remembers & calculates its own origin. 
    for(var i=0;i<20;i++){ 
        context.clearRect(0,0,canvas.width,canvas.height); 
        context.translate(5,0); 
        context.drawImage(person,0,0); 
        // wait 1 second 
    } 
    
  2. 由于所有的转变是相对于当前画布原点坐标,你不必重新指定坐标任何转化方法 - 画布“记住”它的当前原点为您服务。

  3. 单个画布图不受转换的影响。转换将整个画布和新图画移动到“一起去”。任何在转换之前存在的图纸都不会受到后续转换的影响 - 预先存在的图纸仍然完全保留在第一次绘制的位置。

+0

感谢您的回答!所以你说任何时候你在做html5转换时,你只能将转换应用到整个canvas而不是特定的对象(即不使用''setTransform()''')?在我看来,在这个例子中,''''''''''''函数可能会应用它自己的一种不使用''setTransform()''''的转换,因为该函数只适用于2D这个程序正在使用3d。 – loremIpsum1771

+0

此外,如果使用'''setTransform()'''是实现'''Transform()'''方法的唯一方法,那么你怎样才能使用它的3D形状,B/C我目前正在使用jQuery使用'''canvas.getContext(“2d”)'''获取上下文,但是我不知道是否有方法在3d中执行此操作。 – loremIpsum1771