canvas小球连线碰撞效果 html+css+js

举报
北极光之夜。 发表于 2021/04/20 02:01:53 2021/04/20
【摘要】 先看效果(完整代码在底部): canvas小球连线碰撞完整源代码 html+css+js 这是我的B站地址~热烈欢迎 实现(看注释,可一步一步跟着实现): 0:定义标签: <h1>北极光之夜。</h1> <canvas id="canvas"></canvas> 12 1. 定义变量: /* 获取画布 */ var canvas =...

先看效果(完整代码在底部):

canvas小球连线碰撞完整源代码 html+css+js


这是我的B站地址~热烈欢迎

实现(看注释,可一步一步跟着实现):

0:定义标签:

 <h1>北极光之夜。</h1>
 <canvas id="canvas"></canvas>

  
  
 
 
  • 1
  • 2

1. 定义变量:

  /* 获取画布 */ var canvas = document.querySelector("#canvas"); var ctx = canvas.getContext("2d"); /* 数组,存小球 */ var arr = []; /* 一共60个球 */ var num = 60; /* xZou与yZou为鼠标坐标,temp为变量,判断鼠标是否在canvas内 */ var xZou,yZou,temp;

  
  
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

2.绑定窗口大小发生改变事件,让canvas随时铺满浏览器可视区,直接copy用:

   /* 绑定窗口大小发生改变事件,让canvas随时铺满浏览器可视区 */ window.onresize=resizeCanvas; function resizeCanvas(){ canvas.width=window.innerWidth; canvas.height=window.innerHeight; arr.length = 0; chushi(); } resizeCanvas(); 

  
  
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

3. 初始化数组:

  /* 初始化数组 */ function chushi(){ for(let i=0;i<num;i++){ arr.push({ /*指定值之间的随机数: Math.random() * (max - min) + min; */ /* 球的x轴随机坐标 */ x:10+Math.random()*(canvas.width-20), /* 球的y轴随机坐标 */ y:10+Math.random()*(canvas.height-20), /* 球的半径,可以设置随机大小,我就不设置了 */ r:10, /* 球移动距离大小 dx,dy */ dx:10*Math.random()-5, dy:10*Math.random()-5, /* 颜色,这是蓝色 */ color: "rgba(7, 156, 255,1)" }) } }

  
  
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

4. 绘制小球与连线:

 /* 绘制小球 */ function draw(){ for(let i=0;i<num;i++){ var yuan = arr[i]; /* 绘制圆形 */ ctx.beginPath(); ctx.arc(yuan.x,yuan.y,yuan.r,0,3.14*2,false); ctx.fillStyle = yuan.color; ctx.fill(); for(let j=i;j<num;j++){ /* 绘制球与球之间连线,只有x轴与y轴都只相差150内的才连线 */ if(Math.abs(yuan.x-arr[j].x)<150&&Math.abs(yuan.y-arr[j].y)<150){ /* 绘制连线 */ ctx.beginPath(); /* ctx.globalAlpha = 0.1; */ ctx.moveTo(yuan.x,yuan.y); /* 绘制鼠标坐标与球之间连线,只有x轴与y轴都只相差150内的才连线 */ if(Math.abs(yuan.x-xZou)<150&&Math.abs(yuan.y-yZou)<150&&temp){ ctx.lineTo(xZou,yZou); } ctx.lineTo(arr[j].x,arr[j].y); ctx.closePath(); /* 设置线条颜色,越远透明度越低,用勾股定理判断距离 */ let tm = Math.sqrt(Math.abs(yuan.x-arr[j].x)*Math.abs(yuan.x-arr[j].x) + Math.abs(yuan.y-arr[j].y)*Math.abs(yuan.y-arr[j].y)) / 212; ctx.strokeStyle = `rgba(7, 156, 255,${1-tm})`; ctx.stroke(); /*  ctx.fill(); */ } } } }

  
  
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

Math.abs()返回绝对值。
Math.sqrt()返回平方根。

5. 更新小球运动:

 /* 小球运动 */ function updates(){ for(let i=0;i<num;i++){ /* 更新球的坐标,鼠标坐标与球之间只有x轴与y轴都只相差150内的球才会跟着鼠标走 */ if(Math.abs(arr[i].x-xZou)<150&&Math.abs(arr[i].y-yZou)<150&&temp){ /* 离鼠标越近走越慢 */ arr[i].x += -(arr[i].x-xZou)/(10*Math.random()+20); arr[i].y += -(arr[i].y-yZou)/(10*Math.random()+20); } /* 否则球走的距离与方向为原数组里存放的 */ else{ arr[i].x += arr[i].dx; arr[i].y += arr[i].dy; } /* 当球边碰到窗口边时把原来走的距离设置为负数,这样小球会碰撞效果 */ if(arr[i].x<=arr[i].r || arr[i].x >= (canvas.width - arr[i].r) ){ arr[i].dx = -arr[i].dx; } if(arr[i].y<=arr[i].r || arr[i].y >= (canvas.height - arr[i].r) ){ arr[i].dy = -arr[i].dy; } } }

  
  
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

6. 设置定时器:

 /* 定时器,开始清除,渲染,更新 */ chushi(); setInterval(function(){ ctx.clearRect(0,0,canvas.width,canvas.height); draw(); updates(); },50)

  
  
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

7. 鼠标进入离开canvas事件:

 /* 鼠标进入canvas事件, */ var xZou,yZou,temp; canvas.addEventListener('mousemove',function(e){ /* 赋值 */ xZou = e.clientX; yZou = e.clientY; temp=1; }) /* 鼠标离开canvas,tmep为0,上面的跟随鼠标运动无效了 */ canvas.addEventListener('mouseout',function(e){ temp=0; })

  
  
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

完整代码:

<!DOCTYPE html>
<html lang="zh-CN">
<head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> *{ margin: 0; padding: 0; } body{ height: 100vh; display: flex; justify-content: center; align-items: center; background-color: rgb(11, 10, 46); } h1{ font-family: 'fangsong'; position: absolute; font-size: 5em; color: rgb(17, 167, 226); transform: translateX(40px); text-shadow: 0 0 10px rgb(38, 17, 226), 0 0 20px rgb(38, 17, 226), 0 0 30px rgb(38, 17, 226); user-select: none; } </style>
</head>
<body> <h1>北极光之夜。</h1> <canvas id="canvas"></canvas> <script> /* 获取画布 */ var canvas = document.querySelector("#canvas"); var ctx = canvas.getContext("2d"); /* 数组,存小球 */ var arr = []; /* 一共60个球 */ var num = 60; /* xZou与yZou为鼠标坐标,temp为变量,判断鼠标是否在canvas内 */ var xZou,yZou,temp; /* 绑定窗口大小发生改变事件,让canvas随时铺满浏览器可视区 */ window.onresize=resizeCanvas; function resizeCanvas(){ canvas.width=window.innerWidth; canvas.height=window.innerHeight; arr.length = 0; chushi(); } resizeCanvas(); /* 初始化数组 */ function chushi(){ for(let i=0;i<num;i++){ arr.push({ /*指定值之间的随机数: Math.random() * (max - min) + min; */ /* 球的x轴随机坐标 */ x:10+Math.random()*(canvas.width-20), /* 球的y轴随机坐标 */ y:10+Math.random()*(canvas.height-20), /* 球的半径,可以设置随机大小,我就不设置了 */ r:10, /* 球移动距离大小 dx,dy */ dx:10*Math.random()-5, dy:10*Math.random()-5, /* 颜色,这是蓝色 */ color: "rgba(7, 156, 255,1)" }) } } /* 绘制小球 */ function draw(){ for(let i=0;i<num;i++){ var yuan = arr[i]; /* 绘制圆形 */ ctx.beginPath(); ctx.arc(yuan.x,yuan.y,yuan.r,0,3.14*2,false); ctx.fillStyle = yuan.color; ctx.fill(); for(let j=i;j<num;j++){ /* 绘制球与球之间连线,只有x轴与y轴都只相差150内的才连线 */ if(Math.abs(yuan.x-arr[j].x)<150&&Math.abs(yuan.y-arr[j].y)<150){ /* 绘制连线 */ ctx.beginPath(); /* ctx.globalAlpha = 0.1; */ ctx.moveTo(yuan.x,yuan.y); /* 绘制鼠标坐标与球之间连线,只有x轴与y轴都只相差150内的才连线 */ if(Math.abs(yuan.x-xZou)<150&&Math.abs(yuan.y-yZou)<150&&temp){ ctx.lineTo(xZou,yZou); } ctx.lineTo(arr[j].x,arr[j].y); ctx.closePath(); /* 设置线条颜色,越远透明度越低,用勾股定理判断距离 */ let tm = Math.sqrt(Math.abs(yuan.x-arr[j].x)*Math.abs(yuan.x-arr[j].x) + Math.abs(yuan.y-arr[j].y)*Math.abs(yuan.y-arr[j].y)) / 212; ctx.strokeStyle = `rgba(7, 156, 255,${1-tm})`; ctx.stroke(); /*  ctx.fill(); */ } } } } /* 小球运动 */ function updates(){ for(let i=0;i<num;i++){ /* 更新球的坐标,鼠标坐标与球之间只有x轴与y轴都只相差150内的球才会跟着鼠标走 */ if(Math.abs(arr[i].x-xZou)<150&&Math.abs(arr[i].y-yZou)<150&&temp){ /* 离鼠标越近走越慢 */ arr[i].x += -(arr[i].x-xZou)/(10*Math.random()+20); arr[i].y += -(arr[i].y-yZou)/(10*Math.random()+20); } /* 否则球走的距离与方向为原数组里存放的 */ else{ arr[i].x += arr[i].dx; arr[i].y += arr[i].dy; } /* 当球边碰到窗口边时把原来走的距离设置为负数,这样小球会碰撞效果 */ if(arr[i].x<=arr[i].r || arr[i].x >= (canvas.width - arr[i].r) ){ arr[i].dx = -arr[i].dx; } if(arr[i].y<=arr[i].r || arr[i].y >= (canvas.height - arr[i].r) ){ arr[i].dy = -arr[i].dy; } } } /* 定时器,开始清除,渲染,更新 */ chushi(); setInterval(function(){ ctx.clearRect(0,0,canvas.width,canvas.height); draw(); updates(); },50) /* 鼠标进入canvas事件, */ var xZou,yZou,temp; canvas.addEventListener('mousemove',function(e){ /* 赋值 */ xZou = e.clientX; yZou = e.clientY; temp=1; }) /* 鼠标离开canvas,tmep为0,上面的跟随鼠标运动无效了 */ canvas.addEventListener('mouseout',function(e){ temp=0; }) </script>

</body>
</html>

  
  
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158

总结:

夏天到了~~
在这里插入图片描述

文章来源: blog.csdn.net,作者:北极光之夜。,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/luo1831251387/article/details/115187689

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。