实现图片盖章功能,在图片上点击,增加“图章”小图片,可以拖拽“图章”到任意位置,也可以点击图章右下角园框,令图片跟着鼠标旋转和放缩。
操作方法:1.点击增加“图章”2.选中移动图标3.点中右下角放缩旋转图章。
实现代码如下:
1. 窗口Xaml代码
<Window x:Class="Lenovo.YogaPaster.ImageEditWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Title="ImageEditWindow" Height="300" Width="300"><Grid><Grid.RowDefinitions><RowDefinition Height="20*"/><RowDefinition Height="*"/></Grid.RowDefinitions><Canvas x:Name="canvas" Background="Yellow" /><Button Content="保存成图片" Click="Button_Click_1" Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Center"/></Grid> </Window>
2. 窗口后台代码:
using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Imaging; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; 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.Shapes; using Lenovo.YP.Utils; using Microsoft.Win32; using Point = System.Windows.Point;namespace Lenovo.YogaPaster {/// <summary>/// ImageEditWindow.xaml 的交互逻辑/// </summary>public partial class ImageEditWindow : Window{public ImageEditWindow(){InitializeComponent();this.Loaded += (sender, e) =>{canvas.MouseLeftButtonDown += canvas_MouseLeftButtonDown;};}private void canvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e){PhotoEditHelper.CommomMaxZIndex++;var image = new MoveImage { ContainerCanvas = canvas };Point point = e.GetPosition(canvas);image.CreateImage(point);}/// <summary>/// 保存方法/// </summary>public void SavePicture(){//TODO: openFile对话框 SaveFileDialog saveFileDialog = new SaveFileDialog();saveFileDialog.FileName = "图片"; // Default file namesaveFileDialog.DefaultExt = ".bmp"; // Default file extensionsaveFileDialog.Filter = "图片文件 (.bmp)|*.bmp"; // Filter files by extension// Show save file dialog boxNullable<bool> result = saveFileDialog.ShowDialog();// Process save file dialog box resultsif (result == true){// Save documentstring filename = saveFileDialog.FileName;if (File.Exists(filename)){File.Delete(filename);}BitmapSource bitmapSource = PictureMergeHelper.CreateNotRanderElementScreenshot(canvas, 1800, 1080);BitmapEncoder bitmapEncoder = new BmpBitmapEncoder();bitmapEncoder.Frames.Add(BitmapFrame.Create(bitmapSource));FileStream fileStream = new FileStream(filename, FileMode.Create);bitmapEncoder.Save(fileStream);fileStream.Dispose();}}private void Button_Click_1(object sender, RoutedEventArgs e){SavePicture();}} }
3. MoveImage类文件如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging;namespace Lenovo.YP.Utils {/// <summary>/// 添加一个image控件,并实现拖动效果/// </summary>public class MoveImage{#region 字段private int m_ZIndex;/// <summary>/// 当前图章的位置/// </summary>/// /// <summary>/// 旋转图标的起始位置/// </summary>private Point m_ImageRoundStartOffset;/// <summary>/// 旋转图标的当前位置/// </summary>private Point m_ImageRoundOffset;/// <summary>/// 标识图章是否被拖拽/// </summary>private bool m_IsDragging;/// <summary>/// 标识旋转图标是否被是否被拖拽/// </summary>private bool m_IsimageRoundDragging;/// <summary>/// 图章的父容器/// </summary>public Canvas ContainerCanvas { get; set; }/// <summary>/// 图章图片/// </summary>private Image m_FlogImage;/// <summary>/// 旋转按钮图片/// </summary>private Image m_RotateImage;/// <summary>/// 图章和旋转图片的容器/// </summary>private Grid m_MoveImageGrid;/// <summary>/// 选转/// </summary>private RotateTransform m_ImageRotate;/// <summary>/// 缩放/// </summary>private ScaleTransform m_ImageScale;/// <summary>/// 上次位置/// </summary>private Point m_OldPos;#endregionpublic MoveImage(){ }/// <summary>/// 创建一个图标/// </summary>/// <param name="position">图标的位置</param>public void CreateImage(Point position){#region 设置布局m_FlogImage = new Image{//Width = 100,//Height = 100,Source = new BitmapImage(new Uri("/Images/shuzi.jpg", UriKind.RelativeOrAbsolute))};m_RotateImage = new Image{Width = 20,Height = 20,Source = new BitmapImage(new Uri("/Images/round.jpg", UriKind.RelativeOrAbsolute))};m_RotateImage.HorizontalAlignment = HorizontalAlignment.Right;m_RotateImage.VerticalAlignment = VerticalAlignment.Bottom;m_RotateImage.Visibility = Visibility.Hidden;m_MoveImageGrid = new Grid();m_MoveImageGrid.Width = 110;m_MoveImageGrid.Height = 110;m_MoveImageGrid.Children.Add(m_FlogImage);m_MoveImageGrid.Children.Add(m_RotateImage);m_MoveImageGrid.MouseEnter += RootGridMouseEnter;m_MoveImageGrid.MouseLeave += RootGridMouseLeave;m_RotateImage.MouseLeftButtonDown += imageRound_MouseLeftButtonDown;m_RotateImage.MouseMove += imageRound_MouseMove;m_RotateImage.MouseLeftButtonUp += imageRound_MouseLeftButtonUp;// Image in den Vordergrund bringenCanvas.SetZIndex(m_MoveImageGrid, m_ZIndex++);#endregion// Event Handler für das Image installierenm_MoveImageGrid.MouseLeftButtonDown += RootGridMouseLeftButtonDown;m_MoveImageGrid.MouseLeftButtonUp += RootGridMouseLeftButtonUp;m_MoveImageGrid.MouseMove += RootGridMouseMove;// Image leicht transparent machenm_MoveImageGrid.Opacity = 0.8;m_ImageRotate = new RotateTransform(0, 0, 0);m_ImageScale = new ScaleTransform();//m_ImageScale.ScaleX = 1;//m_ImageScale.ScaleY = 1;TransformGroup transformGroup = new TransformGroup();transformGroup.Children.Add(m_ImageRotate);transformGroup.Children.Add(m_ImageScale);m_MoveImageGrid.RenderTransform = transformGroup;//m_ImageScale111 = new ScaleTransform();//m_ImageScale111.ScaleX = 0.5;//m_ImageScale111.ScaleY = 0.5;//imageRound.RenderTransform = m_ImageScale111;m_MoveImageGrid.RenderTransformOrigin = new Point(0.5, 0.5);// Image positionierenvar pos = position;Canvas.SetLeft(m_MoveImageGrid, pos.X - (m_MoveImageGrid.Width / 2));Canvas.SetTop(m_MoveImageGrid, pos.Y - (m_MoveImageGrid.Height / 2));// Image zum Canvas hinzufügenContainerCanvas.Children.Add(m_MoveImageGrid);}/// <summary>/// 控制旋转图标隐藏/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void RootGridMouseLeave(object sender, MouseEventArgs e){m_RotateImage.Visibility = Visibility.Hidden;}/// <summary>/// 控制选择图标显示/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void RootGridMouseEnter(object sender, MouseEventArgs e){m_RotateImage.Visibility = Visibility.Visible;}#region 控制盖章的移动private void RootGridMouseMove(object sender, MouseEventArgs e){if (m_IsDragging){var pos = e.GetPosition(ContainerCanvas);Canvas.SetLeft(m_MoveImageGrid, Canvas.GetLeft(m_MoveImageGrid) + pos.X - m_OldPos.X);Canvas.SetTop(m_MoveImageGrid, Canvas.GetTop(m_MoveImageGrid) + pos.Y - m_OldPos.Y);m_OldPos = pos;}}private void RootGridMouseLeftButtonUp(object sender, MouseButtonEventArgs e){var grid = sender as Grid;// Canvas.SetZIndex(image, m_ZIndex++);// Bild wieder leicht transparent machengrid.Opacity = 0.8;grid.ReleaseMouseCapture();m_IsDragging = false;}private void RootGridMouseLeftButtonDown(object sender, MouseButtonEventArgs e){var grid = sender as Grid;// auf "nicht"-transparent setzengrid.Opacity = 1;// Position des Pointers relativ zum Bild speichernm_OldPos = e.GetPosition(ContainerCanvas);// isDragging auf true setzen für MouseMovem_IsDragging = true;// Image in den Vordergrund bringenCanvas.SetZIndex(grid, PhotoEditHelper.CommomMaxZIndex++);// Den Pointer einfangen. Bei schnellen Bewegungen kann der// Pointer aus dem Image bewegt werden. Damit die Pointer-// Events weiterhin stattfinden, wird der Pointer eingefangen. grid.CaptureMouse();// als behandelt markieren, damit nicht noch der// PointerPressed-Event Handler des Canvas aufgerufen wird.e.Handled = true;}#endregion#region 控制图章的旋转private void imageRound_MouseLeftButtonUp(object sender, MouseButtonEventArgs e){var image = sender as Image;m_MoveImageGrid.Opacity = 1;image.ReleaseMouseCapture();m_IsimageRoundDragging = false;}private void imageRound_MouseMove(object sender, MouseEventArgs e){if (m_IsimageRoundDragging){//鼠标当前点的坐标m_ImageRoundOffset = e.GetPosition(ContainerCanvas);m_ImageScale.ScaleX =m_ImageScale.ScaleY = GetLength(currCenter, m_ImageRoundStartOffset, m_ImageRoundOffset);m_ImageRotate.Angle = GetAngle(currCenter, m_ImageRoundStartOffset, m_ImageRoundOffset) - 45;}}private Point currCenter;private void imageRound_MouseLeftButtonDown(object sender, MouseButtonEventArgs e){var image = sender as Image;m_MoveImageGrid.Opacity = 1;//中心点坐标currCenter = new Point(Canvas.GetLeft(m_MoveImageGrid) + m_MoveImageGrid.Width / 2, Canvas.GetTop(m_MoveImageGrid) + m_MoveImageGrid.Height / 2);m_ImageRoundStartOffset = new Point(currCenter.X + m_MoveImageGrid.Width / 2, currCenter.Y);m_IsimageRoundDragging = true;Canvas.SetZIndex(m_MoveImageGrid, PhotoEditHelper.CommomMaxZIndex++);image.CaptureMouse();e.Handled = true;}/// 根据余弦定理求两个线段夹角/// </summary> /// <param name="origin">原点</param> /// <param name="start">start点</param> /// <param name="end">end点</param> /// <returns></returns> private double GetAngle(Point origin, Point start, Point end){double cosfi = 0, fi = 0, norm = 0;double dsx = start.X - origin.X;double dsy = start.Y - origin.Y;double dex = end.X - origin.X;double dey = end.Y - origin.Y;cosfi = dsx * dex + dsy * dey;norm = (dsx * dsx + dsy * dsy) * (dex * dex + dey * dey);if (norm == 0) return 0; // origin和end坐标一样cosfi /= Math.Sqrt(norm);if (cosfi >= 1.0) return 0;if (cosfi <= -1.0) return 180;fi = Math.Acos(cosfi);double angle = 180 * fi / Math.PI;if (dey > 0){return angle;}return -angle;}private double GetLength(Point origin, Point start, Point end){double dex = end.X - origin.X;double dey = end.Y - origin.Y;double dsx = start.X - origin.X;double dsy = start.Y - origin.Y;double startLength = Math.Sqrt(Math.Pow(dsx, 2) + Math.Pow(dsy, 2));double endLength = Math.Sqrt(Math.Pow(dex, 2) + Math.Pow(dey, 2));return endLength / startLength;}#endregion}
效果图: