Phoenix LiveView Gallery with Slideshow
defmodule Gallery do | |
@unsplash_url "https://images.unsplash.com" | |
@ids [ | |
"photo-1562971179-4ad6903a7ed6", | |
"photo-1552673597-e3cd6747a996", | |
"photo-1561133036-61a7ed56b424", | |
"photo-1530717449302-271006cdc1bf" | |
] | |
def thumb_url(id), do: image_url(id, %{w: 100, h: 100, fit: "crop"}) | |
def large_url(id), do: image_url(id, %{h: 500, fit: "crop"}) | |
def image_ids(), do: @ids | |
def first_id(ids \\ @ids) do | |
List.first(ids) | |
end | |
def prev_image_id(ids\\@ids, id) do | |
Enum.at(ids, prev_index(ids, id)) | |
end | |
def prev_index(ids, id) do | |
ids | |
|> Enum.find_index(& &1 == id) | |
|> Kernel.-(1) | |
end | |
def next_image_id(ids\\@ids, id) do | |
Enum.at(ids, next_index(ids, id), first_id(ids)) | |
end | |
def next_index(ids, id) do | |
ids | |
|> Enum.find_index(& &1 == id) | |
|> Kernel.+(1) | |
end | |
def image_url(image_id, params) do | |
URI.parse(@unsplash_url) | |
|> URI.merge(image_id) | |
|> Map.put(:query, URI.encode_query(params)) | |
|> URI.to_string() | |
end | |
end |
defmodule GalleryWeb.GalleryLive do | |
use Phoenix.LiveView | |
def mount(_params, _session, socket) do | |
socket = | |
socket | |
|> assign(:current_id, Gallery.first_id()) | |
|> assign(:slideshow, :stopped) | |
{:ok, socket} | |
end | |
def render(assigns) do | |
~L""" | |
<center> | |
<%= for id <- Gallery.image_ids() do %> | |
<img src="<%= Gallery.thumb_url(id) %>" | |
class="<%= thumb_css_class(id, @current_id) %>"> | |
<% end %> | |
</center> | |
<center> | |
<button phx-click="prev">Prev</button> | |
<button phx-click="next">Next</button> | |
<%= if @slideshow == :stopped do %> | |
<button phx-click="play_slideshow">Play</button> | |
<% else %> | |
<button phx-click="stop_slideshow">Stop</button> | |
<% end %> | |
</center> | |
<img src="<%= Gallery.large_url(@current_id) %>"> | |
""" | |
end | |
def handle_event("play_slideshow", _, socket) do | |
{:ok, ref} = :timer.send_interval(1_000, self(), :slideshow_next) | |
{:noreply, assign(socket, :slideshow, ref)} | |
end | |
def handle_event("stop_slideshow", _, socket) do | |
:timer.cancel(socket.assigns.slideshow) | |
{:noreply, assign(socket, :slideshow, :stopped)} | |
end | |
def handle_info(:slideshow_next, socket) do | |
{:noreply, assign_next_id(socket)} | |
end | |
def handle_event("prev", _, socket) do | |
{:noreply, assign_prev_id(socket)} | |
end | |
def handle_event("next", _, socket) do | |
{:noreply, assign_next_id(socket)} | |
end | |
def assign_prev_id(socket) do | |
assign(socket, :current_id, | |
Gallery.prev_image_id(socket.assigns.current_id)) | |
end | |
def assign_next_id(socket) do | |
assign(socket, :current_id, | |
Gallery.next_image_id(socket.assigns.current_id)) | |
end | |
def thumb_css_class(thumb_id, current_id) do | |
if thumb_id == current_id do | |
"thumb-selected" | |
else | |
"thumb-unselected" | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment