私は、canvas要素を使用してWPFでプログラムをプロットする作業をしています。私が達成したいのは、ドラッグ可能な端点を備えたスクロールバーです。これらの種類のスクロールバーの例は、AdobeのAfterEffectsビデオ編集ソフトウェアにあります。
このようなスクロールバーの基本的な機能は、コンテナよりも大きいコンテンツをスクロールできることですが、左右のエンドポイントをドラッグして、コンテンツのスケールを動的に変更できます。
プロットプログラムに同様のスクロールバーを実装しました。ユーザーは、インポイントとアウトポイント(キャンバス内の長方形)をドラッグできる必要があり、プロットキャンバスは、目的の範囲にスケーリングすることでこれに応答する必要があります。これに必要な情報:
- プロット全体の幅(プロットポイントの量)
- コンテナの幅(静的、600px)
- スクロールバーキャンバスの全幅に対するインポイントとアウトポイントのパーセンテージ
この情報を使用して、ScaleAt()メソッドを使用してMatrixTransformを作成し、コンテナー内のプロットキャンバスをスケーリングして、下のスクロールバーのインポイントとアウトポイントに一致させます。このために、私は次のコードを使用しました。resetTransformは、着信データに対応するために1秒間にFPSと呼ばれ、XMAXとYMAXはこれを反映するために他の場所で更新されます。
public void resetTransform(Boolean useSlider = false)
{
//Add transformgroup to plot
double yscale = plot.Height / view.YMAX; //YMAX is maximum plot value received
double xscale = plot.Width / view.XMAX; //XMAX is total ammount of plotted points
Matrix m = new Matrix(1, 0, 0, 1, 0, 0);
if (useSlider)
{
double maxVal = zoomBar.ActualWidth - outPoint.Width;
double outP = Canvas.GetLeft(outPoint); //points position relative to the scrollbar
double inP = Canvas.GetLeft(inPoint);
double center = (((outP + inP) / 2) / maxVal) * plot.ActualWidth;
double delta = (outP-inP);
double factor = (maxVal/delta) * xscale;
double mappedinP = (inP / maxVal) * view.XMAX;
double anchorOut = (outP / maxVal) * view.XMAX;
double anchorIn = (inP / maxVal) * view.XMAX;
m.ScaleAt(factor, -yscale,center,0); //scale around the center point,
m.Translate(0, plot.Height); //to compensate the flipped graph, move it back down
}
scale = new ScaleTransform(m.M11, m.M22, 0, 0); //save scale factors in a scaletransform for reference
signals.scaleSignalStrokes(scale); //Scale the plotlines to compensate for canvas scaling
MatrixTransform matrixTrans = new MatrixTransform(m); //Create matrixtransform
plot.RenderTransform = matrixTrans; //Apply to canvas
}
期待:すべてが機能するはずであり、プロットポイントの量が時間の経過とともに増加すると、プロットされたグラフは適切にスケーリングされます。現実:グラフはポイントを移動すると拡大縮小されますが、代表的なものではありません。さらに、追加されるプロットポイントが多いほど、キャンバス全体が右にシフトし、変換に対する制御が弱くなるように見えます。現在のアルゴリズムは、おそらく私が必要とする結果を得るための間違ったアプローチですが、私はこれを正しく行う方法を考えるのにかなりの時間を費やしました。
アップデート
インタラクションをより明確に示すために、ビデオをアップロードしました。ビデオでは、キャンバスが右にシフトしているのがはっきりとわかります。 スクリーンキャプチャビデオ
2つの境界内に収まるようにキャンバス(プロット)をどのように拡大縮小する必要がありますか?