get the typing back, the rainbows are here, the only thing missing is fractals, lets go mandeltrot set over julia set this time
Bobby Grayson 2 weeks ago 1 files (+119, -10)
Changed files
MODIFIED
lib/blog_web/live/rainbow_live.ex
MODIFIED
lib/blog_web/live/rainbow_live.ex
@@ -22,6 +22,10 @@ @viewport_height 400@logo_width 100@logo_height 50+ # Add these module attributes+ @particle_count 12 # Number of particles per explosion+ @particle_lifetime 80 # How long particles live+def mount(_params, _session, socket) doif connected?(socket) doProcess.send_after(self(), :animate, @frame_interval)@@ -30,9 +34,11 @@{:ok,assign(socket,rainbows: [], # List of rainbow states- dvd_pos: %{ # Add DVD position state- x: Enum.random(-300..300), # Use integers instead of float division- y: Enum.random(-200..200), # Match the SVG viewBox dimensions+ letters: [], # Add letters state back+ particles: [], # Add particles state+ dvd_pos: %{+ x: Enum.random(-300..300),+ y: Enum.random(-200..200),dx: @dvd_speed,dy: @dvd_speed,hue: 0@@ -49,15 +55,53 @@ )}enddef handle_event("keydown", %{"key" => key}, socket) when byte_size(key) == 1 do- # Create a new rainbow with random position+ # Create position for all animations+ pos_x = Enum.random(-100..100)+ pos_y = Enum.random(-50..50)++ # Create a new rainbownew_rainbow = %{id: System.unique_integer([:positive]),frame: 0,- x: Enum.random(-100..100), # Random x position- y: Enum.random(-50..50) # Random y position+ x: pos_x,+ y: pos_y+ }++ # Create particles for spiral explosion+ new_particles = for i <- 1..@particle_count do+ angle = i * (2 * :math.pi / @particle_count)+ %{+ id: System.unique_integer([:positive]),+ frame: 0,+ x: pos_x,+ y: pos_y,+ dx: :math.cos(angle) * 3,+ dy: :math.sin(angle) * 3,+ hue: Enum.random(0..360),+ size: Enum.random(5..15),+ rotation: angle * 180 / :math.pi+ }+ end++ # Create a new letter with enhanced animation+ new_letter = %{+ id: System.unique_integer([:positive]),+ char: key,+ frame: 0,+ x: pos_x,+ y: pos_y,+ size: 200, # Bigger initial size+ rotation_speed: Enum.random(-5..5),+ rotation: 0,+ scale: 0.1 # Start small and grow}- {:noreply, assign(socket, rainbows: [new_rainbow | socket.assigns.rainbows])}+ {:noreply,+ assign(socket,+ rainbows: [new_rainbow | socket.assigns.rainbows],+ letters: [new_letter | socket.assigns.letters],+ particles: new_particles ++ (socket.assigns[:particles] || [])+ )}enddef handle_event("keydown", _key, socket), do: {:noreply, socket}@@ -65,10 +109,10 @@def handle_info(:animate, socket) doProcess.send_after(self(), :animate, @frame_interval)- # Update DVD position and handle bouncing+ # Update DVD positiondvd_pos = update_dvd_position(socket.assigns.dvd_pos)- # Update rainbows (keep existing rainbow update logic)+ # Update rainbowsupdated_rainbows = socket.assigns.rainbows|> Enum.map(fn rainbow ->%{rainbow | frame: rainbow.frame + 1}@@ -77,8 +121,38 @@ |> Enum.reject(fn rainbow ->rainbow.frame >= @animation_stepsend)+ # Update letters with growth and rotation+ updated_letters = socket.assigns.letters+ |> Enum.map(fn letter ->+ new_scale = min(1.0, letter.scale + 0.05) # Grow to full size+ %{letter |+ frame: letter.frame + 1,+ rotation: letter.rotation + letter.rotation_speed,+ scale: new_scale+ }+ end)+ |> Enum.reject(fn letter ->+ letter.frame >= @animation_steps+ end)++ # Update particles+ updated_particles = socket.assigns.particles+ |> Enum.map(fn particle ->+ %{particle |+ frame: particle.frame + 1,+ x: particle.x + particle.dx,+ y: particle.y + particle.dy,+ rotation: particle.rotation + 5+ }+ end)+ |> Enum.reject(fn particle ->+ particle.frame >= @particle_lifetime+ end)+{:noreply, assign(socket,rainbows: updated_rainbows,+ letters: updated_letters,+ particles: updated_particles,dvd_pos: dvd_pos)}end@@ -167,7 +241,18 @@ font-size="20">DVD</text></g>- <%!-- Keep existing rainbow rendering --%>+ <%!-- Particles --%>+ <%= for particle <- @particles do %>+ <g transform={"translate(#{particle.x}, #{particle.y}) rotate(#{particle.rotation})"}>+ <path+ d="M0,-#{particle.size} L#{particle.size/2},#{particle.size} L-#{particle.size/2},#{particle.size} Z"+ fill={"hsl(#{particle.hue}, 100%, 70%)"}+ opacity={calculate_particle_opacity(particle.frame)}+ />+ </g>+ <% end %>++ <%!-- Rainbows --%><%= for rainbow <- @rainbows do %><g transform={"translate(#{rainbow.x}, #{rainbow.y})"}><%= for arc <- calculate_arcs(rainbow.frame) do %>@@ -180,8 +265,32 @@ /><% end %></g><% end %>++ <%!-- Letters --%>+ <%= for letter <- @letters do %>+ <text+ x={letter.x}+ y={letter.y}+ font-size={letter.size}+ fill="white"+ text-anchor="middle"+ dominant-baseline="middle"+ opacity={calculate_letter_opacity(letter.frame)}+ transform={"rotate(#{letter.rotation}, #{letter.x}, #{letter.y}) scale(#{letter.scale})"}+ >+ <%= letter.char %>+ </text>+ <% end %></svg></div>"""+ end++ defp calculate_letter_opacity(frame) do+ 1 - (frame / @animation_steps)+ end++ defp calculate_particle_opacity(frame) do+ 1 - (frame / @particle_lifetime)endend