
手机录制的效果掉帧,实际的视觉效果极其丝滑流畅。
这个效果模拟了ipad里面的 右滑屏幕 时的效果,主页高斯模糊渐变,左侧工具条滑动进入。
高斯模糊动画:
cs
private void Canvas_Draw(CanvasControl sender, CanvasDrawEventArgs args)
{
var ds = args.DrawingSession;
if (sourceImage == null)
return;
if (isAnimating)
{
UpdateAnimation();
}
DrawBlurredImage(ds, sender);
sender.Invalidate();
}
private void UpdateAnimation()
{
float deltaTime = 1f / 60f; // 假设60fps
animationProgress += (deltaTime / animationDuration) * animationSpeed;
if (isReverseAnimation)
{
// 反向动画:从目标值回到0
float t = Math.Clamp(animationProgress, 0f, 1f);
float easedT = EaseInOutCubic(t);
currentBlurAmount = targetBlurAmount * (1f - easedT);
if (animationProgress >= 1f)
{
isAnimating = false;
animationProgress = 0f;
currentBlurAmount = 0f;
}
}
else
{
// 正向动画:从0到目标值
float t = Math.Clamp(animationProgress, 0f, 1f);
float easedT = EaseInOutCubic(t);
currentBlurAmount = targetBlurAmount * easedT;
if (animationProgress >= 1f)
{
isAnimating = false;
animationProgress = 0f;
currentBlurAmount = targetBlurAmount;
}
}
}
private void DrawBlurredImage(CanvasDrawingSession ds, CanvasControl sender)
{
if (sourceImage == null)
return;
var canvasWidth = (float)sender.ActualWidth;
var canvasHeight = (float)sender.ActualHeight;
// 计算图像居中位置
float imageWidth = (float)sourceImage.Size.Width;
float imageHeight = (float)sourceImage.Size.Height;
float x = (canvasWidth - imageWidth) / 2;
float y = (canvasHeight - imageHeight) / 2;
if (currentBlurAmount > 0.1f)
{
// 应用高斯模糊效果
using (var blurEffect = new GaussianBlurEffect
{
Source = sourceImage,
BlurAmount = currentBlurAmount,
Optimization = EffectOptimization.Speed,
BorderMode = EffectBorderMode.Soft
})
{
ds.DrawImage(blurEffect, x, y);
}
}
else
{
// 模糊值太小时直接绘制原图
ds.DrawImage(sourceImage, x, y);
}
}
左侧划入动画:
cs
// 侧边栏滑入动画
private void AnimateSidebarSlideIn()
{
if (isSidebarAnimated)
return;
// 获取 Compositor 和 Visual
var compositor = ElementCompositionPreview.GetElementVisual(SidebarContainer).Compositor;
var visual = ElementCompositionPreview.GetElementVisual(SidebarContainer);
// 创建位移动画
var offsetAnimation = compositor.CreateVector3KeyFrameAnimation();
offsetAnimation.Duration = TimeSpan.FromSeconds(0.4);
// 起始位置
offsetAnimation.InsertKeyFrame(0.0f, new Vector3(-300, 0, 0));
// 结束位置,使用自定义缓动函数
var easing = compositor.CreateCubicBezierEasingFunction(
new Vector2(0.25f, 0.1f),
new Vector2(0.25f, 1.0f)
);
offsetAnimation.InsertKeyFrame(1.0f, new Vector3(20, 0, 0), easing);
visual.StartAnimation("Offset", offsetAnimation);
isSidebarAnimated = true;
}
// 侧边栏滑出动画(反向)
private void AnimateSidebarSlideOut()
{
if (!isSidebarAnimated)
return;
// 获取 Compositor 和 Visual
var compositor = ElementCompositionPreview.GetElementVisual(SidebarContainer).Compositor;
var visual = ElementCompositionPreview.GetElementVisual(SidebarContainer);
// 创建位移动画
var offsetAnimation = compositor.CreateVector3KeyFrameAnimation();
offsetAnimation.Duration = TimeSpan.FromSeconds(0.4);
// 起始位置
offsetAnimation.InsertKeyFrame(0.0f, new Vector3(20, 0, 0));
// 结束位置,使用自定义缓动函数
var easing = compositor.CreateCubicBezierEasingFunction(
new Vector2(0.75f, 0.0f),
new Vector2(0.75f, 0.9f)
);
offsetAnimation.InsertKeyFrame(1.0f, new Vector3(-300, 0, 0), easing);
visual.StartAnimation("Offset", offsetAnimation);
isSidebarAnimated = false;
}
再次来看一下进入进出的效果:
