J'ai essayé d'implémenter la fonction de prévisualisation d'image avec Rails / jQuery

introduction

Lors de la création du site de portfolio, j'avais une fonction de téléchargement d'image, mais il y avait un problème en ce qu'il était difficile de comprendre si une image pouvait être sélectionnée correctement car il n'y avait pas de fonction de prévisualisation.

Par conséquent, j'ai décidé d'ajouter une fonction de prévisualisation d'image et de l'implémenter.

Bien qu'il y ait quelques problèmes, je l'ai mis en œuvre, je voudrais donc le résumer.

supposition

détail de la fonction

Flux de téléchargement d'images

  1. Appuyez sur la balise d'entrée pour l'entrée de fichier
  2. Sélection d'images
  3. Remplacez l'image de vue en plastique par l'image sélectionnée

Au moment de la validation / post-édition

la mise en oeuvre

View

erb:app/views/posts/_form.html.erb



<%= form_with(model: post, local: true) do |form| %>

	<!--···réduction···-->

	<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>Changer l'image
          </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>

	<!--···réduction···-->

<% end %>

JS

ʻThe this.noPhotoImgPath de la classe ImgUplorader` définit n'importe quel chemin.

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 Définir le chemin de l'image

  }

  /*
  * 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;
    }
  }
}

Vérification

La vérification d'opération suivante a été effectuée sur Chrome, Firefox et Safari.

Au moment de la nouvelle affectation

_2020-11-03_6.39.46.mov.gif

Lors de la modification d'un article

_2020-11-03_6.41.47.mov.gif

Tâche

enfin

La prochaine fois, j'aimerais mettre en œuvre une fonction de prévisualisation d'image qui surmonte les problèmes ci-dessus.

Article de référence

[Rails] Implémentation de la fonction de prévisualisation d'image --Qiita

Aperçu d'image multiple de fichier personnalisé Bootstrap4

Recommended Posts

J'ai essayé d'implémenter la fonction de prévisualisation d'image avec Rails / jQuery
J'ai essayé d'implémenter la fonction similaire par communication asynchrone
[Rails] J'ai essayé d'implémenter le traitement par lots avec la tâche Rake
J'ai essayé d'implémenter le modèle Iterator
J'ai essayé d'implémenter le traitement Ajax de la fonction similaire dans Rails
J'ai essayé de créer une fonction de groupe (babillard) avec Rails
J'ai essayé de vérifier AdoptOpenJDK 11 (11.0.2) avec l'image Docker
[Rails] J'ai essayé de faire passer la version de Rails de 5.0 à 5.2
J'ai essayé d'organiser la session en Rails
J'ai essayé d'implémenter le téléchargement de fichiers avec Spring MVC
J'ai essayé d'implémenter TCP / IP + BIO avec JAVA
J'ai essayé d'implémenter une fonction équivalente à Felica Lite avec HCE-F d'Android
J'ai essayé d'implémenter Sterling Sort avec Java Collector
[Rails] Implémenter la fonction de publication d'images
J'ai essayé d'implémenter la méthode de division mutuelle d'Eugrid en Java
Mode API Rails J'ai essayé d'implémenter la fonction de recherche multiple par mot-clé à l'aide de tableaux et d'un traitement itératif.
J'ai essayé d'augmenter la vitesse de traitement avec l'ingénierie spirituelle
[Rails] J'ai essayé de créer une mini application avec FullCalendar
J'ai essayé d'interagir avec Java
J'ai essayé d'expliquer la méthode
[Rails] J'ai essayé de supprimer l'application
J'ai essayé de résoudre le problème de la "sélection multi-étapes" avec Ruby
Je souhaite ajouter une fonction de navigation avec ruby on rails
J'ai essayé de créer un environnement de serveur UML Plant avec Docker
J'ai essayé d'implémenter un mappage OU flexible avec MyBatis Dynamic SQL
J'ai essayé de comprendre comment la méthode des rails "redirect_to" est définie
J'ai essayé de vérifier le fonctionnement du serveur gRPC avec grpcurl
J'ai essayé de comprendre comment la méthode des rails "link_to" est définie
[JQuery] Comment afficher l'image sélectionnée sous forme d'aperçu immédiat + Ajouter une gemme de publication d'image
J'ai essayé de résumer les méthodes utilisées
[Rails] Implémentation de la fonction de catégorie multicouche en utilisant l'ascendance "J'ai essayé de créer une fenêtre avec Bootstrap 3"
J'ai essayé de démarrer avec Web Assembly
Essayez d'implémenter une fonction de connexion avec Spring-Boot
Comment implémenter TextInputLayout avec la fonction de validation
J'ai essayé de résumer l'API Stream
J'ai essayé d'utiliser Selenium comme JQuery
Pour implémenter la publication d'images à l'aide de rails
[Rails] J'ai essayé d'implémenter une transaction qui combine plusieurs processus DB
J'ai essayé de résoudre le problème de la séquence Tribonacci en Ruby, avec récurrence.
[Rails] Implémentez la fonction d'achat de produits avec une carte de crédit enregistrée auprès de PAY.JP
J'ai essayé de visualiser l'accès de Lambda → Athena avec AWS X-Ray
Je veux introduire un comité avec des rails sans devenir trop sale
J'ai essayé de mesurer et de comparer la vitesse de Graal VM avec JMH
Après tout, je voulais prévisualiser le contenu de mysql avec Docker ...
J'ai essayé de comprendre le flux lors de l'analyse d'image avec Vision Framework et Core ML
J'ai essayé d'implémenter des relations polymorphes à Nogizaka.
J'ai essayé de gérer la configuration des jambes de force avec Coggle
J'ai essayé de gérer les informations de connexion avec JMX