arinoth's memo

arinothのメモ

インラインSVGを利用してInDesignと同じように画像を配置する

Webで画像を配置する場合、ピクセル数そのままか、全部サイズを揃えるかのどっちかが多い気がします。 ただ、IT書の組みで同じように配置してしまうと、画像ごとにショットのボタンや文字サイズがマチマチになってしまい、紙の書籍のレイアウト参考になりません。

CSSのwidth: 100%で貼ったもの。サイズが違うダイアログボックスなので倍率がマチマチに。

f:id:arinoth:20160517225235p:plain

InDesignスクリーンショットを貼る場合は、「原寸の40%」という感じに倍率を固定して文字やボタンが同じサイズに見えるよう配置するのが普通なので(例外もありますが)、インラインSVGの力を借りてInDesign風に貼り付ける機能を加えてみました。

すべて同倍率で貼り付け

f:id:arinoth:20160517230002p:plain

この機能を使うと、Markdown原稿の中にSVGタグが入ってちょっと取っつきにくい感じになります。 生のSVGでいいのかだいぶ迷ったのですが、まぁ必要なときに必要な人だけが使えばいいことにしました。

【20150520追記】

実際に使ってみるとMarkdownの中にSVGが混じるのは予想以上にキツく、常用は無理そうです(作った本人がこれほど厳しく感じるのでは、まず他の人が使うのは無理でしょう)。

それと倍率が一律に変更されるのも意外と融通が利かなくて困ったものです。 Markdownのまま、画像ごとにこれは40%、これは25%のように指定できるようにしたいです。SVGの使い方はイキとして、指定方法を考えないといけません……。 f:id:arinoth:20160517230450p:plain

InDesignと同じ貼り付け方というのは要するにどういうこと?

72dpiで1280×800の画像を特に調整せずにInDesignのドキュメントに配置すると、おおよそ「452mm×282mm」になります。

f:id:arinoth:20160517004505p:plain

なぜそうなるかというと、ピクセル数×25.4÷dpiという計算でmm単位の印刷サイズを割り出すからです(25.4はインチをmmに換算する値)。

  • 約452mm ←1280*25.4 / 72
  • 約282mm ←800*25.4/72

これがInDesignでの100%サイズになり、50%、40%と縮小した場合は、印刷サイズ×50%あるいは40%というサイズになります。

同じことをSVGでどう再現するか色々と試行錯誤した結果、

原寸100%で貼る場合
<svg width="452mm" height="282mm" viewBox="0 0 452 282">
    <image width="452" height="282" xlink:href="atariimg/09-01-99.png">
</svg>

※ここでは端数を切っています。

50%縮小して100×100ミリサイズにトリミング
<svg width="100mm" height="100mm" viewBox="0 0 100 100">
    <image width="452" height="282" xlink:href="atariimg/09-01-99.png" 
    transform="scale(0.5) translate(0, 0)">
</svg>

理屈は黄色い本を読んでいただくとして、まとめるとこういう感じです。

  • 配置サイズはsvg開始タグのwidth、height属性でmm指定(InDesignのグラフィックフレームのサイズと思えばOK)
  • viewBoxのサイズは常にwidth、heightと同じにする(これでSVG要素内の座標系の1が1mmと等しくなる)
  • imageタグのwidth、heightは原寸サイズそのまま(原寸で貼ったものをscaleで縮めるイメージ)
  • 画像の倍率指定にはtransform属性のscaleを使う(100%が1.0で40%が0.4になる)
  • 枠内の画像の位置を動かしたいときは、transfrom属性のtranslateを使う(ダイレクト選択ツールで中の画像をずらす感じ)

↓参考書籍

https://www.amazon.co.jp/dp/B00YG8PXNGwww.amazon.co.jp

手作業でSVGを書き直せば、任意サイズでの切り抜きや囲み指示、図中文字指定もできないことはないです。

変換機能について

[Tools]タブを選択して、

  • 「最大幅(通常は版面の幅などを指定してページからはみ出さないようにする)」
  • 「基本倍率(大きすぎる画像は自動縮小)」
  • 「画像の解像度」の3つを指定し、

Markdownの![]()を変換する場合は[Convert From MDImage]をクリック、すでにSVG化している画像を再調整したい場合は[Update SVGImage]をクリックします。

実行後に各プレビューに切り換えると画像サイズが変わっています。

Markdownを直接書き換えて上書き保存してしまうので、事前にコピーを取っておかないと危険です。

f:id:arinoth:20160517233200p:plain

中でやってることは(ちょっと長いですが)ただの置換処理です。

fileUtil.js
    // 置換実行
    var mdsvgtext = mdtext.replace(/!\[[^\]]*\]\(([^\)]+)\)/g, function(str, $1){
      // strはマッチテキスト全体、$1はファイル名
      var imgpath = path.join(workfolder, $1);
      var img = nativeImage.createFromPath(imgpath);
      // 読み込めない場合は変換せずにそのまま返す
      if(img.isEmpty()){
        return str;
      }
      // サイズを取得
      var size = img.getSize();
      var printW = size.width * dpi2mm;
      var printH = size.height * dpi2mm;
      // 小数点第三位までにしておく
      printW = Math.round(printW * 1000) / 1000;
      printH = Math.round(printH * 1000) / 1000;
      // 拡大縮小を反映
      var newscale = scale;
      var scaleW = printW * newscale;
      var scaleH = printH * newscale;
      // 最大サイズより大きい場合はどうする?
      if(scaleW > maxwidth){
        // その分縮小して全体をmaxwidth内に納める
        newscale = maxwidth / printW;
        scaleW = printW * newscale;
        scaleH = printH * newscale;
      }
      // 小数点第三位までにしておく
      newscale = Math.round(newscale * 1000) / 1000;
      scaleW = Math.round(scaleW * 1000) / 1000;
      scaleH = Math.round(scaleH * 1000) / 1000;
      // SVGを生成
      var result = '<svg width="' + scaleW + 'mm" height="' + scaleH + 'mm" ' 
            + 'viewBox="0 0 ' + scaleW + ' ' + scaleH + '">\n';
      result += '<image width="' + printW + '" height="' + printH + '" ' 
            + 'xlink:href="' + $1 + '" '
            + 'transform="scale(' + newscale + ') translate(0,0)"> \n';
      result += '</svg>';
      console.log(result);
      return result;
    });

諦めたこと

GUI編集

時間かかりそうなので即断念。SVG変換後に何かのツールで編集することはできるかもしれないです。

ダイアログボックスの作り方がわからない

本当はメニューからダイアログボックスを表示するUIにしたかったのですが、チュートリアル丸マネの付け焼き刃なので、Angular.jsとかUI Bootstrapの使い方がわかりません……。

時間掛けるところでもないので、唯一わかっているタブにUIを追加しました。

解像度を調べるうまい方法が思いつかない

スクリーンショットの解像度は72dpiが圧倒的に多いのですが、Windowsだと標準は96dpiですし(とはいえ72dpiで吐き出すキャプチャソフトも多い)、Retina Displayだと144dpiになることもあります。

なので、できれば画像ファイルごとに解像度を調べる仕様にしたかったのですが、node.jsのサンプルを探すとたいていImageMagickという外部ツールが必要で、Win、Mac別々にそれをインストールしてもらう仕様になってしまいそうです(よくわかってないのですが)。

サーバサイドならともかく、クライアントツールでそれは厳しいなぁと思い、手動でdpiを指定する方式にしてしまいました。解像度は統一しようと思えばできないことはないですし。


これでとりあえず思い通りにレイアウトすることはできてきたので、後はうまくInDesignに持っていく方法を考えねば……