【问题标题】:HTML5 canvas continuously stroking linesHTML5画布连续抚摸线条
【发布时间】:2013-07-06 19:18:48
【问题描述】:

我想用 HTML5 和 Javascript 画一些不断增长的线条。这是我想做的:

位于我屏幕中心的一个点将有 3 条线(彼此成 120 度)增长到一定长度,比如 50 像素,然后这 3 个顶点中的每一个都将成为一个新的中心并有另外 3 条线。

(由于声誉低,我无法发布图片,希望您知道我在这里的图片的意思...)

我已经编写了一个函数,将我需要的所有点作为中心,从我的屏幕中心开始。我正在考虑在这个数组上写一个循环来画线。我不想直接使用笔划,以便线条只出现在屏幕上。我想要线条一点一点地画出来(这里的英语不好,请原谅我的英语),直到它达到预定义的长度。但是我的代码在这里不能很好地工作,它只显示所有中心点,并且只有最后一个中心点有运动以使 3 条线增长...

我需要知道执行此操作的正确方法...非常感谢!

(请忽略我代码中的变量 time 或 startTime...)

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

var canvas = document.getElementById('myCanvas');
canvas.width= window.innerWidth;
canvas.height= window.innerHeight;
var context = canvas.getContext('2d');
var totalLength = 50;

var centreSet = new Array();
var counter = 0;

var centre = {
    x: canvas.width / 2,
    y: canvas.height / 2,
};

var myLine = {
    length : 0,
    color : 'grey',
    lineWidth : 0.5,
};

function drawLine(centre, context, mylength) {
    context.beginPath();
    context.moveTo(centre.x, centre.y);
    context.lineTo(centre.x, centre.y - mylength);
    context.moveTo(centre.x, centre.y);
    context.lineTo(centre.x - 0.866 * mylength, centre.y + mylength/2);
    context.moveTo(centre.x, centre.y);
    context.lineTo(centre.x + 0.866 * mylength, centre.y + mylength/2);
    context.lineWidth = myLine.lineWidth;
    context.strokeStyle = myLine.color;
    context.closePath();
    context.stroke();
}

function startAnimate(centre, canvas, context, startTime, mylength) {
        // update
    var time = (new Date()).getTime() - startTime;
    var linearSpeed = 5;
    // pixels / second
    var newX = linearSpeed / 10;

    if(mylength < totalLength) {
        mylength = mylength + newX;
        // clear
        //context.clearRect(0, 0, canvas.width, canvas.height);
        drawLine(centre, context, mylength);

        // request new frame
        requestAnimFrame(function() {
            startAnimate(centre, canvas, context, startTime, mylength);
        });
    }

}

function animate(centre, canvas, context, startTime){
            //create array to have all the center points
    centreSet = getCentres(); 
    for (var i = 0; i < centreSet.length; i++){
                    //pass the x and y values in a object for each center we have in the array
        centre.x = str2x(centreSet[i]);
        centre.y = str2y(centreSet[i]);
        startAnimate(centre, canvas, context, startTime, 0);
    }
}

    setTimeout(function() {
    var startTime = (new Date()).getTime();
    animate(centre, canvas, context, startTime);
}, 1000);

我刚刚编辑了你的代码,我添加了以下部分:

var length = 0;
for(var i = 0; i < 380; i++){
window.setTimeout(function() {drawFrame(length);},16.67);
length = length + 0.25; 
}

我希望屏幕看起来会一点一点地绘制增量线,直到达到我想要的长度。但是,似乎没有显示整个增量过程,它只显示了完成的绘图。

谁能告诉我为什么?

