Pen Settings

HTML

CSS

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URLs added here will be added as <link>s in order, and before the CSS in the editor. You can use the CSS from another Pen by using its URL and the proper URL extension.

+ add another resource

JavaScript

Babel includes JSX processing.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Packages

Add Packages

Search for and use JavaScript packages from npm here. By selecting a package, an import statement will be added to the top of the JavaScript editor for this package.

Behavior

Auto Save

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

Format on Save

If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.

Editor Settings

Code Indentation

Want to change your Syntax Highlighting theme, Fonts and more?

Visit your global Editor Settings.

HTML

              
                <body>
  <canvas></canvas>
<!--
* Stronger forces are red. 
* Weaker are green.
* lines disappear when particles are too far apart for the forces to act
* Click to add more particles > forces continuously flick on-and-off and mostly form a triangular lattice, but with tears where there appears to be, but isn't, a force triangle. Changing of the colors show how the force shockwaves travel through the system after a new particle has been added


Life's Not Complete Without Art. 
       __________________
      /\  ______________ \
     /::\ \ZZZZZZZZZZZZ/\ \
    /:/\.\ \        /:/\:\ \
   /:/Z/\:\ \      /:/Z/\:\ \
  /:/Z/__\:\ \____/:/Z/  \:\ \
 /:/Z/____\:\ \___\/Z/    \:\ \
 \:\ \ZZZZZ\:\ \ZZ/\ \     \:\ \
  \:\ \     \:\ \ \:\ \     \:\ \
   \:\ \     \:\ \_\;\_\_____\;\ \
    \:\ \     \:\_________________\
     \:\ \    /:/ZZZZZZZZZZZZZZZZZ/
      \:\ \  /:/Z/    \:\ \  /:/Z/
       \:\ \/:/Z/      \:\ \/:/Z/
        \:\/:/Z/________\;\/:/Z/
         \::/Z/_______tmr__\/Z/
          \/ZZZZZZZZZZZZZZZZZ/
--!>
              
            
!

CSS

              
                body{
  margin:0;
  width:100%;
  background: hsla(0,0%,0%,1);
  overflow:hidden;
}
canvas{
  width:60%;
  height:60%;
}
              
            
!

JS

              
                var w = 500, //width
	 h = 500, //height
	 parts = [],  //particle array
	 count_fr = 100,  //start counter at (#particles)
	 max_parts = 500, //max number of particles
	 fs = 0.09, //fade speed > time to draw and fade lines depending on strength of force (higher # = increase speed)
	cur_frm = 0;  //current frame

var c = document.getElementsByTagName ('canvas')[0]; //get canvas(c) / c[array]
c.width = w;
c.height = h;
var $ = c.getContext ('2d');  // $ var for getContext

init ();

function random (min, max) {   //random min/max
	return (Math.random() * (max - min) + min);
}


function part_cd () {  //particle_countdown > based on count_from #.
	addPart (random(0, h), random(0, h));
	if (parts.length < count_fr) setTimeout (part_cd, 50);
}


function init () {  //start particle countdown; begin animation sequence; listen for mouse click; animate
	part_cd();
	setInterval (animate, 1000 / 50);
	c.addEventListener ('mousedown', onMouseDown, false);
	animate ();
}


function onMouseDown (e) {  //addParticle() on mouse down 
	addPart(e.offsetX, e.offsetY);
}


function addPart(x, y) {   //add particle function
	parts.push ({
		position: {
			x: x || random(0, w),
			y: y || random (0, h)
		},
		force : {
			x: 0,
			y: 0
		},
		upd : {
			x: 0,
			y: 0
		}
	});
}

function animate () {  //animation sequence
//while there are less particles on the canvas than the max allowed, shift 'forces'
	while (parts.length > max_parts) parts.shift(); 
	cur_frm++;
	$.save ();
	$.fillStyle = "rgba(0,0,0,0.3)"; //styles
	$.fillRect (0, 0, w, h);
	$.fillStyle = 'rgba(0,0,0,0)';
	$.restore();
	
	
	var force = {x : 0, y: 0};
	for (var i = 0; i < parts.length; i++) {
		var p1 = parts[i];
	

		for (var j = i + 1; j < parts.length; j++) {
			var p2 = parts[j];

			// length (determines force strength)
			force.x = p2.position.x - p1.position.x;
			force.y = p2.position.y - p1.position.y;

			var magnitude = mag (force);

			var actingDistance = 50-magnitude;

			if ((actingDistance > 0) && (magnitude > 0)) {
				var red = 0;  //red value threshold for strong forces
				var green = 120; //green value threshold for weaker forces
				var color = green - actingDistance * (green / 2);  //the fading of the weaker (green) forces > the initial color value of the connectors (forces)
				//changing of colors based on above 'color' value
					if (color < 0) color = 0;  //red if the color value is less than 0
					if (color > 120) color = 120; //green if color value is greater than 120

				$.save ();
				$.strokeStyle = 'hsla(' + color + ', 100%, 50%, 1)';  //draw connectors based on 'color' value
				$.strokeWidth = 2;
				$.beginPath ();  //begin path to particle1-x,y and particle2-x,y  positions
				$.moveTo (p1.position.x, p1.position.y);
				$.lineTo (p2.position.x, p2.position.y);
				$.stroke(); //draw
				$.closePath(); //connect paths
				$.restore (); //restore canvas
				//the 'forces' > particle connector positions
				force.x *= fs * actingDistance / magnitude;
				force.y *= fs * actingDistance / magnitude;
				p1.force.x -= force.x;
				p1.force.y -= force.y;

				p2.force.x += force.x;
				p2.force.y += force.y;
			}
		}
		draw (p1);
		upd (p1);
	}
}

function mag (vector) {  //force magnitude value
	return Math.sqrt (vector.x * vector.x + vector.y * vector.y);
}
//update particle based on force
function upd (particle) {  
	with (particle) {
		upd.x += force.x;
		upd.y += force.y;
		upd.x *= 0.8;
		upd.y *= 0.8;

		position.x += upd.x;
		position.y += upd.y;

		force.x = 0;
		force.y = 0;
//force thresholds 
		if (position.x > w - 26) {   //position x based on threshold condition; if position value is > width-26, then this condition value becomes the new position value. This is our max-outer boundary.
			position.x = w - 26;
		}
		if (position.x < 21) {  //position x based on threshold condition;  however, if position value is < 21, then this condition value becomes the new position value. This is our 'preferred' outer boundary.
			position.x = 21;
		}
		if (position.y > h - 26) {  //same as above, but applied to y positions. 
			position.y = h - 26;
		}
		if (position.y < 21) {
			position.y = 21;
		}
	}
}
//draw particles
function draw (particle) {
	$.save ();
	$.translate (particle.position.x, particle.position.y);
	$.fillStyle = "hsla("+cur_frm%360 +",50%,50%,1)";

	$.fillRect (0, 0, 5, 5);
	$.restore ();
}
              
            
!
999px

Console