本文告诉大家,win2d 不需要从零开始做,以前做出来的很多库其实只需要做很小修改就可以做出好看的效果,而且用在 UWP 上。本文修改原先 大神写的 GDI 图形到 win2d 上,而且可以运行起来


一开始先发一张图片给大家看,本文就是告诉大家如何做出下面这张图的效果。

本文的算法是学习 山人大大的博客 http://blog.csdn.net/johnsuna/article/details/7981521 ,在他上面做一点修改做出来的。

可以看到他的博客使用的方法就是 GDI ,这是古时候使用的技术,而现在的 UWP 可以在以前的技术上,做一点修改就可以使用。

如果需要使用 win2d ,我希望大家先看这篇文章,本文不会继续告诉大家如何安装 win2d 。

首先需要了解一个技术,从 point 数组画出来。

如果给了一个 point 数组,那么可以使用这个数组画出形状。

在 win2d 下,可以使用 DrawGeometry 方法画出来。

可以看到 DrawGeometry 的第一个参数是 CanvasGeometry ,第二个参数是可以选的 ,一般使用颜色就好了。

但是 CanvasGeometry 是没有构造方法,所以 UWP 需要使用 CanvasGeometry.CreatePolygon 等方法创建出来。

本文因为需要把 point 数组显示,所以就使用了 CanvasGeometry.CreatePolygon 。这个方法的第一个参数是 ICanvasResourceCreator ,获得 ICanvasResourceCreator 很简单,传入 draw.Device 。

所以代码如下。

  1. private void Canvas_OnDraw(CanvasControl sender, CanvasDrawEventArgs args)
  2. {
  3. var draw = args.DrawingSession;
  4. var canvasGeometry = CanvasGeometry.CreatePolygon(draw.Device,
  5. point.Select(temp => new Vector2((float) temp.X, (float) temp.Y)).ToArray());
  6. draw.DrawGeometry(canvasGeometry, Color.FromArgb(255, 100, 100, 100));
  7. }

那么 point 是如何得到,本文使用 http://blog.csdn.net/johnsuna/article/details/7981521 的方法获得。

  1. public static Point[] CreateStone(Point center, int outerRadius, int innerRadius, int arms)
  2. {
  3. int centerX = (int) center.X;
  4. int centerY = (int) center.Y;
  5. Point[] points = new Point[arms * 2];
  6. double offset = Math.PI / 2;
  7. double arc = 2 * Math.PI / arms;
  8. double half = arc / 2;
  9. for (int i = 0; i < arms; i++)
  10. {
  11. Random randomOuter = new Random((int) DateTime.Now.Ticks);
  12. outerRadius = outerRadius -
  13. randomOuter.Next((int) (innerRadius * 0.06 * new Random().Next(-20, 20) / 30d),
  14. (int) (innerRadius * 0.08));
  15. Random randomInner = new Random(Guid.NewGuid().GetHashCode());
  16. innerRadius = innerRadius +
  17. randomInner.Next((int) (innerRadius * 0.02 * new Random().Next(-100, 100) / 150d),
  18. (int) (innerRadius * 0.08));
  19. if (innerRadius > outerRadius)
  20. {
  21. int temp = outerRadius;
  22. outerRadius = innerRadius;
  23. innerRadius = temp;
  24. }
  25. double angleTemp = arc * randomInner.Next(-5, 5) / 10d;
  26. var angle = i * arc;
  27. angle += angleTemp;
  28. points[i * 2].X = (float) (centerX + Math.Cos(angle - offset) * outerRadius) + 20;
  29. points[i * 2].Y = (float) (centerY + Math.Sin(angle - offset) * outerRadius) + 20;
  30. points[i * 2 + 1].X = (float) (centerX + Math.Cos(angle + half - offset) * innerRadius) + 20;
  31. points[i * 2 + 1].Y = (float) (centerY + Math.Sin(angle + half - offset) * innerRadius) + 20;
  32. }
  33. return points;
  34. }

如果需要画出来图形,那么需要两个成员属性

  1. private List<Point[]> _points = new List<Point[]>();
  2. private Dictionary<string, Stone> _stone;

