誰說程式設計師沒有520?學學高階程式設計師都是怎麼表白的……

實驗樓v發表於2018-05-21

關注「實驗樓」,每天分享一個專案教程   

誰說程式設計師只有程式碼和枸杞,今天讓你們看看什麼是程式設計師的浪漫……

正文共:3618 字 

預計閱讀時間:7 分鐘

如果我是程式碼,那麼你就是我的main函式,沒有你,什麼都做不了。

昨天是520,一年一度的秀恩愛大會,又是各種大招亂放的節奏,單身狗們表示受到一萬點暴擊。

說什麼願得一人心,一往而情深……但對於程式設計師們……

520也不過是週末加班的平凡一天。

不過,真的不是程式設計師們不浪漫,是忙啊!忙!

鋪天蓋地的程式碼,臨到頭要交的專案……晚上匆匆吃個飯繼續埋頭通宵敲程式碼不過是日常。

但這絕對不會成為程式設計師們的藉口,相反,儘管工作很忙他們也會想盡辦法為女朋友準備驚喜。

比如這樣:

只要我人生的程式不終止,你的名字一直我的心事。

自從那天與你邂逅,我願往後生命的每一天裡都有你的烙印,至死方休。

若你不愛,默默守護,不打擾是我的溫柔;若你傾心,愛你是我一生的榮光。

或者這樣:

再或者設計一個小遊戲

@ LA pike第一關兩人相遇第二關兩人第一次約會第三關第一次出門旅遊……最後一關打敗瘋狂粉絲,成功回家

甚至設計一款產品也不在話下


@泡泡

雖然520過了,但技術還是要學起來的

下面給大家分享一個超浪漫的程式設計師表白方式

煙花

@王興欣

1.屬性設計

煙花應有的三個狀態狀態:

  • 升空

  • 等待炸裂

  • 炸裂後

煙花:發射點(x,y),爆炸點(xEnd,yEnd),升空後等待炸裂時間(wait),炸裂後微粒個數(count),煙花半徑(radius)

煙花炸裂後微粒:自身位置(x,y),自身大小(size),自身速度(rate),最大煙花半徑(radius)。

config:為全域性變數,以及控制引數,包括畫布寬高,設定煙花屬性等。

2. 設定全域性變數

1.  class Particle{
2.    //預設值寫法
3.    constructor({x, y, size = 1, radius = 1.2} = {}){
4.        this.x = x;
5.        this.y = y;
6.        this.size = size;
7.
8.        this.rate = Math.random(); //每個微粒移動的速度都是隨機不同的
9.        this.angle = Math.PI * 2 * Math.random(); //每個微粒的偏移角度
10.
11.        //每次微粒移動速度分解為橫縱座標的移動。
12.        this.vx = radius * Math.cos(this.angle) * this.rate;
13.        this.vy = radius * Math.sin(this.angle) * this.rate;
14.    }
15.
16.    go(){
17.        this.x += this.vx;
18.        this.y += this.vy;
19.        this.vy += 0.02; //重力影響 y越大實際越偏下
20.
21.        //空氣阻力
22.        this.vx *= 0.98;
23.        this.vy *= 0.98;
24.    }
25.
26.    //畫出微粒的位置
27.    render(ctx){
28.        this.go();
29.        ctx.beginPath();
30.        ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2, false);
31.        ctx.fill();
32.    }
33. }

3. 構建煙花類

1.  class Firework{
2.    constructor({x, y = config.height, xEnd, yEnd, count = 300, wait} = {}){
3.        //煙花自身屬性
4.        this.x = x || config.width / 8 + Math.random() * config.width * 3 / 4;
5.        this.y = y;
6.        this.xEnd = xEnd || this.x;
7.        this.yEnd = yEnd || config.width / 8 + Math.random() * config.width * 3 / 8;
8.        this.size = 2;
9.        this.velocity = -3;
10.
11.        this.opacity = 0.8;
12.        this.color = `hsla(${360 * Math.random() | 0},80%,60%,1)`;
13.        this.wait = wait || 30 + Math.random() * 30;
14.        //微粒個數等
15.        this.count = count;
16.        this.particles = [];
17.        this.createParticles();
18.
19.        this.status = 1;
20.    }
21.    //建立微粒
22.    createParticles(){
23.        for(let i = 0;i < this.count; ++i){
24.            this.particles.push(new Particle({x:this.xEnd, y:this.yEnd}));
25.        }
26.    }
27.    //升空
28.    rise(){
29.        this.y += this.velocity * 1;
30.        this.velocity += 0.005; //升空時產生的阻力
31.        //煙花升空到目標位置開始漸隱
32.        if(this.y - this.yEnd <= 50){
33.            this.opacity = (this.y - this.yEnd) / 50;
34.        }
35.        //如果到了目標位置 就開始第二個狀態
36.        if(this.y <= this.yEnd){
37.            this.status = 2;
38.        }
39.    }
40.
41.    //渲染煙花  煙花所有動作完成之後返回false
42.    render(ctx){
43.        switch(this.status){
44.            case 1: //升空
45.            ctx.save();
46.            ctx.beginPath();
47.            ctx.globalCompositeOperation = 'lighter';
48.            ctx.globalAlpha = this.opacity;
49.            ctx.translate(this.x, this.y);
50.            ctx.scale(0.8, 2.3);
51.            ctx.translate(-this.x, -this.y);
52.            ctx.fillStyle = this.color;
53.            ctx.arc(this.x + Math.sin(Math.PI * 2 * Math.random()) / 1.2, this.y, this.size, 0, Math.PI * 2, false);
54.            ctx.fill();
55.            ctx.restore();
56.
57.            this.rise();
58.            return true;
59.            break;
60.            case 2: //煙花消失階段,等待炸裂
61.            if(--this.wait <= 0){
62.                this.opacity = 1;
63.                this.status = 3;
64.            }
65.            return true;
66.            break;
67.            case 3: //炸裂之後 渲染煙花微粒
68.            ctx.save();
69.            ctx.globalCompositeOperation = 'lighter';
70.            ctx.globalAlpha = this.opacity;
71.            ctx.fillStyle = this.color;
72.            for(let i = 0;i < this.particles.length;++i){
73.            this.particles[i].render(ctx);
74.            }
75.            ctx.restore();
76.            this.opacity -= 0.01;
77.            return this.opacity > 0;
78.            break;
79.            default:
80.            return false;
81.        }
82.    }
83. }

