• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 612
  • Last Modified:

Zoom Calculations

Hi all,

I'm trying to implement zooming on my page.  I would like the center to be wherever the mouse pointer currently is.  Not seeing the solution, but I know it has to do with the ratios in terms of screen coords and real coords.

Explinations would be extremely helpful.

XAML below, code is code behind.




XAML:
<UserControl x:Class="FloorPlan.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     MouseMove="Page_MouseMove">
    <UserControl.Resources>

        <Storyboard x:Name="ZoomStoryboard">
       


       
            <DoubleAnimation x:Name="ZoomAnimationX"
                                 Storyboard.TargetName="FloorScale"
                                 Storyboard.TargetProperty="ScaleX"
                                 Duration="0:0:0.2"/>
                                 
            <DoubleAnimation x:Name="ZoomAnimationY"
                                 Storyboard.TargetName="FloorScale"
                                 Storyboard.TargetProperty="ScaleY"
                                 Duration="0:0:0.2"/>



            <DoubleAnimation x:Name="CenterAnimationX"
                                 Storyboard.TargetName="FloorScale"
                                 Storyboard.TargetProperty="CenterX"
                                 Duration="0:0:0.2"/>

            <DoubleAnimation x:Name="CenterAnimationY"
                                 Storyboard.TargetName="FloorScale"
                                 Storyboard.TargetProperty="CenterY"
                                 Duration="0:0:0.2"/>
        </Storyboard>
     </UserControl.Resources>


    <Canvas x:Name="Floor" MouseWheel="Floor_MouseWheel">
        <Canvas.RenderTransform>
            <ScaleTransform x:Name="FloorScale" ScaleX="1" ScaleY="1"/>
        </Canvas.RenderTransform>        
       
        <Grid  ShowGridLines="false"  x:Name="LayoutRoot" Background="White"  >
       
        </Grid>
       
        <TextBlock x:Name="tbMouseX" Canvas.Left="100" Canvas.Top="100">
        </TextBlock>

        <TextBlock x:Name="tbMouseY" Canvas.Left="150" Canvas.Top="100">
        </TextBlock>
    </Canvas>
   
   
       
</UserControl>


Private Sub Floor_MouseWheel(ByVal sender As System.Object, ByVal e As System.Windows.Input.MouseWheelEventArgs)
        Static _ZoomSteps As Integer = 0
        Static _Zoom As Double = 0
        Static _CenterX As Double
        Static _CenterY As Double

        Dim deltaZoom As Double = e.Delta
 

        _Zoom += deltaZoom / 150
        If _Zoom <= 1 Then
            _Zoom = 1
        End If

        If deltaZoom >= 0 Then
            If _ZoomSteps = -1 Then
                _CenterX = 0
                _CenterY = 0
                _ZoomSteps = 0
            Else
                _CenterX = (_CenterX * (Math.Abs(_ZoomSteps) + mouseX) / (Math.Abs(_ZoomSteps + 1)))
                _CenterY = (_CenterY * (Math.Abs(_ZoomSteps) + mouseY) / (Math.Abs(_ZoomSteps + 1)))

                _ZoomSteps += 1
            End If
        Else
            If _ZoomSteps = 1 Then
                _CenterX = 0
                _CenterY = 0
                _ZoomSteps = 0
            Else
                _CenterX = (_CenterX * Math.Abs(_ZoomSteps) - mouseX) / (Math.Abs(_ZoomSteps - 1))
                _CenterY = (_CenterY * Math.Abs(_ZoomSteps) - mouseY) / (Math.Abs(_ZoomSteps - 1))
                _ZoomSteps -= 1
            End If
        End If



        ZoomAnimationX.[To] = _Zoom
        ZoomAnimationY.[To] = _Zoom

        CenterAnimationX.To = Math.Abs(_CenterX)
        CenterAnimationY.To = Math.Abs(_CenterY)


        ZoomStoryboard.Begin()
        mouseX = CType(_CenterX, Integer)
        mouseY = CType(_CenterY, Integer)
        tbMouseX.Text = mouseX.ToString()
        tbMouseY.Text = mouseY.ToString()
    End Sub

    Private Sub Page_MouseMove(ByVal sender As System.Object, ByVal e As System.Windows.Input.MouseEventArgs)

        mouseX = e.GetPosition(Nothing).X
        mouseY = e.GetPosition(Nothing).Y
        tbMouseX.Text = mouseX.ToString()
        tbMouseY.Text = mouseY.ToString()

    End Sub

