カメラには移動可能なオーバーレイとして想像できるビューポートがあります(コンテンツが配置されていない領域に背景が表示されます)。簡単にするために、私はコンテンツの変換(例えば、ズーム)からスクロール(すなわち、ビューポートの移動)を分離する。
このメンタルモデルに基づいて、あなたはあなたの内容の範囲だけでなく、現在のビューポート(ビューポートよりも小さい内容の場合は、例えば)の空の可能性部分であることを、スクロール可能な範囲を定義することができます。スクロール操作(現在のビューポート内の空きスペースの増減)またはコンテンツ操作(変換および境界変更)ごとに、スクロール可能な境界を再計算する必要があります。スクロールをスクロール可能な境界に制限すると、スクロール操作によってビューポート内の空き領域が増えることはありません。
コンテンツのbounds-in-localプロパティとlocal-to-parent-transformプロパティにバインドされたObjectBinding scrollableBoundsを作成し、ビューポート境界にすることができます。次に、バインディングにバインドされているscollableBoundsPropertyを作成できます。そのプロパティは、適用する前に翻訳を制限するためにスクロールするときにアクセスすることができ、したがってビューポート内の空きスペースの増加を防ぎます。
ObjectBinding<Bounds> scrollableBoundsBinding = new ObjectBinding<>() {
{
// TODO: bind to dependencies: viewport bounds and content bounds
// TODO: (transformed to the same coordinate system)
bind(camera.boundsInParentProperty(),
contentPane.boundsInLocalProperty(),
contentPane.localToParentTransformProperty());
}
@Override protected Bounds computeValue() {
// TODO: compute union of viewport and content bounds
return unionBounds(viewportBounds, contentBounds);
}
};
ObjectProperty<Bounds> scrollableBoundsProperty = new SimpleObjectProperty<>(
scrollableBoundsBinding);
// ...
// on mouse drag:
// dx, dy: relative mouse movement
// tx, ty: current scrolling
// mintx, maxtx, minty, maxty: translation range
// (taken from scrollable bounds and viewport size)
if (dx < 0) { tx = max(mintx, tx + dx); }
else { tx = min(maxtx, tx + dx); }
if (dy < 0) { ty = max(minty, ty + dy); }
else { ty = min(maxty, ty + dy); }
コンテンツがビューポート内に完全に収まるようにすると、スクロールをさらに制限することができます。コンテンツを左上隅に配置します。また、最小ズームレベルを制限して、内容ができるだけ大きく表示されるようにすることもできます。
ユーザビリティに関する注意:すでに別の回答が指摘しているように、コンテンツをドラッグすることを許可することを検討したいと思うかもしれません。効率を低下させてコンテンツからスクロールしようとすると、 Safariでタッチパッド経由でスクロールする方法次に、インタラクションが終了すると、スナップの代わりに元に戻って、ビューポートをコンテンツに再び制限することができます。
コンテンツに可能な変換は何ですか? –
@JoseMartinez私はほとんどの形式の変換を許可していますが、Z軸変換以外の変換は適用されませんが、カメラでX軸とY軸に沿って移動しながら適用する制約を探しています –