画线缩放、瞳距缩放、Line延长到指定长度,内附效果,源码供应,解压就跑

前言

公司项目需要做个画线缩放,我司称之为瞳距缩放,简而言之就是:2张图,从第一张图画一条线,再从第二个图画一条线,第二条线以第一条为基准,延长到一致的长度,并同比缩放图片;文字太枯燥,请先实例图

例子1:以皮卡丘为例,我要把路飞的拳头缩放到皮卡丘头那么大

例子2:以皮卡丘的基准,缩小路飞,与其身高一致

 

好了,相比看了上面的2个效果图,就明白了大致意思,这个demo可以获得,Canvas里面的Line如何顺着线条方向,无限延伸的解决方案,以及画线缩放等...

会运用到高中数学知识,三角函数知识点,所以不熟悉的朋友,需要先温习,这样吧,我带大家温习下,反正工作忙完了,写博客和网友分享经验是最愉悦的事儿...

 

三角函数必要知识点温习

tan:对边 / 临边      tanA = BC / AC

sin:对边 / 斜边    sinA = BC / AB

cos:临边 / 斜边     cosA = AC / AB

已知边 BC 、AC,求角A的度数    ∠A = Math.Atan(BC / AC);   这是最关键的,获取A的角度就解决了所有,起初我还是想了很久的,年龄一大,以前的事就记不得了,划重点这里

好了,三角函数的知识温习到这里就足矣了,想象一下,把这个三角形放到程序的坐标系中,细细品,假如用户随意画的线就是AB,在画好的基础上进行延长.......细细品....

 

画线缩放,难点就是,如何让第二条线延长

请看图

已知了A点B点的坐标,通过坐标系,就能换算出BC边和AC的长度

运用三角函数,∠A的度数就等于:Math.Atan(BC / AC);

拿到的∠A,一切都变得好说了

比如,AB=100

sinA = BC / AB      ----->         sinA = BC / 100     ---->   BC = sinA * 100

BC = 100 * Math.Sin(∠A)

cosA = AC / AB  ---->   cosA = AC / 100  ---->  AC = cosA * 100

AC = 100 * Math.Cos(∠A)

BC、AC边都拿到,相信朋友们能转换成Point了

 

好了,上面都是知识点,很枯燥,程序员还是看代码吧,总归是要代码实现的

<Window x:Class="PupilDistanceDemo.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:PupilDistanceDemo"
        mc:Ignorable="d"
        WindowStartupLocation="CenterScreen"
        Title="瞳距缩放" Height="450" Width="800">
    <Grid>
        <Canvas Background="#0D1728" x:Name="canvas">
            <Image Source="2.jpg" x:Name="img1" Stretch="Fill" Width="300"  Canvas.Top="100" Canvas.Left="50" />
            <Image Source="1.jpg" x:Name="img2" Stretch="Fill" Width="200" Canvas.Top="100" Canvas.Left="400" />
        </Canvas>
        <StackPanel Orientation="Horizontal">
            <Button Margin="5" VerticalAlignment="Top" Click="Button_Click">启动瞳距</Button>
            <Button Margin="5" VerticalAlignment="Top" Click="Button_Click_1">关闭瞳距</Button>
            <Button Margin="5" VerticalAlignment="Top" Click="Button_Click_2">瞳距计算</Button>
            <Button Margin="5" VerticalAlignment="Top" Click="Button_Click_3">重置</Button>
            <StackPanel VerticalAlignment="Top">
                <TextBlock Text="{Binding ElementName=img2,Path=ActualWidth}" Foreground="Red" />
                <TextBlock Text="{Binding ElementName=img2,Path=ActualHeight}" Foreground="Red" />
            </StackPanel>
        </StackPanel>
    </Grid>
