2017-06-12 74 views
0
var stars = function() { 

this.x = Math.floor(Math.random()* 1000) ; 

this.y = Math.floor(Math.random()* 900) ; 

this.radius = 2 ; 

this.starColour = "gold"; 





    } 

    var starNum = 20; 
    var starry = new Array(starNum); 

for(var s = 0 ; s < 100 ; s++){ 

starry[s] = new stars() 
} 


var starDraw = function() { 


var starCanvas = document.getElementById("stars"); 

var starCtx = starCanvas.getContext("2d"); 
starCtx.clearRect(0, 0, 1000, 900); 

for(i = 0; i < 100 ; i++){ 
    var star = starry[i]; 



    starCtx.fillStyle= "white"; 

starCtx.shadowBlur = 5; 

starCtx.shadowColor = "white"; 
    starCtx.beginPath(); 





    // draw it 
    starCtx.arc(star.x, star.y, star.radius, Math.PI * 2, false); 
    starCtx.stroke(); 
    starCtx.fill(); 


    } 


} 






    function starLoop(){ 

starDraw(); 
requestAnimationFrame(starLoop); 
} 

requestAnimationFrame(starLoop); 

所以我想創建一個閃爍的效果,只使用JavaScript的星星,我無法弄清楚如何做到這一點。 我搜查了四周,到目前爲止沒有找到真正的答案,所以如果我能在這裏得到答案,我將不勝感激。我對編碼很陌生,所以請對我輕鬆一下。使用javascript創建閃爍效果

+0

建議使用CSS來製作這種效果。例如:https://jsfiddle.net/psullivan6/ma6e78m0/ –

回答

1

隨機星場。有點誇張,但容易調低(或升高),如果需要的話。

重要的部分是避免直接的隨機值,因爲大自然中的大多數事物都不是隨機的,而是傾向於接近固定點。這稱爲高斯分佈。有幾種方法可以生成這種隨機值。

// gRandom is far more likely to be near 0.5 than 1 or zero 
var gRandom = (Math.random()+Math.random()+Math.random()+Math.random())/4; 

// or 
// gRandom is more likely to be near zero than near 1 
var gRandom = Math.random() * Math.random(); 

我使用這些方法來設置星星的大小(比大的小得多的小星星)並創建顏色和移動。

爲了嘗試獲得更真實的效果,我還將星星移動的距離小於一個像素。這具有改變亮度但不像運動的效果。

代碼有很多的評論

const ctx = canvas.getContext("2d"); 
 
// function calls a callback count times. Saves typing out for loops all the time 
 
const doFor = (count, callback) => { 
 
    var i = 0; 
 
    while (i < count) { 
 
    callback(i++) 
 
    } 
 
}; 
 
// creates a random integer between min and max. If min only given the between 0 and the value 
 
const randI = (min, max = min + (min = 0)) => (Math.random() * (max - min) + min) | 0; 
 
// same as above but as floats. 
 
const rand = (min, max = min + (min = 0)) => Math.random() * (max - min) + min; 
 
// creates a 2d point at x,y. If only x is a point than set to that point 
 
const point = (x = 0, y) => { 
 
    if (x.x && y === undefined) {return { x: x.x,y: x.y} } 
 
    return {x,y: y === undefined ? 0 : y } 
 
}; 
 
function ease (time, amount = 2) { return Math.pow(time % 1,amount) }; 
 
const clamp = (v, min = 1,max = min + (min = 0)) => v < min ? min : v > max ? max : v; 
 

 

 

 

 
// stuff for stars 
 
const skyColour = [10,30,50]; 
 
const density = 1000; // number of star per every density pixels 
 
const colourChangeRate = 16; // Time in frames to change a colour 
 
const stars = []; 
 
const star = { // define a star 
 
    draw() { 
 
    this.count += 1; // integer counter used to triger color change every 16 frames 
 
    if (this.count % colourChangeRate === 0) { // change colour ? 
 
     // colour is a gaussian distrabution (NOT random) centered at #888 
 
     var c = (Math.random() + Math.random() + Math.random() + Math.random()) * 4; 
 
     var str = "#"; 
 
     str += Math.floor(c * this.red).toString(16); // change color 
 
     str += Math.floor(c * this.green).toString(16); // change color 
 
     str += Math.floor(c * this.blue).toString(16); // change color 
 
     
 

 
     this.col = str; 
 
    } 
 
    ctx.fillStyle = this.col; 
 
    // move star around a pixel. Again its not random 
 
    // but a gaussian distrabution. The movement is sub pixel and will only 
 
    // make the stars brightness vary not look like its moving 
 
    var ox = (Math.random() + Math.random() + Math.random() + Math.random())/4; 
 
    var oy = (Math.random() + Math.random() + Math.random() + Math.random())/4; 
 
    ctx.fillRect(this.pos.x + ox, this.pos.y + oy, this.size, this.size); 
 
    } 
 
} 
 
// create a random star 
 
// the size is caculated to produce many more smaller stars than big 
 
function createStar(pos) { 
 
    stars.push(Object.assign({}, star, { 
 
    pos, 
 
    col: "#ccc", 
 
    count: randI(colourChangeRate), 
 
    size: rand(1) * rand(1) * 2 + 0.5, 
 
    red: 1-(rand(1) * rand(1) *rand(1)), // reduces colour channels 
 
    green: 1-(rand(1) * rand(1) *rand(1)), // but only by a very small amount 
 
    blue: 1-(rand(1) * rand(1) *rand(1)), // most of the time but occasional 
 
              // star will have a distinct colour 
 
    })); 
 
} 
 

 
var starCount; 
 
var skyGrad; 
 

 
// render the stars 
 
function mainLoop(time) { 
 
    // resize canva if page size changes 
 
    if (canvas.width !== innerWidth || canvas.height !== innerHeight) { 
 
    canvas.width = innerWidth; 
 
    canvas.height = innerHeight; 
 
    // create a new set of stars 
 
    stars.length = 0; 
 
    // density is number of pixels one the canvas that has one star 
 
    starCount = Math.floor((canvas.width * canvas.height)/density); 
 
    // create the random stars; 
 
    doFor(starCount,() => createStar(point(randI(canvas.width), randI(canvas.height)))); 
 
    skyGrad = ctx.createLinearGradient(0,0,0,canvas.height); 
 
    skyGrad.addColorStop(0,"black"); 
 
    doFor(100,(i)=>{ 
 
     var pos = clamp(i/100,0,1); 
 
     var col = ease(pos); 
 
     skyGrad.addColorStop(
 
      pos, 
 
      "rgb(" + 
 
       Math.floor(skyColour[0] * col) + "," + 
 
       Math.floor(skyColour[1] * col) + "," + 
 
       Math.floor(skyColour[2] * col) + ")" 
 
     ); 
 
    }); 
 
    // floating point error can cause problems if we dont set the top 
 
    // at 1 
 
    skyGrad.addColorStop(1,"rgb("+skyColour[0]+","+skyColour[1]+","+skyColour[2]+")"); 
 
    
 
    } 
 
    ctx.fillStyle = skyGrad; 
 
    ctx.fillRect(0, 0, canvas.width, canvas.height); 
 
    doFor(starCount, (i) => stars[i].draw()); 
 

 
    requestAnimationFrame(mainLoop); 
 
} 
 
requestAnimationFrame(mainLoop);
canvas { 
 
    position: absolute; 
 
    top: 0px; 
 
    left: 0px; 
 
}
<canvas id="canvas"></canvas>