Help with animation using Draggable and ZOffset

Hi, All! I need help figuring out the UX Markup for a complex animation.

I have a set of images. I want the user to be able to drag each image within boundaries (i.e. I don’t want them to be able to drag or fling them off-screen).

When each image is dragged, its ZOffset should place it above everything else, including the other images.

As soon as the image is released, I want it to return to its “home” position, unless the image has been dragged over another object and/or into a specific area, which should trigger a different response.

The images are laid out in two rows and two columns. I’ve used two stack panels to create this layout.

bump

Hi Angela,

Draggable has a Bounds property, which you can set to a ux:Name of an element that serves as the bounds you don’t want your draggables to leave.

You can Change your ZOffset from within a Pressed trigger that you put on a given element. There’s a Released trigger too, if need be.

As far as “returning to home” goes, you’ll likely need to look into using an Attractor and read about EnteredForceField.

Hi, Uldis!

Thanks for the reply and the links. Attractor and EnteredForceField look very promising! So does the Draggable.Bounds property - I will be experimenting with these to see if they solve my problem.

As for the ZOffset - I had already tried this with WhilePressed. It was a bit challenging to figure out the correct syntax for this, as I kept getting error messages that there was no such property. I couldn’t find any examples of this in the documentation.

Finally, I used it inside a Change tag like so:

Change imageName.ZOffset="1000"

and the error messages went away, however, it didn’t work :frowning: Even with a ZOffset of 1000, the image still looks like it is getting dragged under other objects.

I was wondering if this is an issue with the layout, though I thought that ZOffset is not constrained to the layout…

I hope that you can help me figure this out. Please let me know if you need more info.

Hey Angela!

If you are using ZOffset, you should know that a value can be from 0.0 to 1.0. Read this to understand how to use ZOffset.

Hope this helps.

Hi, Arturs!

Thanks for the reply. I do appreciate it, but I have to say that it is incorrect.

I had already read that part of the documentation and did not notice any explicit mention of a range for ZOffset values. The 0.0 and the 1.0 were example values. They do not limit the scope of potential values.

If that were the case, we would be limited to 11 ZOffset values: 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9 and 1.0. That would be very limiting in real-world use cases that are likely to have more than 11 items in any given layout.

What the documentation did state is that a higher ZOffset value will cause an object to be drawn over items with lower ZOffset values.

This can be tested with some simple UX Markup, like this:

<App>
	<StackPanel>
		<Rectangle Width="100" Height="100" Color="Yellow " Margin="30" ZOffset="3">
			<Draggable />
		</Rectangle>
		<Rectangle ux:Name="top" Width="100" Height="100" Color="Blue" Margin="30">
			<Draggable />
		</Rectangle>
	</StackPanel>
</App>

By default, the yellow Rectangle will be drawn over the blue one because of the way that the StackPanel orders its children. The ZOffset value of 3 doesn’t change this, but notice that it doesn’t cause any errors. If ZOffset was limited to values between 0.0-1.0, then I would expect it to throw an error.

Watch what happens when we give the blue rectangle a ZOffset value of 4 WhilePressed:

<App>
	<StackPanel>
		<Rectangle Width="100" Height="100" Color="Yellow " Margin="30" ZOffset="3">
			<Draggable />
		</Rectangle>
		<Rectangle ux:Name="top" Width="100" Height="100" Color="Blue" Margin="30">
			<Draggable />
			<WhilePressed>
				<Change top.ZOffset="4" />
			</WhilePressed>
		</Rectangle>
	</StackPanel>
</App>

The blue rectangle is now drawn over the yellow one. When it is dragged onto the yellow rectangle, it appears to be “in front” of it and not “behind” it.

This will also work with float values greater than the value of the yellow rectangle, which in this example is 3. So 3.1 will work, but 3.01 will also work because 3.01>3.

However, with some experimentation I discovered that the lowest value that will cause the blue rectangle in this example to be drawn above the yellow one is 3.00000012 - not sure why. Not sure what the pattern is. While a ZOffset of 3.00000012 will draw the respective item in front of items with a ZOffset of 3, items with a ZOffset of 4.00000012 will still be drawn behind items with a ZOffset of 4.

ZOffset also works with negative numbers. The code below will cause the blue rectangle to be drawn in front of the yellow one, since its ZOffset of -1 is greater than the yellow rectangle’s ZOffset of -1.1:

<App>
	<StackPanel>
		<Rectangle Width="100" Height="100" Color="Yellow " Margin="30" ZOffset="-1.1">
			<Draggable />
		</Rectangle>
		<Rectangle ux:Name="top" Width="100" Height="100" Color="Blue" Margin="30">
			<Draggable />
			<WhilePressed>
				<Change top.ZOffset="-1" />
			</WhilePressed>
		</Rectangle>
	</StackPanel>
</App>

Finally, notice that the yellow rectangle preserves its inherent Z-Order as the first child in its parent StackPanel as long as the ZOffset value is >=0 (and keep in mind that -0 === 0). If the value is <=-0.1 then the yellow rectangle will be drawn behind the blue rectangle.

We can test this by changing its ZOffset to -0.1 and dragging it onto the blue rectangle. Of course, you can play around with the blue rectangle ZOffset values (the default value and/or the Change value) to alter this behavior and draw the yellow rectangle on top again, despite its -0.1 value.

The reason that I used a ZOffset value of 1000 is that I was being sort of lazy - I didn’t want to try and figure out what the minimum value would have to be in order to draw the item over all other items, so I just used a super large number as a “quick and dirty” way to ensure that it would be drawn over everything… except it wasn’t :frowning:

Hey Angela!

You were right, thank you for correcting me with detailed explanations and examples.

For dragging I can suggest reading this example, it uses a clever way to reorder list.

Hi, Arturs!

Sorry for the delay. I’m glad that you found the explanations and examples useful - hopefully others will too!

Reordering items in a stack panel is great for the purpose of list reordering, as shown in the example you linked to. I’m looking to do something different.

StackPanels order their children along the Y-axis. I’m looking to change the order of items on the Z-axis. You can think of it as changing what “layer” the item resides on from front-to-back (Z-axis), rather than how they are stacked from top-to-bottom (Y-axis).

(And just to give more context, the third dimension would be the X-axis which runs from left-to-right.)