Skip to content

Instantly share code, notes, and snippets.

@edom18
Created March 10, 2013 23:53
Show Gist options
  • Save edom18/5131066 to your computer and use it in GitHub Desktop.
Save edom18/5131066 to your computer and use it in GitHub Desktop.
Lightning Noise
#PerlinNoiseを使った稲妻表現
マウスをY軸の中央に近づけると雷が荒ぶるようにしてみました。
---
[akm2さん](http://jsdo.it/akm2)の[Lightning](http://jsdo.it/akm2/pQbM)を参考に、
ノイズで稲妻を作る部分だけを実装してみました。
ちなみに、上記のコードを[自分なりにコメントを付けて分析したもの](http://jsdo.it/edo_m18/zzcN)もあります。
* {
margin: 0;
padding: 0;
border: 0;
}
<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>
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