2013-05-01 14 views
20

EDIT:Cố gắng tạo hiệu ứng hoa giấy trong html5, làm thế nào để tôi nhận được một màu tô khác nhau cho từng phần tử?

Đối với bất kỳ ai tò mò, đây là kết quả hoàn thành.

http://jsfiddle.net/Javalsu/vxP5q/743/embedded/result/


Tôi đang xây dựng tắt của mã tôi tìm thấy trong liên kết này

http://thecodeplayer.com/walkthrough/html5-canvas-snow-effect

Tôi muốn làm nhiều hơn nữa này một hiệu ứng rơi confetti hơn một hiệu ứng tuyết, và tôi sẽ cần phải làm cho mỗi phần tử có màu khác nhau. Nhưng có vẻ như màu tô được đặt cho toàn bộ canvas cùng một lúc.

Có cách nào để chỉ định một màu tô khác nhau cho mỗi phần tử hay tôi đang đi về điều này một cách hoàn toàn sai?

Cảm ơn

Cập nhật: Đây là sản phẩm hoàn chỉnh nếu ai có nhu cầu confetti

http://jsfiddle.net/mj3SM/6/

window.onload = function() { 
//canvas init 
var canvas = document.getElementById("canvas"); 
var ctx = canvas.getContext("2d"); 

//canvas dimensions 
var W = window.innerWidth; 
var H = window.innerHeight; 
canvas.width = W; 
canvas.height = H; 

//snowflake particles 
var mp = 200; //max particles 
var particles = []; 
for (var i = 0; i < mp; i++) { 
    particles.push({ 
     x: Math.random() * W, //x-coordinate 
     y: Math.random() * H, //y-coordinate 
     r: Math.random() * 15 + 1, //radius 
     d: Math.random() * mp, //density 
     color: "rgba(" + Math.floor((Math.random() * 255)) + ", " + Math.floor((Math.random() * 255)) + ", " + Math.floor((Math.random() * 255)) + ", 0.8)", 
     tilt: Math.floor(Math.random() * 5) - 5 
    }); 
} 

//Lets draw the flakes 
function draw() { 
    ctx.clearRect(0, 0, W, H); 



    for (var i = 0; i < mp; i++) { 
     var p = particles[i]; 
     ctx.beginPath(); 
     ctx.lineWidth = p.r; 
     ctx.strokeStyle = p.color; // Green path 
     ctx.moveTo(p.x, p.y); 
     ctx.lineTo(p.x + p.tilt + p.r/2, p.y + p.tilt); 
     ctx.stroke(); // Draw it 
    } 

    update(); 
} 

//Function to move the snowflakes 
//angle will be an ongoing incremental flag. Sin and Cos functions will be applied to it to create vertical and horizontal movements of the flakes 
var angle = 0; 

function update() { 
    angle += 0.01; 
    for (var i = 0; i < mp; i++) { 
     var p = particles[i]; 
     //Updating X and Y coordinates 
     //We will add 1 to the cos function to prevent negative values which will lead flakes to move upwards 
     //Every particle has its own density which can be used to make the downward movement different for each flake 
     //Lets make it more random by adding in the radius 
     p.y += Math.cos(angle + p.d) + 1 + p.r/2; 
     p.x += Math.sin(angle) * 2; 

     //Sending flakes back from the top when it exits 
     //Lets make it a bit more organic and let flakes enter from the left and right also. 
     if (p.x > W + 5 || p.x < -5 || p.y > H) { 
      if (i % 3 > 0) //66.67% of the flakes 
      { 
       particles[i] = { 
        x: Math.random() * W, 
        y: -10, 
        r: p.r, 
        d: p.d, 
        color: p.color, 
        tilt: p.tilt 
       }; 
      } else { 
       //If the flake is exitting from the right 
       if (Math.sin(angle) > 0) { 
        //Enter from the left 
        particles[i] = { 
         x: -5, 
         y: Math.random() * H, 
         r: p.r, 
         d: p.d, 
         color: p.color, 
         tilt: p.tilt 
        }; 
       } else { 
        //Enter from the right 
        particles[i] = { 
         x: W + 5, 
         y: Math.random() * H, 
         r: p.r, 
         d: p.d, 
         color: p.color, 
         tilt: p.tilt 
        }; 
       } 
      } 
     } 
    } 
} 

//animation loop 
setInterval(draw, 20); 

}

Trả lời

5

Hãy thử nó như thế này: http://jsfiddle.net/vxP5q/

JS:

