canvas实现多种树叶铺满屏幕效果代码

代码语言:html

所属分类:其他

代码描述:canvas实现多种树叶铺满屏幕效果代码,点击切换效果。

代码标签: canvas树叶 铺满 屏幕

下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">

<style>
    body {
  height: 100vh;
  width: 100vw;
  overflow:hidden;
}

canvas {
  height: 100vh;
  width: 100vw;
}
</style>

</head>

<body>
 
    <canvas id="canvas"></canvas>
 
    <script>
        (function () {

  //fields
  var canvas = document.getElementById("canvas");
  var body = document.getElementsByTagName("body")[0];
  var positions = []
  var ctx = canvas.getContext("2d");
  
  /*Initialize flowers*/
  body.addEventListener("click",function(ev){
    drawFlowers(false)
  })
  window.onload = ()=>{drawFlowers(true)}
  window.onresize = ()=>{drawFlowers(false)}

  /*Flower flunctions*/
  function Flower(opt) {
   
    this.r = opt.allowLarge && chance(.05) ? getRandomInt(50,150) : getRandomInt(20,50)
    this.x = getRandomInt(0, canvas.width)
    this.y = getRandomInt(0, canvas.height)

    this.lw = 4;    
    this.angle = getRandomInt(-30,30)
    this.rad = this.angle * (Math.PI / 180) /*FLOWER ROTATION*/
    this.opacity = 1;
    this.petals = chance(.03) ? 4 : 3;
    this.shiftOut = this.petals == 4 ? 0 : 0
    this.petalBase = 0;
    this.petalSpread1 = getRandomFloat(opt.minSpread, opt.maxSpread)
    this.petalLength1 = this.petalSpread1 * getRandomFloat(1.4, 1.8) /*length 1.5 longer than spread*/
    this.petalSpread2 = getRandomFloat(this.petalSpread1+.15,this.petalSpread1-.15);
    this.petalLength2 = this.petalLength1
    this.leafRotation = Math.floor(360/this.petals)/*PETAL ROTATION*/
    this.color1 = vary(opt.color1, opt.colorVariance)
  }
  
  function drawFlowers(firstTime) {
    scaleCanvas() 
    ctx.clearRect(0, 0, canvas.width, canvas.height)
    positions = [];
    
    //drawing options
    var opt = {    
      spaceAround:chance(), 
      allowLarge:chance(0), 
      padding:getRandomFloat(.5,3), /*multiplier*/
      color1:pick(greens),
      stems: chance(.7),
      stemLength : getRandomInt(20,(chance(.2)?150:60)), /*multiplier*/
      stemWidth:getRandomInt(2,5), /*multiplier*/
      colorVariance:getRandomInt(10,20),
      minSpread:getRandomFloat(.4,.7),
      maxSpread:getRandomFloat(.4,1.2),
      fieldEffect:firstTime || chance(.33),
      randomY:chance()
    }
    opt.stemsFirst = opt.fieldEffect || chance()
    canvas.style.transform = "rotate(0deg)"
    if(opt.fieldEffect){
      opt.stemLength *= getRandomInt(4,12)
      opt.stems = true
      opt.spaceAround = false
      if(chance(.1)) canvas.style.transform = "rotate(180deg)"
       
    } 
    opt.isDark = opt.color1.l<50
    console.log(opt.color1.name)
    let bg = new Color(pick(greens))
    if(chance(.2)) bg.h = getRandomInt(0,359)
    bg.l = bg.l>50? bg.l+15: bg.l-15;
    canvas.style.backgroundColor = bg.hsl()
    
    let screenSize = Math.min(window.innerWidth, window.innerHeight)
    let numFlower = opt.fieldEffect?getRandomInt(500,1000):getRandomInt(50,screenSize>1000?3000:1500)
    let flowers = []
    let baseHeightRandom = getRandomInt(window.innerHeight-300,window.innerHeight)
    
    
    for(let i=0; i<numFlower; i++){
      let f = new Flower(opt)
      if(opt.fieldEffect) {      
        let yPos = getRandomInt(-150,150)+(opt.randomY?getRandomInt(window.innerHeight/2.25,window.innerHeight):baseHeightRandom); 
        f.y = yPos        
      }
      flowers.push(f)  
    }
    
    /*sort functions*/
    function hueSort(a,b) { 
       let greenDistance1 = Math.abs(120-a.color1.h)
       let greenDistance2 = Math.abs(120-b.color1.h)
       return (greenDistance1>greenDistance2?-1:1) 
     }
    function lightSort(a,b){
      return a.color1.l>b.color1.l?(opt.isDark?1:-1):(opt.isDark?-1:1)
    }
    
    let filter = pick([hueSort,lightSort])
    console.log("filter is:"+filter, ",isDark:\n"+opt.isDark)
    flowers.sort(filter)
    
    //draw stems first then layer on flower part.
    for(let i=0; i<numFlower; i++){
      let previous = flowers.slice(0,i)
      let f = flowers[i];
      if(opt.spaceAround&&previous.some(function(pos) {
        let d =  distance(new Point(f.x,f.y), new Point(pos.x,pos.y))
        return d<f.r*opt.padding;
      })) {
        f.hide = true;
      } else {
        if(opt.stems && opt.stemsFirst) drawStem(f,opt)
      }
      
    }
    for(let i=0; i<numFlower; i++){
      if(opt.stems && !opt.stemsFirst) drawStem(flowers[i],opt)
      drawFlower(flowers[i],opt)
    }
  } 
  
  function drawStem(f, opt){
    if(f.hide) {
      return false;
    }
    ctx.translate(f.x, f.y);
    let angle = getRandomInt(-20,20)*(Math.PI/180)
    ctx.rotate(angle);
    ctx.translate(-f.x, -f.y);
    
    ctx.fillStyle = f.color1.hsl()
    ctx.strokeStyle = ctx.fillStyle;
    ctx.beginPath()
    ctx.lineWidth = f.petalSpread1*opt.stemWidth;
    let stemLength = f.petalSpread1*getRandomFloat(opt.stemLength-2, opt.stemLength+2)
    ctx.moveTo(f.x,f.y)
    let curve = getRandomInt(5,20)
    if(chance()) curve *= -1
    //each petal is two curves
    ctx.quadraticCurveTo(f.x+curve, f.y+(stemLength/2),
                         f.x, f.y+stemLength);
    ctx.moveTo(f.x,f.y)
    ctx.quadraticCurveTo(f.x+curve, f.y+(stemLength/2),
                         f.x+1, f.y+stemLength);
    
    ctx.save()
    ctx.setTransform(0, .1, 0, 0, 0, 0)
    ctx.restore()
    
    ctx.stroke()
    ctx.translate(f.x, f.y);
    ctx.rotate(-angle);
    ctx.translate(-f.x, -f.y);
    ctx.closePath()
    ctx.restore()
  }
  
  function drawFlower(f,opt) {

    if(f.hide) {
      return false;
    }

    positions.push(new Point(f.x, f.y))
    ctx.save();
    ctx.globalAlpha = f.opacity
    ctx.lineWidth = f.lw;
    ctx.translate(f.x, f.y);
    ctx.rotate(f.rad);
    ctx.translate(-f.x, -f.y);
    
    ctx.fillStyle = f.color1.hsl()
    let lineColor = new Color(f.color1)
    lineColor.l += getRandomInt(-10,10)
  
    //PETALS
    for (let i = 0; i < f.petals; i++) {
      
      ctx.translate(f.x, f.y);
      ctx.rotate(f.leafRotation * (Math.PI / 180));
      ctx.translate(-f.x, -f.y);

      ctx.beginPath();
      ctx.moveTo(f.x, f.y-f.shiftOut); 
      ctx.fillStyle = f.color1.hsl() 
      let sp1 = f.r*f.petalSpread1
      let len1 = f.r*f.petalLength1
      let sp2 = f.r*f.petalSpread2
      let len2 = f.r*f.petalLength2
      let endX = f.petalBase
      let endY = f.shiftOut
      let angle = getRandomInt(15,50) * (Math.PI / 180)
      
      //LEAF
      for (let j = 0; j < 2; j++) {
        
        //'heart' shaped petals via two bezier curves
        ctx.translate(f.x, f.y)     
        ctx.rotate(j*angle);      
        ctx.translate(-f.x, -f.y)
        
        ctx.bezierCurveTo(f.x-sp1,/*control point #1 'upper left'*/
                          f.y-len1,
                          f.x+sp2,/*control point #2 'upper right'*/
                          f.y-len2,
                          f.x+endX,/*ending point*/
     .........完整代码请登录后点击上方下载按钮下载查看

网友评论0