处理 - 线条逐渐变大

时间:2017-06-20 14:29:49

标签: time processing lines

所以我在一个文件中的坐标和我想要一行的秒数逐渐变大。在文件中,我有x1,x2(关于第一个点坐标),x2,y2(第二个点坐标),以及我想要在第二个点方向开始生长线的时间(以秒为单位)。

这是我的代码:

//阅读线

import processing.video.*;
Movie myMovie;
Table table;
float duration, time;

int row_no=1;
int clickcount = 0;

void setup() {
  size(640,480);
  myMovie = new Movie(this, "draft.mov");
  myMovie.loop();


  table = loadTable("data/new.csv");

}

void draw() {

duration = myMovie.duration();
time = myMovie.time();
image(myMovie, 0, 0);  

if(time>= table.getFloat(row_no, 4)){
strokeWeight(15);
stroke(255,14,255);

float a = table.getFloat(row_no, 0);
float b = table.getFloat(row_no,1);

line(table.getFloat(row_no,0),table.getFloat(row_no, 1), a, b);

a = a + 2;
b = b + 2;
}



}
    // Called every time a new frame is available to read

void movieEvent(Movie m) {
  m.read();
} `

1 个答案:

答案 0 :(得分:0)

正如Niccolo建议的那样,先解决问题,拿出任何你不需要的东西,一步一步。

根据您对目标的描述而言,根据您的目标描述而言,这听起来并不像代码与播放电影有任何关系,因此请简单地使用该代码。 (我想到使用电影的唯一原因是使用它的当前时间来控制线条,但除非你想要电影背景,否则不需要它)

在draw()循环中有一些看起来奇怪的东西:

  1. if(time>= table.getFloat(row_no, 4)){假设.csv文件中的第5列以秒为单位保存当前行的提示时间,此条件只会触发一次,因为没有任何增量row_no
  2. line(table.getFloat(row_no,0),table.getFloat(row_no, 1), a, b);可能不是你想要的,可能是一个错字,因为ab已经从相同的.csv列(0和1)中检索到了,这意味着你的行的开始和结束位置都在准确的位置(因此不会呈现一条线)。也许你的意思是line(table.getFloat(row_no,2),table.getFloat(row_no, 3), a, b);
  3. a = a + 2;b = b + 2;:其中一个点的x,y位置可能会偏移2,但新位置永远不会超过此点。在下一个draw()次迭代ab被重新定义,因此偏移量将丢失。
  4. 让我们解决问题:

      

    我有一个文件 坐标和秒我想让一条线逐渐变大。在文件中,我有x1,x2(关于第一个点坐标),x2,y2(第二个点坐标),以及我想要在第二个点方向开始生长线的时间(以秒为单位)。

    1. 加载并解析数据(包含行坐标(x1,y1,x2,y2)和时间(以秒为单位)的行)
    2. “让一条线逐渐变大” - 在当前行(.csv行坐标)和下一行之间根据指定的时间(秒)动画(插值)
    3. 甚至更进一步,如果从头开始,更多的是作为“如何”:

      1. 在一个值和另一个值之间进行插值(暂时忽略时间,保持任务独立且尽可能简单)
      2. 跟踪时间作为值之间插值的参数
      3. 解析.csv行
      4. 在4个值之间进行插值
      5. 根据动画时间递增.csv行
      6. 幸运的是,Processing提供了一个内置函数,用于在值lerp()之间进行线性插值(lerp =简称线性插值)。 它需要三个参数:

        1. 从(开始)
        2. 制作动画的值
        3. 要为(停止)
        4. 设置动画的值
        5. 插值量(介于0.0和1.0之间)
        6. 并返回一个值:start和stop值之间的值。 将插值量视为百分比(0 = 0%,0.5 = 50%,1.0 = 100%)。

          这是一个基本草图来说明这个概念:

          void draw(){
            background(255);
            //map time to an interpolation normalized value 
            float t = map(mouseX,0,width,0.0,1.0);
            //interpolate the values
            float size = lerp(10,90,constrain(t,0.0,1.0));
            ellipse(50,50,size,size);
          }
          

          你可以运行p5.js演示的片段:

          function setup() {
            createCanvas(100,100);
          }
          
          function draw(){
            background(255);
            //map time to an interpolation normalized value 
            var t = map(mouseX,0,width,0.0,1.0);
            //interpolate the values
            var size = lerp(10,90,constrain(t,0.0,1.0));
            ellipse(50,50,size,size);
          }
          <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.11/p5.min.js"></script>

          如果您在x轴上移动鼠标,您会发现根据鼠标位置,直径大小在10到90像素之间。

          完成第1步!

          接下来,您可以使用millis()来跟踪时间,并在毫秒时间内简单地map()(将开始和结束时间之间的当前时间映射到0.0 - 1.0范围):< / p>

          float seconds = 3.5;
          
          //the time in millis since the last update
          int previousMillis;
          //the current time in millis 
          int currentMillis;
          //the time in millis until the next event
          int nextMillis;
          
          
          
          void setup(){
          
            previousMillis = millis();
            currentMillis = millis();
          
            nextMillis = currentMillis + (int)(seconds * 1000);
          
          }
          
          void draw(){
            background(255);
            //update the current timer continously
            currentMillis = millis();
            //map the current time from the previous to the next time as a normalized value (0,0 to 1.0) range
            float t = map(currentMillis,previousMillis,nextMillis,0.0,1.0);
          
            //interpolate the values
            float size = lerp(10,90,constrain(t,0.0,1.0));
            ellipse(50,50,size,size);
          }
          

          以及作为p5.js可运行的演示:

          var seconds = 3.5;
          
          //the time in millis since the last update
          var previousMillis;
          //the current time in millis 
          var currentMillis;
          //the time in millis until the next event
          var nextMillis;
          
          
          
          function setup(){
          
            previousMillis = millis();
            currentMillis = millis();
          
            nextMillis = currentMillis + (int)(seconds * 1000);
          
          }
          
          function draw(){
            background(255);
            //update the current timer continously
            currentMillis = millis();
            //map the current time from the previous to the next time as a normalized value (0,0 to 1.0) range
            var t = map(currentMillis,previousMillis,nextMillis,0.0,1.0);
          
            //interpolate the values
            var size = lerp(10,90,constrain(t,0.0,1.0));
            ellipse(50,50,size,size);
          }
          <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.11/p5.min.js"></script>

          这已经完成了第2步,看起来你已经掌握了第3步(解析.csv值):)

          一旦你理解了如何插入一个值,步骤4应该是微不足道的:只需对不同的变量做4次!

          第5步很简单,因为您只需要检查row_no是否超出了表的行数。

          row_no = row_no + 1;
          if(row_no > table.getRowCount()) row_no = 0;
          

          你可以做的一件好事是使用modulo operator(%)做一个数学表达式:

          row_no = (row_no + 1) % table.getRowCount();
          

          总之,我们假设您的.csv文件看起来有点像这样:

          x1,y1,x2,y2,seconds
          5,5,95,5,4
          95,5,95,95,3
          95,95,5,95,2
          5,95,5,5,1
          

          将这一切放在一起的一种方法是这样的:

          Table table;
          int row_no = 0;
          
          //the time in millis since the last update
          int previousMillis;
          //the current time in millis 
          int currentMillis;
          //the time in millis until the next event
          int nextMillis;
          
          //where to animate the line from
          float x1Start,y1Start,x2Start,y2Start;
          //where to animate the line to 
          float x1Stop,y1Stop,x2Stop,y2Stop;
          //currently interpolated line positions
          float x1Lerp,y1Lerp,x2Lerp,y2Lerp;
          
          void setup(){
            size(100,100);
            strokeWeight(3);
            fill(0);
          
            table = loadTable("data/new.csv","header, csv");
          
            //printing the table in console, handy just for debugging/double checking values
            println("data");
            for(int i = 0 ; i <= table.getRowCount(); i++){
              print(table.getColumnTitle(i)+"\t");
            }
            println();
            for(int i = 0 ; i < table.getRowCount(); i++){
              TableRow row = table.getRow(i);
              for(int j = 0; j < row.getColumnCount(); j++){
                print(row.getFloat(j) + "\t");
              }
              println();
            } 
            //fetch lines and seconds from the current and next rows
            updateFromRow();
          }
          
          void updateFromRow(){
            //update times
            previousMillis = millis();
            currentMillis = millis();
          
            //get the current row and it's line coordinates
            TableRow currentRow = table.getRow(row_no);
            x1Start     = currentRow.getFloat("x1");
            y1Start     = currentRow.getFloat("y1");
            x2Start     = currentRow.getFloat("x2");
            y2Start     = currentRow.getFloat("y2");
            //get the next row and it's line coordinates - notice % module is used to easily loop back to 0 once row_no goes beyond the number of table rows 
            TableRow nextRow = table.getRow((row_no + 1) % table.getRowCount());
            x1Stop     = nextRow.getFloat("x1");
            y1Stop     = nextRow.getFloat("y1");
            x2Stop     = nextRow.getFloat("x2");
            y2Stop     = nextRow.getFloat("y2");
            //get the duration in seconds, convert it to millis( * 1000) and add it to the current millis
            nextMillis = currentMillis + (int)(currentRow.getFloat("seconds") * 1000);
          
            println("updated from row: " + row_no);
          }
          
          void draw(){
            background(255);
            //update the current timer continously
            currentMillis = millis();
            //map the current time from the previous to the next time as a normalized value (0,0 to 1.0) range
            float t = map(currentMillis,previousMillis,nextMillis,0.0,1.0);
            //if the current interpolation value is above 1.0 
            if(t > 1.0){
              t = 0;
              //increment the row
              row_no++;
              //if the current row counter is above the total number of rows, reset back 0
              if(row_no >= table.getRowCount()){
                row_no = 0;
              }
              //update values from incremented row (lines and their coordinates + time)
              updateFromRow();
            }
            text("t:"+t,15,20);
          
            //constrain interpolated value between 0.0 and 1.0
            float interpolationAmount = constrain(t,0.0,1.0);
            //linearly interpolate (lerp) between the current and next line coordinates
            x1Lerp = lerp(x1Start,x1Stop,interpolationAmount);
            y1Lerp = lerp(y1Start,y1Stop,interpolationAmount);
            x2Lerp = lerp(x2Start,x2Stop,interpolationAmount);
            y2Lerp = lerp(y2Start,y2Stop,interpolationAmount);
          
            //finally, render the interpolated line 
            line(x1Lerp,y1Lerp,x2Lerp,y2Lerp);
          }
          

          在跟踪数据方面,可以使用PVector实例(... .csv数据中的x,y分量set()来存储线坐标,并且可以插入线点成对通过PVector's lerp())。 到目前为止,我们只使用线性插值,但您可能还想查看easingtweening