5.5 KiB
5.5 KiB
ImageMarkPengent拡張機能の設計書
- 画像に赤い印や注釈を描ける
- いちいちEXECLなどを開いて画像を加工するのも面倒
機能一覧
分類 | 機能 | 説明 |
---|---|---|
ビュー | WebView表示 | .png/.jpg ファイルを開くとWebViewで表示 |
機能 | マーク描画 | クリックしたところに記号を描画 |
保存機能 | 加工後に保存する(別名保存も対応) |
最初は記号は丸のオブジェクトのみとする ※ 番号付きマーカーや矢印 も将来的に追加できるようにする
仕様について
フォルダの構成
imagemarkpengent/
├── src/
│ └── extension.ts # 拡張機能のメインエントリ
├── package.json # 拡張機能の定義(コマンド、設定など)
├── tsconfig.json # TypeScript設定
├── vsc-extension-quickstart.md # チュートリアル的なREADME
└── .vscode/
開発ステップ
- コマンドを登録し.png/.jpgファイルに対して有効にする
- package.json に explorer/context のコマンドメニュー追加
- 対象拡張子を
.png/.jpg
に限定する
- WebView で画像を表示する処理を追加
- コマンドからWebviewPanelを作成し画像を
<img>
として読み込む - canvas上に画像を描画してユーザーが上から描き込めるようにする
- コマンドからWebviewPanelを作成し画像を
- クリック位置に赤丸を描画できるようにする
- WebView内でJavaScriptを使い
<canvas>
に描画する - 座標はクリックイベントで取得、再描画用に保持
- WebView内でJavaScriptを使い
- 加工画像の保存機能を追加
- 「保存」ボタンをWebView内に用意
canvas.toDataURL()
を取得し、拡張機能にvscode.postMessage()
で送信- 拡張機能側でファイル保存(別名保存もサポート)
完璧なスタートです!
以下に続きの「開発ステップ」とそれぞれの 具体的な手順 を設計書スタイルで追記します。
開発ステップ
ステップ 1. コマンドを登録し .png/.jpg
ファイルに対して有効にする
package.json
にexplorer/context
のコマンドメニュー追加- 対象拡張子を
.png
/.jpg
に限定
ステップ 2. WebView で画像を表示する処理を追加
- コマンドから
WebviewPanel
を作成し画像を<img>
として読み込み canvas
上に画像を描画して、ユーザーが上から描き込めるようにする
ステップ 3. クリック位置に赤丸を描画できるようにする
- WebView内で JavaScript を使い
<canvas>
に赤丸描画 - 座標はクリックイベントで取得、再描画用に保持
ステップ 4. 加工画像の保存機能を追加
- 「保存」ボタンをWebView内に用意
canvas.toDataURL()
を取得し、拡張機能にvscode.postMessage()
で送信- 拡張機能側でファイル保存(別名保存もサポート)
各ステップの具体的な手順
コマンド登録(右クリックメニューに表示)
package.json
"activationEvents": [
"onCommand:imagemarkpengent.openImageEditor"
],
"contributes": {
"commands": [
{
"command": "imagemarkpengent.openImageEditor",
"title": "Open in ImageMarkPengent"
}
],
"menus": {
"explorer/context": [
{
"command": "imagemarkpengent.openImageEditor",
"when": "resourceExtname =~ /\\.(png|jpg|jpeg)$/",
"group": "navigation"
}
]
}
}
WebViewに画像表示
extension.ts
vscode.commands.registerCommand('imagemarkpengent.openImageEditor', (uri: vscode.Uri) => {
const panel = vscode.window.createWebviewPanel(
'imageEditor',
'ImageMarkPengent',
vscode.ViewColumn.One,
{
enableScripts: true,
localResourceRoots: [vscode.Uri.file(path.dirname(uri.fsPath))]
}
);
const imageSrc = panel.webview.asWebviewUri(uri);
panel.webview.html = getWebviewContent(imageSrc.toString());
});
getWebviewContent()
function getWebviewContent(imageSrc: string): string {
return `
<html>
<body>
<canvas id="canvas"></canvas>
<script>
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const img = new Image();
img.src = "${imageSrc}";
img.onload = () => {
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0);
};
canvas.addEventListener('click', (e) => {
const rect = canvas.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
ctx.beginPath();
ctx.arc(x, y, 10, 0, 2 * Math.PI);
ctx.strokeStyle = 'red';
ctx.lineWidth = 2;
ctx.stroke();
});
</script>
</body>
</html>
`;
}
保存処理(vscode拡張から保存)
- WebView内に「保存」ボタン追加
canvas.toDataURL()
を取得し、vscode.postMessage()
で送信extension.ts
で受け取ってバイナリ化し、fs.writeFile()
で保存