谁说程序员没有520?学学高端程序员都是怎么表白的……

关注「实验楼」,每天分享一个项目教程   

谁说程序员只有代码和枸杞,今天让你们看看什么是程序员的浪漫……

正文共: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周时间带你打通“全宇宙最好的语言”


猜你喜欢

转载自blog.csdn.net/moy37rqw1jarn33bgzk/article/details/80429118