I'm trying to do an Matrix animation where I both scale and transpose a canvas at the same time. The only approach I found was using a MatrixTransform and MatrixAnimationUsingKeyFrames. Since there doesnt seem to be any interpolation for matrices built in (only for path/rotate) it seems the only choice is to try and build the interpolation and DiscreteMatrixKeyFrame's yourself.
I did a basic implementation of this but it isnt exactly smooth and I'm not sure if this is the best way and how to handle framerates etc. Anyone have suggestions for improvement? Here's the code:
MatrixAnimationUsingKeyFrames anim = new MatrixAnimationUsingKeyFrames();
int duration = 1;
anim.KeyFrames = Interpolate(new Point(0, 0), centerPoint, 1, factor,100,duration);
this.matrixTransform.BeginAnimation(MatrixTransform.MatrixProperty, anim,HandoffBehavior.Compose);
public MatrixKeyFrameCollection Interpolate(Point startPoint, Point endPoint, double startScale, double endScale, double framerate,double duration)
{
MatrixKeyFrameCollection keyframes = new MatrixKeyFrameCollection();
double steps = duration * framerate;
double milliSeconds = 1000 / framerate;
double timeCounter = 0;
double diffX = Math.Abs(startPoint.X- endPoint.X);
double xStep = diffX / steps;
double diffY = Math.Abs(startPoint.Y - endPoint.Y);
double yStep = diffY / steps;
double diffScale= Math.Abs(startScale- endScale);
double scaleStep = diffScale / steps;
if (endPoint.Y < startPoint.Y)
{
yStep = -yStep;
}
if (endPoint.X < startPoint.X)
{
xStep = -xStep;
}
if (endScale < startScale)
{
scaleStep = -scaleStep;
}
Point currentPoint = new Point();
double currentScale = startScale;
for (int i = 0; i < steps; i++)
{
keyframes.Add(new DiscreteMatrixKeyFrame(new Matrix(currentScale, 0, 0, currentScale, currentPoint.X, currentPoint.Y), KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(timeCounter))));
currentPoint.X += xStep;
currentPoint.Y += yStep;
currentScale += scaleStep;
timeCounter += milliSeconds;
}
keyframes.Add(new DiscreteMatrixKeyFrame(new Matrix(endScale, 0, 0, endScale, endPoint.X, endPoint.Y), KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(0))));
return keyframes;
}