WPF Canvas Zoom and Pan

Copy from https://github.com/SEilers/WpfPanAndZoom

复制代码
//canvas.xaml
<Canvas x:Class="WpfApp69.CanvasZoomAndPanControl"
             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:WpfApp69"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800"
             Background="#333333"
             MouseDown="Canvas_MouseDown"
             MouseUp="Canvas_MouseUp"
             MouseMove="Canvas_MouseMove"
             MouseWheel="Canvas_MouseWheel">

</Canvas>


//xaml.cs

using System;
using System.Collections.Generic;
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.Navigation;
using System.Windows.Shapes;

namespace WpfApp69
{
    /// <summary>
    /// Interaction logic for CanvasZoomAndPanControl.xaml
    /// </summary>
    public partial class CanvasZoomAndPanControl : Canvas
    {
        private readonly MatrixTransform transform = new MatrixTransform();
        private Point initialPosition;
        private bool dragging;
        private UIElement selectedElement;
        private Vector draggingDelta;

        private Color lineColor = Color.FromArgb(0xFF, 0x66, 0x66, 0x66);
        private Color backgroundColor = Color.FromArgb(0xFF, 0x33, 0x33, 0x33);
        private List<Line> gridLines = new List<Line>();
        public CanvasZoomAndPanControl()
        {
            InitializeComponent();
            BackgroundColor = backgroundColor;
            InitGridLines();
        }

        private void InitGridLines()
        {
            for (int x = -4000; x <= 4000; x += 100)
            {
                Line verticalLine = new Line
                {
                    Stroke = new SolidColorBrush(lineColor),
                    X1 = x,
                    Y1 = -4000,
                    X2 = x,
                    Y2 = 4000
                };

                if (x % 1000 == 0)
                {
                    verticalLine.StrokeThickness = 6;
                }
                else
                {
                    verticalLine.StrokeThickness = 2;
                }

                Children.Add(verticalLine);
                gridLines.Add(verticalLine);
            }

            for (int y = -4000; y <= 4000; y += 100)
            {
                Line horizontalLine = new Line
                {
                    Stroke = new SolidColorBrush(lineColor),
                    X1 = -4000,
                    Y1 = y,
                    X2 = 4000,
                    Y2 = y
                };

                if (y % 1000 == 0)
                {
                    horizontalLine.StrokeThickness = 6;
                }
                else
                {
                    horizontalLine.StrokeThickness = 2;
                }

                Children.Add(horizontalLine);
                gridLines.Add(horizontalLine);
            }
        }

        private void Canvas_MouseDown(object sender, MouseButtonEventArgs e)
        {
            if (e.ChangedButton == MouseButton.Right)
            {
                initialPosition = transform.Inverse.Transform(e.GetPosition(this));
            }

            if (e.ChangedButton == MouseButton.Left)
            {
                if (this.Children.Contains((UIElement)e.Source))
                {
                    selectedElement = (UIElement)e.Source;
                    Point mousePosition = Mouse.GetPosition(this);
                    double x = Canvas.GetLeft(selectedElement);
                    double y = Canvas.GetTop(selectedElement);
                    Point elementPosition = new Point(x, y);
                    draggingDelta = elementPosition - mousePosition;
                }
                dragging = true;
            }
        }

        private void Canvas_MouseUp(object sender, MouseButtonEventArgs e)
        {
            dragging = false;
            selectedElement = null;
        }

        private void Canvas_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.RightButton == MouseButtonState.Pressed)
            {
                Point mousePosition = transform.Inverse.Transform(e.GetPosition(this));
                Vector delta = Point.Subtract(mousePosition, initialPosition);
                var translate = new TranslateTransform(delta.X, delta.Y);
                transform.Matrix = translate.Value * transform.Matrix;

                foreach (UIElement child in this.Children)
                {
                    child.RenderTransform = transform;
                }
            }

            if (dragging && e.LeftButton == MouseButtonState.Pressed)
            {
                double x = Mouse.GetPosition(this).X;
                double y = Mouse.GetPosition(this).Y;

                if (selectedElement != null)
                {
                    Canvas.SetLeft(selectedElement, x + draggingDelta.X);
                    Canvas.SetTop(selectedElement, y + draggingDelta.Y);
                }
            }
        }

        private void Canvas_MouseWheel(object sender, MouseWheelEventArgs e)
        {
            float scaleFactor = Zoomfactor;
            if (e.Delta < 0)
            {
                scaleFactor = 1f / scaleFactor;
            }

            Point mousePostion = e.GetPosition(this);

            Matrix scaleMatrix = transform.Matrix;
            scaleMatrix.ScaleAt(scaleFactor, scaleFactor, mousePostion.X, mousePostion.Y);
            transform.Matrix = scaleMatrix;

            foreach (UIElement child in this.Children)
            {
                double x = Canvas.GetLeft(child);
                double y = Canvas.GetTop(child);

                double sx = x * scaleFactor;
                double sy = y * scaleFactor;

                Canvas.SetLeft(child, sx);
                Canvas.SetTop(child, sy);

                child.RenderTransform = transform;
            }
        }

        public Color BackgroundColor
        {
            get
            {
                return backgroundColor;
            }
            set
            {
                backgroundColor = value;
                Background = new SolidColorBrush(backgroundColor);
            }
        }

        public float Zoomfactor { get; set; } = 1.1f;

        public Color LineColor
        {
            get
            {
                return lineColor;
            }
            set
            {
                lineColor = value;
                foreach(var line in gridLines)
                {
                    line.Stroke=new SolidColorBrush(lineColor);
                }
            }
        }
    }
}




//MainWindow.xaml
<Window x:Class="WpfApp69.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp69"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <local:CanvasZoomAndPanControl>
        <Image RenderOptions.BitmapScalingMode="Fant"
               Stretch="Uniform"
               Source="Images/1.jpg"/>
    </local:CanvasZoomAndPanControl>
</Window>
复制代码

 

 

 

 

 

 

 

posted @   FredGrit  阅读(39)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
历史上的今天:
2022-12-18 cppconn cpp create table in cpp file ,show current date time in mysql cli via select current_timestamp command
2022-12-18 cppconn resultsetmetadata get columns count,get column name,resultset get value
点击右上角即可分享
微信分享提示