Fiiremonkey 的跨平台能力,你们有目共睹(一码同介面跨四平台),惟独移动平台在几何绘图方面,质量始终不尽人意,我也曾试着去修正(如:修正曲线平滑问题),也曾找过第三方案(如:AggPas),但都不完美,我一直在想,移动平台有这么强的绘图能力及质量(Android & iOS),若是能直接拿来用,不是很好?为何 Firemonkey 要本身重写?html
目前网上许多针对此问题的改善方案,但多以控件形式,且需依各平台的绘图函数来绘图,或仅提供固定的几何图形控件,若是能延用现有的 TCanvas.Draw????? 绘图代码,只要加入几行代码(或编译开关),就能达到原生绘图的效果,岂不是很理想,因而开是构想这种方案的可行性,最后证明是可行的。android
要先说明的是,这里提供的只是一种改善方案,而不是修正,最终仍是但愿能受到 EMB 官方的关注,由官方来改进这个问题。ios
FMX 的绘图方法:git
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; 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); end;
说明 | Android | iOS | Windows | macOS |
上面的代码,使用 FMX 绘图方法github (移动平台是有问题的)app |
![]() |
![]() |
![]() |
![]() |
下面的代码,使用原生绘图方法函数 (四个平台所有相同了)spa |
![]() |
![]() |
|
![]() |
下面改为原生绘图方案,只要在原有絵图代码前後加入二行代码(原绘图代码不用更动):.net
{$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;
Android, iOS:使用原生绘图 TCanvasHelper 方法3d
咱们没法触及 FMX 的最核心,只能利用这种 Bitmap 方式来变通,要知道这种方式可能带来的问题(记忆体及效能),才不致错用
{$i NativeDraw.inc} uses FMX.Graphics.Native; {$IFDEF UseNativeDraw}Canvas.NativeDraw(Rect, procedure begin {$ENDIF} // 原生绘图 by Aone // 绘图代码 {$IFDEF UseNativeDraw}end);{$ENDIF} // 原生绘图 by Aone
DrawLine | 画线 |
FillRect | 圆距区 |
DrawRect | 圆距框线 |
FillPath | 路径区 |
DrawPath | 路径框线 |
FillEllipse | 椭圆区 |
DrawEllipse | 椭圆框线 |
FillArc | 孤线区 |
DrawArc | 孤框线 |
FillPolygon | 多边形区 |
DrawPolygon | 多边形框线 |
IntersectClipRect | 相交剪裁区 |
ExcludeClipRect | 其它剪裁区 |
原生 | FMX |
![]() |
![]() |
procedure TForm1.PaintBox1Paint(Sender: TObject; Canvas: TCanvas); var Rect, DesRect: TRectF; begin Rect := PaintBox1.LocalRect; Canvas.Stroke.Thickness := 10; 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 / 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;
文件下载:
2017.06.22 新增 TestArc Demo(已更新到 GitHub):