window.onload = function(){ 
//canvas init 
var canvas = document.getElementById("canvas"); 
var ctx = canvas.getContext("2d"); 

//canvas dimensions 
var W = window.innerWidth; 
var H = window.innerHeight; 
canvas.width = W; 
canvas.height = H; 

//snowflake particles 
var mp = 25; //max particles 
var particles = []; 
for(var i = 0; i < mp; i++) 
{ 
    particles.push({ 
     x: Math.random()*W, //x-coordinate 
     y: Math.random()*H, //y-coordinate 
     r: Math.random()*4+1, //radius 
     d: Math.random()*mp, //density 
     color: "rgba(" + Math.floor((Math.random() * 255)) +", " + Math.floor((Math.random() * 255)) +", " + Math.floor((Math.random() * 255)) + ", 0.8)" 
    }) 
} 

//Lets draw the flakes 
function draw() 
{ 
    ctx.clearRect(0, 0, W, H); 



    for(var i = 0; i < mp; i++) 
    { 
     var p = particles[i]; 
     ctx.beginPath(); 
     ctx.fillStyle = p.color; 
     ctx.moveTo(p.x, p.y); 
     ctx.arc(p.x, p.y, p.r, 0, Math.PI*2, true); 
     ctx.fill(); 
    } 

    update(); 
} 

//Function to move the snowflakes 
//angle will be an ongoing incremental flag. Sin and Cos functions will be applied to it to create vertical and horizontal movements of the flakes 
var angle = 0; 
function update() 
{ 
    angle += 0.01; 
    for(var i = 0; i < mp; i++) 
    { 
     var p = particles[i]; 
     //Updating X and Y coordinates 
     //We will add 1 to the cos function to prevent negative values which will lead flakes to move upwards 
     //Every particle has its own density which can be used to make the downward movement different for each flake 
     //Lets make it more random by adding in the radius 
     p.y += Math.cos(angle+p.d) + 1 + p.r/2; 
     p.x += Math.sin(angle) * 2; 

     //Sending flakes back from the top when it exits 
     //Lets make it a bit more organic and let flakes enter from the left and right also. 
     if(p.x > W+5 || p.x < -5 || p.y > H) 
     { 
      if(i%3 > 0) //66.67% of the flakes 
      { 
       particles[i] = {x: Math.random()*W, y: -10, r: p.r, d: p.d, color : p.color}; 
      } 
      else 
      { 
       //If the flake is exitting from the right 
       if(Math.sin(angle) > 0) 
       { 
        //Enter from the left 
        particles[i] = {x: -5, y: Math.random()*H, r: p.r, d: p.d, color: p.color}; 
       } 
       else 
       { 
        //Enter from the right 
        particles[i] = {x: W+5, y: Math.random()*H, r: p.r, d: p.d, color : p.color}; 
       } 
      } 
     } 
    } 
} 

//animation loop 
setInterval(draw, 33); 
} 

Tôi đã làm gì. Khi các pixel được tạo, tôi đã thêm một màu (ngẫu nhiên) duy nhất. Trường hợp cập nhật, tôi đảm bảo rằng các màu sắc được thay đổi và nơi nó được vẽ, tôi đã thay đổi nó để nó sẽ tạo ra một đường dẫn inuque cho mỗi mục confetti.

+0

HOÀN HẢO! Chính xác những gì tôi đang tìm kiếm. Cảm ơn rất nhiều! – Smeegs

3

Câu hỏi hay. Hãy xem xét các vòng lặp vẽ cho mẫu:

ctx.fillStyle = "rgba(255, 255, 255, 0.8)"; 
ctx.beginPath(); 
for(var i = 0; i < mp; i++) 
{ 
    var p = particles[i]; 
    ctx.moveTo(p.x, p.y); 
    ctx.arc(p.x, p.y, p.r, 0, Math.PI*2, true); 
} 
ctx.fill(); 

Nó được làm một con đường, thêm nhiều vòng cung, và sau đó điền nó một lần.

Để thay đổi nó, bạn sẽ cần phải điền nó một lần cho mỗi hạt thay thế. Bạn cũng sẽ muốn cung cấp cho mỗi hạt một màu duy nhất:

for (var i = 0; i < mp; i++) { 
    var p = particles[i]; 
    ctx.fillStyle = p.color; 
    ctx.beginPath();   
    ctx.moveTo(p.x, p.y); 
    ctx.arc(p.x, p.y, p.r, 0, Math.PI * 2, true); 
    ctx.fill(); 
} 

Lưu ý cách beginPath()fill() hiện nay bên vòng lặp. Điều này là quan trọng, bởi vì mỗi cung sẽ cần đường dẫn riêng và điền vào. Điều này là chậm hơn nhiều so với làm cho tất cả chúng với một con đường, nhưng là cần thiết nếu bạn muốn các hạt màu khác nhau.

Đó p.color:

particles.push({ 
    x: Math.random() * W, //x-coordinate 
    y: Math.random() * H, //y-coordinate 
    r: Math.random() * 4 + 1, //radius 
    d: Math.random() * mp, //density 

    // I'm new! 
    color: "rgba(" + Math.floor(Math.random()*255) + 
      ", " + Math.floor(Math.random()*255) + ", 255, 0.8)" 
}) 

Dưới đây là một ví dụ làm việc:

http://jsfiddle.net/j4NZK/1/

1

Đây là một phiên bản dựa trên các bài bởi Niels, tôi muốn có một đối tượng tái sử dụng mà tôi có thể gọi và thêm vào bất kỳ trang nào.

Cách sử dụng:

