效果展示
可以兼容矢量图
xaml:
<UserControl x:Class="CZ_UI_Templates.EntryDataBase.ZoomImageCanvas"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:CZ_UI_Templates.EntryDataBase"
mc:Ignorable="d" x:Name="_WorkView">
<UserControl.Resources>
<Style TargetType="Button">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Foreground" Value="{StaticResource TI_Color1}"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="False">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Foreground" Value="{StaticResource CZ_FontColor}"/>
</Trigger>
</Style.Triggers>
</Style>
<ControlTemplate x:Key="ButtonTemplate" TargetType="Button">
<Border Name="Border" CornerRadius="6" Background="Transparent" BorderBrush="Transparent" BorderThickness="0">
<WrapPanel VerticalAlignment="Center" HorizontalAlignment="Stretch">
<TextBlock Name="IcoText"
TextAlignment="Center"
HorizontalAlignment="Center"
FontFamily="{DynamicResource IconMoonFontFamily}"
Text="{TemplateBinding Content}"
Margin="5,0,5,0">
</TextBlock>
</WrapPanel>
</Border>
</ControlTemplate>
</UserControl.Resources>
<Canvas Margin="1" ClipToBounds="True">
<Border x:Name="border" Canvas.Top="0" Canvas.Right="0"
BorderBrush="Transparent" Panel.ZIndex="1"
MinHeight="30" Height="auto" Width="auto"
Background="White"
BorderThickness="3"
CornerRadius="5">
<WrapPanel Margin="3">
<Button x:Name="btn1" Margin="7 0 5 0" Template="{StaticResource ButtonTemplate}"
Background="Transparent" Tag="-0.1"
BorderThickness="0" Content="" Click="Button_Click"/>
<TextBlock Name="m_ProportionContent" Width="auto" Text="{Binding m_ProportionContentValue}" TextAlignment="Center"/>
<Button x:Name="btn2" Margin="6 0 5 0" Template="{StaticResource ButtonTemplate}"
Background="Transparent" Tag="0.1"
BorderThickness="0" Content="" Click="Button_Click"/>
<Border BorderBrush="{StaticResource CZ_FontColor}" BorderThickness="1" Width="0.5"/>
<Button Content="" Margin="2" Template="{StaticResource ButtonTemplate}"
Background="Transparent" Tag="1"
BorderThickness="0" Click="Button_Click"/>
</WrapPanel>
</Border>
<Canvas Background="White"
x:Name="FirstBase"
MouseWheel="Base_MouseWheel"
MouseMove="FirstBase_MouseMove"
MouseRightButtonDown="Base_MouseRightButtonDown"
MouseRightButtonUp="Base_MouseRightButtonUp"
ClipToBounds="True"
Width="{Binding ElementName=_WorkView, Path=ActualWidth}"
Height="{Binding ElementName=_WorkView, Path=ActualHeight}">
<Canvas Focusable="True"
Background="Transparent"
x:Name="SecondBase"
Width="{Binding ElementName=_WorkView, Path=ActualWidth}"
Height="{Binding ElementName=_WorkView, Path=ActualHeight}"
Canvas.Left="0"
Canvas.Top="0" >
<DockPanel x:Name="View"
Canvas.Left="0"
Canvas.Top="0"
Background="White"
Height="{Binding ElementName=SecondBase, Path=ActualHeight}"
Width="{Binding ElementName=SecondBase, Path=ActualWidth}">
</DockPanel>
<Canvas.RenderTransform>
<TransformGroup x:Name="transGrp">
<ScaleTransform x:Name="sfr" ScaleX="1" ScaleY="1" CenterX="00" CenterY="00"/>
<TranslateTransform x:Name="tlt"/>
<MatrixTransform x:Name="Matfr"/>
</TransformGroup>
</Canvas.RenderTransform>
</Canvas>
</Canvas>
</Canvas>
</UserControl>
后台
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
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.Navigation;
using System.Windows.Shapes;
namespace CZ_UI_Templates.EntryDataBase
{
/// <summary>
/// ZoomImageCanvas.xaml 的交互逻辑
/// </summary>
public partial class ZoomImageCanvas : UserControl, INotifyPropertyChanged
{
/*Canvas放大缩小相关*/
bool View_isMouseRightBtnDown = false;
Point View_lastMousePt;
Point lastCenterPoint;
double View_originOffsetX = 0, View_originOffsetY = 0;
/// <summary>
/// 是否拖动状态
/// </summary>
public bool m_View_isMouseRightBtnDown
{
get => View_isMouseRightBtnDown;
set
{
View_isMouseRightBtnDown = value;
///右键拖动时卡顿的最终解决方案,在拖动时,启用cacheMode,拖动结束后,关闭cacheMode,因为在拖动待连线的模块时如果开启CacheMode,将占用大量内存
if (value)
{
SecondBase.CacheMode = new BitmapCache() { EnableClearType = false, RenderAtScale = 3, SnapsToDevicePixels = false };
}
else
{
SecondBase.CacheMode = null;
}
}
}
//用来记录窗口放大率
private string _ProportionContent;
public string m_ProportionContentValue
{
get => _ProportionContent;
set
{
value = string.Format("{0}%", (m_Proportion * 100)).Split('.')[0];
_ProportionContent = value;
OnPropertyChanged("m_ProportionContentValue");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
private double _Proportion;
public double m_Proportion
{
get => _Proportion;
set
{
_Proportion = value;
m_ProportionContentValue = "";
}
}
public ZoomImageCanvas()
{
InitializeComponent();
m_Proportion = 1;
DataContext = this;
}
public void SetUIElement(UIElement uIElement)
{
Canvas.SetTop(uIElement, 0);
Canvas.SetLeft(uIElement, 0);
if (uIElement != null)
{
this.View.Children.Add(uIElement);
}
}
#region 第一个内层Canvas事件处理
private void Base_MouseWheel(object sender, MouseWheelEventArgs e)
{
//ctrl键按下+鼠标滚动 缩放画面
if ((Keyboard.Modifiers & (ModifierKeys.Control)) == (ModifierKeys.Control))
{ //ctrl键按下
if (e.Delta > 0)
{
m_ZoomIn(Mouse.GetPosition(FirstBase));
}
else
{
m_ZoomOut(Mouse.GetPosition(FirstBase));
}
e.Handled = true;
return;
}
}
private void FirstBase_MouseMove(object sender, MouseEventArgs e)
{
Point point = Mouse.GetPosition(this.FirstBase);
if (m_View_isMouseRightBtnDown)
{
Point SBoffsetA = SecondBase.TranslatePoint(new Point(0, 0), FirstBase);//secondbase的左上角点
Point SBoffsetB = SecondBase.TranslatePoint(new Point(SecondBase.ActualWidth, SecondBase.ActualHeight), FirstBase);//secondbase的右下角点
if ((point.X > View_lastMousePt.X && SBoffsetA.X < FirstBase.ActualWidth * 0.5)
|| (point.X < View_lastMousePt.X && SBoffsetB.X > FirstBase.ActualWidth * 0.5))
{
double x = point.X - View_lastMousePt.X;
double secondLeft = Canvas.GetLeft(SecondBase);
Canvas.SetLeft(SecondBase, secondLeft + x);
View_originOffsetX += x;
lastCenterPoint.X -= x;
}
if ((point.Y > View_lastMousePt.Y && SBoffsetA.Y < FirstBase.ActualHeight * 0.5)
|| (point.Y < View_lastMousePt.Y && SBoffsetB.Y > FirstBase.ActualHeight * 0.5))
{
double y = point.Y - View_lastMousePt.Y;
double secondTop = Canvas.GetTop(SecondBase);
Canvas.SetTop(SecondBase, secondTop + y);
View_originOffsetY += y;
lastCenterPoint.Y -= y;
}
View_lastMousePt = point;
e.Handled = true;
}
else
{
View_lastMousePt = point;
}
}
private void Base_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
m_View_isMouseRightBtnDown = true;
Mouse.OverrideCursor = Cursors.ScrollAll;
}
private void Base_MouseRightButtonUp(object sender, MouseButtonEventArgs e)
{
Mouse.OverrideCursor = null;
m_View_isMouseRightBtnDown = false;
}
#endregion
#region 公共方法
private void m_ZoomIn(Point mousePos)
{
if (sfr.ScaleX < 5)
{
mousePos.X -= View_originOffsetX;
mousePos.Y -= View_originOffsetY;
//原有中心点
Point untransformedOldCenter = new Point(this.sfr.CenterX, this.sfr.CenterY);
Point transformedOldCenter = this.sfr.Transform(untransformedOldCenter);
//新中心点
Point untransformedNewCenter = this.SecondBase.RenderTransform.Inverse.Transform(mousePos);
Point transformedNewCenter = mousePos;
//位置修正
double adjustX = transformedNewCenter.X - transformedOldCenter.X -
untransformedNewCenter.X + untransformedOldCenter.X;
double adjustY = transformedNewCenter.Y - transformedOldCenter.Y -
untransformedNewCenter.Y + untransformedOldCenter.Y;
//更新
this.tlt.X = adjustX;
this.tlt.Y = adjustY;
sfr.CenterX = untransformedNewCenter.X;
sfr.CenterY = untransformedNewCenter.Y;
sfr.ScaleX = sfr.ScaleX * 1.10;
sfr.ScaleY = sfr.ScaleY * 1.10;
m_Proportion = sfr.ScaleX;
}
}
private void m_ZoomOut(Point mousePos)
{
double scaled_SecondBaseWidth = SecondBase.ActualWidth * sfr.ScaleX;
if (scaled_SecondBaseWidth > FirstBase.ActualWidth * 0.2)
{
mousePos.X -= View_originOffsetX;
mousePos.Y -= View_originOffsetY;
//原有中心点
Point untransformedOldCenter = new Point(this.sfr.CenterX, this.sfr.CenterY);
Point transformedOldCenter = this.sfr.Transform(untransformedOldCenter);
//新中心点
Point untransformedNewCenter = this.SecondBase.RenderTransform.Inverse.Transform(mousePos);
Point transformedNewCenter = mousePos;
//位置修正
double adjustX = transformedNewCenter.X - transformedOldCenter.X -
untransformedNewCenter.X + untransformedOldCenter.X;
double adjustY = transformedNewCenter.Y - transformedOldCenter.Y -
untransformedNewCenter.Y + untransformedOldCenter.Y;
//更新
this.tlt.X = adjustX;
this.tlt.Y = adjustY;
sfr.CenterX = untransformedNewCenter.X;
sfr.CenterY = untransformedNewCenter.Y;
sfr.ScaleX = sfr.ScaleX * 0.90;
sfr.ScaleY = sfr.ScaleY * 0.90;
m_Proportion = sfr.ScaleX;
}
}
/// <summary>
/// 视图还原
/// </summary>
public void ViewDefault()
{
View_originOffsetX = 0;
View_originOffsetY = 0;
sfr.ScaleX = 1;
sfr.ScaleY = 1;
tlt.X = 0;
tlt.Y = 0;
sfr.CenterX = 0;
sfr.CenterY = 0;
Canvas.SetLeft(SecondBase, 0);
Canvas.SetTop(SecondBase, 0);
lastCenterPoint = new Point(this.ActualWidth / 2, this.ActualHeight / 2);
m_Proportion = sfr.ScaleX;
}
#endregion
private void Button_Click(object sender, RoutedEventArgs e)
{
Button button = sender as Button;
if (Convert.ToDouble(button.Tag) == 1)
{
ViewDefault();
}
else
{
Point point = new Point() { X = this.ActualWidth / 2, Y = this.ActualHeight / 2 };
if (Convert.ToDouble(button.Tag) > 0)
{
m_ZoomIn(point);
}
else
{
m_ZoomOut(point);
}
}
}
}
}
资源地址:https://download.csdn.net/download/qq_34581845/85060039