c# - una - seo imagenes wordpress
Imagen PanorĂ¡mica y Zoom (12)
Quiero crear un visor de imágenes simple en WPF que permita al usuario:
- Panorámica (con el mouse arrastrando la imagen).
- Zoom (con un control deslizante).
- Mostrar superposiciones (selección de rectángulo, por ejemplo).
- Mostrar imagen original (con barras de desplazamiento si es necesario).
¿Puedes explicarme cómo hacerlo?
No encontré una buena muestra en la web. ¿Debería usar ViewBox? ¿O ImageBrush? ¿Necesito ScrollViewer?
¡Gracias!
@ Merk
Para nuestra solución basada en la expresión lambda, puede usar el siguiente código:
//var tt = (TranslateTransform)((TransformGroup)image.RenderTransform).Children.First(tr => tr is TranslateTransform);
TranslateTransform tt = null;
TransformGroup transformGroup = (TransformGroup)grid.RenderTransform;
for (int i = 0; i < transformGroup.Children.Count; i++)
{
if (transformGroup.Children[i] is TranslateTransform)
tt = (TranslateTransform)transformGroup.Children[i];
}
este código se puede usar como lo es para .Net Frame work 3.0 o 2.0
Espero que te ayude :-)
@Anothen y @ Number8 - La clase Vector no está disponible en Silverlight, por lo que para que funcione solo necesitamos mantener un registro de la última posición vista la última vez que se llamó al evento MouseMove, y comparar los dos puntos para encontrar la diferencia ; luego ajusta la transformación.
XAML:
<Border Name="viewboxBackground" Background="Black">
<Viewbox Name="viewboxMain">
<!--contents go here-->
</Viewbox>
</Border>
Código detrás:
public Point _mouseClickPos;
public bool bMoving;
public MainPage()
{
InitializeComponent();
viewboxMain.RenderTransform = new CompositeTransform();
}
void MouseMoveHandler(object sender, MouseEventArgs e)
{
if (bMoving)
{
//get current transform
CompositeTransform transform = viewboxMain.RenderTransform as CompositeTransform;
Point currentPos = e.GetPosition(viewboxBackground);
transform.TranslateX += (currentPos.X - _mouseClickPos.X) ;
transform.TranslateY += (currentPos.Y - _mouseClickPos.Y) ;
viewboxMain.RenderTransform = transform;
_mouseClickPos = currentPos;
}
}
void MouseClickHandler(object sender, MouseButtonEventArgs e)
{
_mouseClickPos = e.GetPosition(viewboxBackground);
bMoving = true;
}
void MouseReleaseHandler(object sender, MouseButtonEventArgs e)
{
bMoving = false;
}
También tenga en cuenta que no necesita un TransformGroup o colección para implementar pan y zoom; en cambio, una CompositeTransform hará el truco con menos molestias.
Estoy bastante seguro de que esto es realmente ineficiente en términos de uso de recursos, pero al menos funciona :)
Después de usar las muestras de esta pregunta, he hecho una versión completa de la aplicación de panorámica y zoom con el zoom adecuado en relación con el puntero del mouse. Todo el código de panorámica y zoom se ha movido a una clase separada llamada ZoomBorder.
ZoomBorder.cs
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
namespace PanAndZoom
{
public class ZoomBorder : Border
{
private UIElement child = null;
private Point origin;
private Point start;
private TranslateTransform GetTranslateTransform(UIElement element)
{
return (TranslateTransform)((TransformGroup)element.RenderTransform)
.Children.First(tr => tr is TranslateTransform);
}
private ScaleTransform GetScaleTransform(UIElement element)
{
return (ScaleTransform)((TransformGroup)element.RenderTransform)
.Children.First(tr => tr is ScaleTransform);
}
public override UIElement Child
{
get { return base.Child; }
set
{
if (value != null && value != this.Child)
this.Initialize(value);
base.Child = value;
}
}
public void Initialize(UIElement element)
{
this.child = element;
if (child != null)
{
TransformGroup group = new TransformGroup();
ScaleTransform st = new ScaleTransform();
group.Children.Add(st);
TranslateTransform tt = new TranslateTransform();
group.Children.Add(tt);
child.RenderTransform = group;
child.RenderTransformOrigin = new Point(0.0, 0.0);
this.MouseWheel += child_MouseWheel;
this.MouseLeftButtonDown += child_MouseLeftButtonDown;
this.MouseLeftButtonUp += child_MouseLeftButtonUp;
this.MouseMove += child_MouseMove;
this.PreviewMouseRightButtonDown += new MouseButtonEventHandler(
child_PreviewMouseRightButtonDown);
}
}
public void Reset()
{
if (child != null)
{
// reset zoom
var st = GetScaleTransform(child);
st.ScaleX = 1.0;
st.ScaleY = 1.0;
// reset pan
var tt = GetTranslateTransform(child);
tt.X = 0.0;
tt.Y = 0.0;
}
}
#region Child Events
private void child_MouseWheel(object sender, MouseWheelEventArgs e)
{
if (child != null)
{
var st = GetScaleTransform(child);
var tt = GetTranslateTransform(child);
double zoom = e.Delta > 0 ? .2 : -.2;
if (!(e.Delta > 0) && (st.ScaleX < .4 || st.ScaleY < .4))
return;
Point relative = e.GetPosition(child);
double abosuluteX;
double abosuluteY;
abosuluteX = relative.X * st.ScaleX + tt.X;
abosuluteY = relative.Y * st.ScaleY + tt.Y;
st.ScaleX += zoom;
st.ScaleY += zoom;
tt.X = abosuluteX - relative.X * st.ScaleX;
tt.Y = abosuluteY - relative.Y * st.ScaleY;
}
}
private void child_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (child != null)
{
var tt = GetTranslateTransform(child);
start = e.GetPosition(this);
origin = new Point(tt.X, tt.Y);
this.Cursor = Cursors.Hand;
child.CaptureMouse();
}
}
private void child_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if (child != null)
{
child.ReleaseMouseCapture();
this.Cursor = Cursors.Arrow;
}
}
void child_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
this.Reset();
}
private void child_MouseMove(object sender, MouseEventArgs e)
{
if (child != null)
{
if (child.IsMouseCaptured)
{
var tt = GetTranslateTransform(child);
Vector v = start - e.GetPosition(this);
tt.X = origin.X - v.X;
tt.Y = origin.Y - v.Y;
}
}
}
#endregion
}
}
MainWindow.xaml
<Window x:Class="PanAndZoom.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:PanAndZoom"
Title="PanAndZoom" Height="600" Width="900" WindowStartupLocation="CenterScreen">
<Grid>
<local:ZoomBorder x:Name="border" ClipToBounds="True" Background="Gray">
<Image Source="image.jpg"/>
</local:ZoomBorder>
</Grid>
</Window>
MainWindow.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace PanAndZoom
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
}
La forma en que resolvió este problema fue colocar la imagen dentro de un borde con su propiedad ClipToBounds establecida en True. El RenderTransformOrigin en la imagen se establece en 0,5,0.5 por lo que la imagen comenzará a acercarse al centro de la imagen. RenderTransform también se establece en un TransformGroup que contiene una ScaleTransform y una TranslateTransform.
Luego manejé el evento MouseWheel en la imagen para implementar el zoom
private void image_MouseWheel(object sender, MouseWheelEventArgs e)
{
var st = (ScaleTransform)image.RenderTransform;
double zoom = e.Delta > 0 ? .2 : -.2;
st.ScaleX += zoom;
st.ScaleY += zoom;
}
Para manejar el panorama, lo primero que hice fue manejar el evento MouseLeftButtonDown en la imagen, capturar el mouse y registrar su ubicación, también guardo el valor actual de TranslateTransform, esto es lo que se actualiza para implementar el paneo.
Point start;
Point origin;
private void image_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
image.CaptureMouse();
var tt = (TranslateTransform)((TransformGroup)image.RenderTransform)
.Children.First(tr => tr is TranslateTransform);
start = e.GetPosition(border);
origin = new Point(tt.X, tt.Y);
}
Luego manejé el evento MouseMove para actualizar el TranslateTransform.
private void image_MouseMove(object sender, MouseEventArgs e)
{
if (image.IsMouseCaptured)
{
var tt = (TranslateTransform)((TransformGroup)image.RenderTransform)
.Children.First(tr => tr is TranslateTransform);
Vector v = start - e.GetPosition(border);
tt.X = origin.X - v.X;
tt.Y = origin.Y - v.Y;
}
}
Finalmente, no olvides soltar la captura del mouse.
private void image_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
image.ReleaseMouseCapture();
}
En cuanto a los controles de selección para cambiar el tamaño, esto se puede lograr usando un adorno, consulte este artículo para obtener más información.
La respuesta fue publicada anteriormente pero no fue completa. aquí está la versión completa:
XAML
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="MapTest.Window1"
x:Name="Window"
Title="Window1"
Width="1950" Height="1546" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:Controls="clr-namespace:WPFExtensions.Controls;assembly=WPFExtensions" mc:Ignorable="d" Background="#FF000000">
<Grid x:Name="LayoutRoot">
<Grid.RowDefinitions>
<RowDefinition Height="52.92"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Border Grid.Row="1" Name="border">
<Image Name="image" Source="map3-2.png" Opacity="1" RenderTransformOrigin="0.5,0.5" />
</Border>
</Grid>
Código detrás
using System.Linq;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
namespace MapTest
{
public partial class Window1 : Window
{
private Point origin;
private Point start;
public Window1()
{
InitializeComponent();
TransformGroup group = new TransformGroup();
ScaleTransform xform = new ScaleTransform();
group.Children.Add(xform);
TranslateTransform tt = new TranslateTransform();
group.Children.Add(tt);
image.RenderTransform = group;
image.MouseWheel += image_MouseWheel;
image.MouseLeftButtonDown += image_MouseLeftButtonDown;
image.MouseLeftButtonUp += image_MouseLeftButtonUp;
image.MouseMove += image_MouseMove;
}
private void image_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
image.ReleaseMouseCapture();
}
private void image_MouseMove(object sender, MouseEventArgs e)
{
if (!image.IsMouseCaptured) return;
var tt = (TranslateTransform) ((TransformGroup) image.RenderTransform).Children.First(tr => tr is TranslateTransform);
Vector v = start - e.GetPosition(border);
tt.X = origin.X - v.X;
tt.Y = origin.Y - v.Y;
}
private void image_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
image.CaptureMouse();
var tt = (TranslateTransform) ((TransformGroup) image.RenderTransform).Children.First(tr => tr is TranslateTransform);
start = e.GetPosition(border);
origin = new Point(tt.X, tt.Y);
}
private void image_MouseWheel(object sender, MouseWheelEventArgs e)
{
TransformGroup transformGroup = (TransformGroup) image.RenderTransform;
ScaleTransform transform = (ScaleTransform) transformGroup.Children[0];
double zoom = e.Delta > 0 ? .2 : -.2;
transform.ScaleX += zoom;
transform.ScaleY += zoom;
}
}
}
Tengo un ejemplo de un proyecto de wpf completo que usa este código en mi sitio web: apunte la aplicación de notas adhesivas .
Otra forma de hacer el mismo tipo de cosas. Esto se acercará y alejará, así como la panorámica, pero mantendrá la imagen dentro de los límites del contenedor. Escrito como un control así que agregue el estilo a la App.xaml
directamente o a través de Themes/Generic.xaml
si se coloca en un proyecto diferente. Agregado ...
donde el código ha sido eliminado por claridad.
Viewer.cs:
public class Viewer : ContentControl
{
public static readonly DependencyProperty ZoomIncrementProperty =
DependencyProperty.Register("ZoomIncrement", typeof(double), typeof(Viewer),
new FrameworkPropertyMetadata(0.2, FrameworkPropertyMetadataOptions.AffectsRender |
FrameworkPropertyMetadataOptions.AffectsMeasure));
public static readonly DependencyProperty ZoomProperty =
DependencyProperty.Register("Zoom", typeof(double), typeof(Viewer),
new FrameworkPropertyMetadata(1d, FrameworkPropertyMetadataOptions.AffectsRender |
FrameworkPropertyMetadataOptions.AffectsMeasure));
public static readonly DependencyProperty MinZoomProperty =
DependencyProperty.Register("MinZoom", typeof(double), typeof(Viewer),
new FrameworkPropertyMetadata(1d, FrameworkPropertyMetadataOptions.AffectsRender |
FrameworkPropertyMetadataOptions.AffectsMeasure));
public static readonly DependencyProperty MaxZoomProperty =
DependencyProperty.Register("MaxZoom", typeof(double), typeof(Viewer),
new FrameworkPropertyMetadata(5d, FrameworkPropertyMetadataOptions.AffectsRender |
FrameworkPropertyMetadataOptions.AffectsMeasure));
public static readonly DependencyProperty TranslateProperty =
DependencyProperty.Register("Translate", typeof(Point), typeof(Viewer),
new FrameworkPropertyMetadata(new Point(0, 0), FrameworkPropertyMetadataOptions.AffectsRender |
FrameworkPropertyMetadataOptions.AffectsMeasure));
/// <summary>
/// Capture mouse movements
/// </summary>
private bool _capture;
/// <summary>
/// The origin of the transform at the start of capture
/// </summary>
private Point _origin;
/// <summary>
/// The mouse position at the start of capture
/// </summary>
private Point _start;
static Viewer()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(Viewer),
new FrameworkPropertyMetadata(typeof(Viewer)));
}
public double MaxZoom
{
get => (double) GetValue(MaxZoomProperty);
set => SetValue(MaxZoomProperty, value);
}
public double MinZoom
{
get => (double) GetValue(MinZoomProperty);
set => SetValue(MinZoomProperty, value);
}
public Point Translate
{
get => (Point) GetValue(TranslateProperty);
set
{
var width = ActualWidth * Zoom;
var height = ActualHeight * Zoom;
if (value.X > 0)
{
value.X = 0;
}
if (value.X <= ActualWidth - width)
{
value.X = ActualWidth - width;
}
if (value.Y > 0)
{
value.Y = 0;
}
if (value.Y <= ActualHeight - height)
{
value.Y = ActualHeight - height;
}
SetValue(TranslateProperty, value);
}
}
public double Zoom
{
get => (double) GetValue(ZoomProperty);
set
{
if (value <= MinZoom)
{
value = MinZoom;
}
if (value >= MaxZoom)
{
value = MaxZoom;
}
SetValue(ZoomProperty, value);
}
}
public double ZoomIncrement
{
get => (double) GetValue(ZoomIncrementProperty);
set => SetValue(ZoomIncrementProperty, value);
}
public void Reset()
{
Zoom = 1;
Translate = new Point();
}
protected override void OnMouseLeave(MouseEventArgs e)
{
base.OnMouseLeave(e);
Cursor = Cursors.Arrow;
_capture = false;
}
protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
{
base.OnMouseLeftButtonDown(e);
_start = e.GetPosition(this);
_origin = new Point
{
X = Translate.X,
Y = Translate.Y
};
Cursor = Cursors.Hand;
_capture = true;
e.Handled = true;
}
protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e)
{
base.OnMouseLeftButtonUp(e);
Cursor = Cursors.Arrow;
_capture = false;
}
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
if (_capture)
{
var position = e.GetPosition(this);
var v = _start - position;
Translate = new Point
{
X = _origin.X - v.X,
Y = _origin.Y - v.Y
};
}
}
protected override void OnMouseRightButtonDown(MouseButtonEventArgs e)
{
base.OnMouseLeftButtonDown(e);
Reset();
}
protected override void OnPreviewMouseWheel(MouseWheelEventArgs e)
{
base.OnPreviewMouseWheel(e);
var position = e.GetPosition(this);
var abosuluteX = position.X * Zoom + Translate.X;
var abosuluteY = position.Y * Zoom + Translate.Y;
Zoom += e.Delta > 0 ? ZoomIncrement : -ZoomIncrement;
Translate = new Point
{
X = abosuluteX - position.X * Zoom,
Y = abosuluteY - position.Y * Zoom
};
e.Handled = true;
}
}
Viewer.xaml:
<ResourceDictionary ... >
<Style TargetType="{x:Type local:Viewer}"
BasedOn="{StaticResource {x:Type ContentControl}}">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:Viewer}">
<!-- Container -->
<Border
Width="{TemplateBinding Width}"
Height="{TemplateBinding Height}"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Cursor="{TemplateBinding Cursor}">
<Grid ClipToBounds="True">
<!-- Viewbox -->
<Viewbox>
<!-- Content -->
<ContentPresenter
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}" />
<!-- Render Transform -->
<Viewbox.RenderTransform>
<TransformGroup>
<ScaleTransform
ScaleX="{Binding Zoom, RelativeSource={RelativeSource TemplatedParent}}"
ScaleY="{Binding Zoom, RelativeSource={RelativeSource TemplatedParent}}" />
<TranslateTransform
X="{Binding Translate.X, RelativeSource={RelativeSource TemplatedParent}}"
Y="{Binding Translate.Y, RelativeSource={RelativeSource TemplatedParent}}" />
</TransformGroup>
</Viewbox.RenderTransform>
</Viewbox>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
App.xaml
<Application ... >
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="... /Themes/Generic.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
Uso:
<viewers:Viewer>
<Image Source="{Binding ...}"/>
</viewers:Viewer>
Otra versión del mismo tipo de control. Tiene una funcionalidad similar a las demás, pero agrega:
- Soporte táctil (arrastrar / pellizcar)
- La imagen se puede eliminar (normalmente, el control de imagen bloquea la imagen en el disco, por lo que no puede eliminarla).
- Un niño del borde interior, por lo que la imagen panoramizada no se superpone al borde. En el caso de bordes con rectángulos redondeados, busque las clases ClippedBorder.
El uso es simple:
<Controls:ImageViewControl ImagePath="{Binding ...}" />
Y el código:
public class ImageViewControl : Border
{
private Point origin;
private Point start;
private Image image;
public ImageViewControl()
{
ClipToBounds = true;
Loaded += OnLoaded;
}
#region ImagePath
/// <summary>
/// ImagePath Dependency Property
/// </summary>
public static readonly DependencyProperty ImagePathProperty = DependencyProperty.Register("ImagePath", typeof (string), typeof (ImageViewControl), new FrameworkPropertyMetadata(string.Empty, OnImagePathChanged));
/// <summary>
/// Gets or sets the ImagePath property. This dependency property
/// indicates the path to the image file.
/// </summary>
public string ImagePath
{
get { return (string) GetValue(ImagePathProperty); }
set { SetValue(ImagePathProperty, value); }
}
/// <summary>
/// Handles changes to the ImagePath property.
/// </summary>
private static void OnImagePathChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var target = (ImageViewControl) d;
var oldImagePath = (string) e.OldValue;
var newImagePath = target.ImagePath;
target.ReloadImage(newImagePath);
target.OnImagePathChanged(oldImagePath, newImagePath);
}
/// <summary>
/// Provides derived classes an opportunity to handle changes to the ImagePath property.
/// </summary>
protected virtual void OnImagePathChanged(string oldImagePath, string newImagePath)
{
}
#endregion
private void OnLoaded(object sender, RoutedEventArgs routedEventArgs)
{
image = new Image {
//IsManipulationEnabled = true,
RenderTransformOrigin = new Point(0.5, 0.5),
RenderTransform = new TransformGroup {
Children = new TransformCollection {
new ScaleTransform(),
new TranslateTransform()
}
}
};
// NOTE I use a border as the first child, to which I add the image. I do this so the panned image doesn''t partly obscure the control''s border.
// In case you are going to use rounder corner''s on this control, you may to update your clipping, as in this example:
// http://wpfspark.wordpress.com/2011/06/08/clipborder-a-wpf-border-that-clips/
var border = new Border {
IsManipulationEnabled = true,
ClipToBounds = true,
Child = image
};
Child = border;
image.MouseWheel += (s, e) =>
{
var zoom = e.Delta > 0
? .2
: -.2;
var position = e.GetPosition(image);
image.RenderTransformOrigin = new Point(position.X / image.ActualWidth, position.Y / image.ActualHeight);
var st = (ScaleTransform)((TransformGroup)image.RenderTransform).Children.First(tr => tr is ScaleTransform);
st.ScaleX += zoom;
st.ScaleY += zoom;
e.Handled = true;
};
image.MouseLeftButtonDown += (s, e) =>
{
if (e.ClickCount == 2)
ResetPanZoom();
else
{
image.CaptureMouse();
var tt = (TranslateTransform) ((TransformGroup) image.RenderTransform).Children.First(tr => tr is TranslateTransform);
start = e.GetPosition(this);
origin = new Point(tt.X, tt.Y);
}
e.Handled = true;
};
image.MouseMove += (s, e) =>
{
if (!image.IsMouseCaptured) return;
var tt = (TranslateTransform) ((TransformGroup) image.RenderTransform).Children.First(tr => tr is TranslateTransform);
var v = start - e.GetPosition(this);
tt.X = origin.X - v.X;
tt.Y = origin.Y - v.Y;
e.Handled = true;
};
image.MouseLeftButtonUp += (s, e) => image.ReleaseMouseCapture();
//NOTE I apply the manipulation to the border, and not to the image itself (which caused stability issues when translating)!
border.ManipulationDelta += (o, e) =>
{
var st = (ScaleTransform)((TransformGroup)image.RenderTransform).Children.First(tr => tr is ScaleTransform);
var tt = (TranslateTransform)((TransformGroup)image.RenderTransform).Children.First(tr => tr is TranslateTransform);
st.ScaleX *= e.DeltaManipulation.Scale.X;
st.ScaleY *= e.DeltaManipulation.Scale.X;
tt.X += e.DeltaManipulation.Translation.X;
tt.Y += e.DeltaManipulation.Translation.Y;
e.Handled = true;
};
}
private void ResetPanZoom()
{
var st = (ScaleTransform)((TransformGroup)image.RenderTransform).Children.First(tr => tr is ScaleTransform);
var tt = (TranslateTransform)((TransformGroup)image.RenderTransform).Children.First(tr => tr is TranslateTransform);
st.ScaleX = st.ScaleY = 1;
tt.X = tt.Y = 0;
image.RenderTransformOrigin = new Point(0.5, 0.5);
}
/// <summary>
/// Load the image (and do not keep a hold on it, so we can delete the image without problems)
/// </summary>
/// <see cref="http://blogs.vertigo.com/personal/ralph/Blog/Lists/Posts/Post.aspx?ID=18"/>
/// <param name="path"></param>
private void ReloadImage(string path)
{
try
{
ResetPanZoom();
// load the image, specify CacheOption so the file is not locked
var bitmapImage = new BitmapImage();
bitmapImage.BeginInit();
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.UriSource = new Uri(path, UriKind.RelativeOrAbsolute);
bitmapImage.EndInit();
image.Source = bitmapImage;
}
catch (SystemException e)
{
Console.WriteLine(e.Message);
}
}
}
Para hacer zoom con respecto a la posición del mouse, todo lo que necesita es:
var position = e.GetPosition(image1);
image1.RenderTransformOrigin = new Point(position.X / image1.ActualWidth, position.Y / image1.ActualHeight);
Para obtener un Zoom Control profesional para WPF, consulte el ZoomPanel .
No es gratuito, pero es muy fácil de usar y tiene muchas características: acercamiento y paneo animado, soporte para ScrollViewer, compatibilidad con la rueda del mouse, incluido ZoomController (con movimiento, acercamiento, alejamiento, zoom de rectángulo, botones de reinicio). También viene con muchas muestras de código.
Prueba este Zoom Control: http://wpfextensions.codeplex.com
el uso del control es muy simple, haciendo referencia al ensamblaje wpfextensions que:
<wpfext:ZoomControl>
<Image Source="..."/>
</wpfext:ZoomControl>
Barras de desplazamiento no compatibles en este momento. (Será en la próxima versión que estará disponible en una o dos semanas).
La muestra My London Underground lo hace, aunque con un mapa en lugar de una imagen estática.
- Pan: coloque la imagen dentro de un lienzo. Implementa los eventos Mouse Up, Down y Move para mover las propiedades Canvas.Top, Canvas.Left. Cuando está abajo, marca un isDraggingFlag en verdadero, cuando arriba establece el indicador en falso. En movimiento, comprueba si se establece el indicador, si es que compensa las propiedades Canvas.Top y Canvas.Left en la imagen dentro del lienzo.
- Zoom: vincula el deslizador a la transformación de escala del lienzo
- Mostrar superposiciones: agregue lienzos adicionales sin fondo encima del lienzo que contiene la imagen.
- mostrar imagen original: control de imagen dentro de una ViewBox