Created
March 10, 2013 23:53
-
-
Save edom18/5131066 to your computer and use it in GitHub Desktop.
Lightning Noise
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#PerlinNoiseを使った稲妻表現 | |
マウスをY軸の中央に近づけると雷が荒ぶるようにしてみました。 | |
--- | |
[akm2さん](http://jsdo.it/akm2)の[Lightning](http://jsdo.it/akm2/pQbM)を参考に、 | |
ノイズで稲妻を作る部分だけを実装してみました。 | |
ちなみに、上記のコードを[自分なりにコメントを付けて分析したもの](http://jsdo.it/edo_m18/zzcN)もあります。 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
* { | |
margin: 0; | |
padding: 0; | |
border: 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<canvas id="cv" width="300" height="300"></canvas> | |
<script src="https://raw.github.com/edom18/f.js/master/js/f.core.js"></script> | |
<script src="https://raw.github.com/edom18/f.js/master/js/f.math.js"></script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
do (win = window, doc = window.document, f = window.f, exports = window) -> | |
{ceil, abs, min, max, cos, sin, PI} = Math | |
{limit, Point, Xorshift, PerlinNoise} = f.math | |
requestAnimFrame = do -> | |
return window.requestAnimationFrame or | |
window.webkitRequestAnimationFrame or | |
window.mozRequestAnimationFrame or | |
window.oRequestAnimationFrame or | |
window.msRequestAnimationFrame or | |
( callback, element ) -> | |
window.setTimeout(callback, 1000 / 60) | |
# ------------------------- | |
class Lightning | |
constructor: (@cv, @startPoint = new Point(0, 0), @endPoint = new Point(300, 0)) -> | |
@ctx = @cv.getContext '2d' | |
@perlinNoise = new PerlinNoise | |
@perlinNoise.octaves 6 | |
@speed = 0.01 | |
@offset = 0 | |
@length = @startPoint.distance @endPoint | |
@setEvents() | |
do _loop = => | |
@update() | |
@draw(@ctx) | |
requestAnimFrame _loop, @cv | |
setEvents: -> | |
@cv.addEventListener 'mousemove', (e) => | |
half = @cv.height / 2 | |
dist = abs(e.pageY - half) | |
@speed = 1 - (dist / half) + 0.01 | |
, false | |
@cv.addEventListener 'mouseout', => | |
@speed = 0.01 | |
, false | |
setPoint: (@startPoint, @endPoint) -> | |
@length = @startPoint.distance @endPoint | |
update: -> | |
perlinNoise = @perlinNoise | |
baseY = @cv.height / 2 | |
length = @length | |
step = ceil(length / 7.5) | |
normal = @endPoint.subtract(@startPoint).normalize(length / step) | |
rad = normal.angle() | |
xCmp = sin rad | |
yCmp = cos rad | |
@offset += @speed | |
points = [] | |
for i in [0..step] | |
na = abs(length * (perlinNoise.noise (i / 90) - @offset)) * 0.5 | |
_ax = xCmp * na | |
_ay = yCmp * na | |
nb = abs(length * (perlinNoise.noise (i / 90) + @offset)) * 0.5 | |
_bx = xCmp * nb | |
_by = yCmp * nb | |
m = sin PI * (i / step) | |
x = @startPoint.x + normal.x * i + (_ax - _bx) * m | |
y = @startPoint.y + normal.y * i + (_ay - _by) * m | |
points.push new Point x, y | |
@points = points | |
draw: (ctx) -> | |
ctx.fillStyle = 'rgba(11, 86, 147, 0.7)' | |
ctx.fillRect 0, 0, @cv.width, @cv.height | |
ctx.save() | |
ctx.globalCompositeOperation = 'lighter' | |
ctx.fillStyle = 'rgba(0, 0, 0, 1)'; | |
ctx.shadowBlur = 25 | |
ctx.shadowColor = 'rgba(255, 255, 255, 0.95)' | |
points = @points | |
#draw arcs | |
len = points.length | |
ctx.beginPath() | |
for p, i in points | |
d = if len > 1 then p.distance(points[if i is len - 1 then i - 1 else i + 1]) else 0 | |
ctx.moveTo p.x + d, p.y | |
ctx.arc p.x, p.y, d / 2, 0, PI * 2, true | |
ctx.fill() | |
ctx.restore() | |
#draw lines | |
ctx.save() | |
ctx.shadowBlur = 0; | |
ctx.strokeStyle = 'rgba(255, 255, 255, 1)' | |
ctx.lineWidth = Math.random() * 1 + 1 | |
ctx.beginPath() | |
for p, i in points | |
ctx[if i is 0 then 'moveTo' else 'lineTo'] p.x, p.y | |
ctx.stroke() | |
ctx.restore() | |
exports.Lightning = Lightning | |
do (win = window, doc = window.document, f = window.f, exports = window) -> | |
{ceil, abs, min, max, cos, sin, PI} = Math | |
{Point, Xorshift, PerlinNoise} = f.math | |
$ = (selector) -> | |
doc.querySelector selector | |
$$ = (selector) -> | |
doc.querySelectorAll selector | |
cv = null | |
lightning = null | |
init = -> | |
cv = $('#cv') | |
cv.width = window.innerWidth | |
cv.height = window.innerHeight | |
hw = cv.width / 2 | |
hh = cv.height / 2 | |
sx = cv.width - ~~(cv.width * Math.random()) | |
sy = cv.height - ~~(cv.height * Math.random()) | |
ex = cv.width - ~~(cv.width * Math.random()) | |
ey = cv.height - ~~(cv.height * Math.random()) | |
lightning = new Lightning cv, new Point(sx, sy), new Point(ex, ey) | |
resize = -> | |
cv.width = window.innerWidth | |
cv.height = window.innerHeight | |
lightning.setPoint new Point(30, cv.height / 4), new Point(cv.width - 30, cv.height / 2) | |
doc.addEventListener 'DOMContentLoaded', init, false | |
win.addEventListener 'resize', resize, false |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment