フラフラついてくる

実行イメージとソース

<UserControl x:Class="Easing.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Loaded="UserControl_Loaded" MouseMove="UserControl_MouseMove">
    <Canvas x:Name="area" Background="White">
      <Path x:Name="target" Width="20" Height="20" Canvas.Left="0" Canvas.Top="0">
        <Path.Fill>
          <RadialGradientBrush RadiusX="12" RadiusY="8">
            <RadialGradientBrush.RelativeTransform>
              <TranslateTransform X="0.15" Y="-0.15"/>
            </RadialGradientBrush.RelativeTransform>
            <RadialGradientBrush.GradientStops>
              <GradientStop Offset="0" Color="White" />
              <GradientStop Offset="0.058" Color="Blue" />
            </RadialGradientBrush.GradientStops>
          </RadialGradientBrush>
        </Path.Fill>
        <Path.Data>
          <EllipseGeometry RadiusX="20" RadiusY="20" />
        </Path.Data>
      </Path>
    </Canvas>
</UserControl>

Canvas の Left とか Top の設定を毎回書くのがめんどくさかったので省力化

public static class UIElementExtension
{
  public static double GetCanvasLeft(this UIElement source)
  {
    return (double)source.GetValue(Canvas.LeftProperty);
  }
  
  public static double GetCanvasTop(this UIElement source)
  {
    return (double)source.GetValue(Canvas.TopProperty);
  }

  public static void SetCanvasLeft(this UIElement source,double value)
  {
    source.SetValue(Canvas.LeftProperty,value);
  }

  public static void SetCanvasTop(this UIElement source,double value)
  {
    source.SetValue(Canvas.TopProperty, value);
  }
}

で、実際の処理部分

private double targetX = 0d;
private double targetY = 0d;
private double easingRatio = 0.08d;

private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
  CompositionTarget.Rendering += CompositionTarget_Rendering;
}

private void CompositionTarget_Rendering(object sender, EventArgs e)
{
  /*
  var distanceX = targetX - target.GetCanvasLeft();  //距離
  var distanceY = targetY - target.GetCanvasTop();
  var velocityX = distanceX * easingRatio;  //速度
  var velocityY = distanceY * easingRatio;
  target.SetCanvasLeft(velocityX + target.GetCanvasLeft());  //移動
  target.SetCanvasTop(velocityY + target.GetCanvasTop());
  */
   
  target.SetCanvasLeft(((targetX - target.GetCanvasLeft()) * easingRatio) + target.GetCanvasLeft());
  target.SetCanvasTop(((targetY - target.GetCanvasTop()) * easingRatio) + target.GetCanvasTop());
}

private void UserControl_MouseMove(object sender, MouseEventArgs e)
{
  targetX = e.GetPosition(this).X;
  targetY = e.GetPosition(this).Y;
}

イージング面白いです。ちょいと深掘りしてみます。

実行イメージとソース