TIPS 061:ドラッグ&ドロップ時のスタイルを設定する

TIPS 061:ドラッグ&ドロップ時のスタイルを設定する

ドラッグ操作時に、操作中であることを視覚的に明確に示すため、ドラッグ元要素やドロップ領域のスタイルを変更することは、よく行われます。

以下では、dragstart/dragenter/dragleave/dropendなどのイベントを利用して、「ドラッグ時にドラッグ要素に枠線を付与し」、「ドロップ領域進入時に領域の背景色を変化」してみましょう。

[リスト03]ドラッグ元要素、ドロップ領域にスタイルを設定するコード(drop2.html)

  <!DOCTYPE html>
  <html>
  <head>
  <meta charset="UTF-8" />
  <title>HTML5 TIPS</title>
  <script>
  window.addEventListener('DOMContentLoaded', function() {
    // ドラッグ対象要素、ドロップ先要素を取得
    var drag = document.querySelector('#drag');
    var drop = document.querySelector('#drop');
 
    // ドラッグ開始
    drag.addEventListener('dragstart', function(e) {
      e.dataTransfer.setData('text', e.target.id);
      // ドラッグ元要素に対して枠線を付与
      this.style.border = 'solid 1px #f0f';
    }, true);
 
    // ドロップ領域に進入時
    drop.addEventListener('dragenter', function(e) {
      // ドロップ領域の背景を変更
      this.style.backgroundColor = '#ff0';
      e.preventDefault();
    }, true);
 
    // dragoverイベントをキャンセル
    drop.addEventListener('dragover', function(e) {
      e.preventDefault();
    }, true);
 
    // ドロップ領域から外れた時
    drop.addEventListener('dragleave', function(e) {
      // ドロップ領域の背景を元に戻す
      this.style.backgroundColor = '#ffc';
      e.preventDefault();
    }, true);
 
    // ドラッグ操作を終えた時
    drag.addEventListener('dragend', function(e) {
      // ドラッグ元要素から枠線を外す
      this.style.borderStyle = 'none';
      e.preventDefault();
    }, true);
 
    // ドロップ時
    drop.addEventListener('drop', function(e) {
      var id = e.dataTransfer.getData('text');
      e.currentTarget.appendChild(document.getElementById(id));
      e.preventDefault();
    }, true);
  });
  </script>
  </head>
  <body>
  <img id="drag" src="wings.jpg" draggable="true" />
  <div id="drop" style="background-color:#ffc; width:450px; height:200px;"></div>
  </body>
  </html>
図3:ドラッグ時にスタイルを設定(クリックで拡大)

操作自体は、ごく単純です。dragstart/dragendイベントでドラッグ元要素の枠線を、dragenter/dragleaveイベントでドロップ領域の背景色を、それぞれ操作しています。

TIPS 062:他のアプリからテキストデータを受け取る

ドラッグ&ドロップできるのは、ブラウザ(ページ)内部の要素ばかりではありません。他のアプリからドラッグしたテキストやファイルを取得し、ブラウザ内部で処理することもできます。

例えば以下は、外部のアプリで選択したテキストをブラウザ上の決められた領域にドロップする例です。ドロップされたテキストは、そのまま領域内部に表示します。

[リスト04]外部のアプリから選択テキストをドラッグ&ドロップするコード(otherDrop.html)

  <!DOCTYPE html>
  <html>
  <head>
  <meta charset="UTF-8" />
  <title>HTML5 TIPS</title>
  <script>
  window.addEventListener('DOMContentLoaded', function() {
    // ドロップ先要素を取得
    var drop = document.querySelector('#drop');
 
    // ドロップ時の処理を定義
    drop.addEventListener('drop', function(e) {
      // 他のアプリから渡されたテキストを取得
      var msg = e.dataTransfer.getData("text/plain");
      // 取得したデータをページに反映
      drop.textContent = msg;
      e.preventDefault();
    }, true);
 
    // dragoverイベントをキャンセル
    drop.addEventListener('dragover', function(e) {
      e.preventDefault();
    }, true);
  });
  </script>
  </head>
  <body>
  <div id="drop" style="background-color:#ffc; width:450px; height:200px;"></div>
  </body>
  </html>
図4:ドラッグ&ドロップしたテキストを表示(クリックで拡大)
※本サンプルは、IEでは動作しません

