Initializing
Liveweave
Web
expand_more
home
Home
data_object
CSS Explorer
arrow_outward
Palette
Color Explorer
arrow_outward
Polyline
Graphics Editor
arrow_outward
outbox_alt
Generative AI
arrow_outward
frame_source
Python Playground
New
arrow_outward
build
Tools
expand_more
restart_alt
Load "Hello Weaver!"
post_add
Generate Lorem ipsum...
code
Format HTML
code_blocks
Format CSS
data_object
Format JavaScript
library_add
Library
expand_more
A
Algolia JS
Animate CSS
Apex Charts JS
B
Bulma CSS
Bootstrap
C
Chart JS
Chartist
Create JS
D
D3
Dojo
F
Foundation
Fullpage JS
G
Granim JS
Google Charts
H
Halfmoon
J
jQuery
M
Materialize
Moment JS
Masonry JS
Milligram CSS
P
Pure CSS
Primer CSS
Popper JS
Pattern CSS
Picnic CSS
R
React JS
Raphael JS
Raisin CSS
S
Semantic UI
Skeleton CSS
Spectre CSS
Tachyons CSS
T
Tailwind
Three JS
U
UI Kit
Vis JS
W
Water CSS
download
Download
expand_more
developer_mode
Download as HTML
folder_zip
Download as .ZIP
cloud_upload
Save
account_circle
Login
settings
Settings
expand_more
14
px
Live mode
Night mode
Line number
Mini map
Word wrap
sync_alt
Reset Settings
smart_display
Run
<!DOCTYPE html> <html> <head> <script type="text/javascript" src="http://cloud.github.com/downloads/processing-js/processing-js/processing-1.4.1.min.js"></script> <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/paper.js/0.9.9/paper.js"></script> <script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script> <title>Jelly Fish using Paper JS and Processing JS</title> </head> <body> <canvas id="jellies-canvas" resize></canvas> <canvas id="pond-canvas" data-processing-sources="pond_scripts/pond.pjs pond_scripts/Fish.pjs pond_scripts/Boid.pjs pond_scripts/Flagellum.pjs pond_scripts/Food.pjs" resize></canvas> <div id="content"> <p>Jelly Fish by <a href="http://nardove.com/">Ricardo Sanchez</a></p> </div> </body> </html>
body { margin: 0px; border: 0px; padding: 0px; background-color: #69d2e7; overflow: hidden; font-size: 62.5%; font-family: sans-serif, "Arial"; } canvas { margin: 0px; padding: 0px; position: absolute; /*background: #3c3b3b;*/ pointer-events: none; position: absolute; } #content { margin: 0px; padding: 50px; width: 400px; height: 400px; display: inline-block; /*overflow: hidden;*/ position: absolute; } #content h1 { margin: 10px 0px 0px 0px; color: #fff; font-weight: 100; font-size: 3.6em; } #content h2 { margin: 0px; line-height: 1.0em; color: #573E31; } #content p { font-size: 1.4em; color: #573E31; position: absolute; left: 10px; top: 0; } #content p a { text-decoration: none; color: #fff; font-weight: bold; } #jellies-btn { margin: 0px 5px; width: 64px; height: 64px; display: inline-block; cursor: pointer; } #pond-btn { margin: 0px 5px; width: 64px; height: 64px; display: inline-block; cursor: pointer; } .not-found-error { font-size: 3.6em; color: #fff; }
/* Jelly Fish using Paper JS and Processing JS */ /* Created by Ricardo Sánchez */ var numJellies = 3; var jellies = [numJellies]; var jellyStyle = { fillColor: "#FB4C9F", strokeColor: "#CA2A65", strokeJoin: "round", strokeWidth: 2 }; var tentacleStyle = { strokeColor: "#CA2A65", strokeWidth: 2 }; var tentacleTipStyle = { fillColor: "#CA2A65" }; var particleStyle = { strokeColor: "#CA2A65" }; // Paperjs direct mode settings paper.install( window ); window.onload = function() { paper.setup( "jellies-canvas" ); // Create jellies for ( var j = 0; j < numJellies; j++ ) { jellies[j] = new Jelly(); jellies[j].init(); } // Set drawing loop view.onFrame = draw; }; function draw( evt ) { for ( var j = 0; j < numJellies; j++ ) { jellies[j].wander(); //jellies[j].seek( mouse ); jellies[j].update( evt ); jellies[j].checkBounds(); } } // ------------------------------------- // ---- Jelly Class BEGIN function Jelly() { this.path = new Path(); this.location = new Point( -100 , Math.random() * (view.size.height * 0.5) ); this.velocity = new Point( 0, 0 ); this.acceleration = new Point( 0, 0 ); var maxSpeed = Math.random() * 0.4 + 1; var maxForce = 0.4; var pathRadius = 55 + Math.random() * 15; var pathRes = 25; var pathPoints = [pathRes]; var angle = (Math.PI * 2) / pathRes; var wrapAngle = (Math.PI / 2) + angle; var wanderTheta = 0; var orientation = 0; var lastOrientation = 0; var lastLocation; var numTentacles = 12; var tentacles = [numTentacles]; var particleSpan = parseInt( Math.random() * 300 ); var particleCount = 0; var particles = []; this.init = function() { // Creates body path for ( var i = 0; i < pathRes; i++ ) { var theta = angle * i; var thetaUp = theta - (Math.PI / 2); var point = new Point(); // Upper side of the body if ( theta < wrapAngle ) { point.x = Math.cos( thetaUp ) * pathRadius; point.y = Math.sin( thetaUp ) * pathRadius; } // Inner side else if ( theta > wrapAngle && theta + (angle * 2) < wrapAngle + Math.PI ) { point.x = Math.cos( thetaUp ) * pathRadius; point.y = Math.sin( thetaUp ) * ((-pathRadius * 0.85) + pathRadius * 1.25); } // The other upper side of the body else { point.x = Math.cos( thetaUp ) * pathRadius; point.y = Math.sin( thetaUp ) * pathRadius; } pathPoints[i] = point; this.path.add( point ); } this.path.closed = true; this.path.style = jellyStyle; this.path.opacity = 0.8; // Create tentacles for ( var t = 0; t < numTentacles; t++ ) { tentacles[t] = new Tentacle(); tentacles[t].init(); } }; this.update = function( evt ) { lastLocation = this.location.clone(); this.velocity.x += this.acceleration.x; this.velocity.y += this.acceleration.y; this.velocity.length = Math.min( maxSpeed, this.velocity.length ); this.location.x += this.velocity.x; this.location.y += this.velocity.y; this.acceleration.length = 0; // Change jelly path position, without this it won't move this.path.position = this.location.clone(); // Rotation alignment var locVector = new Point( this.location.x - lastLocation.x, this.location.y - lastLocation.y ); orientation = locVector.angle + 90; this.path.rotate( orientation - lastOrientation ); lastOrientation = orientation; // Contraction, expansion motion for ( var n = 0; n < pathRes; n++ ) { var segment = this.path.segments[n]; var sineSeed = (evt.count * maxSpeed + (pathPoints[n].y * 0.55)) / 10; segment.point.x += pathPoints[n].rotate( orientation ).normalize().x * Math.sin( sineSeed ); segment.point.y += pathPoints[n].rotate( orientation ).normalize().y * Math.sin( sineSeed ); } // Attach tentacles to the bottom segments of the body // 7 is entirely arbitrary, this needs to be dynamic for ( var t = 0; t < numTentacles; t++ ) { tentacles[t].update( orientation ); tentacles[t].head.point = this.path.segments[7 + t].point; } // Create bubble particles if ( evt.count % particleSpan == 0 ) { particleSpan = parseInt( Math.random() * 100 + 150 ); particleCount++; particles.push( new Particle( particleCount - 1, this.path.position.clone() ) ); } // Update bubble particles // If a particle die remove it from array for ( var p = 0; p < particles.length; p++ ) { var particle = particles[p]; if ( particle.isDead === true && particle.path.opacity === 0 ) { particles.splice( 0, 1 ); } else { particle.update( evt ); } } }; this.steer = function( target, slowdown ) { var steer; var desired = new Point( target.x - this.location.x, target.y - this.location.y ); var dist = desired.length; if ( dist > 0 ) { if ( slowdown && dist < 100 ) { desired.length = maxSpeed * ( dist / 100 ); } else { desired.length = maxSpeed; } steer = new Point( desired.x - this.velocity.x, desired.y - this.velocity.y ); steer.length = Math.min( maxForce, steer.length ); } else { steer = new Point( 0, 0 ); } return steer; } this.seek = function( target ) { var steer = this.steer( target, false ); this.acceleration.x += steer.x; this.acceleration.y += steer.y; } this.wander = function() { var wanderR = 5; var wanderD = 100; var change = 0.05; wanderTheta += Math.random() * (change * 2) - change; var circleLocation = this.velocity.clone(); circleLocation = circleLocation.normalize(); circleLocation.x *= wanderD; circleLocation.y *= wanderD; circleLocation.x += this.location.x; circleLocation.y += this.location.y; var circleOffset = new Point( wanderR * Math.cos( wanderTheta ), wanderR * Math.sin( wanderTheta ) ); var target = new Point( circleLocation.x + circleOffset.x, circleLocation.y + circleOffset.y ); this.seek( target ); } this.checkBounds = function() { var offset = 200; if ( this.location.x < -offset ) { this.location.x = view.size.width + offset; for ( var t = 0; t < numTentacles; t++ ) { tentacles[t].path.position = this.location.clone(); } } if ( this.location.x > view.size.width + offset ) { this.location.x = -offset; for ( var t = 0; t < numTentacles; t++ ) { tentacles[t].path.position = this.location.clone(); } } if ( this.location.y < -offset ) { this.location.y = view.size.height + offset; for ( var t = 0; t < numTentacles; t++ ) { tentacles[t].path.position = this.location.clone(); } } if ( this.location.y > view.size.height + offset ) { this.location.y = -offset; for ( var t = 0; t < numTentacles; t++ ) { tentacles[t].path.position = this.location.clone(); } } } } // ---- Jelly Class END // ------------------------------------- // ------------------------------------- // ---- Tentacle Class BEGIN function Tentacle() { this.head = new Segment(); this.path = new Path(); var numSegments = parseInt(Math.random() * 5 + 10); var segmentLength = Math.random() * 10 + 5; var pathTip = new Path.Circle( new Point(0, 0), 2.5 ); pathTip.style = tentacleTipStyle; //pathTip.opacity = 0.7; this.init = function() { for ( var i = 0; i < numSegments; i++ ) { this.path.add( new Point( 0, i * segmentLength ) ); } this.path.style = tentacleStyle; this.head = this.path.segments[0]; }; //this.path.opacity = 0.8; // Use simple IK motion this.update = function( orientation ) { this.path.segments[1].point = this.head.point; var dx = this.head.point.x - this.path.segments[1].point.x; var dy = this.head.point.y - this.path.segments[1].point.y; var angle = Math.atan2( dy, dx ) + (orientation * (Math.PI / 180)); angle += Math.PI / 2; this.path.segments[1].point.x += Math.cos( angle ); this.path.segments[1].point.y += Math.sin( angle ); for ( var i = 2; i < numSegments; i++ ) { var pt = new Point( (this.path.segments[i].point.x - this.path.segments[i-2].point.x), (this.path.segments[i].point.y - this.path.segments[i-2].point.y) ); var len = pt.length; if ( len > 0.0 ) { this.path.segments[i].point.x = this.path.segments[i-1].point.x + (pt.x * segmentLength) / len; this.path.segments[i].point.y = this.path.segments[i-1].point.y + (pt.y * segmentLength) / len; } } pathTip.position.x = this.path.segments[numSegments-1].point.x; pathTip.position.y = this.path.segments[numSegments-1].point.y; }; } // ---- Tentacle Class END // ------------------------------------- // ------------------------------------- // ---- Particle Class BEGIN function Particle( id, location ) { location.x += Math.random() * 30; location.y += Math.random() * 30; this.id = id; this.isDead = false; this.path = new Path.Circle( location, Math.random() * 3 + 2 ); this.path.style = particleStyle; this.path.opacity = 0.8; var lifeSpan = 250; var age = lifeSpan; var waveFactor = Math.random() * 2 + 2; this.update = function( evt ) { this.path.position.x += Math.cos( evt.time * waveFactor ); this.path.position.y -= 0.8; this.path.opacity = age / lifeSpan; age--; if ( age === 0 ) { this.isDead = true; this.path.remove(); } } } // ---- Particle Class END // -------------------------------------