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

本文告诉大家,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 。

所以代码如下。

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

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

        public static Point[] CreateStone(Point center, int outerRadius, int innerRadius, int arms)
{
int centerX = (int) center.X;
int centerY = (int) center.Y;
Point[] points = new Point[arms * 2];
double offset = Math.PI / 2;
double arc = 2 * Math.PI / arms;
double half = arc / 2;
for (int i = 0; i < arms; i++)
{
Random randomOuter = new Random((int) DateTime.Now.Ticks);
outerRadius = outerRadius -
randomOuter.Next((int) (innerRadius * 0.06 * new Random().Next(-20, 20) / 30d),
(int) (innerRadius * 0.08));
Random randomInner = new Random(Guid.NewGuid().GetHashCode());
innerRadius = innerRadius +
randomInner.Next((int) (innerRadius * 0.02 * new Random().Next(-100, 100) / 150d),
(int) (innerRadius * 0.08));
if (innerRadius > outerRadius)
{
int temp = outerRadius;
outerRadius = innerRadius;
innerRadius = temp;
}
double angleTemp = arc * randomInner.Next(-5, 5) / 10d;
var angle = i * arc;
angle += angleTemp;
points[i * 2].X = (float) (centerX + Math.Cos(angle - offset) * outerRadius) + 20;
points[i * 2].Y = (float) (centerY + Math.Sin(angle - offset) * outerRadius) + 20;
points[i * 2 + 1].X = (float) (centerX + Math.Cos(angle + half - offset) * innerRadius) + 20;
points[i * 2 + 1].Y = (float) (centerY + Math.Sin(angle + half - offset) * innerRadius) + 20;
} return points;
}

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

        private List<Point[]> _points = new List<Point[]>();

        private Dictionary<string, Stone> _stone;

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

    public class Stone
{
public static Point[] CreateStone(Point center, int outerRadius, int innerRadius, int arms)
{
int centerX = (int) center.X;
int centerY = (int) center.Y;
Point[] points = new Point[arms * 2];
double offset = Math.PI / 2;
double arc = 2 * Math.PI / arms;
double half = arc / 2;
for (int i = 0; i < arms; i++)
{
Random randomOuter = new Random((int) DateTime.Now.Ticks);
outerRadius = outerRadius -
randomOuter.Next((int) (innerRadius * 0.06 * new Random().Next(-20, 20) / 30d),
(int) (innerRadius * 0.08));
Random randomInner = new Random(Guid.NewGuid().GetHashCode());
innerRadius = innerRadius +
randomInner.Next((int) (innerRadius * 0.02 * new Random().Next(-100, 100) / 150d),
(int) (innerRadius * 0.08));
if (innerRadius > outerRadius)
{
int temp = outerRadius;
outerRadius = innerRadius;
innerRadius = temp;
}
double angleTemp = arc * randomInner.Next(-5, 5) / 10d;
var angle = i * arc;
angle += angleTemp;
points[i * 2].X = (float) (centerX + Math.Cos(angle - offset) * outerRadius) + 20;
points[i * 2].Y = (float) (centerY + Math.Sin(angle - offset) * outerRadius) + 20;
points[i * 2 + 1].X = (float) (centerX + Math.Cos(angle + half - offset) * innerRadius) + 20;
points[i * 2 + 1].Y = (float) (centerY + Math.Sin(angle + half - offset) * innerRadius) + 20;
} return points;
} public Func<float, float, int, int, Point> GetCenter;
public Func<float, int> GetinnerRadius;
public Func<float, int> GetouterRadius;
public int maxCorners = 18;
public int minCorners = 3;
}

所以在构造使用下面代码

        public MainPage()
{
InitializeComponent(); _stone = new Dictionary<string, Stone>()
{
{
"星", new Stone()
{
minCorners = 3,
maxCorners = 20,
GetCenter = (perX, perY, i, j) => new Point((int) (perX * j), (int) (perY * i)),
GetouterRadius = perX => (int) (perX * 0.18f),
GetinnerRadius = perX => (int) (perX * 0.06f)
}
},
};
}

在界面弄个按钮

        <xaml:CanvasControl x:Name="canvas" Margin="10,10,10,100" Height="600" ClearColor="White" Draw="Canvas_OnDraw"></xaml:CanvasControl>

         <Button Margin="10,600,10,10" Content="星" Click="Button_OnClick"></Button>
            