4.放煙花

1.  const canvas = {
2.    init: function(){
3.        //一些屬性的設定 可以不用管
4.        this.setProperty();
5.        this.renderBg();
6.
7.        //迴圈體 **主要
8.        this.loop();
9.    },
10.    setProperty: function(){
11.        this.fireworks = [];
12.        this.width = config.width;
13.        this.height = config.height;
14.        this.fireworkTime = (config.fireworkTime.min + (config.fireworkTime.max - config.fireworkTime.min) * Math.random()) | 0;
15.
16.        this.bgCtx = document.querySelector('#bg').getContext('2d');
17.        this.fireworkCtx = document.querySelector('#firework').getContext('2d');
18.    },
19.    renderBg(){
20.        this.bgCtx.fillStyle = 'hsla(210, 60%, 5%, 0.9)'
21.        this.bgCtx.fillRect(0, 0, this.width, this.height);
22.    },
23.
24.    loop(){
25.        requestAnimationFrame(this.loop.bind(this));
26.        this.fireworkCtx.clearRect(0, 0, this.width, this.height);
27.
28.        //隨機建立煙花
29.        if(--this.fireworkTime <= 0){
30.            this.fireworks.push(new Firework(config.fireworkOpt));
31.            //每次到點之後重新設定煙花產生時間 (|0轉化為整數)
32.            this.fireworkTime = (config.fireworkTime.min + (config.fireworkTime.max - config.fireworkTime.min) * Math.random()) | 0;
33.        }
34.
35.        for(let i = this.fireworks.length - 1; i >= 0; --i){
36.            //渲染煙花 (若返回值為false則移除煙花)
37.            !this.fireworks[i].render(this.fireworkCtx) && this.fireworks.splice(i,1);    
38.        }
39.
40.    }
41. }
42. canvas.init();

5.完善

此時煙花是這樣的,感覺少了點小尾巴。現在我們每一幀都是清除了畫布,如果要加上小尾巴其實也很簡單,每一幀都不要清除畫布,而是覆蓋一層新的有透明度的天空上去。

1.  //canvas.loop方法
2.
3. // this.fireworkCtx.clearRect(0, 0, this.width, this.height);
4. this.fireworkCtx.fillStyle = config.skyColor;
5. this.fireworkCtx.fillRect(0,0,this.width,this.height);  

這時就變成這樣了。但是,還是缺少了在爆炸瞬間天空變亮的場景。那麼在畫煙花的時候,先會獲取一下煙花的顏色以及透明度。

1.  // *****Firework constructor
2. // this.color = `hsla(${360 * Math.random() | 0},80%,60%,1)`;
3. this.hue = 360 * Math.random() | 0;
4. this.color = `hsla(${this.hue},80%,60%,1)`;
1.  // *****Firework 新增例項方法
2. getSkyColor(){
3.    const skyColor = {
4.        //只有炸裂階段才返回亮度
5.        lightness: this.status == 3 ? this.opacity : 0 ,
6.        hue: this.hue
7.    };
8.    return skyColor;
9. }
1.  // *****config 修改config的skyColor
2. // skyColor: 'hsla(210, 60%, 5%, 0.2)',
3. skyColor: 'hsla({hue}, 60%, {lightness}%, 0.2)',
1.  // canvas.loop方法
2. //this.fireworkCtx.fillStyle = config.skyColor;
3. //每次替換色調與亮度值。
4. this.fireworkCtx.fillStyle = config.skyColor.replace('{lightness}', 5 + this.skyColor.lightness * 15).replace('{hue}' , this.skyColor.hue);
5.
6. this.skyColor = { //新增
7.    lightness: 0,
8.    hue: 210
9. };
10. for(let i = this.fireworks.length - 1; i >= 0; --i){
11.    //新增 天空顏色為最亮的煙花的顏色
12.    this.skyColor = this.skyColor.lightness >= this.fireworks[i].getSkyColor().lightness ? this.skyColor : this.fireworks[i].getSkyColor();
13.    !this.fireworks[i].render(this.fireworkCtx) && this.fireworks.splice(i,1);    
14. }

大功告成。


作者:sugarain

文中部分內容整理自網路


學習更多


樓+「 Python實戰 」、「 Linux運維與Devops實戰 」優惠報名中——來自騰訊、Intel、IBM等網際網路大廠的一線大牛,帶你12周內打通Python、Linux的任督二脈!

點選下面的連結瞭解詳情:

一個暑假打通Python任督二脈!12周特訓再次開啟~

11周打通 Linux 任督二脈,實驗樓技術天團帶你飛!

他在一線網際網路大廠研發PHP數年,用6周時間帶你打通“全宇宙最好的語言”


相關文章