Phoenix LiveView Gallery with Slideshow
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
/* to add to assets/css/app.css */ | |
.thumb-selected { | |
border: 4px solid #0069d9; | |
} | |
.thumb-unselected { | |
opacity: 0.5; | |
} |
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
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 |
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
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