canvas绘制经典星空连线效果

阅读: 评论:0

canvas绘制经典星空连线效果

canvas绘制经典星空连线效果

来自:

下面开始coding:
先写个canvas标签

<canvas height="620" width="1360" id="canvas"></canvas>

加上一些默认的样式:

*{margin:0;padding:0; } body{ overflow: hidden; }

这里的overflow:hidden是为了防止出现滚动条
下面开始写JS:
首先我们要得到那个 canvas 并得到绘制上下文:

var canvasEl = ElementById('canvas');
var ctx = Context('2d'); var mousePos = [0, 0]; 

紧接着我们声明两个变量,分别用于存储“星星”和边:

var nodes = [];
var edges = [];

然后我们定义一些其他的变量:

var easingFactor = 5.0;  //缓动因子
var backgroundColor = '#000'; //背景颜色 var nodeColor = '#fff'; //点颜色 var edgeColor = '#fff'; //边颜色 var pageWidth = window.innerWidth, //窗口宽度 pageHeight = window.innerHeight; //窗口高度

设置画布的大小铺满整个屏幕:

准备工作完成,我们要开始构建点了:

function constructNodes() { for (var i = 0; i < 100; i++) { var node = { drivenByMouse: i == 0, x: Math.random() * canvasEl.width, y: Math.random() * canvasEl.height, vx: Math.random() * 1 - 0.5, vy: Math.random() * 1 - 0.5, radius: Math.random() > 0.9 ? 3 + Math.random() * 3 : 1 + Math.random() * 3 }; nodes.push(node); } nodes.forEach(function (e) { nodes.forEach(function (e2) { if (e == e2) { return; } var edge = { from: e, to: e2 } addEdge(edge); }); }); }

先创建100个点,每个点设置6个属性,drivenByMouse属性只有第一个点为true,其他的点为false,第一个点作为鼠标跟随点,不显示出来,可以与其他点连线。x,y作为点的初始位置,取得是画布内的随机点,vx,vy表示点的初始速度,范围为-0.5到0.5之间的随机数,radius表示点的半径,大部分的点为小的,少数的点为大的。

点都构建完毕了,就要构建点与点之间的连线了,我们用到双重遍历,把两个点捆绑成一组,放到 edges 数组中。注意这里我用了另外一个函数来完成这件事,而没有直接用 edges.push() ,为什么?

假设我们之前连接了 A、B两点,也就是外侧循环是A,内侧循环是B,那么在下一次循环中,外侧为B,内侧为A,是不是也会创建一条边呢?而实际上,这两个边除了方向不一样以外是完全一样的,这完全没有必要而且占用资源。因此我们在 addEdge 函数中进行一个判断:

function addEdge(edge) { var ignore = false; edges.forEach(function (e) { if (e.from == edge.from & e.to == ) { ignore = true; } if (e.to == edge.from & e.from == ) { ignore = true; } }); if (!ignore) { edges.push(edge); } }

至此,我们的准备工作就完毕了,下面我们要让点动起来:

function step() {nodes.forEach(function (e) {if (e.drivenByMouse) { return; } e.x += e.vx; e.y += e.vy; function clamp(min, max, value) { if (value > max) { return max; } else if (value < min) { return min; } else { return value; } } if (e.x <= 0 || e.x >= canvasEl.width) { e.vx *= -1; e.x = clamp(0, canvasEl.width, e.x) } if (e.y <= 0 || e.y >= canvasEl.height) { e.vy *= -1; e.y = clamp(0, canvasEl.height, e.y) } }); adjustNodeDrivenByMouse(); render(); questAnimationFrame(step); } function adjustNodeDrivenByMouse() { nodes[0].x += (mousePos[0] - nodes[0].x) / easingFactor; nodes[0].y += (mousePos[1] - nodes[0].y) / easingFactor; } 

这段代码就是遍历粒子,并且更新其状态。根据一个简单的物理公式 s = s + v,每次执行都会 更新到点的下一步的状态。
adjustNodeDrivenByMouse函将第一个点作为鼠标的跟随点,easingFactor为缓动因子可以让点的运动比鼠标运动的稍慢一点。
然后我们要让整个粒子系统连续地运转起来就需要一个timer了,但是十分不提倡大家使用 setInterval,而是尽可能使用 requestAnimationFrame,它能保证你的帧率锁定在当前浏览器的频率下,一般为60HZ。

剩下的就是绘制了

function render() { ctx.fillStyle = backgroundColor; ctx.fillRect(0, 0, canvasEl.width, canvasEl.height); edges.forEach(function (e) { var l = lengthOfEdge(e); var threshold = canvasEl.width / 8; if (l > threshold) { return; } ctx.strokeStyle = edgeColor; ctx.lineWidth = (1.0 - l / threshold) * 2.5; ctx.globalAlpha = 1.0 - l / threshold; ctx.beginPath(); veTo(e.from.x, e.from.y); ctx., e.to.y); ctx.stroke(); }); ctx.globalAlpha = 1.0; nodes.forEach(function (e) { if (e.drivenByMouse) { return; } ctx.fillStyle = nodeColor; ctx.beginPath(); ctx.arc(e.x, e.y, e.radius, 0, 2 * Math.PI); ctx.fill(); }); } function lengthOfEdge(edge) { return Math.sqrt(Math.pow((edge.from.x - ), 2) + Math.pow((edge.from.y - ), 2)); } 

绘制的时候我们要判断线的长度如果大于某一个值,则不绘制该线了,如果在范围之内粗细,与颜色的透明度都与线的长度相关,点除了第一个鼠标跟随点,其他的画入即可。
最后加入鼠标移动事件,启动定时器:

大功告成!!

转载于:.html

本文发布于:2024-02-03 02:38:09,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170689908948094.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:星空   效果   经典   canvas
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23