来自:https://segmentfault.com/a/1190000009675230

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

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

加上一些默认的样式:

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

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

var canvasEl = document.getElementById('canvas');
var ctx = canvasEl.getContext('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; //窗口高度

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

window.onresize = function () {
canvasEl.width = pageWidth;
canvasEl.height = pageHeight; if (nodes.length == 0) {
constructNodes();
} render();
}; window.onresize();

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

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 == edge.to) {
ignore = true;
} if (e.to == edge.from & e.from == edge.to) {
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();
window.requestAnimationFrame(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();
ctx.moveTo(e.from.x, e.from.y);
ctx.lineTo(e.to.x, 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 - edge.to.x), 2) + Math.pow((edge.from.y - edge.to.y), 2));
}

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

window.onmousemove = function (e) {
mousePos[0] = e.clientX;
mousePos[1] = e.clientY;
} window.requestAnimationFrame(step);

大功告成!!

canvas绘制经典星空连线效果的更多相关文章

  1. canvas绘制经典折线图(一)

    最终效果图如下: 实现步骤如下:注-引用了jQuery HTML代码 <!doctype html> <html lang="en"> <head&g ...

  2. canvas实现粒子星空连线

    <!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>离 ...

  3. Canvas学习:封装Canvas绘制基本图形API

    Canvas学习:封装Canvas绘制基本图形API Canvas Canvas学习   从前面的文章中我们了解到,通过Canvas中的CanvasRenderingContext2D对象中的属性和方 ...

  4. 使用 HTML5 Canvas 绘制出惊艳的水滴效果

    HTML5 在不久前正式成为推荐标准,标志着全新的 Web 时代已经来临.在众多 HTML5 特性中,Canvas 元素用于在网页上绘制图形,该元素标签强大之处在于可以直接在 HTML 上进行图形操作 ...

  5. Android自定义控件 -Canvas绘制折线图(实现动态报表效果)

    有时候我们在项目中会遇到使用折线图等图形,Android的开源项目中为我们提供了很多插件,但是很多时候我们需要根据具体项目自定义这些图表,这一篇文章我们一起来看看如何在Android中使用Canvas ...

  6. canvas绘制线和矩形

    ###canvas绘制矩形 HTML中的元素canvas只支持一种原生的图形绘制:矩形.所有其他的图形的绘制都至少需要生成一条路径 1.绘制矩形 canvas提供了三种方法绘制矩形: ----> ...

  7. canvas绘制图像轮廓效果

    在2d图形可视化开发中,经常要绘制对象的选中效果. 一般来说,表达对象选中可以使用边框,轮廓或者发光的效果.  发光的效果,可以使用canvas的阴影功能,比较容易实现,此处不在赘述. 绘制边框 绘制 ...

  8. HTML5学习总结——canvas绘制象棋(canvas绘图)

    一.HTML5学习总结——canvas绘制象棋 1.第一次:canvas绘制象棋(笨方法)示例代码: <!DOCTYPE html> <html> <head> & ...

  9. 使用canvas绘制时钟

    使用canvas绘制时钟  什么使canvas呢?HTML5 <canvas> 元素用于图形的绘制,通过脚本 (通常是JavaScript)来完成.<canvas> 标签只是图 ...

随机推荐

  1. 【ocp 052又加新题了】052新加的考试题及答案整理-第13题

    13.Which two are true about AWR snapshots? A) They are stored In the SYSAUX tablespace. B) They are ...

  2. [Swift]多维数组的表示和存储:N维数组映射到一维数组(一一对应)!

    数组:有序的元素序列. 若将有限个类型相同的变量的集合命名,那么这个名称为数组名.组成数组的各个变量称为数组的分量,也称为数组的元素,有时也称为下标变量.用于区分数组的各个元素的数字编号称为下标.数组 ...

  3. falsk 请求钩子

    请求钩子是通过装饰器的形式实现,Flask支持如下四种请求钩子:before_first_request在处理第一个请求前执行before_request在每次请求前执行如果在某修饰的函数中返回了一个 ...

  4. 2016级算法第五次上机-B.Bamboo&APTX4844魔发药水

    Bamboo&APTX4844魔发药水 题意 "于是,Bamboo耐着性子,看巫师从袖子里掏出 M 瓶时光泉水和 K 粒绿色能量.每瓶时光泉水重量为 c ,生发效果为 l:每粒绿色能 ...

  5. 使用Mondrian Virtual OLAP Cube 实现星座模型并在saiku展现分析

    1.什么是星座模型? 2.哪些地方可以用到星座模型? 3.Mondrian怎么构建星座模型,构建过程又涉及到哪些理论概念. 答1:这里描述了维度模型常用的 星型.雪花.星座模型,简而言之就是多事实表模 ...

  6. 2018-2019-2 网络对抗技术 20165314 Exp6 信息搜集与漏洞扫描

    一.原理与实践说明 1.实践内容 本实践的目标是掌握信息搜集的最基础技能.具体有: 1.各种搜索技巧的应用 2.DNS IP注册信息的查询 3.基本的扫描技术:主机发现.端口扫描.OS及服务版本探测. ...

  7. C语言字符串的操作

    C语言字符串操作函数 1. 字符串反转 - strRev2. 字符串复制 - strcpy3. 字符串转化为整数 - atoi4. 字符串求长 - strlen5. 字符串连接 - strcat6. ...

  8. Leo-io 的C语言实现简单五子棋游戏观后感

    源代码: /************************************************************** ** 文 件 名:wuziqi.cpp ** 功    能:扫 ...

  9. 安卓与windows

    windows phone 还是PC啊?windows PC的话,应该就是你现在用的电脑系统吧,PC系统和安卓是不一样的,安卓是移动设备系统,基于的构架也不同,意思就是电脑上装不上安卓,移动设备也装不 ...

  10. Revit二次开发_快速显示隐藏剖面框

    最近遇到一种状况需要经常切换剖面框的可见性,于是想将剖面框的显示与隐藏做成一个按钮,方便切换. 其他类似元素想做成快速切换可见性应该可以使用类似做法. 这次的隐藏对象是剖面框,所以我直接就隐藏元素了. ...