七夕来临,最近正好在学习Canvas,所以做了一个七夕爱心,下面是演示图(转换的不清楚,不要太在意)。

下面放一张高清图

特点:

1、会获取当前系统时间并在页面上显示。

2、跳动的小球是从白色爱心上一行一行跳动的,然后随机向右或向左运行,因为爱心是在左侧屏幕,所以看起来大部分小球都是向右跳动的。

3、优化了弹跳函数性能,避免小球过多吃内存问题,运行时可打开控制台查看小球数,程序会自动清理超过屏幕的小球。

4、相关代码已上传至我的资源,可供下载交流研究。

缺点:

1、因为主要是为了学习,所以没有增加页面自适应功能,可能会出现不同电脑画面位置不一样的情况,可自行增加页面自适应功能。

实现原理:

1、心形的实现:

首先用visio制作心形模型,我做的是15*14的宫格,如下图:

接下来将模型中的心形转换成JS二维数组,在程序中,有圆的宫格用1代替,没有圆的宫格用0代替,因此数组脚本代码如下:

我给数组JS脚本命名为:love15_14.js

lovegit=[
    //心形图形数组化
    //有心形代表1,没有心形代表0
    [0,0,1,1,1,0,0,0,0,0,1,1,1,0,0],
    [0,1,1,1,1,1,0,0,0,1,1,1,1,1,0],
    [1,1,1,1,1,1,1,0,1,1,1,1,1,1,1],
    [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
    [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
    [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
    [0,1,1,1,1,1,1,1,1,1,1,1,1,1,0],
    [0,1,1,1,1,1,1,1,1,1,1,1,1,1,0],
    [0,0,1,1,1,1,1,1,1,1,1,1,1,0,0],
    [0,0,0,1,1,1,1,1,1,1,1,1,0,0,0],
    [0,0,0,0,1,1,1,1,1,1,1,0,0,0,0],
    [0,0,0,0,0,1,1,1,1,1,0,0,0,0,0],
    [0,0,0,0,0,0,1,1,1,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,1,0,0,0,0,0,0,0]
];

2、时间的实现:

这个很简单,new一个JS的Date()方法,然后解析即可得到时分秒。

3、文字的实现:

这个更简单,直接给一个变量附上字符串,后面在程序中会调用。

下面是实现脚本的代码,我在这里命名为:love.js

var WINDOW_WIDTH = 1690;
var WINDOW_HEIGHT = 780;
var RADIUS = 12;
var MARGIN_TOP=60;
var MARGIN_LEFT=30;
var count=0;
var balls=[];
const colors =['#33B5E5','#0099CC','#AA66CC','#9933CC','#99CC00',
    '#669900','#FFBB33','#FF8800','#FF4444','#CC0000'];

const endTime = new Date(2018,7,17,23,59,55);//定义截止时间
var curShowTimeSeconds = 0;

window.οnlοad=function () {
  var canvas = document.getElementById('canvas');
  var context = canvas.getContext('2d');

  canvas.width = WINDOW_WIDTH;
  canvas.height = WINDOW_HEIGHT;
  curShowTimeSeconds = getCurrentShowTimeSeconds();

    setInterval(function () {
        render(context);
        update();
    },50);
};
function getCurrentShowTimeSeconds() {
    var curTime = new Date();
    var ret = endTime.getTime()-curTime.getTime();
    ret = Math.round(ret/1000);
    return ret>0?ret:0;
}
function update() {
    var nextShowTimeSeconds = getCurrentShowTimeSeconds();

    var nextSeconds = nextShowTimeSeconds%60;
    var curSeconds = curShowTimeSeconds%60;
    if(nextSeconds != curSeconds){
        addLoves(MARGIN_LEFT,MARGIN_TOP);
        curShowTimeSeconds = nextShowTimeSeconds;
    }
    updateLoves();
    console.log(balls.length);
}
function render(cxt) {
    cxt.clearRect(0,0,WINDOW_WIDTH,WINDOW_HEIGHT);
    painting(cxt);
    renderLoveGit(MARGIN_LEFT,MARGIN_TOP,cxt);
    for(var i=0;i<balls.length;i++){
        cxt.fillStyle=balls[i].color;

        cxt.beginPath();
        cxt.arc(balls[i].x,balls[i].y,RADIUS,0,2*Math.PI,false);
        cxt.closePath();

        cxt.fill();
    }
}
//画七夕函数
function painting(cxt) {
    var time_now = new Date();
    var s_time = [time_now.getHours(),time_now.getMinutes(),time_now.getSeconds()];
    cxt.beginPath();
    cxt.font='100px Arial';
    // var grd = cxt.createLinearGradient(800,0,1200,0);
    // grd.addColorStop(0,'#33B5E5');
    // grd.addColorStop(0.1,'#0099CC');
    // grd.addColorStop(0.2,'#AA66CC');
    // grd.addColorStop(0.3,'#9933CC');
    // grd.addColorStop(0.4,'#99CC00');
    // grd.addColorStop(0.5,'#669900');
    // grd.addColorStop(0.6,'#FFBB33');
    // grd.addColorStop(0.7,'#FF8800');
    // grd.addColorStop(0.8,'#FF4444');
    // grd.addColorStop(0.9,'#9933CC');
    // grd.addColorStop(1,'#AA66CC');
    cxt.strokeStyle='white';
    cxt.strokeText(parseInt(s_time[0]/10)+''+parseInt(s_time[0]%10)+":"+parseInt(s_time[1]/10)+''+parseInt(s_time[1]%10)+':'+parseInt(s_time[2]/10)+''+parseInt(s_time[2]%10),800,220);
    cxt.closePath();
    cxt.beginPath();
    cxt.font='80px Arial';
    cxt.strokeText('祝天下有情人终成眷属,七夕快乐',350,400);
    cxt.closePath();
}
//更新小球的函数
function updateLoves() {
    for (var i = 0; i < balls.length; i++) {
        balls[i].x += balls[i].vx;
        balls[i].y += balls[i].vy;
        balls[i].vy += balls[i].g;
        if (balls[i].y >= WINDOW_HEIGHT - RADIUS) {
            balls[i].y = WINDOW_HEIGHT - RADIUS;
            balls[i].vy = -balls[i].vy * 0.75;
        }
    }
    var cnt = 0;
    for(var i=0;i<balls.length;i++){
        if(balls[i].x+RADIUS>0 && balls[i].x-RADIUS<WINDOW_WIDTH)
            balls[cnt++]=balls[i];
    }
    while(balls.length>cnt){
        balls.pop();
    }
}
//加入一个小爱心
function addLoves(x,y) {
    // for(var i=0;i<14;i++){
        for(var j=0;j<15;j++){
            if(lovegit[count][j]==1){
                var aBall ={
                    x:x+j*2*(RADIUS+1)+(RADIUS+1),
                    y:y+count*2*(RADIUS+1)+(RADIUS+1),
                    g:1.5+Math.random(),//1.5~2.5之间
                    vx:Math.pow(-1,Math.ceil(Math.random()*1000))*15, //取负4或正4
                    vy:-5,
                    color:colors[Math.floor(Math.random()*colors.length)]
                };
                balls.push(aBall);
            }
        }
        count++;
        if(count==14){
            count=0;
        }
    // }
}
function renderLoveGit(x,y,cxt) {
    cxt.fillStyle='white';
    for(var i=0;i<14;i++){
        for(var j=0;j<15;j++){
            if(lovegit[i][j]==1){
                cxt.beginPath();
                // colorSelect = colors[Math.floor(Math.random()*10)];
                // cxt.fillStyle=colorSelect;
                cxt.arc(x+j*2*(RADIUS+1)+(RADIUS+1),y+i*2*(RADIUS+1)+(RADIUS+1),RADIUS,0,2*Math.PI,false);
                cxt.closePath();
                cxt.fill();
            }
        }
    }
}

最后是背景图,我也上传上来给大家:命名为img_three.jpg

最后是HTML文件:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>七夕快乐</title>
    <style type="text/css" rel="stylesheet">
        canvas{
            background-image: url("./img/img_three.jpg");
        }
    </style>
</head>
<body>
<canvas id="canvas" style="border: solid 1px black;">
    您的浏览器不支持canvas,请更换浏览器后重新操作
</canvas>
<script src="js/love15_14.js"></script>  <!--引入爱心数组-->
<script src="js/love.js"></script>   <!--引入操作脚本-->
</body>
</html>

将上面的两个js文件和图片在HTML文件中正确引入即可实现七夕爱心跳动的效果。

在此祝各位程序员七夕快乐,没有女朋友写代码也是可以的哈。