Open in new window

0
Kyle Abrahams
Asked:
Kyle Abrahams
  • 2
1 Solution
 
jgordosCommented:
What, exactly, is the question?
0
 
Kyle AbrahamsSenior .Net DeveloperAuthor Commented:
How do you zoom to the mouse pointer correctly?  (similiar to google maps)
0
 
Kyle AbrahamsSenior .Net DeveloperAuthor Commented:
My issue was that I was calling e.GetPosition with nothing when I needed to get it relative to the object:
            mouseX = e.GetPosition(LayoutRoot).X
            mouseY = e.GetPosition(LayoutRoot).Y

I updated the XAML to keep layoutroot at the top level, then have the floor as a child of that.  Attached is the relevant code for anyone else who may stumble upon this and need it.



<UserControl x:Class="FloorPlan.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     MouseMove="Page_MouseMove" MouseLeftButtonDown="Floorplan_MouseLeftButtonDown" MouseLeftButtonUp="FloorPlan_MouseLeftButtonUp"
     LostMouseCapture="FloorPlan_LostMouseCapture" LostFocus="FloorPlan_LostFocus" MouseEnter="FloorPlan_MouseEnter"
     MinHeight="600" MinWidth="800"> 
    <UserControl.Resources>

        <Storyboard x:Name="ZoomStoryboard">
        
        
            <DoubleAnimation x:Name="ZoomAnimationX" 
                                 Storyboard.TargetName="FloorScale" 
                                 Storyboard.TargetProperty="ScaleX" 
                                 Duration="0:0:0.2"/>
                                 
            <DoubleAnimation x:Name="ZoomAnimationY" 
                                 Storyboard.TargetName="FloorScale" 
                                 Storyboard.TargetProperty="ScaleY" 
                                 Duration="0:0:0.2"/>



            <DoubleAnimation x:Name="CenterAnimationX" 
                                 Storyboard.TargetName="FloorScale" 
                                 Storyboard.TargetProperty="CenterX" 
                                 Duration="0:0:0.2"/>

            <DoubleAnimation x:Name="CenterAnimationY" 
                                 Storyboard.TargetName="FloorScale" 
                                 Storyboard.TargetProperty="CenterY" 
                                 Duration="0:0:0.2"/>
        </Storyboard>
     </UserControl.Resources>


    <Canvas x:Name="LayoutRoot">
        <Canvas.RenderTransform>
            <TransformGroup x:Name="FloorTransform">
                <ScaleTransform x:Name="FloorScale" ScaleX="1" ScaleY="1"/>
                <TranslateTransform x:Name="FloorTranslate" X="0" Y="0"/>
            </TransformGroup>
        </Canvas.RenderTransform>
        <Canvas x:Name="Floor" MouseWheel="Floor_MouseWheel" >
    
      
        
        <Grid  ShowGridLines="false"  x:Name="FloorGrid" Background="White"  >
       
        </Grid>
        
        <TextBlock x:Name="tbMouseX" Canvas.Left="100" Canvas.Top="100">
        </TextBlock>

        <TextBlock x:Name="tbMouseY" Canvas.Left="150" Canvas.Top="100">
        </TextBlock>

        <TextBlock x:Name="tbCanX" Canvas.Left="100" Canvas.Top="150">
        </TextBlock>

        <TextBlock x:Name="tbCanY" Canvas.Left="150" Canvas.Top="150">
        </TextBlock>
    </Canvas>

    </Canvas>

