JavaScript
jQuery
dropzone
ドラッグ&ドロップ
26
どのような問題がありますか?

投稿日

更新日

画像をドラッグ&ドロップでアップロードして並び替え

画像をドラッグ&ドロップでアップロード

画像をドラッグ&ドロップで並び替える
方法をご紹介します!

用途

webサイトとかで、施設に画像を結びつけて、かつ、それをソート順で表示したいとかあるときに使えるよ。

ついでに画像も削除できます。
ついでに画像に説明文も登録できます。

画像のドラッグ&ドロップでアップロードと並び替え.png

参考サイト

https://codepen.io/malkafly/pen/gbVYZb
↑ほぼこれを丸パクリです。ありがとうございます!!!

使うプラグイン

  • みんな大好きDropzoneJS
  • jQuey UIのSortable
    私はここからyarnで追加しました

コード

html側

<form method="post" action="/api/v1/facility-image/upload/" id="my-awesome-dropzone" class="image-upload-area dropzone">
    <input type="hidden" name="client_id" value="{{ $facility->id }}"></div>
</form>
    
<ul class="visualizacao sortable dropzone-previews"></ul>
<div class="preview" style="display:none;">
    <li>
        <div>
            <div class="dz-preview dz-file-preview">
                <img class="facility-image" data-dz-thumbnail />
                <input type="text" class="caption">
                <button type="button" class="btn btn-info caption-button" data-image-id="">説明文登録</button>
                <div class="dz-progress"><span class="dz-upload" data-dz-uploadprogress></span></div>
                <div class="dz-error-message"><span data-dz-errormessage></span></div>
            </div>
        </div>
    </li>
</div>

javascript側

import Dropzone from 'dropzone'

require('es-jquery-sortable')

let myDropzone = {}

dropzoneSetting()

//画像の並び替え
$(document).ready(function(){
    let group = $('.sortable').sortable({
        group: 'sortable',
        onDrop: function($item, container, _super) {
            var data = group.sortable('serialize').get()
            _super($item, container)

            //DB上の並び順を更新する
            axios.post('/api/v1/facility-image/update-order/', {
                    data: data,
                })
                .catch((error) => {
                    swal('', '並び順の更新に失敗しました', 'error')
                    console.log(error)
                })
        }
    })
})

/**
 * dropzone.jsの処理
 * 
 */
async function dropzoneSetting() {
    Dropzone.autoDiscover = false

    //最大ファイルアップロードサイズ
    let maxFileSize = 3

    //企業ID
    let clientId = $('#client-id').data('clientId')

    myDropzone = new Dropzone('.image-upload-area', {
        url: '/api/v1/facility-image/upload/',
        params: {
            client_id: clientId,
        },
        dictDefaultMessage: 'ここにファイルをドラッグ&ドロップ、または、クリックしてファイルを選択',
        dictRemoveFile: '',
        dictCancelUpload: '',
        dictFileTooBig: 'ファイルサイズは' + maxFileSize + 'MBまで',
        dictInvalidFileType: 'JPEG,PNGのみ可能',
        addRemoveLinks: true,
        maxFilesize: maxFileSize,
        acceptedFiles: 'image/*',
        parallelUploads: 1,
        uploadMultiple: false,
        previewsContainer: '.visualizacao', 
        previewTemplate : $('.preview').html(),
        renameFile: (file) => {
            let fileName = new Date().getTime() + '_' + file.size

            let extension = file.name.split('.').pop()
            return fileName + '.' + extension
        },
    })

    //アップロードに失敗した場合
    myDropzone.on('error', async function(file, errorMessage) {
        //ファイル数が多い場合
        if(errorMessage === '最大8ファイルまでしか添付できません') {
            myDropzone.removeFile(file)
            swal('', errorMessage, 'warning')
        } else if(errorMessage === 'セッションが切れました。もう一度ログインしてください。') {
            await swal('', 'セッションが切れました。もう一度ログインし直してください。', 'warning')
            location.replace(location.href)
        }
    })
    
    //画像を削除したときに、サーバー上のファイルも削除する
    myDropzone.on("removedfile", function(file) {
        let imageId = file.imageId

        //画像ID
        axios.get('/api/v1/facility-image/delete-by-image-id/' + imageId)
            .catch((error) => {
                console.log(error)
            })
    })

    //既存の画像が表示されたときに情報を追加する
    myDropzone.on("addedfile", function(file) {
        $('.dz-preview').each(function() {
            let imageId = $(this).children('.caption-button').data('imageId')

            //画像IDが設定されていない場合のみ追加する
            if(!imageId) {
                let imageId = file.imageId

                //今回追加した画像の場合は飛ばす
                if(!imageId) {
                    return
                }

                $(this).children('.caption-button').data('imageId', imageId)

                let caption = file.caption
                $(this).children('.caption').val(caption)

                $(this).parents('li').data('imageId', imageId)
            }
        })
    })

    //新しい画像がアップロードされたときに、画像IDを追加する
    myDropzone.on("success", function(file, response) {
        $('.dz-preview').each(function() {
            let existImageId = $(this).children('.caption-button').data('imageId')

            //画像IDが設定されていない場合のみ追加する
            if(!existImageId) {
                let imageId = response
                $(this).children('.caption-button').data('imageId', imageId)
                $(this).parents('li').data('imageId', imageId)
            }
        })
    })

    //すでに保存されている画像を表示する
    $('.exist-image').each(function() {
        let path = $(this).data('path')
        let info = {
            name: '',
            size: '',
            imageId: $(this).data('id'),
            caption: $(this).data('caption')
        }
        myDropzone.emit("addedfile", info)

        if(path) {
            myDropzone.emit("thumbnail", info, path)
        } else {
            let base64 = 'data:' + $(this).data('type') + ';base64,' + $(this).data('binary')
            myDropzone.emit("thumbnail", info, base64)
        }

        myDropzone.emit("complete", info)
    })

    //画像の説明文を登録
    $(document).on('click', '.caption-button', function() {
        let input = $(this).prev()

        axios.post('/api/v1/facility-image/save-caption/', {
                caption: input.val(),
                image_id: $(this).data('imageId'),
            })
            .then(() => {
                swal('', '説明文を登録しました', 'success')
            })
            .catch((error) => {
                swal('', '説明文の登録に失敗しました', 'error')
                console.log(error)
            })
    })
}

#まとめ
php側(私はLaravel使用しています)は、自分で実装してくださいね。
cssも自分で書いてね。

全然コードの説明してなくて、すみません。
いや、こういうの毎回やろうと思ったときに、過去のソースひっぱってくるの大変なので、Qiitaに置きました...

ユーザー登録して、Qiitaをもっと便利に使ってみませんか。
  1. あなたにマッチした記事をお届けします
    ユーザーやタグをフォローすることで、あなたが興味を持つ技術分野の情報をまとめてキャッチアップできます
  2. 便利な情報をあとで効率的に読み返せます
    気に入った記事を「ストック」することで、あとからすぐに検索できます
ユーザー登録ログイン
shima0218
しがなすぎるエンジニア

コメント

この記事にコメントはありません。
あなたもコメントしてみませんか :)
ユーザー登録
すでにアカウントを持っている方はログイン
26
どのような問題がありますか?
ユーザー登録して、Qiitaをもっと便利に使ってみませんか

この機能を利用するにはログインする必要があります。ログインするとさらに下記の機能が使えます。

  1. ユーザーやタグのフォロー機能であなたにマッチした記事をお届け
  2. ストック機能で便利な情報を後から効率的に読み返せる
ユーザー登録ログイン
ストックするカテゴリー