0

I have been struggling with an issue for a number of days now. I believe I am close but the solution keeps eluding me.

I have a canvas to which I dynamically place different shapes on. Using the ManipulationDelta event I allow the user to move the shape around. Within this event I also get the Bounds of the window and use them to keep the user from dragging the shape off the screen. All of this works currently.

void OnShapeManipulation(object sender, ManipulationDeltaRoutedEventArgs e)
    {
        Shape shape = sender as Shape; 
        CompositeTransform tt = shape.RenderTransform as CompositeTransform;

        tt.TranslateX += e.Delta.Translation.X;
        tt.TranslateY += e.Delta.Translation.Y;   

        double top = Window.Current.Bounds.Top;
        double bottom = Window.Current.Bounds.Bottom ;
        double right = Window.Current.Bounds.Right ;
        double left = Window.Current.Bounds.Left ;

        if (tt.TranslateY < top)
            tt.TranslateY = top;

        if (tt.TranslateY > (bottom - shape.ActualHeight))
            tt.TranslateY = bottom - shape.ActualHeight;

        if (tt.TranslateX > (right - shape.ActualWidth))
            tt.TranslateX = right - shape.ActualWidth;

        if (tt.TranslateX < left)
            tt.TranslateX = left; 
    }

The issue is that when the tablet is rotated I scale the canvas as shown here.

void MainCanvas_SizeChanged(object sender, SizeChangedEventArgs e)
    {
        double actualWidth = this.MainCanvas.ActualWidth / 1366;
        double actualHeight = this.MainCanvas.ActualHeight / 768;
        double min = Math.Min(actualWidth, actualHeight);

        if (!this.istransformed && min == 1)
            return;

        this.istransformed = true;

        var transform = MainCanvas.RenderTransform as CompositeTransform;
        transform.ScaleX = min;
        transform.ScaleY = min;
        transform.CenterX = this.ActualWidth / 2;
        transform.CenterY = this.ActualHeight / 2;  
    }

This also works, but with one caveat. In this portrait mode / scaled canvas the shapes can only be dragged around a portion of the canvas. Breaking on the ManipulationDelta shows that the shape themselves despite being scaled visually still believe they are their original Height and Width. The coordinates for that shape also reflect the unscaled canvas. For instance a Circle will say that its X is 1000, even though it is visible on the screen and the max canvas width is only 786 at the time.

How do I apply the scale correctly to my movement translation?

Thanks

jrandomuser
  • 1,510
  • 19
  • 50
  • MVVM is your friend. Do not use Transforms for this. See my examples [1](http://stackoverflow.com/a/15580293/643085) [2](http://stackoverflow.com/a/15469477/643085) [3](http://stackoverflow.com/a/15821573/643085) [4](http://stackoverflow.com/a/16947081/643085) – Federico Berasategui Aug 21 '13 at 17:59

2 Answers2

1

As you are already anticipating, the translation will be adjusted by the scale. Assuming your scale is uniform. This is the basic approach:

scale = 1;
distance = 500;
transform.ScaleX = transform.ScaleY = scale;
// actually moves 500
transform.TranslateX = distance / scale;

scale = 2;
distance = 500;
transform.ScaleX = transform.ScaleY = scale;
// actually moves 250
transform.TranslateX = distance / scale;

Best of luck!

Jerry Nixon
  • 31,313
  • 14
  • 117
  • 233
0

You need to scale e.Delta.Translation.X and e.Delta.Translation.Y by the inverse of whatever your current scale factor is. Dragging something by (20,40) in the scaled down view is actually a larger movement in the coordinate space your shapes are using i.e. (40,80).

You might want to take a look at your bounds checking as well, I can't remember off the top of my head if ActualWidth and ActualHeight are the scaled values or not.

FlyingStreudel
  • 4,434
  • 4
  • 33
  • 55