</UserControl>





Private Sub Floor_MouseWheel(ByVal sender As System.Object, ByVal e As System.Windows.Input.MouseWheelEventArgs)
        Static _ZoomSteps As Integer = 0
        Static _Zoom As Double = 1 'same as ScaleX, ScaleY



        Dim deltaX As Double = Floor.ActualWidth / 2 - mouseX
        Dim deltaY As Double = Floor.ActualHeight / 2 - mouseY

        'adjust for current scale.
        deltaX = deltaX * FloorScale.ScaleX
        deltaY = deltaY * FloorScale.ScaleY



        Dim deltaZoom As Double = e.Delta

        'how much to zoom in, adjust divisor for granualirity
        _Zoom += deltaZoom / 150
        If _Zoom <= 1 Then
            _Zoom = 1
        End If

        'zoom in
        If deltaZoom >= 0 Then

            'max 20 zoom steps
            If _ZoomSteps < 20 Then
                _ZoomSteps += 1
            End If

            'zoom out
        Else
            If _ZoomSteps > 0 Then
                _ZoomSteps -= 1
            End If
        End If


        Dim p As New Point(mouseX / ActualWidth, mouseY / ActualHeight)
        ZoomAnimationX.[To] = _Zoom
        ZoomAnimationY.[To] = _Zoom

        LayoutRoot.RenderTransformOrigin = p


        CenterAnimationX.[To] = p.X ' mouseX * CType(1 / _Zoom, Double)
        CenterAnimationY.[To] = p.Y 'mouseY * CType(1 / _Zoom, Double)


        ZoomStoryboard.Begin()

        tbMouseX.Text = CType(mouseX, Integer).ToString()
        tbMouseY.Text = CType(mouseY, Integer).ToString()


    End Sub

    Private Sub Page_MouseMove(ByVal sender As System.Object, ByVal e As System.Windows.Input.MouseEventArgs)

        If dragging Then
            FloorTranslate.X += e.GetPosition(Nothing).X - mouseX
            FloorTranslate.Y += e.GetPosition(Nothing).Y - mouseY
            LayoutRoot.RenderTransform = FloorTransform
            mouseX = e.GetPosition(Nothing).X
            mouseY = e.GetPosition(Nothing).Y
            'If LayoutRoot.GetLeft(Floor) < 0 Then
            '    LayoutRoot.SetLeft(Floor, 0)
            'End If
        Else
            mouseX = e.GetPosition(LayoutRoot).X
            mouseY = e.GetPosition(LayoutRoot).Y
        End If

 
        tbMouseX.Text = CType(mouseX, Int16).ToString()
        tbMouseY.Text = CType(mouseY, Int16).ToString()

    End Sub



    Private Sub Floorplan_MouseLeftButtonDown(ByVal sender As System.Object, ByVal e As System.Windows.Input.MouseButtonEventArgs)
        dragging = True
        mouseX = e.GetPosition(Nothing).X
        mouseY = e.GetPosition(Nothing).Y
    End Sub
    Private Sub FloorPlan_MouseLeftButtonUp(ByVal sender As System.Object, ByVal e As System.Windows.Input.MouseButtonEventArgs)
        dragging = False
    End Sub

    Private Sub FloorPlan_LostMouseCapture(ByVal sender As System.Object, ByVal e As System.Windows.Input.MouseEventArgs)
        dragging = False
    End Sub

    Private Sub FloorPlan_LostFocus(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
        dragging = False

    End Sub

    Private Sub FloorPlan_MouseEnter(ByVal sender As System.Object, ByVal e As System.Windows.Input.MouseEventArgs)
        dragging = False
    End Sub

Open in new window

0

Featured Post

2018 Annual Membership Survey

Here at Experts Exchange, we strive to give members the best experience. Help us improve the site by taking this survey today! (Bonus: Be entered to win a great tech prize for participating!)

  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now