Skip to content

Instantly share code, notes, and snippets.

@Strikeskids
Last active August 29, 2015 14:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Strikeskids/9f640af465ebd49b0b61 to your computer and use it in GitHub Desktop.
Save Strikeskids/9f640af465ebd49b0b61 to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
<script src="http://cdnjs.cloudflare.com/ajax/libs/mathjs/1.2.0/math.js"></script>
<style id="jsbin-css">
#source {
display: none;
}
</style>
</head>
<body>
<canvas id="main" width="1000" height="500"></canvas>
<svg id="source">
<path id="sourcePath" d="m91.5,72c89,-22 219,-82 295,-22c76,60 154,122 77,120c-77,-2 -63,-96 -116,-67c-53,29 -31,85 -23,100c8,15 98,2 122,2c24,0 119,9 119,21c0,12 -60,24 -108,30c-48,6 -143,5 -143.5,5c0.5,0 90.5,8 119.5,19c29,11 124,18 117,46c-7,28 -108,11 -133,9c-25,-2 -109,-7 -109.5,-7c0.5,0 68.5,27 68,27c0.5,0 -188.5,6 -189,6c0.5,0 -19.5,-198 -20,-198c0.5,0 -164.5,-69 -75.5,-91z"/>
</svg>
<script id="jsbin-javascript">
var ctx, source;
var pi2 = 2 * Math.PI
var currentFrame;
var Circle = function me_Circle(radius, angle, rate) {
this.radius = radius
this.angle = angle
this.rate = rate
}
Circle.prototype.update = function(delta) {
this.angle += delta * pi2 * this.rate / 1000
this.angle %= pi2
}
Circle.prototype.main = function(x, y) {
return {
x: x + Math.cos(this.angle) * this.radius,
y: y + Math.sin(this.angle) * this.radius
}
}
var circles = [
]
var points = []
var sourcePoints = []
function rev(n, bits) {
var reved=0,i=0;
for(;i<bits;++i) {
reved=(reved<<1)|(n>>i)&1;
}
return reved;
}
function bitCount(points) {
var bits;
for(bits=0,i=1;i<=points;i<<=1,++bits) {}
return bits
}
var center;
window.addEventListener('load', function() {
ctx = document.getElementById('main').getContext('2d')
source = document.getElementById('sourcePath')
var points = 256, i, bits = bitCount(points)-1, inc = source.getTotalLength()/(points-1)
for (i=0;i<points;++i) {
sourcePoints.push(source.getPointAtLength(i*inc))
}
var sourceData, trig, lower, upper, lowerIndex, upperIndex, bit, level
sourceData = sourcePoints.map(function(point) {
return math.complex({re: point.x, im: point.y})
})
sourceData = sourceData.map(function(point, i) {
return sourceData[rev(i, bits)]
})
for (bit=0;bit<bits;++bit) {
var outerSize = (1<<bit), innerSize = (1<<(bits-bit-1))
for (level=0;level<outerSize;++level) {
trig = math.complex({r: 1, phi: Math.PI * level / outerSize})
for (i=0;i<innerSize;++i) {
lowerIndex = i*2*outerSize + level
upperIndex = lowerIndex + outerSize
lower = sourceData[lowerIndex]
upper = math.multiply(sourceData[upperIndex], trig)
sourceData[lowerIndex] = math.add(lower, upper)
sourceData[upperIndex] = math.subtract(lower, upper)
}
}
}
center = {
x: sourceData[0].re/points,
y: sourceData[0].im/points
}
for (i=1;i<points;++i) {
var num = sourceData[i].toPolar()
circles.push(new Circle(num.r/points, num.phi, (((i+points/2)%points)-points/2)/20))
}
circles.sort(function (a, b) {
if (a.radius > b.radius) {
return -1
} else if (b.radius > a.radius){
return 1
} else {
return 0
}
})
circles.splice(80)
// circles.reverse()
window.requestAnimationFrame(frame)
})
var frame = function me_frame(timestamp) {
var start, prev, progress, change, calls;
start = me_frame.start || timestamp
prev = me_frame.prev || timestamp
progress = timestamp - start
change = timestamp - prev
me_frame.prev = timestamp
var x, y
x = center.x
y = center.y
ctx.clearRect(0, 0, 1000, 500)
ctx.fillStyle = '#888'
ctx.strokeStyle = '#000'
circles.forEach(function(circle) {
circle.update(change)
ctx.beginPath()
ctx.arc(x, y, circle.radius, 0, pi2)
var newp = circle.main(x, y)
ctx.moveTo(x, y)
x = newp.x
y = newp.y
ctx.lineTo(x, y)
ctx.stroke()
})
// points.push({x: x, y: y})
ctx.strokeStyle = '#0f0'
ctx.beginPath()
ctx.moveTo(sourcePoints[0].x, sourcePoints[0].y)
sourcePoints.forEach(function(point) {
ctx.lineTo(point.x, point.y)
})
ctx.stroke()
ctx.strokeStyle = 'f00'
ctx.fillStyle = '#f00'
ctx.beginPath()
ctx.arc(x, y, 3, 0, pi2)
ctx.fill()
// ctx.moveTo(points[0].x, points[0].y)
// points.forEach(function(point) {
// ctx.lineTo(point.x, point.y)
// })
// ctx.stroke()
currentFrame = window.requestAnimationFrame(frame)
}
var stop = function() {
window.cancelAnimationFrame(currentFrame)
}
</script>
<script id="jsbin-source-css" type="text/css">#source {
display: none;
}</script>
<script id="jsbin-source-javascript" type="text/javascript">var ctx, source;
var pi2 = 2 * Math.PI
var currentFrame;
var Circle = function me_Circle(radius, angle, rate) {
this.radius = radius
this.angle = angle
this.rate = rate
}
Circle.prototype.update = function(delta) {
this.angle += delta * pi2 * this.rate / 1000
this.angle %= pi2
}
Circle.prototype.main = function(x, y) {
return {
x: x + Math.cos(this.angle) * this.radius,
y: y + Math.sin(this.angle) * this.radius
}
}
var circles = [
]
var points = []
var sourcePoints = []
function rev(n, bits) {
var reved=0,i=0;
for(;i<bits;++i) {
reved=(reved<<1)|(n>>i)&1;
}
return reved;
}
function bitCount(points) {
var bits;
for(bits=0,i=1;i<=points;i<<=1,++bits) {}
return bits
}
var center;
window.addEventListener('load', function() {
ctx = document.getElementById('main').getContext('2d')
source = document.getElementById('sourcePath')
var points = 256, i, bits = bitCount(points)-1, inc = source.getTotalLength()/(points-1)
for (i=0;i<points;++i) {
sourcePoints.push(source.getPointAtLength(i*inc))
}
var sourceData, trig, lower, upper, lowerIndex, upperIndex, bit, level
sourceData = sourcePoints.map(function(point) {
return math.complex({re: point.x, im: point.y})
})
sourceData = sourceData.map(function(point, i) {
return sourceData[rev(i, bits)]
})
for (bit=0;bit<bits;++bit) {
var outerSize = (1<<bit), innerSize = (1<<(bits-bit-1))
for (level=0;level<outerSize;++level) {
trig = math.complex({r: 1, phi: Math.PI * level / outerSize})
for (i=0;i<innerSize;++i) {
lowerIndex = i*2*outerSize + level
upperIndex = lowerIndex + outerSize
lower = sourceData[lowerIndex]
upper = math.multiply(sourceData[upperIndex], trig)
sourceData[lowerIndex] = math.add(lower, upper)
sourceData[upperIndex] = math.subtract(lower, upper)
}
}
}
center = {
x: sourceData[0].re/points,
y: sourceData[0].im/points
}
for (i=1;i<points;++i) {
var num = sourceData[i].toPolar()
circles.push(new Circle(num.r/points, num.phi, (((i+points/2)%points)-points/2)/20))
}
circles.sort(function (a, b) {
if (a.radius > b.radius) {
return -1
} else if (b.radius > a.radius){
return 1
} else {
return 0
}
})
circles.splice(80)
// circles.reverse()
window.requestAnimationFrame(frame)
})
var frame = function me_frame(timestamp) {
var start, prev, progress, change, calls;
start = me_frame.start || timestamp
prev = me_frame.prev || timestamp
progress = timestamp - start
change = timestamp - prev
me_frame.prev = timestamp
var x, y
x = center.x
y = center.y
ctx.clearRect(0, 0, 1000, 500)
ctx.fillStyle = '#888'
ctx.strokeStyle = '#000'
circles.forEach(function(circle) {
circle.update(change)
ctx.beginPath()
ctx.arc(x, y, circle.radius, 0, pi2)
var newp = circle.main(x, y)
ctx.moveTo(x, y)
x = newp.x
y = newp.y
ctx.lineTo(x, y)
ctx.stroke()
})
// points.push({x: x, y: y})
ctx.strokeStyle = '#0f0'
ctx.beginPath()
ctx.moveTo(sourcePoints[0].x, sourcePoints[0].y)
sourcePoints.forEach(function(point) {
ctx.lineTo(point.x, point.y)
})
ctx.stroke()
ctx.strokeStyle = 'f00'
ctx.fillStyle = '#f00'
ctx.beginPath()
ctx.arc(x, y, 3, 0, pi2)
ctx.fill()
// ctx.moveTo(points[0].x, points[0].y)
// points.forEach(function(point) {
// ctx.lineTo(point.x, point.y)
// })
// ctx.stroke()
currentFrame = window.requestAnimationFrame(frame)
}
var stop = function() {
window.cancelAnimationFrame(currentFrame)
}</script></body>
</html>
#source {
display: none;
}
var ctx, source;
var pi2 = 2 * Math.PI
var currentFrame;
var Circle = function me_Circle(radius, angle, rate) {
this.radius = radius
this.angle = angle
this.rate = rate
}
Circle.prototype.update = function(delta) {
this.angle += delta * pi2 * this.rate / 1000
this.angle %= pi2
}
Circle.prototype.main = function(x, y) {
return {
x: x + Math.cos(this.angle) * this.radius,
y: y + Math.sin(this.angle) * this.radius
}
}
var circles = [
]
var points = []
var sourcePoints = []
function rev(n, bits) {
var reved=0,i=0;
for(;i<bits;++i) {
reved=(reved<<1)|(n>>i)&1;
}
return reved;
}
function bitCount(points) {
var bits;
for(bits=0,i=1;i<=points;i<<=1,++bits) {}
return bits
}
var center;
window.addEventListener('load', function() {
ctx = document.getElementById('main').getContext('2d')
source = document.getElementById('sourcePath')
var points = 256, i, bits = bitCount(points)-1, inc = source.getTotalLength()/(points-1)
for (i=0;i<points;++i) {
sourcePoints.push(source.getPointAtLength(i*inc))
}
var sourceData, trig, lower, upper, lowerIndex, upperIndex, bit, level
sourceData = sourcePoints.map(function(point) {
return math.complex({re: point.x, im: point.y})
})
sourceData = sourceData.map(function(point, i) {
return sourceData[rev(i, bits)]
})
for (bit=0;bit<bits;++bit) {
var outerSize = (1<<bit), innerSize = (1<<(bits-bit-1))
for (level=0;level<outerSize;++level) {
trig = math.complex({r: 1, phi: Math.PI * level / outerSize})
for (i=0;i<innerSize;++i) {
lowerIndex = i*2*outerSize + level
upperIndex = lowerIndex + outerSize
lower = sourceData[lowerIndex]
upper = math.multiply(sourceData[upperIndex], trig)
sourceData[lowerIndex] = math.add(lower, upper)
sourceData[upperIndex] = math.subtract(lower, upper)
}
}
}
center = {
x: sourceData[0].re/points,
y: sourceData[0].im/points
}
for (i=1;i<points;++i) {
var num = sourceData[i].toPolar()
circles.push(new Circle(num.r/points, num.phi, (((i+points/2)%points)-points/2)/20))
}
circles.sort(function (a, b) {
if (a.radius > b.radius) {
return -1
} else if (b.radius > a.radius){
return 1
} else {
return 0
}
})
circles.splice(80)
// circles.reverse()
window.requestAnimationFrame(frame)
})
var frame = function me_frame(timestamp) {
var start, prev, progress, change, calls;
start = me_frame.start || timestamp
prev = me_frame.prev || timestamp
progress = timestamp - start
change = timestamp - prev
me_frame.prev = timestamp
var x, y
x = center.x
y = center.y
ctx.clearRect(0, 0, 1000, 500)
ctx.fillStyle = '#888'
ctx.strokeStyle = '#000'
circles.forEach(function(circle) {
circle.update(change)
ctx.beginPath()
ctx.arc(x, y, circle.radius, 0, pi2)
var newp = circle.main(x, y)
ctx.moveTo(x, y)
x = newp.x
y = newp.y
ctx.lineTo(x, y)
ctx.stroke()
})
// points.push({x: x, y: y})
ctx.strokeStyle = '#0f0'
ctx.beginPath()
ctx.moveTo(sourcePoints[0].x, sourcePoints[0].y)
sourcePoints.forEach(function(point) {
ctx.lineTo(point.x, point.y)
})
ctx.stroke()
ctx.strokeStyle = 'f00'
ctx.fillStyle = '#f00'
ctx.beginPath()
ctx.arc(x, y, 3, 0, pi2)
ctx.fill()
// ctx.moveTo(points[0].x, points[0].y)
// points.forEach(function(point) {
// ctx.lineTo(point.x, point.y)
// })
// ctx.stroke()
currentFrame = window.requestAnimationFrame(frame)
}
var stop = function() {
window.cancelAnimationFrame(currentFrame)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment