Difference between revisions of "Template:Duesseldorf/2021 gras"

Line 1: Line 1:
 
<html>
 
<html>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.18.0/TweenMax.min.js"></script>
 
<script src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/16327/MorphSVGPlugin.min.js"></script>
 
 
<style>
 
<style>
#grass_stage{
 
  position: fixed;
 
  /* width: 800px; */
 
  /* height: 600px; */
 
  bottom: 0;
 
  left: 0;
 
  /* transform: translate(-50%, -100%); */
 
}
 
 
#grass_stage path {
 
  fill: none;
 
  stroke: green;
 
}
 
 
</style>
 
</style>
 
  
 
<script>
 
<script>
 +
/**
 +
Author: Lucas Mota Ribeiro
 +
This project creates an adaptive array of leafs and animate them.
 +
*/
  
class Grass {
+
/**
 +
* Load leaf generator when document is ready.
 +
*/
 +
$(document).ready(function(){
 +
    exec();
 +
});
  
  constructor(path, offset, width, height, minHeight, maxHeight, maxAngle, startAngle) {
+
var MID_HEIGHT = 1; // The height of the middle of the leaf.
 +
var HEIGHT = 33; // Leaf Height.
 +
var WIDTH = 17; // Leaf width.
 +
var distance = 10; // Distance between leafs.
 +
var ANGLE = Math.PI / 2; // The angle tha the leaf starts.
 +
var RANDOMNESS  = 14; // How random these parameters are the leaf's array.
 +
var time = 0; // Time counter.
 +
var leafColor = '#013e04'; // Color of the leaf.
  
    this.path = path;   
+
var FPS = 30;
   
+
var SPEED = 5;
    this.width    = random(1, 5);
+
var LAMBDA = 0.5;
    this.height  = random(20, maxHeight);
+
    this.maxAngle = random(30, maxAngle);
+
    this.angle    = Math.random() * randomSign() * startAngle * Math.PI / 180;   
+
   
+
    var offsetX = 1.5;
+
   
+
    // Start position
+
    var sx = offset / 2 + random(width - offset);
+
    var sy = height; 
+
   
+
    // Curvature
+
    var csx = sx - offsetX;
+
    var csy = sy - this.height / (Math.random() < 0.5 ? 1 : 2);
+
  
    // Parallel point
+
/*!
    var psx = csx;
+
* Funtion to generate leafs.
     var psy = csy;
+
*/
   
+
function exec() {
    var dx = sx + this.width;
+
     /*!
     var dy = sy;
+
    * Array of leafs.
 +
    */
 +
     var grass = [];
  
     this.coords  = [sx, sy, csx, csy, psx, psy, dx, dy];             
+
     /*!
       
+
    * Canvas element to draw the leafs.
    this.growing = false;
+
    */
    this.morphed = false;
+
     var canvas = document.getElementById("canvas");
   
+
    this.start  = 0;
+
    this.elapsed = 0;
+
   
+
    this.height_ = this.height; 
+
    this.height  = random(20, Math.min(500, this.height));
+
   
+
    var ambient = 0.85;
+
   
+
    var color = [
+
      Math.floor(random(16,  48)  * ambient), 
+
      Math.floor(random(100, 255) * ambient),
+
      Math.floor(random(16,  48)  * ambient)
+
    ];
+
   
+
    var w = this.width / 2;
+
     var d = `M${sx},${sy + 2},h${w},h${w}z`;
+
   
+
    TweenLite.set(path, { fill: `rgb(${color})`, attr: { d }});
+
  }
+
 
+
  grow() {
+
   
+
    this.morphed = true;
+
    this.growing = false;
+
    this.elapsed = now() - this.start;
+
  
     TweenLite.to(this, random(2.5, 3.5), { height: this.height_, ease: Power1.easeInOut });
+
     /*!
  }
+
    * Canvas 2D context.
 
+
    */
  morph(morphSVG) {
+
     var ctx = canvas.getContext("2d");
   
+
     var time  = random(1.5, 3.5);
+
    var delay = random(0.5, 4.5);
+
   
+
    this.growing = true;
+
   
+
    TweenLite.to(this.path, time, { morphSVG, delay, onComplete: () => this.grow()});
+
  }
+
 
+
  update(time) {
+
   
+
    if (this.growing) return;
+
   
+
    time -= this.elapsed;
+
  
     var coords = this.coords;
+
     canvas.width = window.innerWidth - 2;
     var tip = Math.sin(time * 0.0007);
+
     /*!
 +
    * Canvas width.
 +
    */
 +
    var canvW = canvas.width;
  
     var th = this.angle + Math.PI / 2 + tip * Math.PI / 180 * (this.maxAngle * Math.cos(time * 0.0002));
+
     /*!
     var px = coords[0] + this.width  + this.height * Math.cos(th);
+
    * List of random digits as string.
     var py = coords[1] - this.height * Math.sin(th);
+
    */
           
+
     var digits = "";
     var d = `M${coords[0]},${coords[1]}`;  
+
 
     d += `C${coords[0]},${coords[1]},${coords[2]},${coords[3]},${px},${py}`;
+
     /*!
     d += `C${px},${py},${coords[4]},${coords[5]},${coords[6]},${coords[7]}z`;
+
    * Random counter.
      
+
    */
     if (!this.morphed) {
+
     var randCounter = 0;
      this.morph(d);
+
 
      this.start = now();
+
 
    } else {
+
     /////////////////////////////////////////////////////
      this.path.setAttribute("d", d);
+
     //
 +
     //            FUNCTIONS
 +
     //
 +
    /////////////////////////////////////////////////////
 +
 
 +
    /*!
 +
    * Gets next random digit from the array of digits.
 +
    */
 +
    function nextRand(){
 +
        var size = digits.length;
 +
        randCounter = (randCounter == size) ? 0 : ++randCounter;
 +
        return digits[randCounter];
 
     }
 
     }
  }
 
 
 
  destroy() {
 
   
 
    TweenLite.killTweensOf(this);
 
    TweenLite.killTweensOf(this.path);
 
   
 
    this.path.parentElement.removeChild(this.path);
 
  }
 
}
 
  
function getWidth() {
+
    /*!
  return Math.max(
+
    * Create leafs.
    document.body.scrollWidth,
+
    */
    document.documentElement.scrollWidth,
+
    function createLeafs(){
    document.body.offsetWidth,
+
        randCounter = 0;
    document.documentElement.offsetWidth,
+
        for (var dist = 0; dist < canvas.width + 50; dist += distance) {
    document.documentElement.clientWidth
+
            var leaf={}
  );
+
            var paralAng=ANGLE-Math.PI/2;
}
+
            leaf.rand0 = nextRand();
 +
            leaf.rand1 = nextRand();
 +
            leaf.rand2 = nextRand();
  
var xmlns  = "http://www.w3.org/2000/svg";
+
            //console.log(leaf.rand0+" "+leaf.rand1+" "+leaf.rand2+" "+(((leaf.rand0-5)/5)*HEIGHT*RANDOMNESS/100)+HEIGHT);
 +
            leaf.Y0 = canvas.height + 5;
 +
            leaf.X0 = dist;
 +
            leaf.X1 = Math.floor(HEIGHT*Math.cos(ANGLE));
 +
            leaf.Y1 = Math.floor(HEIGHT*Math.sin(ANGLE));
 +
            leaf.X2 = Math.floor(MID_HEIGHT*Math.cos(ANGLE));//0
 +
            leaf.Y2 = Math.floor(MID_HEIGHT*Math.sin(ANGLE));//75
 +
            leaf.X3 =  leaf.X2 + Math.floor(WIDTH*Math.cos(paralAng));
 +
            leaf.Y3 =  leaf.Y2 + Math.floor(WIDTH*Math.sin(paralAng));
 +
            leaf.X4 =  leaf.X2 + Math.floor(WIDTH*Math.cos(paralAng+Math.PI));
 +
            leaf.Y4 =  leaf.Y2 + Math.floor(WIDTH*Math.sin(paralAng+Math.PI));
  
var perf  = window.performance;
+
            leaf.path1 = new Path2D('M '+leaf.X0+' '+leaf.Y0+' q '+leaf.X3+' -'+leaf.Y3+' '+leaf.X1+' -'+leaf.Y1);
var now    = perf ? perf.now.bind(perf) : Date.now;
+
            leaf.path2 = new Path2D('M '+leaf.X0+' '+leaf.Y0+' q '+leaf.X4+' -'+leaf.Y4+' '+leaf.X1+' -'+leaf.Y1);
 +
            grass.push(leaf); // Add lead to array.
 +
        }
 +
    }
  
var stage = document.querySelector("#stage");
+
    /*!
 +
    * Draw the array of leafs for a certain time.
 +
    * @param time The current time.
 +
    */
 +
    function drawGrass(time) {
 +
        randCounter = 0;
 +
        grass = [];
 +
        for(var dist = -100; dist < canvas.width + 50; dist += distance){
 +
            var time_ang = Math.PI/6*Math.cos((dist * LAMBDA + time * SPEED) * Math.PI / 180);
 +
            var leaf = {}, tHeight = 0, tMheight = 0, tWidth = 0;
 +
            var paralAng = ANGLE-Math.PI/2+time_ang;
 +
            var aux;
 +
            leaf.rand0 = nextRand();
 +
            leaf.rand1 = nextRand();
 +
            leaf.rand2 = nextRand();
 +
            aux = ((leaf.rand0 - 5) * HEIGHT * RANDOMNESS / 500);
 +
            tHeight =aux+HEIGHT;
 +
            /*if(i==0){
 +
              console.log(">>"+typeof(aux) +" "+typeof(HEIGHT)+" "+typeof(tHeight));
 +
            }*/
 +
            tMheight = ((((leaf.rand1-5)/5)*MID_HEIGHT*RANDOMNESS/100)+MID_HEIGHT);
 +
            tWidth = ((((leaf.rand2-5)/5)*WIDTH*RANDOMNESS/100)+WIDTH);
  
var start  = now();
+
            //console.log(leaf.rand0+" "+leaf.rand1+" "+leaf.rand2+" "+((((leaf.rand0-5)/5)*HEIGHT*RANDOMNESS/100)+HEIGHT));
var blades = [];
+
            //
 +
            leaf.Y0 = canvas.height+5;
 +
            leaf.X0 = dist;
 +
            leaf.X1 = Math.floor(tHeight*Math.cos(ANGLE+time_ang));
 +
            leaf.Y1 = Math.floor(tHeight*Math.sin(ANGLE+time_ang));
 +
            leaf.X2 = Math.floor(tMheight*Math.cos(ANGLE+time_ang));//0
 +
            leaf.Y2 = Math.floor(tMheight*Math.sin(ANGLE+time_ang));//75
 +
            leaf.X3 = leaf.X2 + Math.floor(tWidth*Math.cos(paralAng));
 +
            leaf.Y3 = leaf.Y2 + Math.floor(tWidth*Math.sin(paralAng));
 +
            leaf.X4 = leaf.X2 + Math.floor(tWidth*Math.cos(paralAng+Math.PI));
 +
            leaf.Y4 = leaf.Y2 + Math.floor(tWidth*Math.sin(paralAng+Math.PI));
  
var offset = 20;
+
            leaf.path1 =new Path2D('M '+leaf.X0+' '+leaf.Y0+' q '+leaf.X3+' '+(-leaf.Y3)+' '+leaf.X1+' '+(-leaf.Y1));
var width  = getWidth();
+
            leaf.path2 =new Path2D('M '+leaf.X0+' '+leaf.Y0+' q '+leaf.X4+' '+(-leaf.Y4)+' '+leaf.X1+' '+(-leaf.Y1));
var height = 100;
+
            grass.push(leaf);
var total  = getWidth() / 6;
+
        }
 +
        // var k =3;
 +
        //console.log("ANGLE:"+Math.floor(ANGLE*180/Math.PI)+" P0:"+grass[k].X0+" "+(400-grass[k].Y0)+" P1:"+(grass[k].X0+grass[k].X1)+" "+grass[k].Y1+" P2:"+(grass[k].X0+grass[k].X2)+" "+grass[k].Y2+" P3:"+(grass[k].X0+grass[k].X3)+" "+grass[k].Y3+" P4:"+(grass[k].X0+grass[k].X4)+" "+grass[k].Y4);
 +
        ctx.lineWidth = 2;
  
var minHeight  = 10;
+
        for(var i = 0; i < grass.length; i++){
var maxHeight  = height * .8;
+
            ctx.fillStyle = leafColor;
var maxAngle  = 20;
+
            var leaf = grass[i];
var startAngle = 40;
+
            ctx.fill(leaf.path1);
 +
            ctx.fill(leaf.path2);
 +
            //ctx.strokeStyle = "rgba(1,62,4,0.5)";
  
TweenLite.set(stage, { width, height });
+
            // console.log(typeof(leaf.X0));
 +
            var grad = ctx.createLinearGradient(leaf.X0 + leaf.X1, leaf.Y0 - leaf.Y1, leaf.X0, leaf.Y0);
 +
            var opacity = 0; //55% visible
 +
            grad.addColorStop(0,'rgba(1,62,4,'+opacity+')');
  
TweenLite.ticker.addEventListener("tick", render);
+
            grad.addColorStop(0.2, leafColor);
 +
            grad.addColorStop(1, leafColor);
 +
            ctx.strokeStyle = grad;
  
init();
+
            ctx.beginPath();
 +
            ctx.moveTo(leaf.X0, leaf.Y0);
 +
            ctx.lineTo(leaf.X0+leaf.X1, leaf.Y0-leaf.Y1);
 +
            ctx.stroke();
 +
            /*ctx.fillStyle = '#000';
 +
            if(i == 0){
 +
                ctx.font="20px Georgia";
 +
                ctx.fillText("x0:"+leaf.X0+" y0:"+leaf.Y0,10,10);
 +
                ctx.fillText("x1:"+leaf.X1+" y1:"+leaf.Y1,10,40);
 +
                ctx.fillText("x2:"+leaf.X2+" y2:"+leaf.Y2,10,70);
 +
                ctx.fillText("x3:"+leaf.X3+" y3:"+leaf.Y3,10,100);
 +
                ctx.fillText("x4:"+leaf.X4+" y4:"+leaf.Y4,10,130);
 +
        ctx.fillText("r0:"+leaf.rand0+" r1:"+leaf.rand1+" r2:"+leaf.rand2,500,20);
 +
                ctx.fillText("Height:"+tHeight.toString(),10,160);
 +
                ctx.fillText("Width:"+tWidth,10,190);
 +
                ctx.fillRect(leaf.X0+leaf.X2-5/2,leaf.Y0-leaf.Y2-5/2,5,5);
 +
            }*/
 +
        }
 +
    }
  
function init() {
+
    function resizeCanvas() {
 +
        canvas.width = $('canvas').parent().innerWidth();
 +
        //console.log(window.innerWidth);
 +
        ctx.clearRect(0, 0, canvas.width, canvas.height);
 +
    }
  
  blades.forEach(blade => blade.destroy());
+
    /////////////////////////////////////////////////////
 +
    //
 +
    //          EXECUTION
 +
    //
 +
    /////////////////////////////////////////////////////
  
  blades = [];
+
    // Populate random digits string
 +
    for(var i = 0; i < 137;i++){
 +
        digits += Math.floor(Math.random() * 10**9);
 +
    }
  
  for (var i = 0; i < total; i++)
+
    createLeafs();
     var path = createSVG("path", stage);
+
     console.log("HI");
     blades[i] = new Grass(path, offset, width, height, minHeight, maxHeight, maxAngle, startAngle);
+
     // Updates canvas for a certain FPS.
  }
+
    window.setInterval(function () {
 +
        resizeCanvas();
 +
        drawGrass(time);
 +
        time = (time<=360) ? ++time : 0;
 +
    }, 1000/FPS);
 
}
 
}
  
