サンプル・プログラムの実行例

サンプル・プログラムのダウンロード
pasteImage.html | サンプル・プログラム本体 |
バージョン | 更新日 | 内容 |
---|---|---|
1.1.0 | 2024/12/06 | 画像縮小処理--resizeImage()を追加 |
1.0.0 | 2024/11/30 | 初版 |
解説:初期値
pasteImage.html
25: // 初期値(START) ==========================================================
26: const TITLE = 'クリップボードの画像取得+リサイズ'; // プログラム・タイトル
27: const REFERENCE = 'https://www.pahoo.org/e-soul/webtech/js01/js01-17-01.shtm';
28: const WIDTH = 600; // 横幅(ピクセル)
29: const MAX_IMAGES = 4; // 最大画像数
30: const MAX_WIDTH = 1200; // 画像の最大幅(ピクセル)
31: const MAX_HEIGHT = 630; // 画像の最大高(ピクセル)
32:
33: // imgのリスト;MAX_IMAGESの数だけ用意すること
34: const IMAGE_LIST = ['image1', 'image2', 'image3', 'image4'];
35:
36: document.addEventListener('DOMContentLoaded', () => {
37: //タイトル等を表示する.
38: document.title = TITLE;
39: document.getElementById('title').innerHTML = TITLE + ' <span style="font-size:small;">' + getLastModified() + '版</span>';
40: document.getElementById('reference').innerHTML =`
41: ※参考サイト <a href="${REFERENCE}">${REFERENCE}</a>
42: `;
43:
44: //スタイルシートをセットする.
45: document.getElementById('help').style.width = WIDTH + 'px';
46: document.getElementById('help1').innerHTML = `画像は ${MAX_IMAGES}個までペーストできます.`;
47: let width = Math.floor(WIDTH / MAX_IMAGES);
48: IMAGE_LIST.forEach((value, index) => {
49: document.getElementById(value).style.width = width + 'px';
50: document.getElementById(value).style.height = 'auto';
51: });
52: });
53: // 初期値(END) ==========================================================
解説:画像を指定サイズに縮小
pasteImage.html
130: /**
131: * 画像を指定サイズに縮小し,WebP画像に変換し,オブジェクトURL形式で返す
132: * @param Object blob 画像データ(Blob形式)
133: * @param Number width リサイズ後の幅(ピクセル)
134: * @param Number height リサイズ後の高さ(ピクセル)
135: * @return String オブジェクトURL形式
136: */
137: function resizeImage(blob, width, height) {
138: // 画像をロードするまで待つ
139: return new Promise((resolve, reject) => {
140: // 縮小倍率
141: let scale = 1.0;
142:
143: // 画像をロードする
144: const img = new Image();
145: const url = URL.createObjectURL(blob);
146:
147: img.onload = () => {
148: // 元の画像サイズ
149: const originalWidth = img.width;
150: const originalHeight = img.height;
151:
152: // 縮小後のサイズ計算
153: if (originalWidth > width) {
154: scale = width / originalWidth;
155: }
156: if (originalHeight > height * scale) {
157: scale = height / originalHeight;
158: }
159: const newWidth = originalWidth * scale;
160: const newHeight = originalHeight * scale;
161:
162: // canvasを生成する
163: const canvas = document.createElement('canvas');
164: canvas.width = newWidth;
165: canvas.height = newHeight;
166:
167: // canvasに描画する
168: const ctx = canvas.getContext('2d');
169: ctx.drawImage(img, 0, 0, newWidth, newHeight);
170:
171: // BlobのURLを解放する
172: URL.revokeObjectURL(url);
173:
174: // WebP画像をオブジェクトURL形式で返す
175: resolve(canvas.toDataURL('image/webp'));
176: };
177:
178: img.onerror = (err) => {
179: console.error('画像の読み込みに失敗しました:', err);
180: URL.revokeObjectURL(url);
181: reject(err);
182: };
183:
184: img.src = url;
185: });
186: }
ユーザー関数 resizeImage は、Blob形式の画像データを受け取り、width, height より大きい場合には縮小する。縮小の有無に関わらず、画像データを小さくできる WebP形式に変換し、POSTでサーバに送信しやすいように オブジェクトURL形式として返す。