【问题讨论】:

    标签: javascript html canvas


    【解决方案1】:

    关于您的动画循环为何失败的后续问题

    通过将 setTimeout 置于 for 循环中,每个新的 setTimeout 都会取消之前的 setTimeout。

    所以你只剩下最后一个 setTimeout 运行完成。

    在动画循环中,您通常在每个“帧”中做 3 件事:

    1. 更改一些数据以反映新帧与前一帧的不同之处。
    2. 画出框架。
    3. 测试动画是否完整。如果没有,请再做一帧(转到 #1)。

    setTimeout函数用于做#3的最后一部分(做另一帧)

    所以 setTimeout 确实充当了您的动画循环。 --- 不需要你的 for 循环。

    这是您将如何重构代码以遵循此模式:

    var length=0;
    var maxLength=50;
    
    function draw(){
    
        // make the line .25 longer
        length=length+.25;
    
        // draw
        drawFrame(length);
    
        // test if the line is fully extended
        // if not, call setTimeout again
        // setTimeout(draw,100) will call this same draw() function in 100ms
        if(length<maxLength){
            setTimeout(draw,100);
        }
    }
    

    【讨论】:

      【解决方案2】:

      [已编辑:包括在行到达终端距离后生成子对象]

      在您的代码中,当线条达到最大延伸时,您并没有产生新的中心点。

      我建议您的每个中心对象至少有这么多信息,以便在它们的线达到终端长度时生成一组新的中心对象:

      var newCentrePoint={
          x:x,
          y:y,
          maxLength:newMaxLength,
          growLength:growLength,
          currentLength:0,
          isActive:true
      }
      

      x,y 是中心点的坐标。

      maxLength 是 3 行终止前的最大扩展。

      growLength 是每一行在每个新帧中的增长量。

      currentLength 是当前行的长度。

      isActive 是一个标志,指示该点是在增长线(真)还是终止(假)

      然后,当每行达到终端长度时,您可以生成一组新的行,如下所示:

      // spawns 3 new centre points – default values are for testing
      function spawn(point,newMaxLength,newColor,growLength,newLineWidth){
          var max=newMaxLength||point.maxLength/2;
          var color=newColor|| (colors[++colorIndex%(colors.length)]);
          var grow=growLength||point.growLength/2;
          var lw=newLineWidth||point.lineWidth-1;
      
          // new center points are spawned at the termination points of the 3 current lines
          newPoint((point.x),(point.y-point.maxLength),max,color,grow,lw);
          newPoint((point.x-0.866*point.maxLength),(point.y+point.maxLength/2),max,color,grow,lw);
          newPoint((point.x+0.866*point.maxLength),(point.y+point.maxLength/2),max,color,grow,lw);
      }
      
      // creates a new point object and puts in the centreSet array for processing
      function newPoint(x,y,newMaxLength,newColor,growLength,newLineWidth){
          var newPt={
              x:x,
              y:y,
              maxLength:newMaxLength,
              color:newColor,
              lineWidth:newLineWidth,
              growLength:growLength,
              currentLength:0,
              isActive:true
          }
          centreSet.push(newPt);
      }
      

      这是代码和小提琴:http://jsfiddle.net/m1erickson/Vc8Gf/

      <!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(){
      
          var canvas=document.getElementById("canvas");
          var context = canvas.getContext('2d');
      
          // colors
          var colors=["red","blue","gold","purple","green"];
          var colorIndex=0;
      
          //
          var centreSet=[]
          var generations=1;
      
          // seed point
          newPoint(canvas.width/2,canvas.height/2,100,"red",15);
      
          // start 
          draw();
      
          //
          function draw(){
              //
              context.clearRect(0,0,canvas.width,canvas.height);
              //
              for(var i=0;i<centreSet.length;i++){
                  //
                  var centre=centreSet[i];
      
      
                  //
                  if(centre.isActive){
                      // 
                      centre.currentLength+=centre.growLength;
                      //
                      if(centre.currentLength>=centre.maxLength){
                          centre.isActive=false;
                          centre.currentLength=centre.maxLength;
                          spawn(centre);
                      }
                  }
                  //
                  drawLines(centre);
              }
              //
              if(generations<120){
                  setTimeout(draw,500);
              }else{
                  context.font="18pt Verdana";
                  context.fillText("Finished 120 generations",40,350);
              }
          }
      
      
          function spawn(point,newMaxLength,newColor,growLength,newLineWidth){
              var max=newMaxLength||point.maxLength/2;
              var color=newColor|| (colors[++colorIndex%(colors.length)]);
              var grow=growLength||point.growLength/2;
              var lw=newLineWidth||point.lineWidth-1;
              newPoint((point.x),(point.y-point.maxLength),max,color,grow,lw);
              newPoint((point.x-0.866*point.maxLength),(point.y+point.maxLength/2),max,color,grow,lw);
              newPoint((point.x+0.866*point.maxLength),(point.y+point.maxLength/2),max,color,grow,lw);
              generations++;
          }
      
          function newPoint(x,y,newMaxLength,newColor,growLength,newLineWidth){
              var newPt={
                  x:x,
                  y:y,
                  maxLength:newMaxLength,
                  color:newColor,
                  lineWidth:newLineWidth,
                  growLength:growLength,
                  currentLength:0,
                  isActive:true
              }
              centreSet.push(newPt);
          }
      
      
          function drawLines(centre) {
      
              var length=centre.currentLength;
              //
              context.beginPath();
              context.moveTo(centre.x, centre.y);
              context.lineTo(centre.x, centre.y - length);
              //
              context.moveTo(centre.x, centre.y);
              context.lineTo(centre.x - 0.866 * length, centre.y + length/2);
              //
              context.moveTo(centre.x, centre.y);
              context.lineTo(centre.x + 0.866 * length, centre.y + length/2);
              //
              context.strokeStyle=centre.color;
              context.lineWidth = centre.lineWidth;
              context.stroke();
          }
      
      }); // end $(function(){});
      </script>
      
      </head>
      
      <body>
          <canvas id="canvas" width=400 height=400></canvas>
      </body>
      </html>
      

      【讨论】:

      • 嗨,马克,我想知道我的代码哪里做错了,因为结果输出显示了所有中心点和最后一个点的增量绘图..
      • 您好!在您的代码中,您的中心对象可以扩展为包含足够的数据,以便在线路到达终端距离后生成 3 个子中心对象。我添加到我的答案以说明如何。
      • 在我的代码中,我已经有一个数组,其中包含生成 3 行所需的所有中心点,它位于 aminate(), centerSet = getCentres();
      猜你喜欢
      • 1970-01-01
      • 2019-07-04
      • 1970-01-01
      • 1970-01-01
      • 2011-09-11
      • 2020-04-22
      • 2016-10-11
      • 2013-09-05
      相关资源
      最近更新 更多