I m using MouseDragElementBehavior in my WP7 application to drag an image down the canvas. I m able to get the coordinates (X,Y positions) after the image dragging. But I want to retain the same image position after tombstoning also.
private void MouseDragElementBehavior_Dragging(object sender, MouseEventArgs e)
{
Point currentPos = e.GetPosition(image1);
if (currentPos.X < 190)
{
double targetOffset = 700;
DoubleAnimation animation = new DoubleAnimation();
animation.EasingFunction = new CircleEase();
animation.Duration = new Duration(new TimeSpan(0, 0, 10));
animation.From = TextScroll.AnimatableOffset;
animation.To = targetOffset;
Storyboard.SetTarget(animation, TextScroll);
Storyboard.SetTargetProperty(animation, new PropertyPath("(AnimatableScrollViewer.AnimatableOffset)"));
Storyboard storyboard = new Storyboard();
storyboard.Children.Add(animation);
storyboard.Begin();
}
App app = (App)Application.Current;
app.current_X = currentPos.X.ToString();
app.current_Y = currentPos.Y.ToString();
TextScroll.AnimatableOffset = -700;
}
I have stored and retrived the values from isolated storage for tombstoning.
private void LoadSettings()
{
var settings = IsolatedStorageSettings.ApplicationSettings;
current_X = settings["Xpos"].ToString();
current_Y = settings["Ypos"].ToString();
}
private void SaveSettings()
{
var settings = IsolatedStorageSettings.ApplicationSettings;
settings.Add("Xpos", current_X);
settings.Add("Ypos",current_Y);
settings.Save();
}
Now I would like to use the values to position the image at the same coordinates as before tombstoning. I dont know how to position the image with the X and Y coordinates provided.
Here is the XAML code where I use the image.
<Canvas Margin="12,0,3,-834" Grid.Row="1">
<Image Height="800" Source="37.jpg" Stretch="Fill" Width="480" Canvas.Left="-11" x:Name="image1">
<i:Interaction.Behaviors>
<el:MouseDragElementBehavior ConstrainToParentBounds="True" Dragging="MouseDragElementBehavior_Dragging" />
</i:Interaction.Behaviors>
</Image>
</Canvas>
First, Point currentPos = e.GetPosition(image1); is getting the position of the mouse relative to the image. Maybe you want to get the position relative to the canvas instead?
Or, you can use this to get the position within the canvas:
canvas1.GetLeft(image1);
canvas1.GetTop(image1);
Then, you can set the position of something within a canvas like this:
canvas1.SetLeft(image1, x);
canvas1.SetTop(image1, y);
To do that, you would need to name your Canvas:
<Canvas x:Name="canvas1" Margin="12,0,3,-834" Grid.Row="1">
Related
I post this before and it was remove for being a duplicate. It is not. My problem is different then what that other people is doing. He is not doing zoom nor pan, and does not have a boarder.
I am using Stretch="Fill" to place my entire picture in the borders of an Image box. I am using a Border so that I can do Zoom and Pan. I am using the Canvas to draw rectangles around giving click areas. I want to map the left mouse click coordinates of the Canvas with zoom and pan back to the original image. here is my XAML code :
`
<Border x:Name="VideoPlayerBorder" ClipToBounds="True" Background="Gray" >
<Canvas x:Name="CanvasGridScreen" MouseLeftButtonDown="VideoPlayerSource_OnMouseLeftButtonDown" >
<Image x:Name="VideoPlayerSource" Opacity="1" RenderTransformOrigin="0.5,0.5" MouseLeftButtonUp="VideoPlayerSource_OnMouseLeftButtonUp" MouseWheel="VideoPlayerSource_OnMouseWheel" MouseMove="VideoPlayerSource_OnMouseMove" Width="{Binding Path=ActualWidth, ElementName=CanvasGridScreen}" Height="{Binding Path=ActualHeight, ElementName=CanvasGridScreen}" Stretch="Fill" >
</Image>
</Canvas>
`
here is my C# code:
`private void VideoPlayerSource_OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
VideoPlayerSource.CaptureMouse();
var tt = (TranslateTransform)((TransformGroup)VideoPlayerSource.RenderTransform).Children.First(tr => tr is TranslateTransform);
start = e.GetPosition(VideoPlayerBorder);
origin = new Point(tt.X, tt.Y);
_stIR = start;
_stIR2 = start;
addRemoveItems(sender, e);
}
private void addRemoveItems(object sender, MouseButtonEventArgs e)
{
// this is the event that will check if we clicked on a rectangle or if we clicked on the canvas
// if we clicked on a rectangle then it will do the following
if (e.OriginalSource is Rectangle)
{
// if the click source is a rectangle then we will create a new rectangle
// and link it to the rectangle that sent the click event
Rectangle activeRec = (Rectangle)e.OriginalSource; // create the link between the sender rectangle
CanvasGridScreen.Children.Remove(activeRec); // find the rectangle and remove it from the canvas
}
// if we clicked on the canvas then we do the following
else
{
// generate a random colour and save it inside the custom brush variable
Custombrush = new SolidColorBrush(Color.FromRgb((byte)r.Next(1, 255),
(byte)r.Next(1, 255), (byte)r.Next(1, 233)));
// create a re rectangle and give it the following properties
// height and width 50 pixels
// border thickness 3 pixels, fill colour set to the custom brush created above
// border colour set to black
Rectangle newRec = new Rectangle
{
Width = 50,
Height = 50,
StrokeThickness = 3,
Fill = Custombrush,
Stroke = Brushes.Black
};
// once the rectangle is set we need to give a X and Y position for the new object
// we will calculate the mouse click location and add it there
Canvas.SetLeft(newRec, Mouse.GetPosition(CanvasGridScreen).X); // set the left position of rectangle to mouse X
Canvas.SetTop(newRec, Mouse.GetPosition(CanvasGridScreen).Y); // set the top position of rectangle to mouse Y
CanvasGridScreen.Children.Add(newRec); // add the new rectangle to the canvas
}
}
private void VideoPlayerSource_OnMouseWheel(object sender, MouseWheelEventArgs e)
{
TransformGroup transformGroup = (TransformGroup)VideoPlayerSource.RenderTransform;
ScaleTransform transform = (ScaleTransform)transformGroup.Children[0];
double zoom = e.Delta > 0 ? .2 : -.2;
double transformScaleX = Math.Round((transform.ScaleX + zoom), 2);
double transformScaleY = Math.Round((transform.ScaleY + zoom), 2);
if (transformScaleX <= 8.2 && transformScaleX >= 1)
{
transform.ScaleX = Math.Round(transform.ScaleX + zoom, 2);
transform.ScaleY = Math.Round(transform.ScaleY + zoom, 2);
zoomFactor2 = zoomFactor2 + zoom;
zoomFactor = zoomFactor2;
}
}
void PanMethod(MouseEventArgs e)
{
var tt = (TranslateTransform)((TransformGroup)VideoPlayerSource.RenderTransform).Children.First(tr => tr is TranslateTransform);
Vector v = start - e.GetPosition(VideoPlayerBorder);
if (zoomFactor > 1.0)
{
tt.X = origin.X - v.X;
tt.Y = origin.Y - v.Y;
}
}
is there a function that would give me this information ? is there a way of using TransformGroup or ScaleTransform to return the actual location in the picture that was clicked? again the Image with possible zoom and/or pan
Check out: https://learn.microsoft.com/en-us/dotnet/api/system.windows.media.visual.transformtovisual
The right way to translate coordinates back to the original pre-transforms control is to use the TransformToVisual helper. It's probably a good idea to do that regardless since transforms could be applied higher up in the stack.
In your case you want to call:
GeneralTransform transform = CanvasGridScreen.TransformToVisual(VideoPlayerSource);
Point normalizedPoint = transform.Transform(new Point(0, 0));
I'm currently trying to insert random images onto a canvas using mouse click coordinates. However, I am unsure where the X & Y coordinates would be placed in the code. Any pointers would be great thanks!
private void canvas1_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
Point p = Mouse.GetPosition(canvas1);
double x = p.X;
double y = p.Y;
Image myImage = new Image();
string[] imageNames = { "greenslime.png", "blueslime.png", "redslime.png", "yellowslime.png" };
var rand = new Random();
string imageName = imageNames[rand.Next(imageNames.Length)];
string imageSlime = string.Concat("", imageName);
myImage.Source = new BitmapImage(new Uri(imageSlime, UriKind.Relative));
myImage.Width = 200;
myImage.Height = 200;
canvas1.Children.Add(myImage);
}
You should use the Canvas.Top/Canvas.Left attached dependency properties.
In code behind you should use:
myImage.Source = new BitmapImage(new Uri(imageSlime, UriKind.Relative));
myImage.Width = 200;
myImage.Height = 200;
Canvas.SetLeft(myImage, x);
Canvas.SetTop(myImage, y);
canvas1.Children.Add(myImage);
Because the image is placed in the canvas, the canvas will use these properties.
In XAML it would be:
<Canvas x:Name="canvas1">
<Image Canvas.Top="10" Canvas.Left="20" Width="200" Height="200" />
</Canvas>
HubPage is my landing page. On Hubpage.xaml, I have a grid of 3x3, containing a Rectangle, what I'm calling a "cell". In HubPage.xaml.cs, particularly in the HubPage() constructor, I create a storyboard for each cell:
CreateStoryboardForCell("Column0Row0");
CreateStoryboardForCell("Column0Row1");
...
CreateStoryboardForCell("Column2Row2");
I want to add a storyboard to the Page.Resources, normally I would do it in XAML, but I am attempting it from C#. Now, here is the CreateStoryboardForCell implementation:
private void CreateStoryboardForCell(string cellName)
{
// Create two DoubleAnimations, one for scaleX and one for scaleY, and set their properties.
Duration duration = new Duration(TimeSpan.FromSeconds(0.2));
DoubleAnimation myDoubleAnimation1 = new DoubleAnimation();
DoubleAnimation myDoubleAnimation2 = new DoubleAnimation();
myDoubleAnimation1.Duration = duration;
myDoubleAnimation2.Duration = duration;
Storyboard sb = new Storyboard();
sb.Duration = duration;
sb.Children.Add(myDoubleAnimation1);
sb.Children.Add(myDoubleAnimation2);
// Set the targets of the animations
Storyboard.SetTarget(myDoubleAnimation1, Column0Row0);
Storyboard.SetTarget(myDoubleAnimation2, Column0Row0);
// Set the attached properties of ScaleX and ScaleY
// to be the target properties of the two respective DoubleAnimations
Storyboard.SetTargetProperty(myDoubleAnimation1, "(UIElement.RenderTransform).(CompositeTransform.ScaleX)");
Storyboard.SetTargetProperty(myDoubleAnimation2, "(UIElement.RenderTransform).(CompositeTransform.ScaleY)");
myDoubleAnimation1.To = 15;
myDoubleAnimation2.To = 22;
// Make the Storyboard a resource.
try
{
pageRoot.Resources.Add("story" + cellName, sb);
}
catch (Exception e)
{
Status.Text = "Error adding storyboard resource for cell" + cellName + ": " + e.Message;
}
}
pageRoot is from Hubpage.xaml: Page x:Name="pageRoot", etc. I do not get an exception when adding the resource, but I cannot see the resource when I set the breakpoint, so I assume it was added successfully, as I can see the count increasing, and no exception was thrown.
Moving on, I have a click handler for each column cell, where I infer the row and column number and try to start up the corresponding storyboard added to the page resource earlier. Here is the code:
private void Column1_Cell_Click(object sender, RoutedEventArgs e)
{
Rectangle rect = sender as Rectangle;
int x = (int)rect.GetValue(Grid.RowProperty);
int y = (int)rect.GetValue(Grid.ColumnProperty);
string storyboardName = "storyColumn" + y + "Row" + x;
Storyboard storyboard = (Storyboard)FindName(storyboardName);
storyboard.Begin();
}
but the FindName call always returns a null storyboard. What am I missing here?
I've written this code for you.I hope benefits to business
Here is code:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="Column0Row0"/>
<ColumnDefinition x:Name="Column0Row1"/>
<ColumnDefinition x:Name="Column0Row2"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Rectangle Fill="Pink" x:Name="rectangle" MouseLeftButtonDown="Rectangle_MouseLeftButtonDown"/>
<Rectangle Grid.Column="1" Grid.Row="1" Fill="Coral" MouseLeftButtonDown="Rectangle_MouseLeftButtonDown"/>
<Rectangle Grid.Column="2" Grid.Row="2" Fill="Orange" MouseLeftButtonDown="Rectangle_MouseLeftButtonDown"/>
</Grid>
Code Behind :
private void CreateStoryboardForCell(Rectangle target)
{
ScaleTransform trans = new ScaleTransform();
target.RenderTransform = trans;
DoubleAnimation anim = new DoubleAnimation(1, 2, TimeSpan.FromMilliseconds(1000));
trans.BeginAnimation(ScaleTransform.ScaleXProperty, anim);
trans.BeginAnimation(ScaleTransform.ScaleYProperty, anim);
}
private void Rectangle_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
CreateStoryboardForCell((Rectangle)sender);
}
Please try this code.I always use this code for finding a storyboard.It works.
Here is code:
FrameworkElement element = new FrameworkElement();
Storyboard sb=new Storyboard ();
sb = element.FindResource("Please write here Storyboard Key") as Storyboard;
sb.Begin(target element name , true);
If BeginStoryboard doesn't support in WinRT.You can use the following code.I created the animation in codedehind.Maybe you can solve the problem like this;I did some research on this problem.
I tried this code.It works
Here is code:
private void Rectangle_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Storyboard storyboard = new Storyboard();
ScaleTransform scale = new ScaleTransform(1.0, 1.0);
animatedRectangle.RenderTransformOrigin = new Point(0.5, 0.5);
animatedRectangle.RenderTransform = scale;
DoubleAnimation scaleAnimation1 = new DoubleAnimation(1, 2, TimeSpan.FromMilliseconds(1000));
DoubleAnimation scaleAnimation2 = new DoubleAnimation(1, 2, TimeSpan.FromMilliseconds(1000));
storyboard.Children.Add(scaleAnimation1);
storyboard.Children.Add(scaleAnimation2);
Storyboard.SetTargetProperty(scaleAnimation1, new PropertyPath("RenderTransform.ScaleX"));
Storyboard.SetTargetProperty(scaleAnimation2, new PropertyPath("RenderTransform.ScaleY"));
Storyboard.SetTarget(scaleAnimation1, animatedRectangle);
Storyboard.SetTarget(scaleAnimation2, animatedRectangle);
storyboard.Begin();
}
I have a grid of images and buttons, and I want to animate motion from one position to another (actually a few spaces to the left) automatically, but it hasn't worked. I've tried using a storyboard in xaml and programatically as in the code below, but its now working. Please help!!!
public static void MoveTo(Grid target)
{
Canvas.SetLeft(target, 0);
var top = Canvas.GetTop(target);
var left = Canvas.GetLeft(target);
TranslateTransform trans = new TranslateTransform();
target.RenderTransform = trans;
double newX = (double)(left - 300);
double newY = (double)top;
DoubleAnimation anim1 = new DoubleAnimation(top, -15, TimeSpan.FromSeconds(10));
//DoubleAnimation anim1 = new DoubleAnimation(top, newY - top, TimeSpan.FromSeconds(10));
DoubleAnimation anim2 = new DoubleAnimation(left, newX - left, TimeSpan.FromSeconds(10));
anim1.AutoReverse = true;
anim1.RepeatBehavior = RepeatBehavior.Forever;
trans.BeginAnimation(TranslateTransform.XProperty, anim1);
trans.BeginAnimation(TranslateTransform.YProperty, anim2);
}
totally TranslateTransform isnt good for that you want .better to use thinkness animation
i advise you dont use canavas and change it to grid but if you use canavas use this code
private void Animationsss(Grid grd)
{
//create an animation
DoubleAnimation da = new DoubleAnimation();
//set from animation to start position
//dont forget set canvas.left for grid if u dont u will get error
da.From = Canvas.GetLeft(grd);
//set second position of grid
da.To = -100;
//set duration
da.Duration = new Duration(TimeSpan.FromSeconds(2));
//run animation if u want stop ,start etc use story board
grd.BeginAnimation(Canvas.LeftProperty, da);
}
if you use grid code is this :
private void Animation(Grid grd)
{
ThicknessAnimation ta = new ThicknessAnimation();
//your first place
ta.From = grd.Margin;
//this move your grid 1000 over from left side
//you can use -1000 to move to left side
ta.To = new Thickness(1000, 0, 0, 0);
//time the animation playes
ta.Duration = new Duration(TimeSpan.FromSeconds(10));
//dont need to use story board but if you want pause,stop etc use story board
grd.BeginAnimation(Grid.MarginProperty, ta);
}
you can use opacity animation for fade your grid ... it show good if move and fade !
private void Animationsss(Grid grd)
{
DoubleAnimation da = new DoubleAnimation(1, 0, new Duration(TimeSpan.FromSeconds(2)));
grd.BeginAnimation(Grid.OpacityProperty, da);
}
if there isnt any reason u can change canavas to grid and also better use TranslateTransform for resize controls like code below this code resize control if mouse enter in it :
private void grid1_MouseEnter(object sender, MouseEventArgs e)
{
//at first its normal size
ScaleTransform st = new ScaleTransform(1, 1);
//animation size to 1.25 persent of real size
DoubleAnimation da = new DoubleAnimation(1,1.25, new Duration(TimeSpan.FromSeconds(2)));
//set transform to control
grid1.RenderTransform = st;
//animation transform now From Y And X
st.BeginAnimation(ScaleTransform.ScaleXProperty, da);
st.BeginAnimation(ScaleTransform.ScaleYProperty, da);
}
if you animation for width or height do same work like scale transform :)
hope i can help you ...:))
leave comment for me please
You can also use xaml for this:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="TestBed.MainWindow"
x:Name="Window"
Title="MainWindow"
Width="640" Height="480">
<Window.Resources>
<Storyboard x:Key="MoveGrid">
<ThicknessAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Margin)" Storyboard.TargetName="grid">
<EasingThicknessKeyFrame KeyTime="0:0:1" Value="-300,0,0,0"/>
</ThicknessAnimationUsingKeyFrames>
</Storyboard>
</Window.Resources>
<Window.Triggers>
<EventTrigger RoutedEvent="ButtonBase.Click" SourceName="button">
<BeginStoryboard x:Name="MoveGrid_BeginStoryboard" Storyboard="{StaticResource MoveGrid}"/>
</EventTrigger>
</Window.Triggers>
<Canvas>
<Grid x:Name="grid" Height="300" Width="300" Background="Black">
<Button x:Name="button" Content="Move the gird!" Height="30" Margin="10,0" />
</Grid>
</Canvas>
</Window>
Using the following XAML:
<Grid x:Name="grid" Background="LightBlue" ClipToBounds="True">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Viewbox x:Name="imgViewbox" >
<InkCanvas Grid.Row="0" Name="inkCanvas" Background="Red" >
<Image Source="Images/pic.png" HorizontalAlignment="Left" x:Name="imgObject" VerticalAlignment="Top" />
<Label>Testing</Label>
</InkCanvas>
</Viewbox>
</Grid>
I am trying to rotate around the center of the image and also use the wheel mouse to zoom. I have set up this transform group and event:
public MainWindow() {
InitializeComponent();
DataContext = new MainWindowViewModel();
transformGroup = new TransformGroup();
scaleTransform = new ScaleTransform();
rotateTransform = new RotateTransform();
translateTransform = new TranslateTransform();
transformGroup.Children.Add(rotateTransform);
transformGroup.Children.Add(scaleTransform);
transformGroup.Children.Add(translateTransform);
imgViewbox.RenderTransform = transformGroup;
imgViewbox.MouseWheel += ImageViewboxMouseWheel;
}
Rotate is simple:
void Rotate(object sender, RoutedEventArgs e) {
//imgViewbox.RenderTransformOrigin = new Point(0.5,0.5);
rotateTransform.Angle += 90;
}
but zoom is doing all sorts of weird stuff jumping around the screen. The code for zoom is here:
void ImageViewboxMouseWheel(object sender, MouseWheelEventArgs e) {
//imgViewbox.RenderTransformOrigin = new Point(0, 0);
double zoomFactor = DefaultZoomFactor;
if (e.Delta <= 0) zoomFactor = 1.0 / DefaultZoomFactor;
// DoZoom requires both the logical and physical location of the mouse pointer
var physicalPoint = e.GetPosition(imgViewbox);
if (transformGroup.Inverse != null) {
DoZoom(zoomFactor, transformGroup.Inverse.Transform(physicalPoint), physicalPoint);
}
else {
throw new ArgumentException("Missing Inverse");
}
//Set the center point of the ScaleTransform object to the cursor location.
scaleTransform.CenterX = e.GetPosition(imgViewbox).X;
scaleTransform.CenterY = e.GetPosition(imgViewbox).Y;
Debug.WriteLine(string.Format("IVMW Center {0},{1}", scaleTransform.CenterX, scaleTransform.CenterY));
}
public void DoZoom(double deltaZoom, Point mousePosition, Point physicalPosition) {
double currentZoom = scaleTransform.ScaleX;
currentZoom *= deltaZoom;
translateTransform.X = -1*(mousePosition.X*currentZoom - physicalPosition.X);
translateTransform.Y = -1*(mousePosition.X*currentZoom - physicalPosition.Y);
scaleTransform.ScaleX = currentZoom;
scaleTransform.ScaleY = currentZoom;
}
I have removed as much as I can, animations and such. Hopefully leaving only the key parts. I believe that the major problem is the scaleTransform.Center[X|Y] as the numbers that are being returned are all over the quadrant even when I try to click exactly in the same location. The RenderTransformOrigin doesn't seem to make any difference with the Center position but I am aware that I need it to rotate around center.
What am I doing wrong?
You need to offset the jump you get from changing the ScaleTranform's CenterX/Y in the TranslateTransform, here is a snippet from a pan & zoom control i wrote:
private void This_MouseWheel(object sender, MouseWheelEventArgs e)
{
if (IsZoomEnabled)
{
Point cursorPos = e.GetPosition(this);
Point newCenter = _scaleT.Inverse.Transform(_translateT.Inverse.Transform(cursorPos));
Point oldCenter = new Point(_scaleT.CenterX, _scaleT.CenterY);
Vector oldToNewCenter = newCenter - oldCenter;
_scaleT.CenterX = newCenter.X;
_scaleT.CenterY = newCenter.Y;
_translateT.X += oldToNewCenter.X * (_scaleT.ScaleX - 1.0);
_translateT.Y += oldToNewCenter.Y * (_scaleT.ScaleY - 1.0);
...
Hopefully you can adapt this to your code. Where the new center is calculated you might need to take your RotateTransform into account.