Last active
September 5, 2016 19:25
-
-
Save ggb/2b3f831a41af4288cb39440fbc8a793e to your computer and use it in GitHub Desktop.
Inspired by http://codepen.io/zahratee/pen/JKmQQZ
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
module Particle exposing (..) | |
import Array | |
import Task | |
import Html.App as App | |
import Window exposing (Size, resizes) | |
import Color exposing (Color, black, white, rgba) | |
import Element exposing (Element, toHtml) | |
import Collage exposing (Form, collage, move, rect, filled, circle) | |
import AnimationFrame exposing (times) | |
import Mouse exposing (Position, moves) | |
import Time exposing (Time) | |
import Random exposing (Generator, generate, list, float) | |
import Basics.Extra exposing (never) | |
type Msg | |
= Move Position | |
| Frame Time | |
| Resize Size | |
| Add (List Float) | |
type alias Particle = | |
{ x: Float | |
, y: Float | |
, dx: Float | |
, dy: Float | |
, color: Color | |
, radius: Float | |
} | |
type alias ParticleField = | |
{ particles: List Particle | |
, size: Size | |
, lastPosition: Position | |
} | |
initField : ParticleField | |
initField = | |
{ particles = [] | |
, size = {width=600, height=600} | |
, lastPosition = {x=0, y=0} | |
} | |
floatList : Generator (List Float) | |
floatList = | |
list 5 (float 0 1) | |
subscriptions : ParticleField -> Sub Msg | |
subscriptions model = | |
Sub.batch | |
[ moves Move | |
, times Frame | |
, resizes Resize | |
] | |
drawParticle : Particle -> Form | |
drawParticle particle = | |
move | |
(particle.x, particle.y) | |
(filled particle.color (circle particle.radius)) | |
draw : ParticleField -> Element | |
draw {particles, size} = | |
particles | |
|> List.map drawParticle | |
-- |> (::) (filled white (rect (toFloat size.width) (toFloat size.height))) | |
|> collage size.width size.height | |
split : Int -> List a -> List (List a) | |
split = | |
let | |
split' acc num origin = | |
if List.length origin == 0 then | |
acc | |
else | |
split' (List.take num origin :: acc) num (List.drop num origin) | |
in | |
split' [] | |
randomColor : Float -> Float -> Color | |
randomColor m n = | |
let | |
m' = m * 205 |> round | |
n' = n * 205 |> round | |
in | |
if (m' + n') % 2 == 0 then | |
rgba (50 + m') (50 + n') 0 (0.25 + ((m + n) / 8)) | |
else | |
rgba 0 (50 + m') (50 + n') (0.25 + ((m + n) / 8)) | |
createParticle : Position -> Size -> List Float -> Particle | |
createParticle {x,y} {width, height} l = | |
let | |
arr = Array.fromList l | |
sget i = Array.get i arr |> Maybe.withDefault 0 | |
in | |
{ x = (toFloat x) - (toFloat width / 2) | |
, y = (toFloat y) * (-1) + (toFloat height / 2) | |
, dx = -1.5 + (sget 0) * 3 | |
, dy = 1 + (sget 1 + (1 - sget 4)) * 3 | |
, color = randomColor (sget 2) (sget 3) | |
, radius = 1 + (sget 4) * 21 | |
} | |
addParticles : List Float -> ParticleField -> ParticleField | |
addParticles numbers field = | |
let | |
newParticles = | |
numbers | |
|> split 5 | |
|> List.map (createParticle field.lastPosition field.size) | |
in | |
{field | particles = newParticles ++ field.particles |> List.take 200 } | |
updatePositions : ParticleField -> ParticleField | |
updatePositions field = | |
{ field | particles | |
= field.particles | |
|> List.map (\p -> {p | x = p.x - p.dx, y = p.y - p.dy}) | |
} | |
update : Msg -> ParticleField -> (ParticleField, Cmd Msg) | |
update msg field = | |
case msg of | |
Move newPosition -> | |
({field | lastPosition = newPosition}, generate Add floatList) | |
Frame t -> | |
updatePositions field ! [] | |
Resize newSize -> | |
{field | size = newSize} ! [] | |
Add numbers -> | |
addParticles numbers field ! [] | |
main : Program Never | |
main = | |
App.program | |
{ init = (initField, Task.perform never Resize Window.size) | |
, view = draw >> toHtml | |
, update = update | |
, subscriptions = subscriptions | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment