ghostly-gravity-garden.js

total 0
used 0
limit 0
/* title: Ghostly Gravity Garden categories: gravity particles interactive files: head point stage --- Drag the glowing star to bend the paths of eighty orbiting points. Double-click to scatter the garden. A little experiment from Ghostly for Jaybird. */ class MainStage extends Stage { canvas = 'playspace' mounted() { const { width, height } = this.dimensions this.well = new Point({ x: width / 2, y: height / 2, radius: 14 }) this.particles = Array.from({ length: 80 }, () => { const a = Math.random() * Math.PI * 2 const r = 55 + Math.random() * Math.min(width, height) * .42 const speed = Math.sqrt(190 / r) return { point: new Point({ x: this.well.x + Math.cos(a) * r, y: this.well.y + Math.sin(a) * r, radius: 1.5 + Math.random() * 2.2 }), vx: -Math.sin(a) * speed, vy: Math.cos(a) * speed, hue: 170 + Math.random() * 130, trail: [] } }) const canvas = document.getElementById('playspace') const locate = e => { const rect = canvas.getBoundingClientRect() return { x: (e.clientX - rect.left) * canvas.width / rect.width, y: (e.clientY - rect.top) * canvas.height / rect.height } } this.draggingWell = false canvas.addEventListener('pointerdown', e => { const p = locate(e) if (Math.hypot(p.x - this.well.x, p.y - this.well.y) < 48) { this.draggingWell = true canvas.setPointerCapture(e.pointerId) this.well.x = p.x this.well.y = p.y } }) canvas.addEventListener('pointermove', e => { if (!this.draggingWell) return const p = locate(e) this.well.x = p.x this.well.y = p.y }) canvas.addEventListener('pointerup', () => { this.draggingWell = false }) canvas.addEventListener('pointercancel', () => { this.draggingWell = false }) canvas.addEventListener('dblclick', () => this.scatter()) } scatter() { for (const b of this.particles) { const a = Math.random() * Math.PI * 2 b.vx += Math.cos(a) * 3 b.vy += Math.sin(a) * 3 b.trail.length = 0 } } draw(ctx) { this.clear(ctx) const { width, height } = this.dimensions ctx.fillStyle = '#080d1d' ctx.fillRect(0, 0, width, height) for (const b of this.particles) { const p = b.point const dx = this.well.x - p.x const dy = this.well.y - p.y const distance = Math.sqrt(dx * dx + dy * dy + 900) const acceleration = Math.min(.8, 170 / (distance * distance)) b.vx = (b.vx + dx / distance * acceleration) * .999 b.vy = (b.vy + dy / distance * acceleration) * .999 p.x += b.vx p.y += b.vy if (p.x < -90 || p.x > width + 90 || p.y < -90 || p.y > height + 90) { const a = Math.random() * Math.PI * 2 const r = 60 + Math.random() * Math.min(width, height) * .3 p.x = this.well.x + Math.cos(a) * r p.y = this.well.y + Math.sin(a) * r b.vx = -Math.sin(a) b.vy = Math.cos(a) b.trail.length = 0 } b.trail.push({ x: p.x, y: p.y }) if (b.trail.length > 28) b.trail.shift() ctx.beginPath() b.trail.forEach((v, i) => { if (i === 0) ctx.moveTo(v.x, v.y) else ctx.lineTo(v.x, v.y) }) ctx.strokeStyle = `hsla(${b.hue}, 95%, 75%, .36)` ctx.lineWidth = 1.2 ctx.stroke() ctx.beginPath() ctx.arc(p.x, p.y, p.radius, 0, Math.PI * 2) ctx.fillStyle = `hsl(${b.hue}, 95%, 80%)` ctx.fill() } const glow = ctx.createRadialGradient( this.well.x, this.well.y, 2, this.well.x, this.well.y, 58 ) glow.addColorStop(0, 'rgba(100,230,255,.75)') glow.addColorStop(1, 'rgba(100,230,255,0)') ctx.beginPath() ctx.arc(this.well.x, this.well.y, 58, 0, Math.PI * 2) ctx.fillStyle = glow ctx.fill() ctx.beginPath() ctx.arc(this.well.x, this.well.y, this.well.radius, 0, Math.PI * 2) ctx.fillStyle = '#b9f5ff' ctx.fill() ctx.font = '13px sans-serif' ctx.fillStyle = '#d5e7fa' ctx.fillText('Drag the star • Double-click to scatter', 16, 26) } } stage = MainStage.go()
Run
Meta Data
title Ghostly Gravity Garden
imports ()
files ('head', 'point', 'stage')
unused_keys ()
unknown_keys ('categories',)
categories ['gravity', 'particles', 'interactive']
filepath_exists True
path ghostly-gravity-garden.js
filepath ghostly-gravity-garden.js
clean_files ('../point_src/core/head.js', '../point_src/pointpen.js', '../point_src/compass.js', '../point_src/center.js', '../point_src/point-content.js', '../point_src/pointdraw.js', '../point_src/relative-xy.js', '../point_src/pointcast.js', '../point_src/point.js', '../point_src/stage-hooks.js', '../point_src/stage-resize.js', '../point_src/functions/resolve.js', '../point_src/stage.js')
markdown {'html': '<p>Drag the glowing star to bend the paths of eighty orbiting points.\nDouble-click to scatter the garden.\nA little experiment from Ghostly for Jaybird.</p>', 'content': 'title: Ghostly Gravity Garden\ncategories: gravity\n particles\n interactive\nfiles:\n head\n point\n stage\n---\n\nDrag the glowing star to bend the paths of eighty orbiting points.\nDouble-click to scatter the garden.\nA little experiment from Ghostly for Jaybird.'}