confetti.Init(#IdofContainer(div)#, 50,25,100) 

Code:

var confetti = { 
angle: 0, 
ctx: 0, 
H: 0, 
W: 0, 
mp: 0, 
particles: [], 
endFunction: '', 
Init: function (parent, maxParticles, iCount, speed, endFunct) { 
    confetti.stopped = false; 
    confetti.runner = null; 
    confetti.endFunction = endFunct; 
    var canvas = document.getElementById("confettiCanvasId"); 
    if (canvas) { 
     canvas.parentNode.removeChild(canvas); 
    } 
    canvas = document.createElement('canvas'); 
    canvas.className = 'confettiCanvas'; 
    canvas.id = 'confettiCanvasId' 
    $id(parent).appendChild(canvas); 
    var ctx = canvas.getContext("2d"); 
    var W = $id(parent).clientHeight; 
    var H = $id(parent).clientWidth; 
    canvas.width = W; 
    canvas.height = H; 
    confetti.particles = []; 
    for (var i = 0; i < maxParticles; i++) { 
     confetti.particles.push({ 
      x: Math.random() * W, 
      y: Math.random() * H, 
      r: Math.random() * 4 + 1, //radius 
      d: Math.random() * maxParticles, //density 
      color: "rgba(" + Math.floor((Math.random() * 255)) + ", " + Math.floor((Math.random() * 255)) + ", " + Math.floor((Math.random() * 255)) + ", 0.8)" 
     }); 
    } 
    myCounter = new confetti.Counter({ 
     seconds: iCount, 
     speed: speed, 
     onUpdateStatus: function (sec) { 
      $l(Math.random() * 255) 
      ctx.clearRect(0, 0, W, H); 
      for (var i = 0; i < maxParticles; i++) { 
       var p = confetti.particles[i]; 
       ctx.beginPath(); 
       ctx.fillStyle = p.color; 
       ctx.moveTo(p.x, p.y); 
       ctx.arc(p.x, p.y, p.r, 0, Math.PI * 2, true); 
       ctx.fill(); 
      } 

      confetti.angle += 0.01; 
      for (var i = 0; i < maxParticles; i++) { 
       var p = confetti.particles[i]; 
       p.y += Math.cos(confetti.angle + p.d) + 1 + p.r/2; 
       p.x += Math.sin(confetti.angle) * 2; 
       if (p.x > W + 5 || p.x < -5 || p.y > H) { 
        if (i % 3 > 0) //66.67% of the flakes 
        { 
         confetti.particles[i] = {x: Math.random() * W, y: -10, r: p.r, d: p.d, color: p.color}; 
        } 
        else { 
         if (Math.sin(confetti.angle) > 0) { 
          confetti.particles[i] = {x: -5, y: Math.random() * H, r: p.r, d: p.d, color: p.color}; 
         } 
         else { 
          confetti.particles[i] = {x: W + 5, y: Math.random() * H, r: p.r, d: p.d, color: p.color}; 
         } 
        } 
       } 
      } 
     }, 
     onCounterEnd: function() { 
      stopTimer(); 
      myCounter.stop(); 
      confetti.Stop(); 
     }}); 
    myCounter.start(); 
}, 
FadeOut:function fadeOut() { 
    var alpha = 1.0; // full opacity 
    for (var i = 0; i < confetti.particles.length; i++) { 
     var p = confetti.particles[i]; 
     interval = setInterval(function() { 
      //confetti.canvas.width = confetti.canvas.width; // Clears the canvas 
      p.color = "rgba(255, 0, 0, " + alpha + ")"; 
      alpha = alpha - 0.05; // decrease opacity (fade out) 
      if (alpha < 0) { 
       //confetti.canvas.width = confetti.canvas.width; 
       clearInterval(interval); 
      } 
     }, 50); 


    } 
     }, 
Counter: function Countdown(options) { 
    var timer, 
     instance = this, 
     seconds = options.seconds || 10, 
     updateStatus = options.onUpdateStatus || function() { 
     }, 
     counterEnd = options.onCounterEnd || function() { 
     }; 

    function decrementCounter() { 
     updateStatus(seconds); 
     if (seconds === 0) { 
      counterEnd(); 
      instance.stop(); 
     } 
     seconds--; 
    } 

    this.start = function() { 
     clearInterval(timer); 
     timer = 0; 
     seconds = options.seconds; 
     timer = setInterval(decrementCounter, options.speed); 
    }; 

    this.stop = function() { 
     clearInterval(timer); 
    }; 
}, 
Stop: function stop() { 
    $('#confettiCanvasId').fadeOut(); 
    setTimeout(function(){ 
     var canvas = document.getElementById("confettiCanvasId"); 
     if (canvas) { 
      canvas.parentNode.removeChild(canvas); 
     } 
     if (confetti.endFunction) { 
      confetti.endFunction(); 
     } 
    },1000); 

} 
}; 

CSS:

.confettiCanvas{ 
overflow: hidden; 
position: absolute; 
height: 100%; 
width: 100%; 
top: 0; 
left: 0; 
}