_points 就是所有画出的点,_stone 就是告诉说,如何画,因为可以传入的数值 角度,长宽,胖瘦,微移间隙 等的不同,可以画出不同的图形,所以需要通过一个属性来告诉如何画

  1. public class Stone
  2. {
  3. public static Point[] CreateStone(Point center, int outerRadius, int innerRadius, int arms)
  4. {
  5. int centerX = (int) center.X;
  6. int centerY = (int) center.Y;
  7. Point[] points = new Point[arms * 2];
  8. double offset = Math.PI / 2;
  9. double arc = 2 * Math.PI / arms;
  10. double half = arc / 2;
  11. for (int i = 0; i < arms; i++)
  12. {
  13. Random randomOuter = new Random((int) DateTime.Now.Ticks);
  14. outerRadius = outerRadius -
  15. randomOuter.Next((int) (innerRadius * 0.06 * new Random().Next(-20, 20) / 30d),
  16. (int) (innerRadius * 0.08));
  17. Random randomInner = new Random(Guid.NewGuid().GetHashCode());
  18. innerRadius = innerRadius +
  19. randomInner.Next((int) (innerRadius * 0.02 * new Random().Next(-100, 100) / 150d),
  20. (int) (innerRadius * 0.08));
  21. if (innerRadius > outerRadius)
  22. {
  23. int temp = outerRadius;
  24. outerRadius = innerRadius;
  25. innerRadius = temp;
  26. }
  27. double angleTemp = arc * randomInner.Next(-5, 5) / 10d;
  28. var angle = i * arc;
  29. angle += angleTemp;
  30. points[i * 2].X = (float) (centerX + Math.Cos(angle - offset) * outerRadius) + 20;
  31. points[i * 2].Y = (float) (centerY + Math.Sin(angle - offset) * outerRadius) + 20;
  32. points[i * 2 + 1].X = (float) (centerX + Math.Cos(angle + half - offset) * innerRadius) + 20;
  33. points[i * 2 + 1].Y = (float) (centerY + Math.Sin(angle + half - offset) * innerRadius) + 20;
  34. }
  35. return points;
  36. }
  37. public Func<float, float, int, int, Point> GetCenter;
  38. public Func<float, int> GetinnerRadius;
  39. public Func<float, int> GetouterRadius;
  40. public int maxCorners = 18;
  41. public int minCorners = 3;
  42. }

所以在构造使用下面代码

  1. public MainPage()
  2. {
  3. InitializeComponent();
  4. _stone = new Dictionary<string, Stone>()
  5. {
  6. {
  7. "星", new Stone()
  8. {
  9. minCorners = 3,
  10. maxCorners = 20,
  11. GetCenter = (perX, perY, i, j) => new Point((int) (perX * j), (int) (perY * i)),
  12. GetouterRadius = perX => (int) (perX * 0.18f),
  13. GetinnerRadius = perX => (int) (perX * 0.06f)
  14. }
  15. },
  16. };
  17. }

在界面弄个按钮

  1. <xaml:CanvasControl x:Name="canvas" Margin="10,10,10,100" Height="600" ClearColor="White" Draw="Canvas_OnDraw"></xaml:CanvasControl>
  2. <Button Margin="10,600,10,10" Content="星" Click="Button_OnClick"></Button>

然后写他的点击代码

  1. private void Button_OnClick(object sender, RoutedEventArgs e)
  2. {
  3. string str = ((Button) sender).Content?.ToString();
  4. _points = new List<Point[]>();
  5. int width = 500;
  6. int height = 500;
  7. int numX = 10;
  8. int numY = 10;
  9. float perX = width * 1f / numX;
  10. float perY = height * 1f / numY;
  11. int minCorners = _stone[str].minCorners;
  12. int maxCorners = _stone[str].maxCorners;
  13. int lastCorners = minCorners;
  14. Random random = new Random();
  15. for (int i = 0; i < numX; i++)
  16. {
  17. for (int j = 0; j < numY; j++)
  18. {
  19. int corners = random.Next(minCorners, maxCorners);
  20. if (Math.Abs(corners - lastCorners) < (maxCorners - minCorners) / 2)
  21. corners = RetrievRandomCorners(minCorners, maxCorners);
  22. lastCorners = corners;
  23. Point point = _stone[str].GetCenter(perX, perY, i, j);
  24. int outerRadius = _stone[str].GetouterRadius(perX);
  25. int innerRadius = _stone[str].GetinnerRadius(perX);
  26. var points = Stone.CreateStone(point, outerRadius,
  27. innerRadius, corners);
  28. _points.Add(points);
  29. }
  30. }
  31. canvas.Invalidate();
  32. }

尝试跑一下,点击一次按钮就会有不同的图形,是不是感觉世界都是假的。

是不是觉得这样已经完成?实际上不要忘记很重要一步,win2d在不使用需要自己手动把他从视觉树释放,所以在后台代码页面跳出使用下面代码


  1. private void Page_OnUnloaded(object sender, RoutedEventArgs e)
  2. {
  3. canvas.RemoveFromVisualTree();
  4. canvas = null;
  5. }

感觉这个星期的时间很快,我仔细想了从 2015 年开始 UWP 的研究到现在,实际我一个软件都没做出来,就是在写写博客。如果你觉得有哪个地方不想去看,或者垃圾微软写的不太好的,但你不想去研究的,就可以告诉我,我去研究一下,如果我学会了,我就会写一篇博客,虽然我写出来肯定比不上微软的。

代码:https://github.com/lindexi/UWP/tree/master/uwp/control/win2d/Dclutterpalan


本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。欢迎转载、使用、重新发布,但务必保留文章署名林德熙(包含链接:http://blog.csdn.net/lindexi_gd ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系

win2d 画出好看的图形的更多相关文章

  1. 2018-9-1-win2d-画出好看的图形

    title author date CreateTime categories win2d 画出好看的图形 lindexi 2018-09-01 16:25:40 +0800 2018-2-13 17 ...

  2. wpf 在不同DPI下如何在DrawingVisual中画出清晰的图形

    环境Win10 VS2017 .Net Framework4.7.1   本文仅讨论在DrawingVisual中进行的画图.   WPF单位,系统DPI,显示器DPI三者的定义及关系 WPF单位:一 ...

  3. 用CSS画出好玩的图形

    1.上三角 #triangle-up { width: 0; height: 0; border-left: 50px solid transparent; border-right: 50px so ...

  4. win2d 通过 CanvasActiveLayer 画出透明度和裁剪

    本文告诉大家如果在 UWP 的 win2d 通过 CanvasActiveLayer 创建一层,在这里画出的图片有透明度或者裁剪 在 win2d 如果需要对某个元素裁剪,可以使用很多方法,本文只是告诉 ...

  5. 使用CAShapeLayer与UIBezierPath画出想要的图形

    使用CAShapeLayer与UIBezierPath可以实现不在view的drawRect方法中就画出一些想要的图形 步骤: 1.新建UIBezierPath对象bezierPath 2.新建CAS ...

  6. opengl画不出直线 线段 坐标轴 却能画出其他图形的坑

    原文作者:aircraft 原文链接:https://www.cnblogs.com/DOMLX/p/12054507.html 好多次都是画坐标轴的三条直线画不出来,虽然最后都解决了  但是还是耽误 ...

  7. matlplotlib根据函数画出图形

    根据函数画出函数的轨迹 import matht = np.linspace(0, math.pi, 1000)x = np.sin(t)y = np.cos(t) + np.power(x, 2.0 ...

  8. 利用python画出动态高优先权优先调度

    之前写过一个文章. 利用python画出SJF调度图 动态高度优先权优先调度 动态优先权调度算法,以就绪队列中各个进程的优先权作为进程调度的依据.各个进程的优先权在创建进程时所赋予,随着进程的推进或其 ...

  9. H5坦克大战之【画出坦克】

    今天是个特殊的日子,圣诞节,也是周末,在这里先祝大家圣诞快乐!喜庆的日子,我们可以稍微放松一下,扯一扯昨天雷霆对战凯尔特人的比赛,这场比赛大威少又双叒叕拿下三双,而且是一个45+11+11的超级三双, ...

随机推荐

  1. 每日算法之三十四:Multiply Strings

    大数相乘,分别都是用字符串表示的两个大数.求相乘之后的结果表示. 首先我们应该考虑一下測试用例会有哪些,先准备測试用例对防御性编程会有比較大的帮助.可以考虑一些极端情况.有以下几种用例: 1)&quo ...

  2. python ndarray相关操作:拼接

  3. 【水滴石穿】React-Redux-Demo

    这个项目没有使用什么组件,可以理解就是个redux项目 项目地址为:https://github.com/HuPingKang/React-Redux-Demo 先看效果图 点击颜色字体颜色改变,以及 ...

  4. python 正则表达式简介

  5. cmakelists.txt中配置openg环境出现: undefined reference to symbol 'glLightfv'

    cmakelists.txt中配置openg环境出现: undefined reference to symbol 'glLightfv' 解决方法: 在cmakelists.txt添加 find_p ...

  6. 基于OSS+DataLakeAnalytics+QuickBI的Serverless的查询分析和可视化BI

    基于OSS的数据查询分析和可视化BI报表 数据存储在OSS后,有多种查询分析的方法,包括阿里云MaxCompute.DataLakeAnalytics产品等Severless查询分析服务,也可以自建S ...

  7. 智能算法之Matlab实现(1)——遗传算法(1)

    遗传算法的过程在这里先不介绍了,可能在接下来的几篇文章会介绍,这里介绍些实用的. (1)Sheffield遗传算法工具箱的安装 我共享了下修改过文件名和后缀名的原版工具箱,地址为:http://pan ...

  8. docker如何push镜像到docker hub个人的仓库

    docker如何push镜像到docker hub个人的仓库 step1——找到本地镜像的ID:docker images step2——登陆Hub:docker login --username=u ...

  9. Java练习 SDUT-1588_圆的面积

    圆的面积 Time Limit: 1000 ms Memory Limit: 32768 KiB Problem Description Give you the radius of a circle ...

  10. Python基础:07迭代器

    迭代器是在版本 2.2 被加入Python 的,它为类序列对象提供了一个类序列的接口.Python 的迭代无缝地支持序列对象,而且它还允许迭代非序列类型,包括用户定义的对象.它的出现,对列表迭代.字典 ...