TOP > カテゴリ > HTML5・JavaScript >

JavaScriptでクリップボードの貼り付けに対応する[HTML5のClipboard API/contenteditable]

ブラウザで「クリップボードの貼り付け」に対応する方法です。ご紹介するサンプルではJavaScriptを使用してWindows OSのクリップボードの画像、ブラウザでクリップボードへコピーした画像などをcanvasへ描画します。

ブラウザの動作確認は「Edge、IE11、Chrome、FireFox」です。林檎さんのサファリパークやオペラ歌手、ペガサスなどは確認しておりません。

クリップボードの貼り付けを試す

次のWebアプリでクリップボードの貼り付けを試す事が可能です。

クリップボードから画像ファイルの作成

JavaScriptでのクリップボード操作

JavaScriptでのクリップボード操作にはHTML5の「Clipboard API」がありますが、全てのブラウザが対応しているわけではありません。(2016年3月時点)

そこで、対応しているブラウザには「Clipboard API」を使用して、未対応のブラウザにはHTML5の「contenteditable」(コンテンツ編集許可)の属性を使用してクリップボードの画像を取得します。

HTML5の「contenteditable」の属性がある<div>タグなどでは、そのエリア内に文字列や画像をペタペタと貼り付ける事が可能です。JavaScriptでそのペタペタ貼り付けた画像の<img>を取得する事でクリップボードの代用とします。

各ブラウザによるClipboard APIの対応表

次の表はクリップボードのPaste(ペースト/貼り付け)の対応表です。

ブラウザClipboard API(Paste)備考
Chrome対応全て貼り付ける事が可能。
Edge対応Officeなどの一部の画像を貼り付ける事が出来ない。ペイントなどの画像はOK。
FireFox未対応なのでcontenteditableで代用ブラウザでコピーした別ドメインの画像は貼り付ける事が出来ない。
IE11未対応なのでcontenteditableで代用ブラウザでコピーした別ドメインの画像は貼り付ける事が出来ない。

※2016年3月時点では色々と制限がありますね^^;

サンプルコード

[実行画面]

いつもながら雑なコードですが、勘弁してください :-)

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script>

// キャンバス
var src_canvas; 
var src_ctx;

// イメージ
var image;

// ブラウザ判定
var clipboard_flg;
if((!window.navigator.msSaveBlob) && 
   (window.navigator.userAgent.toUpperCase().indexOf('CHROME') != -1)){
  // chrome
  clipboard_flg = true; 
}else if((window.navigator.msSaveBlob) && 
   (window.navigator.userAgent.toUpperCase().indexOf('CHROME') != -1)){
  // Edge
  clipboard_flg = true; 
}else{
  // その他
  clipboard_flg = false;   
}

window.onload = function(){   
  
  src_canvas = document.getElementById("SrcCanvas");
  src_ctx = src_canvas.getContext("2d");    
    
  image = document.getElementById("img_source");
}

// クリップボードの画像を取得(Chrome/Edgeのみ)
if (clipboard_flg){
    
  document.addEventListener('paste', function(e) {
   
    e.preventDefault();
    
    var items = e.clipboardData.items;
    var dti = null; // DataTransferItemオブジェクト    
    
    // クリップボードの種類がイメージならば
    for(i = 0; i < items.length; i++) {    
      if(items[i].type.indexOf("image") != -1) {
        dti = items[i];
        break;
      }
    }
    
    if(dti){
      image.onload = function(){
        src_canvas.width  = image.width;
        src_canvas.height = image.height;
          
        // キャンバスに画像を描画
        src_ctx.drawImage(image,0,0);
      }
      
      // DataTransferItemオブジェクトからFileオブジェクトを取得して
      // 新しいオブジェクトのURLをイメージソースに設定する
      image.src = window.URL.createObjectURL(dti.getAsFile());
    }else{
      alert('クリップボードから画像を取得できませんでした。\n※ブラウザがEdgeの場合は仕様で取得できない場合があります。');
    }

  });
}

// クリップボードの画像を取得(Chrome/Edge以外)
function getClipboardImage(){
  
  // Chrome/Edgeはスルー
  if (clipboard_flg) return false;
  
    // IMGの再帰検索
    function SearchImage(parent){

      for(var i=0;i< parent.children.length;i++){
        var child = parent.children[i]; 
        
        // 子ノード
        if(child.nodeName.toUpperCase() == 'IMG'){ 
          try{   
            
            // canvasの汚染対策(canvasは一度汚染すると永久に汚染される)
            var pollution_canvas = document.createElement("canvas");
            pollution_canvas.style.display = 'none';
            document.body.appendChild(pollution_canvas); 
              pollution_canvas.width  = child.width;
              pollution_canvas.height = child.height;
              pollution_ctx = pollution_canvas.getContext("2d");
              
              // FireFox対策
              try{
                pollution_ctx.drawImage(child,0,0);  
              }catch(e){
                throw 'SecurityError';
              }
              // クロスドメインの場合はここで例外が発生する
              pollution_ctx.getImageData(0, 0, pollution_canvas.width, pollution_canvas.height);              
            document.body.removeChild(pollution_canvas);              
            
            // ここから本来の処理
            src_canvas.width  = child.width;
            src_canvas.height = child.height;              
              
            // キャンバスに画像を描画
            src_ctx.drawImage(child,0,0);   
          }catch(e){
            alert(e +'\n\n' +'ブラウザでコピーした別ドメインの画像は貼り付けできません。\n'+
                 '※これはブラウザのセキュリティ対策です。\n※全ての画像を貼り付けたい場合はChromeをご利用ください。');
          }              
          return true;          
        }
      }
      
      // 再帰処理
      for(var i=0;i< parent.children.length;i++){
        if (SearchImage(parent.children[i])) return true;
      }      
    }  
  
  var paste = document.getElementById("PasteArea");

  // IMGの再帰検索
  SearchImage(paste);
          
  paste.innerHTML = '1. このエリアをマウスでクリックします。<br><br>2. キーボードの「Ctrl」キーを押しながら「V」キーを押します。';
  document.getElementById("PasteArea").style.border='2px solid #ccc';     
}

</script>
</head>
<body>
<p></p>
<div id="PasteArea" contenteditable="true" onkeyup ="getClipboardImage();" 
  onclick="PasteArea.style.border='1px solid #1e90ff';"         
  onblur="PasteArea.style.border='1px solid #ccc';" 
  style="width:85%;height:130px;border:1px solid #ccc;padding:10px;"> 
  1. このエリアをマウスでクリックします。<br>
  <br>
  2. キーボードの「Ctrl」キーを押しながら「V」キーを押します。
</div>
<p></p>
<img id="img_source" style="display:none;">
<canvas id="SrcCanvas"></canvas>
<p></p>
</body>
</html> 

このサンプルではマウスの右クリックでポップアップメニューを表示して、そこから「貼り付け」で画像を貼り付けるのには対応していませんので注意してください。

参考リンク

Clipboard API and events(W3C)
ClipboardEvent(MDN)
DataTransfer(MDN)





掲示板

ソフトウェア、ハードウェアのプログラミング用の掲示板を作成しました。質問やわからない事は@掲示板でユーザー同士で情報を共有して下さい。

関連記事



公開日:2016年03月31日 最終更新日:2016年04月01日
記事NO:01867