外部のアプリからデータを受け取るには、DataTransferオブジェクトのgetDataメソッドに、受け取るデータの種類を指定します(1)。指定できるデータの種類には、以下のようなものがあります。

表4:指定できるデータの種類(getDataメソッドの引数)

設定値概要
text/plain平のテキスト
text/htmlHTML文字列
text/xmlXML文字列
text/uri-listURI、ファイル名のリスト

ここでは、「text/plain」を指定していますので、ドロップされたデータを平のテキストとして取得します。ここではtextContentプロパティで、取得したテキストをそのままページに反映させていますが、例えばカンマ区切りテキストなどを取得して、これをテーブルとして加工するようなことも可能です。

TIPS 063:ファイルをドラッグ&ドロップする

ドラッグ&ドロップ APIでは、ブラウザの外部からファイルを受け渡しすることもできます。例えば以下は、前回のTIPS55のサンプルを(ファイル入力ボックスではなく)ドラッグ&ドロップでファイルを受け渡せるように書き換えたものです。

[リスト05]ドラッグ&ドロップでファイルを指定(otherDropFile.html)

  <!DOCTYPE html>
  <html>
  <head>
  <meta charset="UTF-8" />
  <title>HTML5 TIPS</title>
  <script>
  window.addEventListener('DOMContentLoaded', function() {
    // ドロップ先要素を取得
    var drop = document.querySelector('#drop');

    // ドロップ時の処理を定義
    drop.addEventListener('drop', function(e) {
      // ドロップされたファイルを取得(1)
      var f = e.dataTransfer.files[0];
      // ファイルの読み込みに成功したら、その内容を<img id="result">に反映
      var reader = new FileReader();
      reader.addEventListener('load', function() {
        document.querySelector('#dropped').src = reader.result;
      }, false);
      // ファイルをData URL形式で取得
      reader.readAsDataURL(f);
      e.preventDefault();
    }, true);
 
    // dragoverイベントをキャンセル
    drop.addEventListener('dragover', function(e) {
      e.preventDefault();
    }, true);
  });
  </script>
  </head>
  <body>
  <div id="drop" style="background-color:#ffc; width:450px; height:200px;">
    <img id="dropped" />
  </div>
  </body>
  </html>
図5:ドラッグ&ドロップしたファイルをページに表示(クリックで拡大)
※本サンプルは、IEでは動作しません

ポイントとなるのは、実に(1)の一点のみです。ドラッグ&ドロップされたファイルは、DataTransferオブジェクトのfilesプロパティでアクセスできます。filesプロパティの戻り値はFileオブジェクトですので、あとはそのままFileReaderオブジェクトのreadAsXxxxxメソッドに引き渡すことが可能です。FileReaderオブジェクトに関する詳細は、前回の記事も合わせて参照してください。

人気記事トップ10

人気記事ランキングをもっと見る

企画広告も役立つ情報バッチリ! Sponsored

ClickHouse Cloudが実現した広告運用SaaS「ATOM」のデータ基盤革新、パフォーマンスを向上しながら、運用負荷とコストを削減 11月11日 6:20 AIで開発が加速する時代、品質保証はどう変わる? Tricentisが示すAIエージェント活用の実像 11月9日 6:45 悪用までの猶予が「1分」に迫るフロンティアAI時代に開発と本番を貫く脆弱性管理が必要 10月29日 8:30 欧州CRA対応とSBOM運用。AI生成コードのOSS混入問題の対策とは ――スニペット単位で検出する「FossID」「Insignary Clarity」によるSBOM運用 9月16日 6:40 PostgreSQLからTiDBへ、稼働中SaaSで進める段階的DB移行の実践と再設計への展望 9月7日 6:30 機能安全開発におけるGoogleTestの活用を支援!「Parasoft C/C++test CT」で実現する効率化&AI連携 4月14日 6:30 【CNDW2025】Grafanaが明かす「オブザーバビリティの哲学」ー最小限の労力で実用的なインサイトを得るには 1月23日 6:30 【CNDW2025】プロダクト急増に備える基盤刷新 ーウェルスナビがECSからEKSへの移行で得た知見とは 1月15日 6:30 【CNDW2025】250環境を5人で運用、構築時間は30分に ーKINTOテクノロジーズが語るインフラ基盤組織の作り方 2025年12月18日 6:30 新たな自動化で熱視線! AIエージェントの「推論能力」を支える2つのコンポーネントとは? 2025年11月28日 6:30