【问题标题】:Strange act of canvas when Scale/ Zoom in Silverlight在 Silverlight 中缩放/缩放时画布的奇怪行为
【发布时间】:2012-05-21 10:44:26
【问题描述】:

我正在使用 Silverlight 5 进行缩放,

我的想法是根据画布上的鼠标位置以及拖动画布的能力进行缩放,

我遇到的问题是当比例小于1,大约0.6或0.5时,指向画布的一角并向上滚动,画布会改变它的位置或“跳跃”,请帮忙?

这两张照片描述了之前然后之后的状态:

我有以下 XAML:

<Grid x:Name="LayoutRoot" Background="White">
    <ScrollViewer x:Name="sv" Margin="0,0,0,76" ScrollViewer.VerticalScrollBarVisibility="Disabled" Background="#FFE3E7F1">
        <Canvas x:Name="grd" Height="394" Width="630">
            <Canvas x:Name="cvs" Background="White" MouseWheel="cvs_MouseWheel" MouseLeftButtonDown="cvs_MouseLeftButtonDown" MouseLeftButtonUp="cvs_MouseLeftButtonUp" MouseMove="cvs_MouseMove" Height="391" Canvas.Left="2" Canvas.Top="1" Width="625">
                <Canvas.Effect>
                    <DropShadowEffect ShadowDepth="0"/>
                </Canvas.Effect>
                <Rectangle Height="70" Canvas.Left="155" Canvas.Top="58" Width="79" Fill="#FFFFBFBF"/>
                <Rectangle Height="70" Canvas.Left="544" Canvas.Top="126" Width="79" Fill="#FF8B92FF"/>
            </Canvas>
        </Canvas>
    </ScrollViewer>
</Grid>

这里是 C#:

public partial class MainPage : UserControl
{
    CompositeTransform canvasTransform = new CompositeTransform();
    bool canDragCanvas;
    double mouseRelatedPositionX = 0;
    double mouseRelatedPositionY = 0;
    public MainPage()
    {
        // Required to initialize variables
        InitializeComponent();
    }

    private void cvs_MouseWheel(object sender, System.Windows.Input.MouseWheelEventArgs e)
    {
        var scaleFactor = 0.2*(e.Delta < 0?-1:1);
        var centerX = e.GetPosition(cvs).X;
        var centerY = e.GetPosition(cvs).Y;
        if (centerX > cvs.ActualWidth * canvasTransform.ScaleX || centerX < 0 || centerY > cvs.ActualHeight * canvasTransform.ScaleY || centerY < 0)
        {
            centerX = cvs.ActualWidth/2;
            centerY = cvs.ActualHeight/2;
        }
        canvasTransform.CenterX = centerX;
        canvasTransform.CenterY = centerY;
        canvasTransform.ScaleX += scaleFactor;
        canvasTransform.ScaleY += scaleFactor;
        cvs.RenderTransform = canvasTransform;
    }

    private void cvs_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
    {
        canDragCanvas = true;
        mouseRelatedPositionX = e.GetPosition(cvs).X;
        mouseRelatedPositionY = e.GetPosition(cvs).Y;
    }

    private void cvs_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
    {
        canDragCanvas = false;
    }

    private void cvs_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
    {
        if(!canDragCanvas) return;
        var leftValueToAdd = e.GetPosition(cvs).X - mouseRelatedPositionX;
        var topValueToAdd = e.GetPosition(cvs).Y - mouseRelatedPositionY;
        UpdateCanvasPosition(leftValueToAdd*canvasTransform.ScaleX, topValueToAdd*canvasTransform.ScaleX);
    }

    void UpdateCanvasPosition(double leftValueToAdd,double topValueToAdd)
    {
        var leftOffset = canvasTransform.CenterX - canvasTransform.CenterX * canvasTransform.ScaleX;
        var rightOffset = (cvs.ActualWidth - canvasTransform.CenterX) - (cvs.ActualWidth - canvasTransform.CenterX) * canvasTransform.ScaleX;
        var topOffset = canvasTransform.CenterY - canvasTransform.CenterY * canvasTransform.ScaleY;
        var bottomOffset = (cvs.ActualHeight - canvasTransform.CenterY) - (cvs.ActualHeight - canvasTransform.CenterY) * canvasTransform.ScaleY;

        var canvasLeftInBorders = Canvas.GetLeft(cvs)+ leftValueToAdd + leftOffset > 0;
        var canvasRightInBorders = Canvas.GetLeft(cvs) + cvs.ActualWidth * canvasTransform.ScaleX + leftValueToAdd + leftOffset < grd.ActualWidth;
        var canvasTopInBorders = Canvas.GetTop(cvs) + topValueToAdd + topOffset > 0;
        var canvasBottomInBorders = Canvas.GetTop(cvs) + cvs.ActualHeight * canvasTransform.ScaleY + topValueToAdd + topOffset < grd.ActualHeight;

        if (leftValueToAdd > 0)
        {
            if (canvasLeftInBorders)
                leftValueToAdd = 0;
        }
        else if (leftValueToAdd < 0)
            if (canvasRightInBorders)
                leftValueToAdd = 0;

        if (topValueToAdd > 0)
        {
            if (canvasTopInBorders)
                topValueToAdd = 0;
        }
        else if (topValueToAdd < 0)
            if (canvasBottomInBorders)
                topValueToAdd = 0;

        Canvas.SetLeft(cvs, Canvas.GetLeft(cvs) + leftValueToAdd);
        Canvas.SetTop(cvs,Canvas.GetTop(cvs)+topValueToAdd);
    }
}

【问题讨论】:

  • +1 用于提供代码、XAML 和图片!希望更多的问题是那么清楚。欢迎顶部 SO。

标签: silverlight zooming scaletransform


【解决方案1】:

基本上,您将鼠标事件附加到正在缩放的​​表面上,并且鼠标坐标也会改变。 Silverlight 被设计为在您旋转、缩放和倾斜时仍然具有交互性。

您想在顶部放置一个未缩放的透明层,并将鼠标方法附加到该层。

如果您打开该层,您将不得不计算碰撞,但您可以使该层仅在鼠标按下时出现并在鼠标抬起时消失。

【讨论】:

  • 是的,这正在工作...... Thaaaaanks .. 我是多么愚蠢.. -_-
猜你喜欢
  • 2011-05-29
  • 1970-01-01
  • 2016-08-26
  • 2014-05-16
  • 2013-12-31
  • 2016-12-21
  • 1970-01-01
  • 2014-06-26
  • 1970-01-01
相关资源
最近更新 更多