WPF。
(我预先申请了看似代码墙,但问题对我来说似乎很复杂,我希望尽可能完整)。
我有一个放在 InkCanvas 上的图像:
拖动完成后。注意: 我希望左上角位于“X”的位置,即 DRAGCOMPLETE 时光标所在的位置:
这是我用来实现上述图像的代码。本质上,问题归结为在调整图像大小后计算正确的平移变换。我已经尝试了所有我能想到的但没有成功。真正令人困惑的是,光标的偏移量似乎在某种程度上取决于图像被放到 InkCanvas 上的位置。也就是说,如果图像被放置在更靠近左边界的位置,则偏移量会比放置在中心位置时更加明显。非常混乱。
private void IC_Drop(object sender, DragEventArgs e)
{
InkCanvas ic = sender as InkCanvas;
ic.EditingMode = InkCanvasEditingMode.None;
ImageInfo image_Info = e.Data.GetData(typeof(ImageInfo)) as ImageInfo;
if (image_Info != null)
{
Image image = new Image();
image.Width = image_Info.Width * 4;
image.Stretch = Stretch.Fill;
image.Source = new BitmapImage(image_Info.Uri);
Point position = e.GetPosition(ic);
TranslateTransform mov = new TranslateTransform(position.X, position.Y);
image.RenderTransform = mov;
ic.Children.Add(image);
ImageResizing imgResize = ImageResizing.Create(image);
}
}
ImageResizing.Create() 现在将 rendertransforms 和 thumb 装饰器添加到图像以调整大小、移动和旋转:
private ImageResizing(Image image)
{
if (image == null)
throw new ArgumentNullException("image");
_image = image;
ScaleTransform scale = new ScaleTransform();
RotateTransform rot = new RotateTransform();
TranslateTransform mov = new TranslateTransform();
TransformGroup tg = new TransformGroup();
tg.Children.Add(image.RenderTransform);
tg.Children.Add(scale);
tg.Children.Add(rot);
tg.Children.Add(mov);
image.RenderTransform = tg;
image.RenderTransformOrigin = new Point(0.5,0.5);
// Create the adorner.
_adorner = new MyImageAdorner(image);
// Get the Adorner Layer and add the Adorner.
InstallAdorner();
}
TopLeft Thumb 装饰器定义为:
Thumb topLeft;
Path outline;
public MyImageAdorner(UIElement adornedElement)
: base(adornedElement)
{
visualChildren = new VisualCollection(this);
// Initialize the Resizing (i.e., corner) thumbs with specialized cursors.
BuildAdornerCorner(ref topLeft, Cursors.SizeNWSE);
topLeft.DragDelta += new DragDeltaEventHandler(TopLeft_DragDelta);
topLeft.DragCompleted += TopLeft_DragCompleted;
}
// Helper method to instantiate the corner Thumbs, set the Cursor property,
// set some appearance properties, and add the elements to the visual tree.
void BuildAdornerCorner(ref Thumb cornerThumb, Cursor customizedCursor)
{
if (cornerThumb != null) return;
cornerThumb = new Thumb();
// Set some arbitrary visual characteristics.
cornerThumb.Cursor = customizedCursor;
cornerThumb.Height = cornerThumb.Width = 15;
cornerThumb.Opacity = 0.40;
cornerThumb.Background = new SolidColorBrush(Colors.MediumBlue);
visualChildren.Add(cornerThumb);
}
我正在使用 DragDelta 将轮廓路径元素定位到最终所需的大小,如下所示:
// Top Left Corner is being dragged. Anchor is Bottom Right.
void TopLeft_DragDelta(object sender, DragDeltaEventArgs e)
{
ScaleTransform sT = new ScaleTransform(1 - e.HorizontalChange / outline.ActualWidth, 1 - e.VerticalChange / outline.ActualHeight,
outline.ActualWidth, outline.ActualHeight);
outline.RenderTransform = sT;
}
请注意,我打算使用左上角从右下角调整图像大小。因此,随着左上角被拖动,图像的所有点都将远离右下角。
最后,我使用 DragCompleted 事件在图像上实际执行新的渲染:
private void TopLeft_DragCompleted(object sender, DragCompletedEventArgs e)
{
// Get new scaling from the Outline.
ScaleTransform sT = outline.RenderTransform as ScaleTransform;
double anchorX = sT.CenterX;
double anchorY = sT.CenterY;
// Get the previous scaling
TransformGroup gT = AdornedElement.RenderTransform as TransformGroup;
ScaleTransform sT0 = gT.Children[1] as ScaleTransform;
double oldscaleX = sT0.ScaleX;
double oldscaleY = sT0.ScaleY;
double oldCenterX = anchorX - (outline.ActualWidth ) * oldscaleX;
double oldCenterY = anchorY - (outline.ActualHeight) * oldscaleY;
// Get the previous translation
TranslateTransform tT = gT.Children[3] as TranslateTransform;
sT0.CenterX = anchorX;
sT0.CenterY = anchorY;
sT0.ScaleX *= sT.ScaleX;
sT0.ScaleY *= sT.ScaleY;
double newCenterX = anchorX -(outline.ActualWidth) * sT0.ScaleX;
double newCenterY = anchorY -(outline.ActualHeight) * sT0.ScaleY;
tT.X += newCenterX - oldCenterX;
tT.Y += newCenterY - oldCenterY;
// Put transforms back.
gT.Children[1] = sT0;
gT.Children[3] = tT;
AdornedElement.RenderTransform = gT;
outline.RenderTransform = Transform.Identity;
}
为了完整起见,装饰器被定位为:
protected override Size ArrangeOverride(Size finalSize)
{
double eW = AdornedElement.RenderSize.Width;
double eH = AdornedElement.RenderSize.Height;
FrameworkElement ele = AdornedElement as FrameworkElement;
EnforceSize(ele);
eH = ele.Height;
eW = ele.Width;
Size aS = new Size(eW, eH);
// calculate the center of the image.
var center = new Point(eW / 2, eH / 2);
topLeft.Arrange(new Rect(new Point(-center.X, -center.Y), aS));
topRight.Arrange(new Rect(new Point(center.X, -center.Y), aS));
bottomLeft.Arrange(new Rect(new Point(-center.X, center.Y), aS));
bottomRight.Arrange(new Rect(new Point(center.X, center.Y), aS));
// The RotateHandle is placed slightly above the Top of the Image center.
// The MoveHandle is placed at the center of the Image.
rotateHandle.Arrange(new Rect(new Point(0, -(center.Y + HANDLEMARGIN)), aS));
moveHandle.Arrange(new Rect(new Point(0, 0), aS));
// Place a blue outline arround the image.
outline.Data = new RectangleGeometry(new Rect(aS));
outline.Arrange(new Rect(aS));
// Return the final size.
return aS;
}
我一定会很感激任何帮助或建议。我究竟做错了什么?
TIA
注意:这个问题的答案是缩放导致倾斜