DTPab

DTPにまつわるあれこれ

アイテムの存在するページの確認

あるアイテムがドキュメントの何ページ目にあるのかというのは、スクリプトを介して意外と簡単に取得できます。ただ、それが意図した結果かどうかというのは別の話です。スクリプトではよくある話ですね。
というわけで、まずは下図をご覧ください。

f:id:uske_S:20170813131325p:plain

見開きいっぱいのオブジェクトがA〜D、そしてマゼンタ色の正方形が3つあります。A〜Dはわずかに(肉眼ではわからないレベルで)数値を変えてあります(後述)。マゼンタの正方形はページマージンがオブジェクトのど真ん中になるように配置しています。
判型はA4なので、座標値は左ページの左端を0としたとき、ノドの中央が210mm、右ページの右端が420mmになります。また、ページ下部の数字がページのノンブルです。
さて、InDesignはこれらのオブジェクトを何ページ目にあると判断するでしょうか。スクリプトではオブジェクトのparentPageプロパティを参照することで、そのページを取得することができます*1。それと併せて、細かな座標値の確認もしてみます。それぞれに対して下記のスクリプトを実行してみましょう。

var s = app.activeDocument.selection[0], result = [];
result.push("【ページ】"+s.parentPage.name);
result.push("【座標値】左端:"+decRound(s.geometricBounds[1]));
result.push("【座標値】中央:"+decRound((s.geometricBounds[3]-s.geometricBounds[1])/2));
result.push("【座標値】右端:"+decRound(s.geometricBounds[3]));
$.writeln(result.join("\n"));
//四捨五入関数
function decRound (x){
    var hoge = Math.pow(10,2);
    return Math.round(x*hoge)/hoge;
    }

結果は下記の通りです。
A(幅420mm、中央に配置)
【ページ】2
【座標値】左端:0
【座標値】中央:210
【座標値】右端:420
B(Aを右に0.01mm右に移動したもの)
【ページ】3
【座標値】左端:0.01
【座標値】中央:210.01
【座標値】右端:420.01
C(Aを0.1mm右方向に大きくしたもの)
【ページ】2
【座標値】左端:0
【座標値】中央:210.05
【座標値】右端:420.1
D(Aを中心基準で0.1mm小さくしたもの)
【ページ】3
【座標値】左端:0.05
【座標値】中央:210
【座標値】右端:419.95
マゼンタ左
【ページ】2
【座標値】左端:-7.5
【座標値】中央:0
【座標値】右端:7.5
マゼンタ中央
【ページ】3
【座標値】左端:202.5
【座標値】中央:210
【座標値】右端:217.5
マゼンタ右
【ページ】3
【座標値】左端:412.5
【座標値】中央:420
【座標値】右端:427.5

この結果から、下記のようなInDesignの仕様?を見て取れます。

  1. parentPageとして取得されるページは、オブジェクトの中心の座標(Bなど)
  2. 中心の座標がページの境目ピッタリだと、ノンブルの大きい方になる(マゼンタ中央など)
  3. ただしオブジェクトの端点がノンブルの小さいページのページマージンに触れる場合は、中央座標が次のページに存在しても、parentPageはノンブルの小さい方のページとなる(C)

1と2については直感的に分かりやすいのですが、3についてはこういう仕様だ、と考えて納得するしかないですね。
余談ですが、先程のデータのノンブルをいじって左右の見開きを入れ替えると、parentPageで取得されたページ側にオブジェクトが移動します。

f:id:uske_S:20170813131340p:plain

さて、ここからが本題です。
例えば、目次や索引、また相互参照のような機能をスクリプトで実装しようとした場合、このparentPageのこうした仕様を把握しておかないと、冒頭に書いたように「意図した結果」が得られないことになるわけです。
例えばオブジェクトの配置してあるページ数を抽出して索引を作ろう、と仮定してみます。
先程の見開きから、左右ページにまたいであるものについては「ページ数の小さい方」を基準にページを抽出してください、という仕様だったらどうでしょうか。一律にparentPageで取得してしまうと、BやD、マゼンタの中央のものは3ページとして抽出され、スクリプトの結果が意図したものになりません。
また、parentPageはそのオブジェクトが存在するページオブジェクトを取得しますが、ペーストボード上(製版線の外)のオブジェクトに対してはparentPageはページオブジェクトではなくnullを返します。したがって、仮にペーストボードのオブジェクトもどのスプレッドにあるのか調べたいという場合は、中綴製作所さんのこの記事などを参考にしてください*2
で、実際どうすれば「意図した結果」が得られるかですが、純粋に座標値から判断するしかありません。オブジェクトであればgeometricBoundsvisibleBounds、テキスト類であればhorizontalOffsetなどで座標を得る必要があります。

ただ、このparentPageに頼らない方法は、かなり骨が折れます。単純にparentPageで目的が達成できればそれに越したことはありません。スクリプトの仕様を十分に検討し、どうしてもこの方法でないとまずい、という場合にのみ採用されると良いと思います。
実際にこの座標値基準でのページ取得ですが、だいたい下記のような事項について処理の検討が必要になります。

  • 単位設定の「定規の単位>開始位置」がスプレッドかそれ以外か(これが「ページ」や「ノド元」だと途端に作業負担が増えるので「スプレッド」を推奨)
  • 右開きか左開きか
  • オブジェクトがドキュメントの何スプレッド目にあるか
  • スプレッドに存在するページの数を確認(3ページ以上で構成された見開きも存在する可能性を加味する)
  • ページそれぞれのサイズ(幅)を確認(ページごとにサイズが違う可能性を加味する)
  • 対象となるオブジェクトの左側の座標、右側の座標などから何を基準にページとするか決める

思いつく範囲で列記してみました。まだ足りないような気もしますが、概ねこんなところでしょう…。
長くなってしまったので記事はこの辺で終えたいと思いますが、parentPageがどうこうというより、このInDesignの仕様(見開き上に存在するオブジェクトの帰属ページに関する仕様)は知っておくべきかなと思います。
最後に、索引抽出スクリプト、というところでは以下の照山さんの記事に面白いスクリプトがあります。興味のある方は中を覗いてみてください。

mottainaidtp.seesaa.net

以上、アイテムの存在するページの確認の仕方についての一考察でした。

*1:CS5以降のプロパティ

*2:オブジェクトのparentPageがnullを返すのかページオブジェクトを返すのかの基準は、オブジェクトの大半がペーストボードにあったとしても、ページの仕上がりに触れているどうかが基準です(オブジェクトの中央座標が基準ではありません)