c# – 当缩放中心因地铁式应用程序中的捏(缩放)或其他手势而发生变化时,如何在画布上缩放时避免“跳跃”

我怎样才能避免“跳”,而画布对象上的调整,当缩放中心的变化,由于撑开(变焦)或其他姿势的Metro风格的应用程序

我尝试存档的行为类似于预安装的win8地图应用的缩放行为.如果您执行捏合手势(放大或缩小),缩放中心将设置在手指之间的中间位置.如果你抬起一个手指,将其放置在另一个点,你能够立即对另一变焦操作,变焦变化中心正确,内部消除(UI的跳跃在画布对象的坐标)任何跳跃.

我正在尝试使用复合变换在大型Canvas对象(在C#WinRT应用程序中)上实现类似的行为.我想允许翻译和缩放,没有旋转(现在,也许我稍后会添加它):

我这样初始化,将缩放中心放在屏幕中心:

this.compositeTransform = new CompositeTransform();
this.compositeTransform.CenterX = this.mainPage.Width / 2.0;
this.compositeTransform.CenterY = this.mainPage.Height / 2.0;

this.innerCanvas.RenderTransform = compositeTransform;

然后我将使用操作delta事件来获取输入数据

private void InnerCanvas_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
{                        
    this.compositeTransform.ScaleX *= e.Delta.Scale;
    this.compositeTransform.ScaleY *= e.Delta.Scale;

    this.compositeTransform.CenterX = e.Position.X;
    this.compositeTransform.CenterY = e.Position.Y;

    this.compositeTransform.TranslateX += e.Delta.Translation.X;
    this.compositeTransform.TranslateY += e.Delta.Translation.Y;                      
}

只要我执行相同的手势,这就可以正常工作.当我执行捏合手势时,正确计算新中心.然而,改变缩放中心会导致突然跳跃,例如在捏动手势之后抬起其中一个手指时.当然,我只能为捏手势改变中心,但跳跃的问题仍然存在.这当然是合乎逻辑的,因为缩放适用于新的缩放中心.我还没想出办法,如何避免跳跃.由于比例值本身保持不变,因此必须可以使用相同的外观(不变的坐标)和更改的中心.

我当前的理由是,我必须改变平移X和translateY坐标不知何故,为了在某种程度上失去平衡的新中心点,该UI元素的当前屏幕坐标保持不变.像这样的东西(scaleTransform是一个ScaleTransform,它只获取缩放数据)…

Point reverseScaleTransform =
    this.scaleTransform.Inverse.TransformPoint(new Point(e.Position.X,e.Position.Y));

this.compositeTransform.TranslateX += reverseScaleTransform.X - e.Position.X;
    this.compositeTransform.TranslateY += reverseScaleTransform.Y - e.Position.Y;

但这也不起作用.整个事情似乎是平板电脑上的一个标准问题,但我没有找到解决方案,尽管搜索过多,也许我使用错误的关键词.

最佳答案 我终于想通了,如何通过手动转换解决问题,而不是使用ScrollViewer.

    TranslateTransform tmpTranslate = new TranslateTransform();

    private void InnerCanvas_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
    {                                       
        //Transform world space into local space (origin: Scale center from the last manipulation event)            

        this.tmpTranslate.X = this.compositeTransform.CenterX;
        this.tmpTranslate.Y = this.compositeTransform.CenterY;

        Point center = this.compositeTransform.Inverse.TransformPoint(e.Position);

        Point localPoint = tmpTranslate.Inverse.TransformPoint(center);                        

        //Now scale the point in local space

        localPoint.X *= this.compositeTransform.ScaleX;
        localPoint.Y *= this.compositeTransform.ScaleY;

        //Transform local space into world space again
        Point worldPoint = tmpTranslate.TransformPoint(localPoint);

        //Take the actual scaling...
        Point distance = new Point(
            worldPoint.X - center.X,
            worldPoint.Y - center.Y);

        //...amd balance the jump of the changed scaling origin by changing the translation            

        this.compositeTransform.TranslateX += distance.X;
        this.compositeTransform.TranslateY += distance.Y;

        //Also set the scaling values themselves, especially set the new scale center...

        this.compositeTransform.ScaleX *= e.Delta.Scale;
        this.compositeTransform.ScaleY *= e.Delta.Scale;            

        this.compositeTransform.CenterX = center.X;
        this.compositeTransform.CenterY = center.Y;

        //And consider a translational shift

        this.compositeTransform.TranslateX += e.Delta.Translation.X;
        this.compositeTransform.TranslateY += e.Delta.Translation.Y;                                    
    }
点赞