[update] 形状绘制更新箭头绘制

This commit is contained in:
Dubi906w 2024-08-14 21:44:13 +08:00
parent 9d7e27f22d
commit 22efc05e86
8 changed files with 152 additions and 33 deletions

View File

@ -738,6 +738,7 @@ namespace Ink_Canvas {
#region
private async void SymbolIconCursor_Click(object sender, RoutedEventArgs e) {
if (ShapeDrawingV2Layer.IsInShapeDrawingMode) ShapeDrawingV2Layer.EndShapeDrawing();
if (currentMode != 0) {
ImageBlackboard_MouseUp(null, null);
} else {
@ -764,6 +765,8 @@ namespace Ink_Canvas {
((Panel)lastBorderMouseDownObject).Background = new SolidColorBrush(Colors.Transparent);
if (sender == Cursor_Icon && lastBorderMouseDownObject != Cursor_Icon) return;
if (ShapeDrawingV2Layer.IsInShapeDrawingMode) ShapeDrawingV2Layer.EndShapeDrawing();
// 切换前自动截图保存墨迹
if (inkCanvas.Strokes.Count > 0 &&
inkCanvas.Strokes.Count > Settings.Automation.MinimumAutomationStrokeNumber)
@ -854,6 +857,8 @@ namespace Ink_Canvas {
((Panel)lastBorderMouseDownObject).Background = new SolidColorBrush(Colors.Transparent);
if (sender == Pen_Icon && lastBorderMouseDownObject != Pen_Icon) return;
if (ShapeDrawingV2Layer.IsInShapeDrawingMode) ShapeDrawingV2Layer.EndShapeDrawing();
if (Pen_Icon.Background == null || StackPanelCanvasControls.Visibility == Visibility.Collapsed) {
inkCanvas.EditingMode = InkCanvasEditingMode.Ink;
@ -947,6 +952,8 @@ namespace Ink_Canvas {
((Panel)lastBorderMouseDownObject).Background = new SolidColorBrush(Colors.Transparent);
if (sender == SymbolIconSelect && lastBorderMouseDownObject != SymbolIconSelect) return;
if (ShapeDrawingV2Layer.IsInShapeDrawingMode) ShapeDrawingV2Layer.EndShapeDrawing();
if (SelectedMode == ICCToolsEnum.LassoMode) {
if (SelectionPopupV2.IsOpen == false) {
var transform = SymbolIconSelect.TransformToVisual(Main_Grid);
@ -976,6 +983,8 @@ namespace Ink_Canvas {
((Panel)lastBorderMouseDownObject).Background = new SolidColorBrush(Colors.Transparent);
if (sender == Eraser_Icon && lastBorderMouseDownObject != Eraser_Icon) return;
if (ShapeDrawingV2Layer.IsInShapeDrawingMode) ShapeDrawingV2Layer.EndShapeDrawing();
forceEraser = true;
forcePointEraser = true;
@ -1057,6 +1066,8 @@ namespace Ink_Canvas {
((Panel)lastBorderMouseDownObject).Background = new SolidColorBrush(Colors.Transparent);
if (sender == EraserByStrokes_Icon && lastBorderMouseDownObject != EraserByStrokes_Icon) return;
if (ShapeDrawingV2Layer.IsInShapeDrawingMode) ShapeDrawingV2Layer.EndShapeDrawing();
forceEraser = true;
forcePointEraser = false;

View File

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Reflection;
using System.Windows;
using System.Windows.Controls;
@ -19,6 +20,11 @@ namespace Ink_Canvas {
public static Guid StrokeShapeTypeGuid = new Guid("6537b29c-557f-487f-800b-cb30a8f1de78");
public static Guid StrokeIsShapeGuid = new Guid("40eff5db-9346-4e42-bd46-7b0eb19d0018");
public StylusPointCollection RawStylusPointCollection { get; set; }
public MainWindow.ShapeDrawingHelper.ArrowLineConfig ArrowLineConfig { get; set; } =
new MainWindow.ShapeDrawingHelper.ArrowLineConfig();
// 自定义的墨迹渲染
protected override void DrawCore(DrawingContext drawingContext,
DrawingAttributes drawingAttributes) {
@ -29,7 +35,14 @@ namespace Ink_Canvas {
}
if ((int)this.GetPropertyData(StrokeShapeTypeGuid) == (int)MainWindow.ShapeDrawingType.DashedLine ||
(int)this.GetPropertyData(StrokeShapeTypeGuid) == (int)MainWindow.ShapeDrawingType.DottedLine) {
(int)this.GetPropertyData(StrokeShapeTypeGuid) == (int)MainWindow.ShapeDrawingType.Line ||
(int)this.GetPropertyData(StrokeShapeTypeGuid) == (int)MainWindow.ShapeDrawingType.DottedLine ||
(int)this.GetPropertyData(StrokeShapeTypeGuid) == (int)MainWindow.ShapeDrawingType.ArrowOneSide ||
(int)this.GetPropertyData(StrokeShapeTypeGuid) == (int)MainWindow.ShapeDrawingType.ArrowTwoSide) {
if (StylusPoints.Count < 2) {
base.DrawCore(drawingContext, drawingAttributes);
return;
}
StreamGeometry geometry = new StreamGeometry();
var pts = new List<Point>(this.StylusPoints.ToPoints());
using (StreamGeometryContext ctx = geometry.Open()) {
@ -42,8 +55,37 @@ namespace Ink_Canvas {
DashCap = PenLineCap.Round,
StartLineCap = PenLineCap.Round,
EndLineCap = PenLineCap.Round,
DashStyle = (int)this.GetPropertyData(StrokeShapeTypeGuid) == (int)MainWindow.ShapeDrawingType.DottedLine ? DashStyles.Dot : DashStyles.Dash
};
if ((int)this.GetPropertyData(StrokeShapeTypeGuid) != (int)MainWindow.ShapeDrawingType.Line &&
(int)this.GetPropertyData(StrokeShapeTypeGuid) != (int)MainWindow.ShapeDrawingType.ArrowOneSide &&
(int)this.GetPropertyData(StrokeShapeTypeGuid) != (int)MainWindow.ShapeDrawingType.ArrowTwoSide)
pen.DashStyle = (int)this.GetPropertyData(StrokeShapeTypeGuid) == (int)MainWindow.ShapeDrawingType.DottedLine ? DashStyles.Dot : DashStyles.Dash;
if ((int)this.GetPropertyData(StrokeShapeTypeGuid) == (int)MainWindow.ShapeDrawingType.ArrowOneSide) {
pts = new List<Point>(this.StylusPoints.ToPoints());
RawStylusPointCollection = StylusPoints.Clone();
double w = ArrowLineConfig.ArrowWidth, h = ArrowLineConfig.ArrowHeight;
var theta = Math.Atan2(pts[0].Y - pts[1].Y, pts[0].X - pts[1].X);
var sint = Math.Sin(theta);
var cost = Math.Cos(theta);
var pointList = new List<Point> {
new Point(pts[0].X, pts[0].Y),
new Point(pts[1].X, pts[1].Y),
new Point(pts[1].X + (w * cost - h * sint), pts[1].Y + (w * sint + h * cost)),
new Point(pts[1].X, pts[1].Y),
new Point(pts[1].X + (w * cost + h * sint), pts[1].Y - (h * cost - w * sint)),
};
StylusPoints = new StylusPointCollection(pointList);
var _pts = new List<Point>(this.StylusPoints.ToPoints());
using (StreamGeometryContext ctx = geometry.Open()) {
ctx.BeginFigure(_pts[0], false , false);
_pts.RemoveAt(0);
ctx.PolyLineTo(_pts,true, true);
}
drawingContext.DrawGeometry(new SolidColorBrush(DrawingAttributes.Color),pen, geometry);
return;
}
drawingContext.DrawGeometry(new SolidColorBrush(Colors.Transparent),pen, geometry);
}

View File

@ -538,7 +538,7 @@ namespace Ink_Canvas {
}
if (final_w >= 1 && final_h >= 1) {
// 此處還需要修改行為讓其能夠縮放到1x1
// TODO 此處還需要修改行為讓其能夠縮放到1x1
StrokeSelectionBorder.Width = final_w >=1 ? final_w : 1;
StrokeSelectionBorder.Height = final_h >=1 ? final_h : 1;

View File

@ -1590,7 +1590,7 @@ namespace Ink_Canvas {
ShapeDrawingPopupV2.IsOpen = false;
};
ShapeDrawingV2.ShapeSelectedEvent += (sender, args) => {
ShapeDrawingV2Layer.StartShapeDrawing(args.Type);
ShapeDrawingV2Layer.StartShapeDrawing(args.Type, args.Name);
};
}

View File

@ -12,7 +12,9 @@ namespace Ink_Canvas {
// 线
if (type == MainWindow.ShapeDrawingType.Line ||
type == MainWindow.ShapeDrawingType.DashedLine ||
type == MainWindow.ShapeDrawingType.DottedLine) {
type == MainWindow.ShapeDrawingType.DottedLine ||
type == MainWindow.ShapeDrawingType.ArrowOneSide ||
type == MainWindow.ShapeDrawingType.ArrowTwoSide) {
if (pts.Count != 2) throw new Exception("传入的点个数不是2个");
var stk = new IccStroke(new StylusPointCollection() {
new StylusPoint(pts[0].X, pts[0].Y),
@ -25,5 +27,35 @@ namespace Ink_Canvas {
return new StrokeCollection();
}
public static class ShapeDrawingHelper {
/// <summary>
/// 根据给定的两个点计算角度
/// </summary>
/// <param name="firstPoint"></param>
/// <param name="lastPoint"></param>
/// <returns></returns>
public static double CaculateRotateAngleByGivenTwoPoints(Point firstPoint, Point lastPoint) {
var vec1 = new double[] {
lastPoint.X - firstPoint.X ,
lastPoint.Y - firstPoint.Y
};
var vec_base = new double[] { 0, firstPoint.Y };
var cosine = (vec_base[0] * vec1[0] + vec_base[1] * vec1[1]) /
(Math.Sqrt(Math.Pow(vec_base[0],2) + Math.Pow(vec_base[1],2)) *
Math.Sqrt(Math.Pow(vec1[0],2) + Math.Pow(vec1[1],2)));
var angle = Math.Acos(cosine);
var isIn2And3Quadrant = lastPoint.X <= firstPoint.X;
var rotateAngle = Math.Round(180 + 180 * (angle / Math.PI) * (isIn2And3Quadrant ? 1 : -1), 0);
return rotateAngle;
}
public class ArrowLineConfig {
public int ArrowWidth { get; set; } = 20;
public int ArrowHeight { get; set; } = 7;
}
}
}
}

View File

@ -8,7 +8,9 @@
xmlns:helpers="clr-namespace:Ink_Canvas.Helpers"
mc:Ignorable="d"
d:DesignWidth="1920" d:DesignHeight="1080">
<Grid Name="FullscreenGrid">
<Grid>
<helpers:DrawingVisualCanvas IsHitTestVisible="False" x:Name="DrawingVisualCanvas"/>
<Grid Name="FullscreenGrid"/>
<Border Name="Toolbar" Height="48" Width="728" Background="#fafafa" BorderBrush="#e4e4e7" BorderThickness="1" CornerRadius="6" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="0,0,0,36">
<Grid>
<Border Name="ToolbarMoveHandle" Width="24" Height="48" Background="#d4d4d8" BorderBrush="#88a1a1aa" Margin="-1,-1,0,-1" CornerRadius="6,0,0,6" HorizontalAlignment="Left" BorderThickness="1">
@ -24,7 +26,7 @@
</Image.Source>
</Image>
</Border>
<Button Foreground="White" Content="完成" Padding="16,6" FontSize="16"
<Button Foreground="White" Content="完成" Padding="16,6" FontSize="16" Click="DoneButtonClicked"
HorizontalAlignment="Right" VerticalAlignment="Center" Margin="0,0,8,0">
<Button.Resources>
<SolidColorBrush
@ -174,30 +176,29 @@
<Border Padding="12,0" Height="32" Background="#bb450a0a" CornerRadius="4">
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
<TextBlock FontSize="14" Foreground="White" FontWeight="Bold" Text="形状绘制模式 : "/>
<TextBlock FontSize="14" Foreground="White" Text="直线"/>
<TextBlock Name="ShapeDrawingTypeText" FontSize="14" Foreground="White" Text="直线"/>
</StackPanel>
</Border>
<Border Padding="12,0" Height="32" Background="#bb422006" CornerRadius="4">
<Border Name="AngleTooltip" Padding="12,0" Height="32" Background="#bb422006" CornerRadius="4">
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
<TextBlock FontSize="14" Foreground="White" Text="总数 : "/>
<TextBlock FontSize="14" Foreground="White" FontWeight="Bold" Text="2"/>
<TextBlock FontSize="14" Foreground="White" Text="角度 : "/>
<TextBlock FontSize="14" Foreground="White" Name="AngleText" FontWeight="Bold" Text="0°"/>
</StackPanel>
</Border>
<Border Padding="12,0" Height="32" Background="#bb052e16" CornerRadius="4">
<Border Name="LengthTooltip" Padding="12,0" Height="32" Background="#bb052e16" CornerRadius="4">
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
<TextBlock FontSize="14" Foreground="White" Text="长度 : "/>
<TextBlock FontSize="14" Foreground="White" FontWeight="Bold" Text="128.98像素"/>
<TextBlock FontSize="14" Foreground="White" Name="LengthText" FontWeight="Bold" Text="0.00 px"/>
</StackPanel>
</Border>
<Border Padding="12,0" Height="32" Background="#bb172554" CornerRadius="4">
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
<TextBlock FontSize="14" Foreground="White" Text="粗细 : "/>
<TextBlock FontSize="14" Foreground="White" FontWeight="Bold" Text="4像素"/>
<TextBlock FontSize="14" Foreground="White" FontWeight="Bold" Name="PenSizeText" Text="4 像素"/>
</StackPanel>
</Border>
</modern:SimpleStackPanel>
</Grid>
</Border>
<helpers:DrawingVisualCanvas IsHitTestVisible="False" x:Name="DrawingVisualCanvas"/>
</Grid>
</UserControl>

View File

@ -45,12 +45,22 @@ namespace Ink_Canvas {
}
Toolbar.Visibility = Visibility.Collapsed;
AngleTooltip.Visibility = Visibility.Collapsed;
LengthTooltip.Visibility = Visibility.Collapsed;
FullscreenGrid.MouseDown += FullscreenGrid_MouseDown;
FullscreenGrid.MouseUp += FullscreenGrid_MouseUp;
FullscreenGrid.MouseMove += FullscreenGrid_MouseMove;
}
private Point CaculateCenteredToolbarPosition() {
var aw = Toolbar.Width;
var ah = Toolbar.Height;
var left = (MainWindow.ActualWidth - aw) / 2;
var top = MainWindow.ActualHeight - ah - 128;
return new Point(left, top);
}
public MainWindow MainWindow { get; set; }
public Border[] ToolButtons = new Border[] { };
@ -70,25 +80,43 @@ namespace Ink_Canvas {
private void ToolbarMoveHandle_MouseDown(object sender, MouseButtonEventArgs e) {
if (IsToolbarMoveHandleDown) return;
MouseDownPointInHandle = FullscreenGrid.TranslatePoint(e.GetPosition(null),ToolbarMoveHandle);
ToolbarMoveHandle.CaptureMouse();
IsToolbarMoveHandleDown = true;
Trace.WriteLine("MD");
ToolbarMoveHandle.CaptureMouse();
}
private void ToolbarMoveHandle_MouseUp(object sender, MouseButtonEventArgs e) {
if (IsToolbarMoveHandleDown == false) return;
ToolbarMoveHandle.ReleaseMouseCapture();
if (!IsToolbarMoveHandleDown) return;
IsToolbarMoveHandleDown = false;
Trace.WriteLine("MU");
ToolbarMoveHandle.ReleaseMouseCapture();
}
private void ToolbarMoveHandle_MouseMove(object sender, MouseEventArgs e) {
if (!IsToolbarMoveHandleDown) return;
var ptInScreen = e.GetPosition(null);
ToolbarNowPosition = new Point(ptInScreen.X - MouseDownPointInHandle.X, ptInScreen.Y - MouseDownPointInHandle.Y);
UpdateToolbarPosition(ToolbarNowPosition);
}
private MainWindow.ShapeDrawingType? _shapeType;
public void StartShapeDrawing(MainWindow.ShapeDrawingType type) {
public bool IsInShapeDrawingMode {
get => _shapeType != null;
}
public void StartShapeDrawing(MainWindow.ShapeDrawingType type, string name) {
_shapeType = type;
FullscreenGrid.Background = new SolidColorBrush(Color.FromArgb(1,0,0,0));
FullscreenGrid.Visibility = Visibility.Visible;
Toolbar.Visibility = Visibility.Visible;
var pt = CaculateCenteredToolbarPosition();
ToolbarNowPosition = pt;
UpdateToolbarPosition(pt);
ShapeDrawingTypeText.Text = name ?? "未知形状";
PenSizeText.Text = $"{(MainWindow.inkCanvas.DefaultDrawingAttributes.Width + MainWindow.inkCanvas.DefaultDrawingAttributes.Height) / 2} 像素";
}
private void DoneButtonClicked(object sender, RoutedEventArgs e) {
EndShapeDrawing();
}
public void EndShapeDrawing() {
@ -98,14 +126,6 @@ namespace Ink_Canvas {
Toolbar.Visibility = Visibility.Collapsed;
}
private void ToolbarMoveHandle_MouseMove(object sender, MouseEventArgs e) {
if (IsToolbarMoveHandleDown == false) return;
var ptInScreen = e.GetPosition(null);
Trace.WriteLine($"x:{ptInScreen.X} y:{ptInScreen.Y}");
ToolbarNowPosition = new Point(ptInScreen.X - MouseDownPointInHandle.X, ptInScreen.Y - MouseDownPointInHandle.Y);
UpdateToolbarPosition(ToolbarNowPosition);
}
private void ToolButton_MouseDown(object sender, MouseButtonEventArgs e) {
if (ToolButtonMouseDownBorder != null) return;
ToolButtonMouseDownBorder = (Border)sender;
@ -131,8 +151,8 @@ namespace Ink_Canvas {
if (isFullscreenGridDown) return;
points.Clear();
points.Add(e.GetPosition(null));
FullscreenGrid.CaptureMouse();
isFullscreenGridDown = true;
FullscreenGrid.CaptureMouse();
}
private void FullscreenGrid_MouseUp(object sender, MouseButtonEventArgs e) {
@ -141,8 +161,12 @@ namespace Ink_Canvas {
isFullscreenGridDown = false;
if (_shapeType == null) return;
using (DrawingContext dc = DrawingVisualCanvas.DrawingVisual.RenderOpen()) {}
MainWindow.inkCanvas.Strokes.Add(MainWindow.DrawShapeCore(points, (MainWindow.ShapeDrawingType)_shapeType));
if (points.Count >= 2)
MainWindow.inkCanvas.Strokes.Add(MainWindow.DrawShapeCore(points, (MainWindow.ShapeDrawingType)_shapeType));
points.Clear();
AngleTooltip.Visibility = Visibility.Collapsed;
LengthTooltip.Visibility = Visibility.Collapsed;
}
private void FullscreenGrid_MouseMove(object sender, MouseEventArgs e) {
@ -154,8 +178,15 @@ namespace Ink_Canvas {
using (DrawingContext dc = DrawingVisualCanvas.DrawingVisual.RenderOpen()) {
if ((_shapeType == MainWindow.ShapeDrawingType.Line ||
_shapeType == MainWindow.ShapeDrawingType.DashedLine ||
_shapeType == MainWindow.ShapeDrawingType.DottedLine) && points.Count >= 2) {
_shapeType == MainWindow.ShapeDrawingType.DottedLine ||
_shapeType == MainWindow.ShapeDrawingType.ArrowOneSide ||
_shapeType == MainWindow.ShapeDrawingType.ArrowTwoSide) && points.Count >= 2) {
MainWindow.DrawShapeCore(points, (MainWindow.ShapeDrawingType)_shapeType).Draw(dc);
var angle = MainWindow.ShapeDrawingHelper.CaculateRotateAngleByGivenTwoPoints(points[0], points[1]);
if (AngleTooltip.Visibility == Visibility.Collapsed) AngleTooltip.Visibility = Visibility.Visible;
AngleText.Text = $"{angle}°";
if (LengthTooltip.Visibility == Visibility.Collapsed) LengthTooltip.Visibility = Visibility.Visible;
LengthText.Text = $"{Math.Round(Math.Sqrt(Math.Pow((points[1].Y - points[0].Y), 2) + Math.Pow((points[1].X - points[0].X), 2)),2)} 像素";
}
}
}

View File

@ -177,6 +177,7 @@ namespace Ink_Canvas.Popups {
public event EventHandler<RoutedEventArgs> ShapeDrawingPopupShouldCloseEvent;
public class ShapeSelectedEventArgs : EventArgs {
public MainWindow.ShapeDrawingType Type { get; set; }
public string Name { get; set; }
}
public event EventHandler<ShapeSelectedEventArgs> ShapeSelectedEvent;
private void CloseButtonBorder_MouseDown(object sender, MouseButtonEventArgs e) {
@ -209,7 +210,8 @@ namespace Ink_Canvas.Popups {
ShapeDrawingButtonBorder_MouseLeave(sender, null);
ShapeDrawingPopupShouldCloseEvent?.Invoke(this,new RoutedEventArgs());
ShapeSelectedEvent?.Invoke(this, new ShapeSelectedEventArgs() {
Type = ((ShapeDrawingItem)((Border)sender).Tag).Type
Type = ((ShapeDrawingItem)((Border)sender).Tag).Type,
Name = ((ShapeDrawingItem)((Border)sender).Tag).Name
});
}
}