Beim Erstellen der Portfolio-Site hatte ich eine Funktion zum Hochladen von Bildern, aber es gab ein Problem, bei dem es schwierig war zu verstehen, ob ein Bild richtig ausgewählt werden konnte, da es keine Vorschaufunktion gab.
Aus diesem Grund habe ich beschlossen, eine Bildvorschau-Funktion hinzuzufügen und diese zu implementieren.
Obwohl es einige Probleme gibt, habe ich es implementiert, daher möchte ich es zusammenfassen.
View
erb:app/views/posts/_form.html.erb
<%= form_with(model: post, local: true) do |form| %>
<!--···Kürzung···-->
<div class="form-file custom-file mb-3">
<% if post.image.present? %>
<div class="form-image-uploader__saved-img">
<span class="form-image-uploader__saved-img-inner">
<%= image_tag post.image.to_s %>
</span>
</div>
<div class="block-toggle">
<div class="block-toggle__press">
<div class="btn btn-outline-secondary">
<i class="fas fa-arrow-circle-down"></i>Bild ändern
</div>
</div>
<div class="block-toggle__content" style="display:none;">
<label for="post_image" class="form-image-uploader__preview">
<%= image_tag 'nophoto.jpg' %>
</label>
<%= form.file_field :image, class:'form-image-uploader__save' %>
<%= form.hidden_field :image_cache, class:'form-image-uploader__cache' %>
</div>
</div>
<% else %>
<label for="post_image" class="form-image-uploader__preview">
<%= image_tag 'nophoto.jpg' %>
</label>
<%= form.file_field :image, class:'form-image-uploader__save' %>
<%= form.hidden_field :image_cache, class:'form-image-uploader__cache' %>
<% end %>
</div>
<!--···Kürzung···-->
<% end %>
JS
Das this.noPhotoImgPath
der ImgUplorader
-Klasse legt einen beliebigen Pfad fest.
app/javascript/packs/application.js
/*Slide Toggle
------------------------------------------------------*/
$(document).on('turbolinks:load', () =>{
$('.block-toggle__press .btn').on('click', event =>{
$(event.currentTarget).parent('.block-toggle__press').next('.block-toggle__content').slideToggle(700);
});
});
/*Image uplorader
------------------------------------------------------*/
$(document).on('turbolinks:load', () =>{
const imgUplorader = new ImgUplorader;
imgUplorader.copyToSaveInput();
});
class ImgUplorader{
constructor(){
this.selectorPreview = '.form-image-uploader__preview';
this.selectorSave = '.form-image-uploader__save';
this.selectorCache = '.form-image-uploader__cache';
this.noPhotoImgPath = '/assets/nophoto.jpg';// <=Nophoto Legen Sie den Bildpfad fest
}
/*
* Change preview image to nophoto image when image is not selected
* @param input : Element of current target
*/
copyToSaveInput(){
$(document).on('change', this.selectorSave, event => {
const input = $(event.currentTarget);
const filesLength = input[0].files.length;
const cacheDefaultVal = $(input).next(this.selectorCache)[0].defaultValue;
// Change preview image to nophoto image when image is not selected
if (this.hasNotImg(filesLength)) {
this.changeNoPhotoImg(input);
return;
}
// Change preview image to selected image when image is selected
this.changeSelectedImg(input);
});
}
/*
* Return true when input doesn't have file
* @param filesLength : file length of input
* @return bool
*/
hasCacheDefaultImg(filesLength){
if(filesLength == 0){
return true;
}
return false;
}
/*
* Return true when input doesn't have file
* @param filesLength : file length of input
* @return bool
*/
hasNotImg(filesLength){
if(filesLength == 0){
return true;
}
return false;
}
/*
* Change preview image to nophoto image when image is not selected
* @param input : Element of current target
*/
changeNoPhotoImg(input){
$(input).prev(this.selectorImg).children('img').attr('src', this.noPhotoImgPath);
}
/*
* Change preview image to selected image when image is selected
* @param input : Element of current target
*/
changeSelectedImg(input){
const reader = new FileReader();
reader.onload = (progressEvent) => {
$(input).prev(this.selectorImg).children('img').attr('src', progressEvent.currentTarget.result);
}
const file = input[0].files[0];
reader.readAsDataURL(file);
}
}
SCSS
app/assets/stylesheets/application.scss
/*form-image-uploader
------------------------------------------------------*/
.form-image-uploader {
@at-root {
#{&}__saved-img {
margin-bottom: 1em;
@at-root {
#{&}-inner {
border: 1px solid #ced4da;
border-radius: 0.25rem;
display: inline-block;
}
}
img {
max-height: 300px;
}
}
#{&}__preview {
display: inline-block;
border: 1px solid #ced4da;
border-radius: 0.25rem;
position: relative;
cursor: pointer;
img {
max-width: 100px;
width: auto;
max-height: 100px;
height: 100%;
&:hover {
opacity: 0.7;
}
}
}
}
}
/*block-toggle
------------------------------------------------------*/
.block-toggle {
@at-root {
#{&}__press {
cursor: pointer;
margin-bottom: 0.5em;
}
#{&}__content {
border: 1px solid #ced4da;
border-radius: 0.25rem;
padding: 0.5em;
}
}
}
Die folgende Überprüfung des Vorgangs wurde in Chrome, Firefox und Safari durchgeführt.
--Wenn der ausgewählte Bildname lang ist, ist der Dateiname horizontal lang und überschreitet das umschließende HTML-Element. --Nach der Auswahl eines Bildes klicken Sie auf die Schaltfläche "Abbrechen" → Es wäre schön, eine Funktion hinzufügen zu können, um das Vorschaubild auf noptho zurückzusetzen.
Das nächste Mal möchte ich eine Bildvorschau-Funktion implementieren, die die oben genannten Probleme löst.
[Rails] Implementierung der Bildvorschau-Funktion --Qiita