0

我已经解决这个问题好几天了。我第一次在构造函数模式中编写了我的代码。我想在过渡中扩展 10 条贝塞尔线的高度。我尝试过 kineticjs(我失败),尝试过 Setinterval(创建 jerk在动画中)。所以我最终求助于 requestAnimationFrame。但是由于这种构造函数模式,我完全不知道在哪里包含它以及要进行哪些更改。

这就是我到目前为止所做的——JSFIDDLE

所以基本上我将在过渡中扩展我的 endY 和 cpY1 和 cpy2。在画布的鼠标悬停时,所有贝塞尔线的高度必须在过渡中增加,使其具有动画般的感觉。

JAVASCRIPT:

//for entire code please have a look at the fiddle.this is just 10% of my code
//for simplification purpose,you can use 3 instances instead of 9!!!
    (function() {
        hair = function() {
            return this;
        };


    hair.prototype={

     draw_hair:function(a,b,c,d,e,f,g,h){

            var sx  =136+a;//start position of curve.used in moveTo(sx,sy)
            var sy  =235+b;
            var cp1x=136+c;//control point 1
            var cp1y=222+d;
            var cp2x=136+e;//control point 2
            var cp2y=222+f;
            var endx=136+g;//end points
            var endy=210+h;

         var canvas = document.getElementById('myCanvas');
         var context = canvas.getContext('2d');
         context.strokeStyle="grey";
         context.lineWidth="8";
         context.beginPath();
         context.moveTo(sx,sy);
         context.bezierCurveTo(cp1x,cp1y,cp2x,cp2y,endx,endy);
         context.lineCap = 'round';
         context.stroke();
    }
};
})();
4

1 回答 1

0

这是你想要的关于头发生长的答案。

这也包含您想要的有关如何创建头发“对象”的信息。

代码和小提琴:http: //jsfiddle.net/m1erickson/8K825/

<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>

<style>
    body{ background-color: ivory; }
    canvas{border:1px solid red;}
</style>

<script>
$(function(){

    window.requestAnimationFrame = (function(callback) {
      return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame ||
      function(callback) {
        window.setTimeout(callback, 1000 / 60);
      };
    })();

    var canvas=document.getElementById("canvas");
    var ctx=canvas.getContext("2d");

    var canvasOffset=$("#canvas").offset();
    var offsetX=canvasOffset.left;
    var offsetY=canvasOffset.top;

    // the Hair "object"
    // Hair is a containing object that hosts a user-specified # of hairs
    var Hair = (function () {

        // constructor
        function Hair(x,y,width,height,haircount) {

            this.x=x;
            this.y=y;
            this.width=width;
            this.height=height;
            this.right=this.x+this.width;
            this.bottom=this.y+this.height;
            this.hairCount=haircount;
            this.startX=x+20;
            this.startY=y+height-3;  //235;
            this.hairHeight=25;
            this.hairGrowth=0;
            this.lastEndX=[];

            for(var i=0;i<haircount;i++){
                this.lastEndX[i]= x+20+(i*15);
            }

        }
        // grows the hair
        // works by changing the Y value of the end & control points
        Hair.prototype.grow = function(increment){
            this.hairGrowth+=increment;
            return(this.hairGrowth);
        }
        // draw all the hairs
        Hair.prototype.draw = function(mouseX){

            // clear this object's space on the canvas
            // and set its styles
            ctx.clearRect(this.x,this.y,this.width,this.height);
            ctx.beginPath();
            ctx.strokeStyle="grey";
            ctx.lineWidth=7;
            ctx.lineCap = 'round';
            ctx.beginPath();

            for(var i=0;i<this.hairCount;i++){

                // straight hair 
                var sx=cp1x=cp2x= this.startX+(i*15);
                var sy= this.startY;
                var cp1y = cp2y = (this.startY-(this.hairHeight+this.hairGrowth)/2);
                var endy = this.startY-this.hairHeight-this.hairGrowth;
                var endx = this.lastEndX[i];

                // create bend, if any
                if(Math.abs(mouseX-sx)<=10){ 
                    endx = sx+(mouseX-sx)*1.1;
                    this.lastEndX[i]=endx;
                };

                // draw this curve
                ctx.moveTo(sx,sy);
                ctx.bezierCurveTo(cp1x,cp1y,cp2x,cp2y,endx,endy);

            }
            // stroke
            ctx.stroke();
            // temp outline
            ctx.lineWidth=1;
            ctx.beginPath();
            ctx.rect(this.x,this.y,this.width,this.height);
            ctx.stroke();
        }
        //
        return Hair;
    })();


    var direction=1;
    var fps = 3;
    function animate() {
        setTimeout(function() {

            // change hair length
            var hairLength=hair.grow(direction);
            if(hairLength<1 || hairLength>10){ direction=(-direction); }

            // draw
            hair.draw();

            // request next frame
            requestAnimationFrame(animate);

        }, 1000 / fps);
    }


    function handleMouseMove(e){
      mouseX=parseInt(e.clientX-offsetX);
      mouseY=parseInt(e.clientY-offsetY);
      $("#movelog").html("Move: "+ mouseX + " / " + mouseY);

      // Put your mousemove stuff here
      if(mouseX>=hair.x && mouseX<=hair.right && mouseY>=hair.y && mouseY<=hair.bottom){
          hair.draw(mouseX);
      }
    }

    $("#canvas").mousemove(function(e){handleMouseMove(e);});

    $("#grow").click(function(e){ animate(); });

    // create a new patch of hair 
    var hair=new Hair(25,50,150,50,8);
    hair.draw(225);


}); // end $(function(){});
</script>

</head>

<body>
    <p id="movelog">Move</p>
    <canvas id="canvas" width=300 height=200></canvas><br>
    <button id="grow">Grow Hair</button>
</body>
</html>

[添加:“类”的解释和从类中实例化一个对象]

var Hair=(function(){ …; return Hair; })()创建一个头发“类”。

var hair = new Hair(…)创建一个实际可用的头发“对象”。

将 Hair 类视为模板(或蓝图或千篇一律)。Hair-class里面的所有代码只定义了类的属性和方法。您实际上并没有调用 Hair 类中的任何代码。您只需将其用作模板来创建实际的头发对象。

您可以根据需要使用 Hair 类创建任意数量的实际头发对象——它是可重用的。创建头发对象的行为称为“实例化头发类”。

顺便说一句,javascript 实际上没有类,所以这只是一个伪类。但这是另一种解释!

你问:direction=0.25有什么用?

方向变量用于在动画期间头发“生长”时逐渐增加头发的高度。.25 告诉头发的控制点/端点每动画帧上升 0.25 个像素。

你问:回调函数和那个settimeout有什么意义?

setTimeout正在包装requestAnimationFrame,以便动画以固定的每秒帧数发生。

RequestAnimationFrame (RAF) 在优化性能方面做得很好,但您无法单独使用 RAF 控制每秒帧数。如果将 RAF 包装在 setTimeout 中,则可以控制每秒帧数。例如,当 fps==3 时,setTimeout(anyFunction,1000/fps) 将每秒触发大约 3 次 anyFunction。请参阅有关 RAF+setTimeout 的这篇精彩文章:http ://creativejs.com/resources/requestanimationframe/

正如您所发现的,没有 setTimeout 的 RAF 仍然可以工作,但 RAF 会尝试尽可能快地长出头发,而不是使用 fps 间隔。

于 2013-06-14T17:42:04.343 回答