function render() {
+
/*!
 
+
* Updates leafs' height.
  var elapsed = now() - start;
+
* @param new_height The new height.
 
+
*/
  if (!blades.length) return;
+
function updateHeight(new_height) {
 
+
     HEIGHT = Number(new_height);
  for (var i = 0; i < total; i++) {
+
     blades[i].update(elapsed);
+
  }
+
 
}
 
}
  
function createSVG(type, parent) {
+
/*!
  var node = document.createElementNS(xmlns, type);
+
* Updates leafs' middle height.
  parent && parent.appendChild(node);
+
* @param new_Mheight The new middle height.
  return node;
+
*/
 +
function updateMHeight(new_Mheight) {
 +
    MID_HEIGHT = Number(new_Mheight);
 
}
 
}
  
function random(min, max) {
+
/*!
  if (max == null) {
+
* Updates leafs' width.
     max = min;
+
* @param new_width The new width.
    min = 0;
+
*/
  }
+
function updateWidth(new_width) {
  return min + Math.random() * (max - min);
+
     WIDTH = Number(new_width);
 
}
 
}
  
function randomSign() {
+
/*!
  return Math.random() < 0.5 ? 1 : -1;
+
* Updates leafs' starting angle.
 +
* @param new_width The new angle.
 +
*/
 +
function updateAngle(new_angle) {
 +
    ANGLE = Number(new_angle) * (Math.PI/180);
 
}
 
}
  
 +
/*!
 +
* Updates how random the leafs parameters will be.
 +
* @param new_random The new randomness.
 +
*/
 +
function updateRandomness(new_random) {
 +
    RANDOMNESS = Number(new_random);
 +
}
  
 +
/*!
 +
* Updates canvas' height.
 +
* @param new_width The new canvas height.
 +
*/
 +
function updateCanvasHeight(new_cheight) {
 +
    var canvas = document.getElementById("canvas");
 +
    canvas.height = Number(new_cheight);
 +
}
 +
 +
/*!
 +
* Updates leafs' distance between each other.
 +
* @param new_distance The new distance between leafs.
 +
*/
 +
function updateLeafsDistance(new_distance) {
 +
    distance = Number(new_distance);
 +
}
 
</script>
 
</script>
  
<svg id="grass_stage">
+
<canvas height="150px" id="canvas"></canvas>
</svg>
+
  
  
 
</html>
 
</html>

Revision as of 09:44, 6 October 2021