然后写他的点击代码

        private void Button_OnClick(object sender, RoutedEventArgs e)
{
string str = ((Button) sender).Content?.ToString(); _points = new List<Point[]>(); int width = 500;
int height = 500;
int numX = 10;
int numY = 10;
float perX = width * 1f / numX;
float perY = height * 1f / numY; int minCorners = _stone[str].minCorners;
int maxCorners = _stone[str].maxCorners; int lastCorners = minCorners;
Random random = new Random();
for (int i = 0; i < numX; i++)
{
for (int j = 0; j < numY; j++)
{
int corners = random.Next(minCorners, maxCorners);
if (Math.Abs(corners - lastCorners) < (maxCorners - minCorners) / 2)
corners = RetrievRandomCorners(minCorners, maxCorners);
lastCorners = corners;
Point point = _stone[str].GetCenter(perX, perY, i, j);
int outerRadius = _stone[str].GetouterRadius(perX);
int innerRadius = _stone[str].GetinnerRadius(perX);
var points = Stone.CreateStone(point, outerRadius,
innerRadius, corners);
_points.Add(points);
}
} canvas.Invalidate();
}

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

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

        private void Page_OnUnloaded(object sender, RoutedEventArgs e)
{
canvas.RemoveFromVisualTree();
canvas = null;
}

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

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

2018-9-1-win2d-画出好看的图形的更多相关文章

  1. win2d 画出好看的图形

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

  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. Android中利用画图类和线程画出闪烁的心形

                                                        本文讲解主要涉及的知识点: 1.线程控制 2.画图类 3.心形函数 大家先看图片: <ig ...

  6. c语言贪吃蛇详解1.画出地图

    c语言贪吃蛇详解-1.画出地图 前几天的实验室培训课后作业我布置了贪吃蛇,今天有时间就来写一下题解.我将分几步来教大家写一个贪吃蛇小游戏.由于大家c语言未学完,这个教程只涉及数组和函数等知识点. 首先 ...

  7. java绘图原理------在窗口界面(或面板上)画出一张或多张图片问题解决方法

    /** *@author blovedr * 功能: java绘图原理------在窗口界面(或面板上)画出一张或多张图片问题解决方法 * 日期: 2018年4月28日     16:20 * 注释: ...

  8. 使用Pangolon在同一副图中,画出两个轨迹,比较误差

    使用 code/ground-truth.txt 和 code/estimate.txt 两条轨迹.请你根据上面公式,实现 RMSE的计算代码,给出最后的 RMSE 结果.作为验算,参考答案为:2.2 ...

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

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

随机推荐

  1. DirectX11笔记(三)--Direct3D初始化代码

    原文:DirectX11笔记(三)--Direct3D初始化代码 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/u010333737/article ...

  2. StringUtils常用方式留存

    StringUtils是org.apache.commons.lang下的一个工具包.主要用途从名字可以看出是针对于String的一些操作工具,里面包含的方法非常多,英语水平尚可以的人可以前往它的官方 ...

  3. 【51NOD1028】大数乘法 V2

    ╰( ̄▽ ̄)╭ 给出2个大整数A,B,计算A*B的结果. (A,B的长度 <= 100000,A,B >= 0) (⊙ ▽ ⊙) 把大整数A看做一个次数界为lenA的多项式A(x),其中x ...

  4. 【JZOJ4894】【NOIP2016提高A组集训第16场11.15】SJR的直线

    题目描述 数据范围 解法 考虑逐次加入每一条直线. 对于当前已加入的直线集合L,现在要新加入一条直线l. 那么它产生的贡献,与平行线有关. 对于任意三条直线,如果其中任意两条平行,那么将不做贡献. 所 ...

  5. No.4 Verilog 表达式

    4-1 操作数 常数.参数.线网.变量.位选.存储器.数组. *部分位选: integer mark; :] inst; :] gpio; inst[mark+ : ] //选择 mark,mark+ ...

  6. input输入框限制录入类型

    输入大小写字母.数字.下划线:<input type="text" onkeyup="this.value=this.value.replace(/[^\w_]/g ...

  7. 2019-10-31-C#-强转空会不会出现异常

    title author date CreateTime categories C# 强转空会不会出现异常 lindexi 2019-10-31 8:53:6 +0800 2019-9-10 11:4 ...

  8. laravel 项目本地版本为5.5,线上mysql 为5.7.21版本,执行严格模式

    看到网上很多说修改 但是在mysql 5.7中没有这个参数设置,故放弃: 结合本项目sina_id 10位超过int的最大范围4294967295,所以报错,修改为bigint  即可.

  9. Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第十一章:模板测试

    原文:Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第十一章:模板测试 代码工程地址: https://github.co ...

  10. OpenCV在各版本上的安装教程

    目录 使用pip安装OpenCV 安装Python版的OpenCV 4 安装Python版的OpenCV 3 在OSX和 macOS上安装OpenCV 3 在Ubuntu上安装Python版的Open ...