问题描述
我一直在尝试在我的网站上添加一个(代码笔)动画,老实说,我不确定我错过了什么。我也试过在 jsfiddle 中运行它,它告诉我 delaunay 没有定义。 https://codepen.io/hduffin1/pen/QOMZJg 我不太确定我做错了什么,因为代码在代码笔内部工作,我已经能够复制我尝试从代码笔使用的其他代码,但无论出于何种原因,我都可以似乎无法让这个工作。
HTML
<canvas id="stars" width="300" height="300"></canvas>
CSS
html,body {
margin: 0;
padding: 0;
}
body {
background-color: #31102f; //#280B29
background: radial-gradient(
ellipse at center,rgba(49,16,47,1) 0%,rgba(40,11,41,1) 100%
);
}
#stars {
display: block;
position: relative;
width: 100%;
height: 16rem;
height: 100vh;
z-index: 1;
}
JS
/**
* Stars
* Inspired by Steve Courtney's poster art for Celsius GS's Drifter - http://celsiusgs.com/drifter/posters.PHP
* by Cory Hughart - http://coryhughart.com
*/
// Settings
var particleCount = 40,flareCount = 10,motion = 0.05,tilt = 0.05,color = '#FFeed4',particleSizeBase = 1,particleSizeMultiplier = 0.5,flareSizeBase = 100,flareSizeMultiplier = 100,linewidth = 1,linkChance = 75,// chance per frame of link,higher = smaller chance
linkLengthMin = 5,// min linked vertices
linkLengthMax = 7,// max linked vertices
linkOpacity = 0.25; // number between 0 & 1
linkFade = 90,// link fade-out frames
linkSpeed = 1,// distance a link travels in 1 frame
glareAngle = -60,glareOpacityMultiplier = 0.05,renderParticles = true,renderParticleGlare = true,renderFlares = true,renderLinks = true,renderMesh = false,flicker = true,flickerSmoothing = 15,// higher = smoother flicker
blurSize = 0,orbitTilt = true,randomMotion = true,noiseLength = 1000,noiseStrength = 1;
var canvas = document.getElementById('stars'),//orbits = document.getElementById('orbits'),context = canvas.getContext('2d'),mouse = { x: 0,y: 0 },m = {},r = 0,c = 1000,// multiplier for delaunay points,since floats too small can mess up the algorithm
n = 0,nAngle = (Math.PI * 2) / noiseLength,nRad = 100,nScale = 0.5,nPos = {x: 0,y: 0},points = [],vertices = [],triangles = [],links = [],particles = [],flares = [];
function init() {
var i,j,k;
// requestAnimFrame polyfill
window.requestAnimFrame = (function(){
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
function( callback ){
window.setTimeout(callback,1000 / 60);
};
})();
// Fade in background
/*
var background = document.getElementById('background'),bgImg = new Image(),bgURL = '/img/background.jpg';
bgImg.onload = function() {
//console.log('background loaded');
background.style.backgroundImage = 'url("'+bgURL+'")';
background.className += ' loaded';
}
bgImg.src = bgURL;
*/
// Size canvas
resize();
mouse.x = canvas.clientWidth / 2;
mouse.y = canvas.clientHeight / 2;
// Create particle positions
for (i = 0; i < particleCount; i++) {
var p = new Particle();
particles.push(p);
points.push([p.x*c,p.y*c]);
}
//console.log(JSON.stringify(points));
// delaunay triangulation
//var delaunay = require('delaunay-fast');
vertices = delaunay.triangulate(points);
//console.log(JSON.stringify(vertices));
// Create an array of "triangles" (groups of 3 indices)
var tri = [];
for (i = 0; i < vertices.length; i++) {
if (tri.length == 3) {
triangles.push(tri);
tri = [];
}
tri.push(vertices[i]);
}
//console.log(JSON.stringify(triangles));
// Tell all the particles who their neighbors are
for (i = 0; i < particles.length; i++) {
// Loop through all tirangles
for (j = 0; j < triangles.length; j++) {
// Check if this particle's index is in this triangle
k = triangles[j].indexOf(i);
// If it is,add its neighbors to the particles contacts list
if (k !== -1) {
triangles[j].forEach(function(value,index,array) {
if (value !== i && particles[i].neighbors.indexOf(value) == -1) {
particles[i].neighbors.push(value);
}
});
}
}
}
//console.log(JSON.stringify(particles));
if (renderFlares) {
// Create flare positions
for (i = 0; i < flareCount; i++) {
flares.push(new Flare());
}
}
// Motion mode
//if (Modernizr && Modernizr.deviceorientation) {
if ('ontouchstart' in document.documentElement && window.DeviceOrientationEvent) {
console.log('Using device orientation');
window.addEventListener('deviceorientation',function(e) {
mouse.x = (canvas.clientWidth / 2) - ((e.gamma / 90) * (canvas.clientWidth / 2) * 2);
mouse.y = (canvas.clientHeight / 2) - ((e.beta / 90) * (canvas.clientHeight / 2) * 2);
//console.log('Center: x:'+(canvas.clientWidth/2)+' y:'+(canvas.clientHeight/2));
//console.log('Orientation: x:'+mouse.x+' ('+e.gamma+') y:'+mouse.y+' ('+e.beta+')');
},true);
}
else {
// Mouse move listener
console.log('Using mouse movement');
document.body.addEventListener('mousemove',function(e) {
//console.log('moved');
mouse.x = e.clientX;
mouse.y = e.clientY;
});
}
// Random motion
if (randomMotion) {
//var SimplexNoise = require('simplex-noise');
//var simplex = new SimplexNoise();
}
// Animation loop
(function animloop(){
requestAnimFrame(animloop);
resize();
render();
})();
}
function render() {
if (randomMotion) {
n++;
if (n >= noiseLength) {
n = 0;
}
nPos = noisePoint(n);
//console.log('NOISE x:'+nPos.x+' y:'+nPos.y);
}
// Clear
context.clearRect(0,canvas.width,canvas.height);
if (blurSize > 0) {
context.shadowBlur = blurSize;
context.shadowColor = color;
}
if (renderParticles) {
// Render particles
for (var i = 0; i < particleCount; i++) {
particles[i].render();
}
}
if (renderMesh) {
// Render all lines
context.beginPath();
for (var v = 0; v < vertices.length-1; v++) {
// Splits the array into triplets
if ((v + 1) % 3 === 0) { continue; }
var p1 = particles[vertices[v]],p2 = particles[vertices[v+1]];
//console.log('Line: '+p1.x+','+p1.y+'->'+p2.x+','+p2.y);
var pos1 = position(p1.x,p1.y,p1.z),pos2 = position(p2.x,p2.y,p2.z);
context.moveto(pos1.x,pos1.y);
context.lineto(pos2.x,pos2.y);
}
context.strokeStyle = color;
context.linewidth = linewidth;
context.stroke();
context.closePath();
}
if (renderLinks) {
// Possibly start a new link
if (random(0,linkChance) == linkChance) {
var length = random(linkLengthMin,linkLengthMax);
var start = random(0,particles.length-1);
startLink(start,length);
}
// Render existing links
// Iterate in reverse so that removing items doesn't affect the loop
for (var l = links.length-1; l >= 0; l--) {
if (links[l] && !links[l].finished) {
links[l].render();
}
else {
delete links[l];
}
}
}
if (renderFlares) {
// Render flares
for (var j = 0; j < flareCount; j++) {
flares[j].render();
}
}
/*
if (orbitTilt) {
var tiltX = -(((canvas.clientWidth / 2) - mouse.x + ((nPos.x - 0.5) * noiseStrength)) * tilt),tiltY = (((canvas.clientHeight / 2) - mouse.y + ((nPos.y - 0.5) * noiseStrength)) * tilt);
orbits.style.transform = 'rotateY('+tiltX+'deg) rotateX('+tiltY+'deg)';
}
*/
}
function resize() {
canvas.width = window.innerWidth * (window.devicePixelRatio || 1);
canvas.height = canvas.width * (canvas.clientHeight / canvas.clientWidth);
}
function startLink(vertex,length) {
//console.log('LINK from '+vertex+' (length '+length+')');
links.push(new Link(vertex,length));
}
// Particle class
var Particle = function() {
this.x = random(-0.1,1.1,true);
this.y = random(-0.1,true);
this.z = random(0,4);
this.color = color;
this.opacity = random(0.1,1,true);
this.flicker = 0;
this.neighbors = []; // placeholder for neighbors
};
Particle.prototype.render = function() {
var pos = position(this.x,this.y,this.z),r = ((this.z * particleSizeMultiplier) + particleSizeBase) * (sizeRatio() / 1000),o = this.opacity;
if (flicker) {
var newVal = random(-0.5,0.5,true);
this.flicker += (newVal - this.flicker) / flickerSmoothing;
if (this.flicker > 0.5) this.flicker = 0.5;
if (this.flicker < -0.5) this.flicker = -0.5;
o += this.flicker;
if (o > 1) o = 1;
if (o < 0) o = 0;
}
context.fillStyle = this.color;
context.globalAlpha = o;
context.beginPath();
context.arc(pos.x,pos.y,r,2 * Math.PI,false);
context.fill();
context.closePath();
if (renderParticleGlare) {
context.globalAlpha = o * glareOpacityMultiplier;
/*
context.ellipse(pos.x,r * 30,90 * (Math.PI / 180),false);
context.fill();
context.closePath();
*/
context.ellipse(pos.x,r * 100,(glareAngle - ((nPos.x - 0.5) * noiseStrength * motion)) * (Math.PI / 180),false);
context.fill();
context.closePath();
}
context.globalAlpha = 1;
};
// Flare class
var Flare = function() {
this.x = random(-0.25,1.25,true);
this.y = random(-0.25,2);
this.color = color;
this.opacity = random(0.001,0.01,true);
};
Flare.prototype.render = function() {
var pos = position(this.x,r = ((this.z * flareSizeMultiplier) + flareSizeBase) * (sizeRatio() / 1000);
// Feathered circles
/*
var grad = context.createradialGradient(x+r,y+r,x+r,r);
grad.addColorStop(0,'rgba(255,255,'+f.o+')');
grad.addColorStop(0.8,'+f.o+')');
grad.addColorStop(1,0)');
context.fillStyle = grad;
context.beginPath();
context.fillRect(x,y,r*2,r*2);
context.closePath();
*/
context.beginPath();
context.globalAlpha = this.opacity;
context.arc(pos.x,false);
context.fillStyle = this.color;
context.fill();
context.closePath();
context.globalAlpha = 1;
};
// Link class
var Link = function(startVertex,numPoints) {
this.length = numPoints;
this.verts = [startVertex];
this.stage = 0;
this.linked = [startVertex];
this.distances = [];
this.traveled = 0;
this.fade = 0;
this.finished = false;
};
Link.prototype.render = function() {
// Stages:
// 0. Vertex collection
// 1. Render line reaching from vertex to vertex
// 2. Fade out
// 3. Finished (delete me)
var i,p,pos,points;
switch (this.stage) {
// VERTEX COLLECTION STAGE
case 0:
// Grab the last member of the link
var last = particles[this.verts[this.verts.length-1]];
//console.log(JSON.stringify(last));
if (last && last.neighbors && last.neighbors.length > 0) {
// Grab a random neighbor
var neighbor = last.neighbors[random(0,last.neighbors.length-1)];
// If we haven't seen that particle before,add it to the link
if (this.verts.indexOf(neighbor) == -1) {
this.verts.push(neighbor);
}
// If we have seen that article before,we'll just wait for the next frame
}
else {
//console.log(this.verts[0]+' prematurely moving to stage 3 (0)');
this.stage = 3;
this.finished = true;
}
if (this.verts.length >= this.length) {
// Calculate all distances at once
for (i = 0; i < this.verts.length-1; i++) {
var p1 = particles[this.verts[i]],p2 = particles[this.verts[i+1]],dx = p1.x - p2.x,dy = p1.y - p2.y,dist = Math.sqrt(dx*dx + dy*dy);
this.distances.push(dist);
}
//console.log('distances: '+JSON.stringify(this.distances));
//console.log('verts: '+this.verts.length+' distances: '+this.distances.length);
//console.log(this.verts[0]+' moving to stage 1');
this.stage = 1;
}
break;
// RENDER LINE ANIMATION STAGE
case 1:
if (this.distances.length > 0) {
points = [];
//var a = 1;
// Gather all points already linked
for (i = 0; i < this.linked.length; i++) {
p = particles[this.linked[i]];
pos = position(p.x,p.y,p.z);
points.push([pos.x,pos.y]);
}
var linkSpeedRel = linkSpeed * 0.00001 * canvas.width;
this.traveled += linkSpeedRel;
var d = this.distances[this.linked.length-1];
// Calculate last point based on linkSpeed and distance travelled to next point
if (this.traveled >= d) {
this.traveled = 0;
// We've reached the next point,add coordinates to array
//console.log(this.verts[0]+' reached vertex '+(this.linked.length+1)+' of '+this.verts.length);
this.linked.push(this.verts[this.linked.length]);
p = particles[this.linked[this.linked.length-1]];
pos = position(p.x,pos.y]);
if (this.linked.length >= this.verts.length) {
//console.log(this.verts[0]+' moving to stage 2 (1)');
this.stage = 2;
}
}
else {
// We're still travelling to the next point,get coordinates at travel distance
// http://math.stackexchange.com/a/85582
var a = particles[this.linked[this.linked.length-1]],b = particles[this.verts[this.linked.length]],t = d - this.traveled,x = ((this.traveled * b.x) + (t * a.x)) / d,y = ((this.traveled * b.y) + (t * a.y)) / d,z = ((this.traveled * b.z) + (t * a.z)) / d;
pos = position(x,z);
//console.log(this.verts[0]+' traveling to vertex '+(this.linked.length+1)+' of '+this.verts.length+' ('+this.traveled+' of '+this.distances[this.linked.length]+')');
points.push([pos.x,pos.y]);
}
this.drawLine(points);
}
else {
//console.log(this.verts[0]+' prematurely moving to stage 3 (1)');
this.stage = 3;
this.finished = true;
}
break;
// FADE OUT STAGE
case 2:
if (this.verts.length > 1) {
if (this.fade < linkFade) {
this.fade++;
// Render full link between all vertices and fade over time
points = [];
var alpha = (1 - (this.fade / linkFade)) * linkOpacity;
for (i = 0; i < this.verts.length; i++) {
p = particles[this.verts[i]];
pos = position(p.x,p.z);
points.push([pos.x,pos.y]);
}
this.drawLine(points,alpha);
}
else {
//console.log(this.verts[0]+' moving to stage 3 (2a)');
this.stage = 3;
this.finished = true;
}
}
else {
//console.log(this.verts[0]+' prematurely moving to stage 3 (2b)');
this.stage = 3;
this.finished = true;
}
break;
// FINISHED STAGE
case 3:
default:
this.finished = true;
break;
}
};
Link.prototype.drawLine = function(points,alpha) {
if (typeof alpha !== 'number') alpha = linkOpacity;
if (points.length > 1 && alpha > 0) {
//console.log(this.verts[0]+': Drawing line '+alpha);
context.globalAlpha = alpha;
context.beginPath();
for (var i = 0; i < points.length-1; i++) {
context.moveto(points[i][0],points[i][1]);
context.lineto(points[i+1][0],points[i+1][1]);
}
context.strokeStyle = color;
context.linewidth = linewidth;
context.stroke();
context.closePath();
context.globalAlpha = 1;
}
};
// Utils
function noisePoint(i) {
var a = nAngle * i,cosA = Math.cos(a),sinA = Math.sin(a),//value = simplex.noise2D(nScale * cosA + nScale,nScale * sinA + nScale),//rad = nRad + value;
rad = nRad;
return {
x: rad * cosA,y: rad * sinA
};
}
function position(x,z) {
return {
x: (x * canvas.width) + ((((canvas.width / 2) - mouse.x + ((nPos.x - 0.5) * noiseStrength)) * z) * motion),y: (y * canvas.height) + ((((canvas.height / 2) - mouse.y + ((nPos.y - 0.5) * noiseStrength)) * z) * motion)
};
}
function sizeRatio() {
return canvas.width >= canvas.height ? canvas.width : canvas.height;
}
function random(min,max,float) {
return float ?
Math.random() * (max - min) + min :
Math.floor(Math.random() * (max - min + 1)) + min;
}
// init
if (canvas) init();
解决方法
当我输入“https://codepen.io/hduffin1/pen/QOMZJg”时,设置中包含“delaunay.js”。
添加以下脚本,它应该可以工作了。
<script src="https://rawgit.com/ironwallaby/delaunay/master/delaunay.js"></script>
/**
* Stars
* Inspired by Steve Courtney's poster art for Celsius GS's Drifter - http://celsiusgs.com/drifter/posters.php
* by Cory Hughart - http://coryhughart.com
*/
// Settings
var particleCount = 40,flareCount = 10,motion = 0.05,tilt = 0.05,color = '#FFEED4',particleSizeBase = 1,particleSizeMultiplier = 0.5,flareSizeBase = 100,flareSizeMultiplier = 100,lineWidth = 1,linkChance = 75,// chance per frame of link,higher = smaller chance
linkLengthMin = 5,// min linked vertices
linkLengthMax = 7,// max linked vertices
linkOpacity = 0.25; // number between 0 & 1
linkFade = 90,// link fade-out frames
linkSpeed = 1,// distance a link travels in 1 frame
glareAngle = -60,glareOpacityMultiplier = 0.05,renderParticles = true,renderParticleGlare = true,renderFlares = true,renderLinks = true,renderMesh = false,flicker = true,flickerSmoothing = 15,// higher = smoother flicker
blurSize = 0,orbitTilt = true,randomMotion = true,noiseLength = 1000,noiseStrength = 1;
var canvas = document.getElementById('stars'),//orbits = document.getElementById('orbits'),context = canvas.getContext('2d'),mouse = { x: 0,y: 0 },m = {},r = 0,c = 1000,// multiplier for delaunay points,since floats too small can mess up the algorithm
n = 0,nAngle = (Math.PI * 2) / noiseLength,nRad = 100,nScale = 0.5,nPos = {x: 0,y: 0},points = [],vertices = [],triangles = [],links = [],particles = [],flares = [];
function init() {
var i,j,k;
// requestAnimFrame polyfill
window.requestAnimFrame = (function(){
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
function( callback ){
window.setTimeout(callback,1000 / 60);
};
})();
// Fade in background
/*
var background = document.getElementById('background'),bgImg = new Image(),bgURL = '/img/background.jpg';
bgImg.onload = function() {
//console.log('background loaded');
background.style.backgroundImage = 'url("'+bgURL+'")';
background.className += ' loaded';
}
bgImg.src = bgURL;
*/
// Size canvas
resize();
mouse.x = canvas.clientWidth / 2;
mouse.y = canvas.clientHeight / 2;
// Create particle positions
for (i = 0; i < particleCount; i++) {
var p = new Particle();
particles.push(p);
points.push([p.x*c,p.y*c]);
}
//console.log(JSON.stringify(points));
// Delaunay triangulation
//var Delaunay = require('delaunay-fast');
vertices = Delaunay.triangulate(points);
//console.log(JSON.stringify(vertices));
// Create an array of "triangles" (groups of 3 indices)
var tri = [];
for (i = 0; i < vertices.length; i++) {
if (tri.length == 3) {
triangles.push(tri);
tri = [];
}
tri.push(vertices[i]);
}
//console.log(JSON.stringify(triangles));
// Tell all the particles who their neighbors are
for (i = 0; i < particles.length; i++) {
// Loop through all tirangles
for (j = 0; j < triangles.length; j++) {
// Check if this particle's index is in this triangle
k = triangles[j].indexOf(i);
// If it is,add its neighbors to the particles contacts list
if (k !== -1) {
triangles[j].forEach(function(value,index,array) {
if (value !== i && particles[i].neighbors.indexOf(value) == -1) {
particles[i].neighbors.push(value);
}
});
}
}
}
//console.log(JSON.stringify(particles));
if (renderFlares) {
// Create flare positions
for (i = 0; i < flareCount; i++) {
flares.push(new Flare());
}
}
// Motion mode
//if (Modernizr && Modernizr.deviceorientation) {
if ('ontouchstart' in document.documentElement && window.DeviceOrientationEvent) {
console.log('Using device orientation');
window.addEventListener('deviceorientation',function(e) {
mouse.x = (canvas.clientWidth / 2) - ((e.gamma / 90) * (canvas.clientWidth / 2) * 2);
mouse.y = (canvas.clientHeight / 2) - ((e.beta / 90) * (canvas.clientHeight / 2) * 2);
//console.log('Center: x:'+(canvas.clientWidth/2)+' y:'+(canvas.clientHeight/2));
//console.log('Orientation: x:'+mouse.x+' ('+e.gamma+') y:'+mouse.y+' ('+e.beta+')');
},true);
}
else {
// Mouse move listener
console.log('Using mouse movement');
document.body.addEventListener('mousemove',function(e) {
//console.log('moved');
mouse.x = e.clientX;
mouse.y = e.clientY;
});
}
// Random motion
if (randomMotion) {
//var SimplexNoise = require('simplex-noise');
//var simplex = new SimplexNoise();
}
// Animation loop
(function animloop(){
requestAnimFrame(animloop);
resize();
render();
})();
}
function render() {
if (randomMotion) {
n++;
if (n >= noiseLength) {
n = 0;
}
nPos = noisePoint(n);
//console.log('NOISE x:'+nPos.x+' y:'+nPos.y);
}
// Clear
context.clearRect(0,canvas.width,canvas.height);
if (blurSize > 0) {
context.shadowBlur = blurSize;
context.shadowColor = color;
}
if (renderParticles) {
// Render particles
for (var i = 0; i < particleCount; i++) {
particles[i].render();
}
}
if (renderMesh) {
// Render all lines
context.beginPath();
for (var v = 0; v < vertices.length-1; v++) {
// Splits the array into triplets
if ((v + 1) % 3 === 0) { continue; }
var p1 = particles[vertices[v]],p2 = particles[vertices[v+1]];
//console.log('Line: '+p1.x+','+p1.y+'->'+p2.x+','+p2.y);
var pos1 = position(p1.x,p1.y,p1.z),pos2 = position(p2.x,p2.y,p2.z);
context.moveTo(pos1.x,pos1.y);
context.lineTo(pos2.x,pos2.y);
}
context.strokeStyle = color;
context.lineWidth = lineWidth;
context.stroke();
context.closePath();
}
if (renderLinks) {
// Possibly start a new link
if (random(0,linkChance) == linkChance) {
var length = random(linkLengthMin,linkLengthMax);
var start = random(0,particles.length-1);
startLink(start,length);
}
// Render existing links
// Iterate in reverse so that removing items doesn't affect the loop
for (var l = links.length-1; l >= 0; l--) {
if (links[l] && !links[l].finished) {
links[l].render();
}
else {
delete links[l];
}
}
}
if (renderFlares) {
// Render flares
for (var j = 0; j < flareCount; j++) {
flares[j].render();
}
}
/*
if (orbitTilt) {
var tiltX = -(((canvas.clientWidth / 2) - mouse.x + ((nPos.x - 0.5) * noiseStrength)) * tilt),tiltY = (((canvas.clientHeight / 2) - mouse.y + ((nPos.y - 0.5) * noiseStrength)) * tilt);
orbits.style.transform = 'rotateY('+tiltX+'deg) rotateX('+tiltY+'deg)';
}
*/
}
function resize() {
canvas.width = window.innerWidth * (window.devicePixelRatio || 1);
canvas.height = canvas.width * (canvas.clientHeight / canvas.clientWidth);
}
function startLink(vertex,length) {
//console.log('LINK from '+vertex+' (length '+length+')');
links.push(new Link(vertex,length));
}
// Particle class
var Particle = function() {
this.x = random(-0.1,1.1,true);
this.y = random(-0.1,true);
this.z = random(0,4);
this.color = color;
this.opacity = random(0.1,1,true);
this.flicker = 0;
this.neighbors = []; // placeholder for neighbors
};
Particle.prototype.render = function() {
var pos = position(this.x,this.y,this.z),r = ((this.z * particleSizeMultiplier) + particleSizeBase) * (sizeRatio() / 1000),o = this.opacity;
if (flicker) {
var newVal = random(-0.5,0.5,true);
this.flicker += (newVal - this.flicker) / flickerSmoothing;
if (this.flicker > 0.5) this.flicker = 0.5;
if (this.flicker < -0.5) this.flicker = -0.5;
o += this.flicker;
if (o > 1) o = 1;
if (o < 0) o = 0;
}
context.fillStyle = this.color;
context.globalAlpha = o;
context.beginPath();
context.arc(pos.x,pos.y,r,2 * Math.PI,false);
context.fill();
context.closePath();
if (renderParticleGlare) {
context.globalAlpha = o * glareOpacityMultiplier;
/*
context.ellipse(pos.x,r * 30,90 * (Math.PI / 180),false);
context.fill();
context.closePath();
*/
context.ellipse(pos.x,r * 100,(glareAngle - ((nPos.x - 0.5) * noiseStrength * motion)) * (Math.PI / 180),false);
context.fill();
context.closePath();
}
context.globalAlpha = 1;
};
// Flare class
var Flare = function() {
this.x = random(-0.25,1.25,true);
this.y = random(-0.25,2);
this.color = color;
this.opacity = random(0.001,0.01,true);
};
Flare.prototype.render = function() {
var pos = position(this.x,r = ((this.z * flareSizeMultiplier) + flareSizeBase) * (sizeRatio() / 1000);
// Feathered circles
/*
var grad = context.createRadialGradient(x+r,y+r,x+r,r);
grad.addColorStop(0,'rgba(255,255,'+f.o+')');
grad.addColorStop(0.8,'+f.o+')');
grad.addColorStop(1,0)');
context.fillStyle = grad;
context.beginPath();
context.fillRect(x,y,r*2,r*2);
context.closePath();
*/
context.beginPath();
context.globalAlpha = this.opacity;
context.arc(pos.x,false);
context.fillStyle = this.color;
context.fill();
context.closePath();
context.globalAlpha = 1;
};
// Link class
var Link = function(startVertex,numPoints) {
this.length = numPoints;
this.verts = [startVertex];
this.stage = 0;
this.linked = [startVertex];
this.distances = [];
this.traveled = 0;
this.fade = 0;
this.finished = false;
};
Link.prototype.render = function() {
// Stages:
// 0. Vertex collection
// 1. Render line reaching from vertex to vertex
// 2. Fade out
// 3. Finished (delete me)
var i,p,pos,points;
switch (this.stage) {
// VERTEX COLLECTION STAGE
case 0:
// Grab the last member of the link
var last = particles[this.verts[this.verts.length-1]];
//console.log(JSON.stringify(last));
if (last && last.neighbors && last.neighbors.length > 0) {
// Grab a random neighbor
var neighbor = last.neighbors[random(0,last.neighbors.length-1)];
// If we haven't seen that particle before,add it to the link
if (this.verts.indexOf(neighbor) == -1) {
this.verts.push(neighbor);
}
// If we have seen that particle before,we'll just wait for the next frame
}
else {
//console.log(this.verts[0]+' prematurely moving to stage 3 (0)');
this.stage = 3;
this.finished = true;
}
if (this.verts.length >= this.length) {
// Calculate all distances at once
for (i = 0; i < this.verts.length-1; i++) {
var p1 = particles[this.verts[i]],p2 = particles[this.verts[i+1]],dx = p1.x - p2.x,dy = p1.y - p2.y,dist = Math.sqrt(dx*dx + dy*dy);
this.distances.push(dist);
}
//console.log('Distances: '+JSON.stringify(this.distances));
//console.log('verts: '+this.verts.length+' distances: '+this.distances.length);
//console.log(this.verts[0]+' moving to stage 1');
this.stage = 1;
}
break;
// RENDER LINE ANIMATION STAGE
case 1:
if (this.distances.length > 0) {
points = [];
//var a = 1;
// Gather all points already linked
for (i = 0; i < this.linked.length; i++) {
p = particles[this.linked[i]];
pos = position(p.x,p.y,p.z);
points.push([pos.x,pos.y]);
}
var linkSpeedRel = linkSpeed * 0.00001 * canvas.width;
this.traveled += linkSpeedRel;
var d = this.distances[this.linked.length-1];
// Calculate last point based on linkSpeed and distance travelled to next point
if (this.traveled >= d) {
this.traveled = 0;
// We've reached the next point,add coordinates to array
//console.log(this.verts[0]+' reached vertex '+(this.linked.length+1)+' of '+this.verts.length);
this.linked.push(this.verts[this.linked.length]);
p = particles[this.linked[this.linked.length-1]];
pos = position(p.x,pos.y]);
if (this.linked.length >= this.verts.length) {
//console.log(this.verts[0]+' moving to stage 2 (1)');
this.stage = 2;
}
}
else {
// We're still travelling to the next point,get coordinates at travel distance
// http://math.stackexchange.com/a/85582
var a = particles[this.linked[this.linked.length-1]],b = particles[this.verts[this.linked.length]],t = d - this.traveled,x = ((this.traveled * b.x) + (t * a.x)) / d,y = ((this.traveled * b.y) + (t * a.y)) / d,z = ((this.traveled * b.z) + (t * a.z)) / d;
pos = position(x,z);
//console.log(this.verts[0]+' traveling to vertex '+(this.linked.length+1)+' of '+this.verts.length+' ('+this.traveled+' of '+this.distances[this.linked.length]+')');
points.push([pos.x,pos.y]);
}
this.drawLine(points);
}
else {
//console.log(this.verts[0]+' prematurely moving to stage 3 (1)');
this.stage = 3;
this.finished = true;
}
break;
// FADE OUT STAGE
case 2:
if (this.verts.length > 1) {
if (this.fade < linkFade) {
this.fade++;
// Render full link between all vertices and fade over time
points = [];
var alpha = (1 - (this.fade / linkFade)) * linkOpacity;
for (i = 0; i < this.verts.length; i++) {
p = particles[this.verts[i]];
pos = position(p.x,p.z);
points.push([pos.x,pos.y]);
}
this.drawLine(points,alpha);
}
else {
//console.log(this.verts[0]+' moving to stage 3 (2a)');
this.stage = 3;
this.finished = true;
}
}
else {
//console.log(this.verts[0]+' prematurely moving to stage 3 (2b)');
this.stage = 3;
this.finished = true;
}
break;
// FINISHED STAGE
case 3:
default:
this.finished = true;
break;
}
};
Link.prototype.drawLine = function(points,alpha) {
if (typeof alpha !== 'number') alpha = linkOpacity;
if (points.length > 1 && alpha > 0) {
//console.log(this.verts[0]+': Drawing line '+alpha);
context.globalAlpha = alpha;
context.beginPath();
for (var i = 0; i < points.length-1; i++) {
context.moveTo(points[i][0],points[i][1]);
context.lineTo(points[i+1][0],points[i+1][1]);
}
context.strokeStyle = color;
context.lineWidth = lineWidth;
context.stroke();
context.closePath();
context.globalAlpha = 1;
}
};
// Utils
function noisePoint(i) {
var a = nAngle * i,cosA = Math.cos(a),sinA = Math.sin(a),//value = simplex.noise2D(nScale * cosA + nScale,nScale * sinA + nScale),//rad = nRad + value;
rad = nRad;
return {
x: rad * cosA,y: rad * sinA
};
}
function position(x,z) {
return {
x: (x * canvas.width) + ((((canvas.width / 2) - mouse.x + ((nPos.x - 0.5) * noiseStrength)) * z) * motion),y: (y * canvas.height) + ((((canvas.height / 2) - mouse.y + ((nPos.y - 0.5) * noiseStrength)) * z) * motion)
};
}
function sizeRatio() {
return canvas.width >= canvas.height ? canvas.width : canvas.height;
}
function random(min,max,float) {
return float ?
Math.random() * (max - min) + min :
Math.floor(Math.random() * (max - min + 1)) + min;
}
// init
if (canvas) init();
html,body {
margin: 0;
padding: 0;
}
body {
background-color: #31102F;
background: radial-gradient(ellipse at center,#31102f 0%,#280b29 100%);
}
#stars {
display: block;
position: relative;
width: 100%;
height: 16rem;
height: 100vh;
z-index: 1;
}
<script src="https://rawgit.com/ironwallaby/delaunay/master/delaunay.js"></script>
<canvas id="stars" width="300" height="300"></canvas>