zoukankan      html  css  js  c++  java
  • 画线缩放、瞳距缩放、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了

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

     1 <Window x:Class="PupilDistanceDemo.MainWindow"
     2         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     3         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     4         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
     5         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
     6         xmlns:local="clr-namespace:PupilDistanceDemo"
     7         mc:Ignorable="d"
     8         WindowStartupLocation="CenterScreen"
     9         Title="瞳距缩放" Height="450" Width="800">
    10     <Grid>
    11         <Canvas Background="#0D1728" x:Name="canvas">
    12             <Image Source="2.jpg" x:Name="img1" Stretch="Fill" Width="300"  Canvas.Top="100" Canvas.Left="50" />
    13             <Image Source="1.jpg" x:Name="img2" Stretch="Fill" Width="200" Canvas.Top="100" Canvas.Left="400" />
    14         </Canvas>
    15         <StackPanel Orientation="Horizontal">
    16             <Button Margin="5" VerticalAlignment="Top" Click="Button_Click">启动瞳距</Button>
    17             <Button Margin="5" VerticalAlignment="Top" Click="Button_Click_1">关闭瞳距</Button>
    18             <Button Margin="5" VerticalAlignment="Top" Click="Button_Click_2">瞳距计算</Button>
    19             <Button Margin="5" VerticalAlignment="Top" Click="Button_Click_3">重置</Button>
    20             <StackPanel VerticalAlignment="Top">
    21                 <TextBlock Text="{Binding ElementName=img2,Path=ActualWidth}" Foreground="Red" />
    22                 <TextBlock Text="{Binding ElementName=img2,Path=ActualHeight}" Foreground="Red" />
    23             </StackPanel>
    24         </StackPanel>
    25     </Grid>
    26 </Window>
      1 using System;
      2 using System.Collections.Generic;
      3 using System.Linq;
      4 using System.Text;
      5 using System.Threading.Tasks;
      6 using System.Windows;
      7 using System.Windows.Controls;
      8 using System.Windows.Data;
      9 using System.Windows.Documents;
     10 using System.Windows.Input;
     11 using System.Windows.Media;
     12 using System.Windows.Media.Imaging;
     13 using System.Windows.Navigation;
     14 using System.Windows.Shapes;
     15 
     16 namespace PupilDistanceDemo
     17 {
     18     /// <summary>
     19     /// MainWindow.xaml 的交互逻辑
     20     /// </summary>
     21     public partial class MainWindow : Window
     22     {
     23         bool isLeftButtonDown = false;
     24         Image image;
     25 
     26         bool isPupilDistance = false;
     27         Size size;
     28 
     29         Point currentPoint;
     30 
     31         public MainWindow()
     32         {
     33             InitializeComponent();
     34 
     35             img1.MouseLeftButtonDown += Img_MouseLeftButtonDown;
     36             img1.MouseMove += Img_MouseMove;
     37             img1.MouseLeftButtonUp += Img_MouseLeftButtonUp;
     38 
     39             img2.MouseLeftButtonDown += Img_MouseLeftButtonDown;
     40             img2.MouseMove += Img_MouseMove;
     41             img2.MouseLeftButtonUp += Img_MouseLeftButtonUp;
     42 
     43             this.Loaded += MainWindow_Loaded;
     44         }
     45 
     46         private void MainWindow_Loaded(object sender, RoutedEventArgs e)
     47         {
     48             size = new Size(img2.ActualWidth, img2.ActualHeight);
     49         }
     50 
     51         private void Img_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
     52         {
     53             isLeftButtonDown = false;
     54             image = null;
     55         }
     56 
     57         private void Img_MouseMove(object sender, MouseEventArgs e)
     58         {
     59             if (isLeftButtonDown && sender is Image imgc)
     60             {
     61                 var point = e.GetPosition(canvas);
     62                 if (isPupilDistance && imgc.Tag is Line line)
     63                 {
     64                     if (image.Equals(imgc))
     65                     {
     66                         var x = point.X;
     67                         var y = point.Y;
     68                         if (x > line.X1) x -= 2;
     69                         else x += 2;
     70                         if (y > line.Y1) y -= 2;
     71                         else y += 2;
     72                         line.X2 = x;
     73                         line.Y2 = y;
     74                     }
     75                 }
     76                 else if (sender is Image image)
     77                 {
     78                     image.SetValue(Canvas.LeftProperty, point.X - currentPoint.X);
     79                     image.SetValue(Canvas.TopProperty, point.Y - currentPoint.Y);
     80                 }
     81             }
     82         }
     83 
     84         private void Img_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
     85         {
     86             image = sender as Image;
     87             isLeftButtonDown = true;
     88             if (sender is Image imgc)
     89             {
     90                 currentPoint = e.GetPosition(imgc);
     91 
     92                 if (isPupilDistance)
     93                 {
     94                     if (imgc.Tag is Line line)
     95                     {
     96                         canvas.Children.Remove(line);
     97                     }
     98 
     99                     line = new Line();
    100                     line.StrokeThickness = 2;
    101                     line.Stroke = new SolidColorBrush(Colors.Red);
    102                     var point = e.GetPosition(canvas);
    103                     line.X1 = point.X - 1;
    104                     line.Y1 = point.Y - 1;
    105                     line.X2 = line.X1;
    106                     line.Y2 = line.Y1;
    107                     canvas.Children.Add(line);
    108                     imgc.Tag = line;
    109                 }
    110             }
    111         }
    112 
    113         private void Button_Click(object sender, RoutedEventArgs e)
    114         {
    115             isPupilDistance = true;
    116         }
    117 
    118         private void Button_Click_1(object sender, RoutedEventArgs e)
    119         {
    120             isPupilDistance = false;
    121         }
    122 
    123         /// <summary>
    124         /// 计算瞳距
    125         /// </summary>
    126         /// <param name="sender"></param>
    127         /// <param name="e"></param>
    128         private void Button_Click_2(object sender, RoutedEventArgs e)
    129         {
    130             var l1 = img1.Tag as Line;
    131             var l2 = img2.Tag as Line;
    132 
    133             if (l1 == null || l2 == null)
    134             {
    135                 MessageBox.Show("请先 启用瞳距 ,再在图片上画线");
    136                 return;
    137             }
    138 
    139             //获取第一个图片的线
    140             var length1 = Distance(new Point(l1.X1, l1.Y1), new Point(l1.X2, l1.Y2));
    141 
    142             //获取第二个图片的线
    143             var length2 = Distance(new Point(l2.X1, l2.Y1), new Point(l2.X2, l2.Y2));
    144 
    145             //利用三角函数计算出以第一个图的线为基准,延长第二个图的线
    146             var AC = Math.Abs(l2.X2 - l2.X1);
    147             var BC = Math.Abs(l2.Y2 - l2.Y1);
    148 
    149             var jiaodu = Math.Atan(BC / AC);
    150             var sinVal = Math.Sin(jiaodu);
    151             var cosVal = Math.Cos(jiaodu);
    152             var ac = cosVal * length1;
    153             var bc = sinVal * length1;
    154 
    155             double xnew = 0, ynew = 0;
    156             if (l2.X2 > l2.X1) xnew = ac + l2.X1;
    157             else xnew = l2.X1 - ac;
    158 
    159             if (l2.Y2 > l2.Y1) ynew = l2.Y1 + bc;
    160             else ynew = l2.Y1 - bc;
    161 
    162             l2.X2 = xnew;
    163             l2.Y2 = ynew;
    164 
    165             var wnew = length1 / (length2 / img2.ActualWidth);
    166             var hnew = length1 / (length2 / img2.ActualHeight);
    167 
    168             //以用户画的起点作为缩放中心
    169             var x = (double)img2.GetValue(Canvas.LeftProperty);
    170             var y = (double)img2.GetValue(Canvas.TopProperty);
    171 
    172             //起始点相对于图片的位置
    173             var l2xToimg = l2.X1 - x;
    174             var l2yToimg = l2.Y1 - y;
    175 
    176             //获取起始点相对于图片的新位置,缩放后
    177             var l2xToimgnew = l2xToimg / img2.ActualWidth * wnew;
    178             var l2yToimgnew = l2yToimg / img2.ActualHeight * hnew;
    179 
    180             img2.SetValue(Canvas.LeftProperty, l2.X1 - l2xToimgnew);
    181             img2.SetValue(Canvas.TopProperty, l2.Y1 - l2yToimgnew);
    182 
    183             //缩放
    184             img2.Width = wnew;
    185             img2.Height = hnew;
    186         }
    187 
    188         /// <summary>
    189         /// 计算点位之间的距离
    190         /// </summary>
    191         /// <param name="p1"></param>
    192         /// <param name="p2"></param>
    193         /// <returns></returns>
    194         private double Distance(Point p1, Point p2)
    195         {
    196             double result = 0;
    197             result = Math.Sqrt((p1.X - p2.X) * (p1.X - p2.X) + (p1.Y - p2.Y) * (p1.Y - p2.Y));
    198             return result;
    199         }
    200 
    201         /// <summary>
    202         /// 重置
    203         /// </summary>
    204         /// <param name="sender"></param>
    205         /// <param name="e"></param>
    206         private void Button_Click_3(object sender, RoutedEventArgs e)
    207         {
    208             List<Line> l = new List<Line>();
    209             foreach (var item in canvas.Children)
    210             {
    211                 if (item is Line line)
    212                 {
    213                     l.Add(line);
    214                 }
    215             }
    216 
    217             l.ForEach(c => canvas.Children.Remove(c));
    218 
    219             img2.Width = size.Width;
    220             img2.Height = size.Height;
    221 
    222             img2.SetValue(Canvas.LeftProperty, 380.0);
    223             img2.SetValue(Canvas.TopProperty, 100.0);
    224         }
    225     }
    226 }

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

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

    点击下载,资源下载

  • 相关阅读:
    WCF和Socket
    MBA-数学
    80端口被占用
    linux系统root密码忘了怎么办 三种方法快速找回root密码
    px、em、rem、%、vw、wh、vm等单位有什么区别?
    知道id如何进入
    查询两个时间段间隔多久的数据
    jsp中的判断
    判断手机登陆还是电脑登陆
    配置pom.xml、spring.xml、spring-mvc.xml、spring-mybatis.xml、web.xml
  • 原文地址:https://www.cnblogs.com/xuling-297769461/p/12034212.html
Copyright © 2011-2022 走看看