핫라인과 스위치로 램프 박스를 만들다.js
이 특별한 예는 새로운 Rails 프런트엔드 스택을 사용할 때의 주요 부분과 기술을 보여줍니다.Turbo를 사용하여 라이트박스 모드에 이미지를 지연 불러오고 자극할 것입니다
우리 시작합시다!먼저 ActiveStorage를 통해 여러 이미지가 연결된 에셋을 추가합니다.
$ bin/rails g scaffold Article title:string images:attachments
우리는 thumb
성명에서 has_many_attached
이라는 변수를 직접 정의했다.# app/models/article.rb
class Article < ApplicationRecord
has_many_attached :images do |attachable|
attachable.variant :thumb, resize_to_limit: [640, 480]
end
end
네 편의 문장을 추가한 후, 우리는 호출했다$ bin/setup
데이터베이스를 만들고 피드를 만듭니다.그 다음에, 우리는 test/fixtures/files
디렉터리를 만들고, 거기에 예시적인 그림을 배치한다.Rails 콘솔에서는 기사마다 2개의 이미지만 추가할 수 있습니다.Article.find_each.with_index do |article, article_index|
(1..2).each do |file_index|
index = article_index * 2 + file_index
article.images.attach(io: File.open(Rails.root.join("test/fixtures/files/#{index}.jpeg")), filename: "#{index}.jpeg")
end
end
글과 이미지 축소판을 격자에 표시합니다.<!-- app/views/articles/index.html.erb -->
<h1>Articles</h1>
<div id="articles" class="grid grid-cols-2 gap-4">
<% @articles.each do |article| %>
<%= render article %>
<% end %>
</div>
<!-- app/views/articles/_article.html.erb -->
<div class="bg-white overflow-hidden shadow rounded-lg" id="<%= dom_id article %>">
<div class="bg-white px-4 py-5 border-b border-gray-200 sm:px-6">
<h3 class="text-lg leading-6 font-medium text-gray-900 m-0"><%= article.title %></h3>
</div>
<ul class="list-none grid grid-cols-2 gap-x-4 gap-y-8 px-4">
<% article.images.each do |image| %>
<li class="relative">
<div class="group block w-full h-32 rounded-lg bg-gray-100 focus-within:ring-2 focus-within:ring-offset-2 focus-within:ring-offset-gray-100 focus-within:ring-indigo-500 overflow-hidden">
<%= image_tag image.variant(:thumb), class: "object-cover h-full w-full group-hover:opacity-75" %>
</div>
</li>
<% end %>
</ul>
</div>
이것이 바로 그것이 보이는 모습이다.모형을 세우다
다음 단계에서 우리는 모드 표기와 논리를 실현할 것이다.HTML 템플릿은 기본적으로 모드 배경, 닫기 버튼 및 컨텐츠 영역으로 구성되어 있습니다.
<!-- app/views/attachments/_modal.html.erb -->
<div class="hidden fixed z-30 inset-0 overflow-y-auto" data-lightbox-target="modal">
<div class="flex items-center justify-center h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
<%# Background %>
<div class="opacity-0 fixed inset-0 transition-opacity" data-lightbox-target="background">
<div class="absolute inset-0 bg-gray-700 bg-opacity-75">
<%# top left slide labels %>
<div class="sm:block absolute top-0 left-0 pt-4 pl-4">
<span class="text-white font-medium"><!-- will hold the slide name --></span>
</div>
<%# X-close icon in top-right corner %>
<div class="sm:block absolute top-0 right-0 pt-4 pr-4">
<%= link_to "#", class: "text-gray-100" do %>
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path></svg>
<% end %>
</div>
</div>
</div>
<%# Trick the browser into centering modal contents %>
<span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">​</span>
<div class="relative inline-block align-bottom rounded-lg text-left overflow-hidden transition-all sm:my-8 sm:align-middle sm:w-3/4 inset-0">
<!-- content will go here -->
</div>
</div>
</div>
기사 색인 보기에서는 다음을 보여 줍니다. <!-- app/views/artices/index.html.erb -->
<h1>Articles</h1>
+ <%= render "attachments/modal" %>
<div id="articles" class="grid grid-cols-2 gap-4">
<% @articles.each do |article| %>
<%= render article %>
<% end %>
</div>
이제 더 많은 토론을 하기 전에, 가장 기본적인 모드 기능인 열기와 닫기, 정상적으로 작동할 수 있도록 확보합시다.이를 위해, 우리는 자극 컨트롤러의 메인 디렉터리에 lightbox_controller
을 만들었다.위 태그에서 찾을 수 있는 modal
과 background
목표에 추가하고 handleOpen
과 handleClose
작업을 정의합니다. 이 두 작업은 본질적으로 CSS 클래스를 전환하여 제어 모드의 가시성을 제어합니다.// app/javascript/controllers/lightbox_controller.js
import { Controller } from "stimulus";
export default class extends Controller {
static targets = ["modal", "background"];
handleOpen(event) {
event.preventDefault();
this.modalTarget.classList.remove("hidden");
this.backgroundTarget.classList.remove("opacity-0");
this.backgroundTarget.classList.add("opacity-100");
}
handleClose(event) {
event.preventDefault();
this.modalTarget.classList.add("hidden");
this.backgroundTarget.classList.remove("opacity-100");
this.backgroundTarget.classList.add("opacity-0");
}
}
이것은 응용 프로그램 레이아웃의 <body>
요소에 추가되므로 모든 뷰에서 램프를 정의할 수 있습니다.<!-- app/views/layouts/application.html.erb -->
<!DOCTYPE html>
<html>
<head>
<title>HotwireExampleTemplate</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<script src="https://cdn.tailwindcss.com"></script>
<%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
<%= javascript_importmap_tags %>
</head>
- <body class="font-sans">
+ <body class="font-sans" data-controller="lightbox">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 font">
<div class="max-w-3xl mx-auto">
<%= yield %>
</div>
</div>
</body>
</html>
모드를 열려면 이미지를 클릭할 때 handleOpen
작업을 호출합니다. <!-- app/views/articles/_article.html.erb -->
<div class="bg-white overflow-hidden shadow rounded-lg" id="<%= dom_id article %>">
<div class="bg-white px-4 py-5 border-b border-gray-200 sm:px-6">
<h3 class="text-lg leading-6 font-medium text-gray-900 m-0"><%= article.title %></h3>
</div>
<ul class="list-none grid grid-cols-2 gap-x-4 gap-y-8 px-4">
<% article.images.each do |image| %>
<li class="relative">
<div class="group block w-full h-32 rounded-lg bg-gray-100 focus-within:ring-2 focus-within:ring-offset-2 focus-within:ring-offset-gray-100 focus-within:ring-indigo-500 overflow-hidden">
- <%= image_tag image, class: "object-cover h-full w-full group-hover:opacity-75" %>
+ <%= image_tag image, class: "object-cover h-full w-full group-hover:opacity-75", data: {action: "click->lightbox#handleOpen"} %>
</div>
</li>
<% end %>
</ul>
</div>
그런 다음 오른쪽 위에 있는 닫기 버튼을 클릭하여 닫습니다. <!-- app/views/attachments/_modal.html.erb -->
<div class="hidden fixed z-30 inset-0 overflow-y-auto" data-lightbox-target="modal">
<div class="flex items-center justify-center h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
<%# Background %>
<div class="opacity-0 fixed inset-0 transition-opacity" data-lightbox-target="background">
<div class="absolute inset-0 bg-gray-700 bg-opacity-75">
<%# top left slide labels %>
<div class="sm:block absolute top-0 left-0 pt-4 pl-4">
<span class="text-white font-medium"><!-- will hold the slide name --></span>
</div>
<%# X-close icon in top-right corner %>
<div class="sm:block absolute top-0 right-0 pt-4 pr-4">
- <%= link_to "#", class: "text-gray-100" do %>
+ <%= link_to "#", class: "text-gray-100", data: {action: "click->lightbox#handleClose"} do %>
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path></svg>
<% end %>
</div>
</div>
</div>
<%# Trick the browser into centering modal contents %>
<span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">​</span>
<div class="inline-block align-bottom rounded-lg text-left overflow-hidden transition-all sm:my-8 sm:align-middle sm:w-3/4 inset-0">
<!-- content will go here -->
</div>
</div>
</div>
터보 프레임을 통해 램프 컨텐트 로드
다음은 램프의 이미지를 표시하기 위해 지연된 터보 프레임을 사용하는 방법을 탐색할 것입니다.먼저
AttachmentsController
을 생성하고 라우트를 정의합니다.$ bin/rails g controller Attachments index
# config/routes.rb
Rails.application.routes.draw do
resources :articles do
+ resources :attachments, only: :index
end
end
그림이 문장에 첨부되어 있기 때문에, 우리는 컨트롤러 params
에서 조회를 진행하였다.성능상의 이유로 layout false
을 설정하였습니다. 프런트엔드에서 스왑할 단일 터보 프레임을 렌더링할 때 전체 <head>
등을 렌더링할 필요가 없습니다.# app/controllers/attachments_controller.rb
class AttachmentsController < ApplicationController
layout false
before_action :set_article, only: :index
def index
end
private
def set_article
@article = Article.find(params[:article_id])
end
end
우리는 <turbo_frame>
을 보여 주었는데, 초보적인 테스트를 위해 <img>
라벨을 표시하기만 하면 된다.<!-- app/views/attachments/index.html.erb -->
<%= turbo_frame_tag :attachment_gallery do %>
<% record.images.each do |image| %>
<%= image_tag image, class: "object-contain rounded-xl px-6 h-full mx-auto max-h-screen" %>
<% end %>
<% end %>
현재 모드에서 우리는 내용 영역에 빈 터보 프레임 표시를 추가하고 우리의 자극 frame
에 새로운 목표를 정의한다(lightbox_controller
). <!-- app/views/attachments/_modal.html.erb -->
<div class="hidden fixed z-30 inset-0 overflow-y-auto" data-lightbox-target="modal">
<div class="flex items-center justify-center h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
<%# Background %>
<div class="opacity-0 fixed inset-0 transition-opacity" data-lightbox-target="background">
<div class="absolute inset-0 bg-gray-700 bg-opacity-75">
<%# top left slide labels %>
<div class="sm:block absolute top-0 left-0 pt-4 pl-4">
<span class="text-white font-medium"><!-- will hold the slide name --></span>
</div>
<%# X-close icon in top-right corner %>
<div class="sm:block absolute top-0 right-0 pt-4 pr-4">
<%= link_to "#", class: "text-gray-100", data: {action: "click->lightbox#handleClose"} do %>
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path></svg>
<% end %>
</div>
</div>
</div>
<%# Trick the browser into centering modal contents %>
<span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">​</span>
<div class="inline-block align-bottom rounded-lg text-left overflow-hidden transition-all sm:my-8 sm:align-middle sm:w-3/4 inset-0">
- <!-- content will go here -->
+ <%= turbo_frame_tag :attachment_gallery, src: "", data: { "lightbox-target": "frame"} %>
</div>
</div>
</div>
이제 터보 프레임에 불러올 URL을 정의하는 동작 매개 변수를 이미지 탭에 추가할 수 있습니다.기억해라. data-lightbox-url-param
이 호출될 때 당신의 자극적인 동작에 의해 해석될 수 있다. 우리는 아래에서 볼 것이다. <!-- app/views/articles/_article.html.erb -->
<div class="bg-white overflow-hidden shadow rounded-lg" id="<%= dom_id article %>">
<div class="bg-white px-4 py-5 border-b border-gray-200 sm:px-6">
<h3 class="text-lg leading-6 font-medium text-gray-900 m-0"><%= article.title %></h3>
</div>
<ul class="list-none grid grid-cols-2 gap-x-4 gap-y-8 px-4">
<% article.images.each do |image| %>
<li class="relative">
<div class="group block w-full h-32 rounded-lg bg-gray-100 focus-within:ring-2 focus-within:ring-offset-2 focus-within:ring-offset-gray-100 focus-within:ring-indigo-500 overflow-hidden">
- <%= image_tag image, class: "object-cover h-full w-full group-hover:opacity-75", data: {action: "click->lightbox#handleOpen"} %>
+ <%= image_tag image.variant(:thumb),
+ class: "object-cover h-full w-full group-hover:opacity-75",
+ data: {
+ action: "click->lightbox#handleOpen",
+ lightbox_url_param: article_attachments_path(article)
+ } %>
</div>
</li>
<% end %>
</ul>
</div>
이를 붙이려면 frame
을 lightbox_controller
에 추가하고 event.params
작업을 호출할 때 handleOpen
에서 URL을 검색해야 합니다.남은 일은 터보 프레임의 src
을 교체하는 것입니다. 이 지연 로드 메커니즘은 남은 작업을 완성할 것입니다. // app/javascript/controllers/lightbox_controller.js
import { Controller } from "stimulus";
export default class extends Controller {
- static targets = ["modal", "background"];
+ static targets = ["modal", "background", "frame"];
handleOpen(event) {
event.preventDefault();
this.modalTarget.classList.remove("hidden");
this.backgroundTarget.classList.remove("opacity-0");
this.backgroundTarget.classList.add("opacity-100");
+ const { url } = event.params;
+ this.frameTarget.src = url;
}
handleClose(event) {
event.preventDefault();
this.modalTarget.classList.add("hidden");
this.backgroundTarget.classList.remove("opacity-100");
this.backgroundTarget.classList.add("opacity-0");
}
}
다음은 Turbo Frame 컨텐트와 선택한 기사의 차이점을 보여주는 중간 결과의 GIF입니다.주의: 조금만 노력하면 더욱 다태적일 수 있다(즉,
Article
과 귀속되지 않고 각종 부가항목과 귀속된다) - 이것은 독자에게 남겨진 연습이다:-)통합 Swiper.js
현재, 이 이미지 목록을 램프 박스로 바꾸기 위해서, 우리는 swiper.js을 사용할 것이다.그러면 importmap에 고정시킵니다.
$ bin/importmap pin swiper
또한 프레젠테이션을 위해 CDN에 swiper CSS를 추가했습니다.<!-- app/views/layouts/application.html.erb -->
<!DOCTYPE html>
<html>
<head>
<title>HotwireExampleTemplate</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
+ <link
+ rel="stylesheet"
+ href="https://unpkg.com/swiper@8/swiper-bundle.min.css"
+ />
<script src="https://cdn.tailwindcss.com"></script>
<%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
<%= javascript_importmap_tags %>
</head>
<body class="font-sans" data-controller="lightbox">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 font">
<div class="max-w-3xl mx-auto">
<%= yield %>
</div>
</div>
</body>
</html>
Swiper는 Navigation
과 같은 일부 기능을 모듈에서 제거하고 어플리케이션 엔트리 포인트에서 활성화합니다. // app/javascript/application.js
// Configure your import map in config/importmap.rb. Read more: https://github.com/rails/importmap-rails
import "tailwind.config";
import "@hotwired/turbo-rails";
import "controllers";
import "trix";
import "@rails/actiontext";
+ import Swiper, { Navigation } from "swiper";
+ Swiper.use([Navigation]);
자극 컨트롤러 포장 브러시는 상당히 간단하다.이것은 container
목표에서 swiper를 초기화하는 것일 뿐입니다. 우리는 이를 next
과 prev
목표를 내비게이션 링크로 설정합니다.// app/javascript/controllers/swiper_controller.js
import Swiper from "swiper";
import { Controller } from "@hotwired/stimulus";
export default class extends Controller {
static targets = ["container", "next", "prev"];
connect() {
this.swiper = new Swiper(this.containerTarget, {
navigation: {
nextEl: this.nextTarget,
prevEl: this.prevTarget,
},
});
}
}
지금 우리가 해야 할 일은 우리의 갤러리 표시를 swiper HTML layout에 부합하도록 재구성하는 것이다.이것은 많든 적든 우리가 swiper-wrapper
류로 모든 내용을 한div에 포장하고 swiper-slide
류로 각 슬라이드를 한div에 포장해야 한다는 것을 의미한다.또한 탐색 버튼에 태그를 추가했습니다.<!-- app/views/attachments/index.html.erb -->
<%= turbo_frame_tag :attachment_gallery do %>
- <% @article.images.each do |image| %>
- <%= image_tag image, class: "object-contain rounded-xl px-6 h-full mx-auto max-h-screen" %>
- <% end %>
+ <div data-controller="swiper">
+ <div class="swiper" data-swiper-target="container">
+ <div class="swiper-wrapper">
+ <% @article.images.each do |image| %>
+ <div class="swiper-slide flex justify-center"
+ <%= image_tag image, class: "object-contain rounded-xl h-96 mx-auto" %>
+ </div>
+ <% end %>
+ </div>
+
+ <div class="swiper-button-prev" data-swiper-target="prev">
+ </div>
+ <div class="swiper-button-next" data-swiper-target="next">
+ </div>
+ </div>
+ </div>
<% end %>
이것이 바로 그것의 진정한 의미이다.보기:올바른 슬라이드로 시작
작은 디테일이 완벽한 램프 체험에 해롭다.현재 어떤 그림을 클릭하든지 첫 번째 슬라이드가 표시됩니다.
우리는 무엇을 할 수 있습니까?이것이 바로 똑똑한 크로스 컨트롤러 통신이 시간을 절약할 수 있는 부분이다.Swiper는 슬라이드에서
slideTo
을 찾을 수 있는 방법이 있기 때문에 우리가 해야 할 일은swiper_controller
에게 전달swiper.slideTo
key
이 있으며 축소판에 다른 자극 동작 매개 변수로 추가할 수 있습니다. <!-- app/views/articles/_article.html.erb -->
<div class="bg-white overflow-hidden shadow rounded-lg" id="<%= dom_id article %>">
<div class="bg-white px-4 py-5 border-b border-gray-200 sm:px-6">
<h3 class="text-lg leading-6 font-medium text-gray-900 m-0"><%= article.title %></h3>
</div>
<ul class="list-none grid grid-cols-2 gap-x-4 gap-y-8 px-4">
<% article.images.each do |image| %>
<li class="relative">
<div class="group block w-full h-32 rounded-lg bg-gray-100 focus-within:ring-2 focus-within:ring-offset-2 focus-within:ring-offset-gray-100 focus-within:ring-indigo-500 overflow-hidden">
<%= image_tag image.variant(:thumb),
class: "object-cover h-full w-full group-hover:opacity-75",
data: {
action: "click->lightbox#handleOpen",
lightbox_url_param: article_attachments_path(article),
+ lightbox_key_param: image.key
} %>
</div>
</li>
<% end %>
</ul>
</div>
event.params
에서 이전에 URL에 대해 설명한 것처럼 키를 캡처할 수 있습니다.현재 우리가 해야 할 일은 loaded promise on a Turbo Frame element을 기다리는 것이다. 프레임의 현재 내비게이션 (이미지 슬라이드 로드) 이 완성되면 그것이 해결될 것이다.그런 다음 이벤트의 세부 객체에 dispatch an “open” event을 추가합니다. // app/javascript/controllers/lightbox_controller.js
import { Controller } from "stimulus";
export default class extends Controller {
static targets = ["modal", "background", "frame"];
- handleOpen(event) {
+ async handleOpen(event) {
event.preventDefault();
this.modalTarget.classList.remove("hidden");
this.backgroundTarget.classList.remove("opacity-0");
this.backgroundTarget.classList.add("opacity-100");
- const { url } = event.params;
+ const { url, key } = event.params;
this.frameTarget.src = url;
+ await this.frameTarget.loaded;
+
+ this.dispatch("open", { detail: { key } });
}
handleClose(event) {
event.preventDefault();
this.modalTarget.classList.add("hidden");
this.backgroundTarget.classList.remove("opacity-100");
this.backgroundTarget.classList.add("opacity-0");
}
}
갤러리 보기에서, 우리는 이 사건을 감청하고 (새) swiper#naviate
조작을 호출합니다.또한 Blob key
을 슬라이드마다 추가하여 다음을 선택할 수 있습니다.<!-- app/views/attachments/index.html.erb -->
<%= turbo_frame_tag :attachment_gallery do %>
- <div data-controller="swiper">
+ <div data-controller="swiper"
+ data-action="lightbox:open@document->swiper#navigate">
<div class="swiper" data-swiper-target="container">
<div class="swiper-wrapper">
<% @article.images.each do |image| %>
<div class="swiper-slide flex justify-center"
+ data-key="<%= image.key %>"
<%= image_tag image, class: "object-contain rounded-xl h-96 mx-auto" %>
</div>
<% end %>
</div>
<div class="swiper-button-prev" data-swiper-target="prev">
</div>
<div class="swiper-button-next" data-swiper-target="next">
</div>
</div>
</div>
<% end %>
swiper_controller
은 상기 동작 navigate
을 갖추고 있다.더 잘 평가하기 위해서, 우리는 이벤트 전달의 키로 설정하는 activeKey
목표를 추가했습니다.변경된 콜백(activeKeyValueChanged
)에서 위에서 정의한 데이터 속성을 사용하여 슬라이드에서 활성 키에 해당하는 정확한 인덱스를 찾습니다.그리고 slideTo
을 호출하고 애니메이션 시간은 0으로 즉시 설정합니다.만약 우리가 외부에서 활동의 관건을 설정하고 싶다면 자극값의 사용은 깔끔한 확장점을 제공할 것이다. // app/javascript/controllers/swiper_controller.js
import Swiper from "swiper";
import { Controller } from "@hotwired/stimulus";
export default class extends Controller {
static targets = ["container", "next", "prev"];
+ static values = { activeKey: String };
connect() {
this.swiper = new Swiper(this.containerTarget, {
navigation: {
nextEl: this.nextTarget,
prevEl: this.prevTarget,
},
});
}
+
+ navigate(event) {
+ event.preventDefault();
+
+ const { key } = event.detail;
+
+ this.activeKeyValue = key;
+ }
+
+ activeKeyValueChanged() {
+ const activeSlide = this.swiper?.slides.findIndex(
+ (slide) => slide.dataset.key == this.activeKeyValue
+ );
+
+ this.swiper?.slideTo(activeSlide, 0);
+ }
}
현재 모든 것이 광고와 같다.이점: 슬라이드 이름 설정
나는 너희들과 마지막 좋은 소식을 나누고 싶다.상기와 같은 메커니즘을 사용하면 우리는 상반된 방식으로 이벤트를 보내서
swiper_controller
에서 lightbox_controller
으로 보내서 모드 제목에 이벤트 슬라이드의 파일 이름을 표시할 것이다.이를 위해 Blob 키를 사용했던 것처럼 슬라이드의 데이터 세트에 파일 이름을 추가합니다. <!-- app/views/attachments/index.html.erb -->
<%= turbo_frame_tag :attachment_gallery do %>
<div data-controller="swiper"
data-action="lightbox:open@document->swiper#navigate">
<div class="swiper" data-swiper-target="container">
<div class="swiper-wrapper">
<% @article.images.each do |image| %>
<div class="swiper-slide flex justify-center"
data-key="<%= image.key %>"
+ data-filename="<%= image.blob.filename %>">
<%= image_tag image, class: "object-contain rounded-xl h-96 mx-auto" %>
</div>
<% end %>
</div>
<div class="swiper-button-prev" data-swiper-target="prev">
</div>
<div class="swiper-button-next" data-swiper-target="next">
</div>
</div>
</div>
<% end %>
Swiper는 slideChange
과 같은 몇 가지 리셋을 공개했는데, 우리는 이 리셋을 사용하여 데이터 집합에서 slide-change
이벤트를 보냈는데, 이는 이벤트 슬라이드의 이름을 포함한다. // app/javascript/controllers/swiper_controller.js
import Swiper from "swiper";
import { Controller } from "@hotwired/stimulus";
export default class extends Controller {
static targets = ["container", "next", "prev"];
static values = { activeKey: String };
connect() {
this.swiper = new Swiper(this.containerTarget, {
navigation: {
nextEl: this.nextTarget,
prevEl: this.prevTarget,
},
+ on: {
+ slideChange: this.handleSlideChange.bind(this),
+ },
});
}
navigate(event) {
event.preventDefault();
const { key } = event.detail;
this.activeKeyValue = key;
}
activeKeyValueChanged() {
const activeSlide = this.swiper?.slides.findIndex(
(slide) => slide.dataset.key == this.activeKeyValue
);
this.swiper?.slideTo(activeSlide, 0);
}
+ handleSlideChange(swiper) {
+ this.dispatch("slide-change", {
+ detail: { slideName: swiper.slides[swiper.activeIndex].dataset.filename },
+ });
+ }
}
lightbox_controller
에서 우리는 새로운 slideName
목표를 추가했고 우리는 새로운 조작 setSlideName
에서 이 사건에서 이 목표를 채웠다. // app/javascript/controllers/lightbox_controller.js
import { Controller } from "stimulus";
export default class extends Controller {
- static targets = ["modal", "background", "frame"];
+ static targets = ["modal", "background", "frame", "slideName"];
async handleOpen(event) {
event.preventDefault();
this.modalTarget.classList.remove("hidden");
this.backgroundTarget.classList.remove("opacity-0");
this.backgroundTarget.classList.add("opacity-100");
const { url, key } = event.params;
this.frameTarget.src = url;
await this.frameTarget.loaded;
this.dispatch("open", { detail: { key } });
}
handleClose(event) {
event.preventDefault();
this.modalTarget.classList.add("hidden");
this.backgroundTarget.classList.remove("opacity-100");
this.backgroundTarget.classList.add("opacity-0");
}
+ setSlideName({ detail }) {
+ this.slideNameTarget.textContent = detail.slideName;
+ }
}
마지막으로 누락된 부분은 태그에 이벤트 탐지기를 선언하고 slideName
대상을 정의하는 것입니다. <!-- app/views/attachments/_modal.html.erb -->
- <div class="hidden fixed z-30 inset-0 overflow-y-auto" data-lightbox-target="modal">
+ <div class="hidden fixed z-30 inset-0 overflow-y-auto" data-lightbox-target="modal" data-action="swiper:slide-change->lightbox#setSlideName">
<div class="flex items-center justify-center h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
<%# Background %>
<div class="opacity-0 fixed inset-0 transition-opacity" data-lightbox-target="background">
<div class="absolute inset-0 bg-gray-700 bg-opacity-75">
<%# top left slide labels %>
<div class="sm:block absolute top-0 left-0 pt-4 pl-4">
- <span class="text-white font-medium"><!-- will hold the slide name --></span>
+ <span class="text-white font-medium" data-lightbox-target="slideName"></span>
</div>
<%# X-close icon in top-right corner %>
<div class="sm:block absolute top-0 right-0 pt-4 pr-4">
<%= link_to "#", class: "text-gray-100", data: {action: "click->lightbox#handleClose"} do %>
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path></svg>
<% end %>
</div>
</div>
</div>
<%# Trick the browser into centering modal contents %>
<span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">​</span>
<div class="inline-block align-bottom rounded-lg text-left overflow-hidden transition-all sm:my-8 sm:align-middle sm:w-3/4 inset-0">
<%= turbo_frame_tag :attachment_gallery, src: "", data: { "lightbox-target": "frame"} %>
</div>
</div>
</div>
Tada, 이것은 우리의 모드입니다. 제목에 파일 이름을 표시합니다!🎉Reference
이 문제에 관하여(핫라인과 스위치로 램프 박스를 만들다.js), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/julianrubisch/building-a-lightbox-with-hotwire-and-swiperjs-20ig텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)