まず、Imageオブジェクトを用意し、Blob形式の画像データをロードする。ここでロード処理は非同期で進むので、本関数は Promise で return するようにする。
ロードした画像サイズを取得し、引数で指定したサイズより大きければ縮小率を計算し、変数 scale に代入する。指定サイズより小さければ、scale はデフォルトの1.0(倍)のままとなる。
画像の縮小は canvas を利用して行う。変換結果は、WebP形式の画像として取得する。
解説:クリップボードの画像を取得する
pasteImage.html
91: // ctrl+V をクリックしたらクリップボードから画像を取得し画面に表示する
92: document.addEventListener('paste', async (event) => {
93: // 格納できる要素(srcが空の要素)を探す
94: let flag = false
95: let imgElement = undefined;
96: for (const id of IMAGE_LIST) {
97: imgElement = document.getElementById(id);
98: if (imgElement && imgElement.src === '') {
99: flag = true;
100: break;
101: }
102: }
103:
104: try {
105: // クリップボードのデータを取得
106: const clipboardItems = await navigator.clipboard.read();
107:
108: for (const item of clipboardItems) {
109: // 画像データ (image/*) を探す
110: const imageType = item.types.find(type => type.startsWith('image/'));
111: if (imageType) {
112: if (! flag) {
113: document.getElementById('result').innerHTML = '情報:投稿できる画像は {$maxImages}個までです.';
114: return;
115: }
116: const blob = await item.getType(imageType);
117: // 画像を指定サイズに縮小してから表示
118: imgElement.src = await resizeImage(blob, MAX_WIDTH, MAX_HEIGHT);
119: // 画像を縮小しないで表示する
120: // imgElement.src = URL.createObjectURL(blob);
121: // 削除ボタンを作成して画像の右上に追加
122: addDeleteButton(imgElement);
123: }
124: }
125: } catch (err) {
126: document.getElementById('result').innerHTML = 'エラー:' + err;
127: }
128: });

次に、Clipboard.read メソッドを使ってクリップボードの内容を読み込み、その中から forループを使って画像データを取り出す。画像データは item.types が MIME形式で "image/*" になっている。
画像データが見つかったら、blob形式で読み込み、img.srcにURL形式で代入する。これで1つの画像を表示できた。

つづいて、画像の右上に削除ボタンを配置する。
pasteImage.html
55: // 画像に削除ボタンを追加する
56: function addDeleteButton (imgElement) {
57: const deleteButton = document.createElement('button');
58: deleteButton.textContent = '削除';
59: deleteButton.style.position = 'absolute';
60: deleteButton.style.top = '0';
61: deleteButton.style.right = '0';
62: deleteButton.style.backgroundColor = 'red';
63: deleteButton.style.color = 'white';
64: deleteButton.style.border = 'none';
65: deleteButton.style.padding = '5px 10px';
66: deleteButton.style.cursor = 'pointer';
67: deleteButton.style.fontSize = '12px';
68: deleteButton.style.zIndex = '10';
69:
70: // 画像の親要素に削除ボタンを追加
71: const imgContainer = document.createElement('div');
72: imgContainer.style.position = 'relative';
73: imgContainer.style.display = 'inline-block';
74: imgContainer.appendChild(imgElement);
75: imgContainer.appendChild(deleteButton);
76:
77: // 画像と削除ボタンをページに追加
78: document.getElementById('image-container').appendChild(imgContainer);
79:
80: // 削除ボタンのクリックイベントを設定
81: deleteButton.addEventListener('click', () => {
82: // src属性を削除し,画像を非表示にする
83: imgElement.removeAttribute('src');
84: // imgをコンテナに付け直す
85: document.getElementById('image-container').appendChild(imgElement);
86: // 画像と削除ボタンを削除する
87: imgContainer.remove();
88: });
89: }
buttonオブジェクトがクリックされたら、画像のsrc属性を削除することで画像を非表示にするとともに、imgオブジェクトを imgContainer に付け直す。
参考サイト
- PHPでBlueskyに投稿する:ぱふぅ家のホームページ
- JavaScriptでクリップボードを使う:ぱふぅ家のホームページ
(2024年12月6日)画像を指定サイズに縮小する機能追加,タイトル変更