[原创] 改善 Firemonkey Canvas 几何绘图质量问题(移动平台)
说明:
Fiiremonkey 的跨平台能力,大家有目共睹(一码同介面跨四平台),唯独移动平台在几何绘图方面,质量始终不尽人意,我也曾试着去修正(如:修正曲线平滑问题),也曾找过第三方案(如:AggPas),但都不完美,我一直在想,移动平台有这么强的绘图能力及质量(Android & iOS),如果能直接拿来用,不是很好?为什么 Firemonkey 要自己重写?
目前网上许多针对此问题的改善方案,但多以控件形式,且需依各平台的绘图函数来绘图,或仅提供固定的几何图形控件,如果能延用现有的 TCanvas.Draw????? 绘图代码,只要加入几行代码(或编译开关),就能达到原生绘图的效果,岂不是很理想,于是开是构想这种方案的可行性,最后证实是可行的。
要先说明的是,这里提供的只是一种改善方案,而不是修正,最终还是希望能受到 EMB 官方的关注,由官方来改进这个问题。
用法及效果:
FMX 的绘图方法:
procedure TForm1.PaintBox1Paint(Sender: TObject; Canvas: TCanvas);
var Rect, DesRect: TRectF;
begin
Rect := PaintBox1.LocalRect;
Canvas.Stroke.Thickness := ;
Canvas.Stroke.Kind := TBrushKind.Solid;
Canvas.Stroke.Dash := TStrokeDash.DashDotDot; DesRect := Rect;
InflateRect(DesRect, -(Canvas.Stroke.Thickness / ), -(Canvas.Stroke.Thickness / )); // 线在区内
Canvas.FillRect(DesRect, , , AllCorners, );
Canvas.DrawRect(DesRect, , , AllCorners, );
end;
说明 | Android | iOS | Windows | macOS |
上面的代码,使用 FMX 绘图方法 (移动平台是有问题的) |
![]() |
![]() |
![]() |
![]() |
下面的代码,使用原生绘图方法 (四个平台全部相同了) |
![]() |
![]() |
|
![]() |
下面改成原生绘图方案,只要在原有絵图代码前後加入二行代码(原绘图代码不用更动):
{$i NativeDraw.inc}
uses FMX.Graphics.Native; procedure TForm1.PaintBox1Paint(Sender: TObject; Canvas: TCanvas);
var Rect, DesRect: TRectF;
begin
Rect := PaintBox1.LocalRect;
Canvas.Stroke.Thickness := 10;
Canvas.Stroke.Kind := TBrushKind.Solid;
Canvas.Stroke.Dash := TStrokeDash.DashDotDot; {$IFDEF UseNativeDraw}Canvas.NativeDraw(Rect, procedure begin {$ENDIF} // 原生绘图 by Aone DesRect := Rect;
InflateRect(DesRect, -(Canvas.Stroke.Thickness / 2), -(Canvas.Stroke.Thickness / 2)); // 线在区内
Canvas.FillRect(DesRect, 30, 30, AllCorners, 1);
Canvas.DrawRect(DesRect, 30, 30, AllCorners, 1); {$IFDEF UseNativeDraw}end);{$ENDIF} // 原生绘图 by Aone
end;
运作原理:
- 它的运作原理很简单,就是先配置一个原生的绘图区域 Bitmap,再将几何图形画在这个区域里,最后将这个区域里的内容,转回 TBitmap,再显示到 Canvas 里
- 利用 Delphi Pascal Helper 语言特性,针对 TCanvas 来做扩展,如此才能达到不改动原有的绘图代码
- 目前这个作法,相同的绘图代码,可以跨四个平台:
Android, iOS:使用原生绘图 TCanvasHelper 方法
- Windows, masOS:使用原来 TCanvas 方法(这二个平台本来就没有质量问题,所以不用重写)
我们无法触及 FMX 的最核心,只能利用这种 Bitmap 方式来变通,要知道这种方式可能带来的问题(记忆体及效能),才不致错用
- 注意:如果引用了 FMX.Graphics.Native 就必需使用下面的方式来写绘图代码,否则请不要引用:
{$i NativeDraw.inc}
uses FMX.Graphics.Native; {$IFDEF UseNativeDraw}Canvas.NativeDraw(Rect, procedure begin {$ENDIF} // 原生绘图 by Aone // 绘图代码 {$IFDEF UseNativeDraw}end);{$ENDIF} // 原生绘图 by Aone
调用原生绘图的 TCanvas 函数:(仅有下面函数有质量问题)
DrawLine | 画线 |
FillRect | 圆距区 |
DrawRect | 圆距框线 |
FillPath | 路径区 |
DrawPath | 路径框线 |
FillEllipse | 椭圆区 |
DrawEllipse | 椭圆框线 |
FillArc | 孤线区 |
DrawArc | 孤框线 |
FillPolygon | 多边形区 |
DrawPolygon | 多边形框线 |
IntersectClipRect | 相交剪裁区 |
ExcludeClipRect | 其它剪裁区 |
TBrush 涂刷 & TStrokeBrush 线刷:
- 支持所有涂刷特性,除了 Bitmap 涂色尚未支持(若有此需求,可自行修改源码,加入此特性)
- FMX 在移动平台是不支持画线加渐层涂色,使用原生绘图,已经可以轻松实现(支持 Linear 线渐层及 Radial 圆渐层效果):
原生 FMX procedure TForm1.PaintBox1Paint(Sender: TObject; Canvas: TCanvas);
var Rect, DesRect: TRectF;
begin
Rect := PaintBox1.LocalRect;
Canvas.Stroke.Thickness := ;
Canvas.Stroke.Kind := TBrushKind.Gradient;
Canvas.Stroke.Dash := TStrokeDash.DashDotDot;
Canvas.Stroke.Gradient.Color := TAlphaColorRec.Blue;
Canvas.Stroke.Gradient.Color1 := TAlphaColorRec.Gold; {$IFDEF UseNativeDraw}Canvas.NativeDraw(Rect, procedure begin {$ENDIF} // 原生绘图 by Aone DesRect := Rect;
InflateRect(DesRect, -(Canvas.Stroke.Thickness / ), -(Canvas.Stroke.Thickness / )); // 线在区内
Canvas.FillRect(DesRect, , , AllCorners, );
Canvas.DrawRect(DesRect, , , AllCorners, ); {$IFDEF UseNativeDraw}end);{$ENDIF} // 原生绘图 by Aone
end;
已知问题:
- 真机 iOS 64bit 无法显示虚线(虚拟机没问题)
- 未完成的函数功能及特性,欢迎大家一起完善
文件下载:
- 源码:https://github.com/OneChen/FMXNativeDraw/
- Android Test apk:TestNativeDraw.apk
2017.06.22 新增 TestArc Demo(已更新到 GitHub):
参考资料:
- https://sourceforge.net/projects/dpfdelphiios/
- https://sourceforge.net/projects/alcinoe/
- https://developer.android.com/reference/android/graphics/Canvas.html
- https://developer.apple.com/reference/coregraphics
[原创] 改善 Firemonkey Canvas 几何绘图质量问题(移动平台)的更多相关文章
- HTML5 Canvas 2D绘图
为了防止无良网站的爬虫抓取文章,特此标识,转载请注明文章出处.LaplaceDemon/ShiJiaqi. http://www.cnblogs.com/shijiaqi1066/p/4851774. ...
- Microsoft.VisualBasic.dll的妙用and 改善C#公共程序类库质量的10种方法
Microsoft.VisualBasic.dll的妙用(开发中肯定会用到哦) 前言 做过VB开发的都知道,有一些VB里面的好的函数在.NET里面都没有,而Microsoft.VisualBasic. ...
- 【原创】C#搭建足球赛事资料库与预测平台(6) 赔率数据表设计2
本博客所有文章分类的总目录:[总目录]本博客博文总目录-实时更新 开源C#彩票数据资料库系列文章总目录:[目录]C#搭建足球赛事资料库与预测平台与彩票数据分析目录 本篇文章开始将逐步介 ...
- 【原创】C#搭建足球赛事资料库与预测平台(2) 数据库与XCode组件
本博客所有文章分类的总目录:[总目录]本博客博文总目录-实时更新 开源C#彩票数据资料库系列文章总目录:[目录]C#搭建足球赛事资料库与预测平台与彩票数据分析目录 本篇文章开始将逐步 ...
- sonar+Jenkins 构建代码质量自动化分析平台
1.Sonar 介绍 Sonar 是一个用于管理代码质量的开源工具,可以分析代码中的bug和漏洞以及Code Smells,支持20多种编程语言的检测,如java,c/c++,python,php等语 ...
- html --- canvas --- javascript --- 绘图方法
Canvas元素是HTML5的一部分,允许脚本语言动态渲染位图像. 如有疑问请访问链接:http://javascript.ruanyifeng.com/htmlapi/canvas.html < ...
- H5新特性——--第三方绘图工具库 echarts(canvas)---SVG绘图
今天学习的内容 3.1:h5新特性---第三方绘图工具库 echarts(canvas) 百度 echarts;d3;two.js;.... 3.2:h5新特性---SVG绘图 3.2:h5新特性-- ...
- (第一章)改善JavaScript,编写高质量代码。
根据<编写高质量代码改善JavaScript程序的188个建议>这本书,来记录我目前所了解的建议方式. 建议1:警惕Unicode乱码 根据ECMA标准规定JavaScript语言可以使用 ...
- Opengl编程指南第二章:状态管理、几何绘图
//http://blog.csdn.net/longhuihu/article/details/7701874 1.绘图基础 清除窗口 glClearColor(0.0, 0.0, 0.0, 0.0 ...
随机推荐
- Tkinter place() 方法
Python GUI - Tkinter place() 方法的使用例子: 这个的几何管理器组织放置在一个特定的位置,在他们的父widget部件. 语法: widget.place( place_ ...
- 归纳一下:C#线程同步的几种方法
转自原文 归纳一下:C#线程同步的几种方法 我们在编程的时候,有时会使用多线程来解决问题,比如你的程序需要在后台处理一大堆数据,但还要使用户界面处于可操作状态:或者你的程序需要访问一些外部资源如数据库 ...
- Delphi数据库的三层架构的问题和解决方法
Delphi数据库的三层架构的问题和解决方法 原创 2014年03月26日 16:26:03 标签: Delphi / 数据库三层架构 / DCOM / DCOMConnection 790 //-- ...
- django-rest-swagger
前提工作 pip3 install --user django>=2.0.0 pip3 install --user django-rest-swagger 安装完成之后,创建一个django项 ...
- mesos in docker
docker pull mesosphere/mesos-master:1.4.0 docker pull mesosphere/mesos-slave:1.4.0 在Docker中运行Mesos的推 ...
- C#登陆界面学习编写 2018.08.03
简单的登陆界面的编写,在编写如下界面时,设置错误次数上限需要用到静态变量 public static int count;//计算错误次数(为静态变量) 可以防止点击登陆后次数被清空,在登陆后打开新的 ...
- AddComponentMenu
[AddComponentMenu] The AddComponentMenu attribute allows you to place a script anywhere in the " ...
- vue 项目搭建
vue init webpack-simple 工程名字<工程名字不能用中文> 简单部署 vue init webpack 工程名字<工程名字不能用中文> 完整部署
- 高性能Web服务器Nginx的配置与部署研究(3)Nginx请求处理机制
1. 处理什么样的请求 处理访问到 Nginx 所在 IP 地址的请求,并且这些请求的 HTTP 头信息中的 Host 为所要处理的域名(如下以80端口为例),如下几个 server 就对应响应的请求 ...
- git回滚到某个commit 上和 返回最新的版本git
1. 代码回退 首先你要用git log 查看你要回到的那个本版, 然后用 git reset --hard HEAD^ 回退到上个版本 git reset --hard commit_id 退到/进 ...