</Window>
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 PupilDistanceDemo
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        bool isLeftButtonDown = false;
        Image image;

        bool isPupilDistance = false;
        Size size;

        Point currentPoint;

        public MainWindow()
        {
            InitializeComponent();

            img1.MouseLeftButtonDown += Img_MouseLeftButtonDown;
            img1.MouseMove += Img_MouseMove;
            img1.MouseLeftButtonUp += Img_MouseLeftButtonUp;

            img2.MouseLeftButtonDown += Img_MouseLeftButtonDown;
            img2.MouseMove += Img_MouseMove;
            img2.MouseLeftButtonUp += Img_MouseLeftButtonUp;

            this.Loaded += MainWindow_Loaded;
        }

        private void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            size = new Size(img2.ActualWidth, img2.ActualHeight);
        }

        private void Img_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            isLeftButtonDown = false;
            image = null;
        }

        private void Img_MouseMove(object sender, MouseEventArgs e)
        {
            if (isLeftButtonDown && sender is Image imgc)
            {
                var point = e.GetPosition(canvas);
                if (isPupilDistance && imgc.Tag is Line line)
                {
                    if (image.Equals(imgc))
                    {
                        var x = point.X;
                        var y = point.Y;
                        if (x > line.X1) x -= 2;
                        else x += 2;
                        if (y > line.Y1) y -= 2;
                        else y += 2;
                        line.X2 = x;
                        line.Y2 = y;
                    }
                }
                else if (sender is Image image)
                {
                    image.SetValue(Canvas.LeftProperty, point.X - currentPoint.X);
                    image.SetValue(Canvas.TopProperty, point.Y - currentPoint.Y);
                }
            }
        }

        private void Img_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            image = sender as Image;
            isLeftButtonDown = true;
            if (sender is Image imgc)
            {
                currentPoint = e.GetPosition(imgc);

                if (isPupilDistance)
                {
                    if (imgc.Tag is Line line)
                    {
                        canvas.Children.Remove(line);
                    }

                    line = new Line();
                    line.StrokeThickness = 2;
                    line.Stroke = new SolidColorBrush(Colors.Red);
                    var point = e.GetPosition(canvas);
                    line.X1 = point.X - 1;
                    line.Y1 = point.Y - 1;
                    line.X2 = line.X1;
                    line.Y2 = line.Y1;
                    canvas.Children.Add(line);
                    imgc.Tag = line;
                }
            }
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            isPupilDistance = true;
        }

        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            isPupilDistance = false;
        }

        /// <summary>
        /// 计算瞳距
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Button_Click_2(object sender, RoutedEventArgs e)
        {
            var l1 = img1.Tag as Line;
            var l2 = img2.Tag as Line;

            if (l1 == null || l2 == null)
            {
                MessageBox.Show("请先 启用瞳距 ,再在图片上画线");
                return;
            }

            //获取第一个图片的线
            var length1 = Distance(new Point(l1.X1, l1.Y1), new Point(l1.X2, l1.Y2));

            //获取第二个图片的线
            var length2 = Distance(new Point(l2.X1, l2.Y1), new Point(l2.X2, l2.Y2));

            //利用三角函数计算出以第一个图的线为基准,延长第二个图的线
            var AC = Math.Abs(l2.X2 - l2.X1);
            var BC = Math.Abs(l2.Y2 - l2.Y1);

            var jiaodu = Math.Atan(BC / AC);
            var sinVal = Math.Sin(jiaodu);
            var cosVal = Math.Cos(jiaodu);
            var ac = cosVal * length1;
            var bc = sinVal * length1;

            double xnew = 0, ynew = 0;
            if (l2.X2 > l2.X1) xnew = ac + l2.X1;
            else xnew = l2.X1 - ac;

            if (l2.Y2 > l2.Y1) ynew = l2.Y1 + bc;
            else ynew = l2.Y1 - bc;

            l2.X2 = xnew;
            l2.Y2 = ynew;

            var wnew = length1 / (length2 / img2.ActualWidth);
            var hnew = length1 / (length2 / img2.ActualHeight);

            //以用户画的起点作为缩放中心
            var x = (double)img2.GetValue(Canvas.LeftProperty);
            var y = (double)img2.GetValue(Canvas.TopProperty);

            //起始点相对于图片的位置
            var l2xToimg = l2.X1 - x;
            var l2yToimg = l2.Y1 - y;

            //获取起始点相对于图片的新位置,缩放后
            var l2xToimgnew = l2xToimg / img2.ActualWidth * wnew;
            var l2yToimgnew = l2yToimg / img2.ActualHeight * hnew;

            img2.SetValue(Canvas.LeftProperty, l2.X1 - l2xToimgnew);
            img2.SetValue(Canvas.TopProperty, l2.Y1 - l2yToimgnew);

            //缩放
            img2.Width = wnew;
            img2.Height = hnew;
        }

        /// <summary>
        /// 计算点位之间的距离
        /// </summary>
        /// <param name="p1"></param>
        /// <param name="p2"></param>
        /// <returns></returns>
        private double Distance(Point p1, Point p2)
        {
            double result = 0;
            result = Math.Sqrt((p1.X - p2.X) * (p1.X - p2.X) + (p1.Y - p2.Y) * (p1.Y - p2.Y));
            return result;
        }

        /// <summary>
        /// 重置
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Button_Click_3(object sender, RoutedEventArgs e)
        {
            List<Line> l = new List<Line>();
            foreach (var item in canvas.Children)
            {
                if (item is Line line)
                {
                    l.Add(line);
                }
            }

            l.ForEach(c => canvas.Children.Remove(c));

            img2.Width = size.Width;
            img2.Height = size.Height;

            img2.SetValue(Canvas.LeftProperty, 380.0);
            img2.SetValue(Canvas.TopProperty, 100.0);
        }
    }
}

看到这里,可以先揉揉眼睛,放松下...

全部代码已经贴上,下面是下载链接,有需要的朋友可以移步下载,欢迎点评,谢谢~

资源下载地址,点击前往

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值