Flutter开发进阶之Canvas

Flutter开发进阶之Canvas

在Flutter开发中Canvas作为一个绘制2D图形的工具,提供了一系列绘图方法,可以用来绘制各种形状、线条、文本和图像等;

Canvas对象是作为CustomPainter的子组件进行构建的;

dart 复制代码
void paint(Canvas canvas, Size size);

一、绘制的保存和恢复

Canvas通过使用以下方法调用原生层(C++)的绘图操作;

dart 复制代码
factory Canvas(PictureRecorder recorder, [ Rect? cullRect ]) = _NativeCanvas;

通过以下方法保存上下文和恢复;

dart 复制代码
void save();
void saveLayer(Rect? bounds, Paint paint);

void restore();
void restoreToCount(int count);
/// 保存数量
int getSaveCount();

二、绘制的变换

添加平移变换,分别在x轴和轴上;

dart 复制代码
void translate(double dx, double dy);

添加对应轴的缩放变换,若不指定sy则x轴和y轴都等比例缩放sx;

dart 复制代码
void scale(double sx, [double? sy]);

根据radians的弧度进行旋转变换;

dart 复制代码
void rotate(double radians);

相对原始角度对应的百分比倾斜变换;

dart 复制代码
void skew(double sx, double sy);

变换4x4矩阵;

dart 复制代码
void transform(Float64List matrix4);

变换的获取;

dart 复制代码
Float64List getTransform();

三、绘制的渲染流水线

还可以按指定规则进行裁剪;

dart 复制代码
void clipRect(Rect rect, { ClipOp clipOp = ClipOp.intersect, bool doAntiAlias = true });
void clipRRect(RRect rrect, {bool doAntiAlias = true});
void clipPath(Path path, {bool doAntiAlias = true});

/// 获取裁剪的边界
Rect getLocalClipBounds();
Rect getDestinationClipBounds();

通过以下API进行形状图元的组合、着色;

dart 复制代码
/// 着色
void drawColor(Color color, BlendMode blendMode);
/// 通过画笔进行点对点划线
void drawLine(Offset p1, Offset p2, Paint paint);
/// 画笔填充
void drawPaint(Paint paint);
/// 绘制矩形
void drawRect(Rect rect, Paint paint);
/// 绘制圆角矩形
void drawRRect(RRect rrect, Paint paint);
/// 绘制两个圆角矩形之差,填充或描边由画笔决定
void drawDRRect(RRect outer, RRect inner, Paint paint);
/// 绘制椭圆
void drawOval(Rect rect, Paint paint);
/// 绘制圆
void drawCircle(Offset c, double radius, Paint paint);
/// 绘制圆弧
void drawArc(Rect rect, double startAngle, double sweepAngle, bool useCenter, Paint paint);
/// 根据path绘制,一般是组合图形
void drawPath(Path path, Paint paint);
/// 给定位置绘制图片
void drawImage(Image image, Offset offset, Paint paint);
void drawImageRect(Image image, Rect src, Rect dst, Paint paint);
/// 图像分割成3x3绘制
void drawImageNine(Image image, Rect center, Rect dst, Paint paint);
/// 绘制图片
void drawPicture(Picture picture);
/// 给定位置的文本绘制
void drawParagraph(Paragraph paragraph, Offset offset);
/// 绘制点序列
void drawPoints(PointMode pointMode, List<Offset> points, Paint paint);
void drawRawPoints(PointMode pointMode, Float32List points, Paint paint);
/// 绘制顶点
void drawVertices(Vertices vertices, BlendMode blendMode, Paint paint);
/// 对绘制图像多个部分进行优化,可以对局部进行控制
void drawAtlas(Image atlas,
                 List<RSTransform> transforms,
                 List<Rect> rects,
                 List<Color>? colors,
                 BlendMode? blendMode,
                 Rect? cullRect,
                 Paint paint);
void drawRawAtlas(Image atlas,
                    Float32List rstTransforms,
                    Float32List rects,
                    Int32List? colors,
                    BlendMode? blendMode,
                    Rect? cullRect,
                    Paint paint);
/// 绘制阴影
void drawShadow(Path path, Color color, double elevation, bool transparentOccluder);

四、绘制的路径

Canvas使用Path来描述描述2D图形路径,路径可以是线段、二次贝塞尔曲线、三次贝塞尔曲线等,这些都可以组合在一起形成一个复杂的图形;

Path可以通过以下的方法来调用原生层的操作;

dart 复制代码
factory Path() = _NativePath;

factory Path.from(Path source) {
    final _NativePath clonedPath = _NativePath._();
    (source as _NativePath)._clone(clonedPath);
    return clonedPath;
  }

通过以下方法决定如何计算路径内部;

dart 复制代码
PathFillType get fillType;
set fillType(PathFillType value);

以下从点开始的路径;

dart 复制代码
/// 点的移动从开始到重新开始
void moveTo(double x, double y);
void relativeMoveTo(double dx, double dy);

/// 直线的连线到重新连线
void lineTo(double x, double y);
void relativeLineTo(double dx, double dy);

/// 贝塞尔曲线
void quadraticBezierTo(double x1, double y1, double x2, double y2);
void relativeQuadraticBezierTo(double x1, double y1, double x2, double y2);

/// 三次贝塞尔
void cubicTo(double x1, double y1, double x2, double y2, double x3, double y3);
void relativeCubicTo(double x1, double y1, double x2, double y2, double x3, double y3);

/// 贝塞尔线段
void conicTo(double x1, double y1, double x2, double y2, double w);
void relativeConicTo(double x1, double y1, double x2, double y2, double w);

/// 直线或圆弧
void arcTo(Rect rect, double startAngle, double sweepAngle, bool forceMoveTo);
void arcToPoint(Offset arcEnd, {
    Radius radius = Radius.zero,
    double rotation = 0.0,
    bool largeArc = false,
    bool clockwise = true,
  });
void relativeArcToPoint(
    Offset arcEndDelta, {
    Radius radius = Radius.zero,
    double rotation = 0.0,
    bool largeArc = false,
    bool clockwise = true,
  });

以下直接给定图形的路径;

dart 复制代码
/// 矩形
void addRect(Rect rect);
/// 椭圆
void addOval(Rect oval);
/// 圆弧
void addArc(Rect oval, double startAngle, double sweepAngle);
/// 线段
void addPolygon(List<Offset> points, bool close);
/// 圆角
void addRRect(RRect rrect);

以下是路径的组合运算;

dart 复制代码
/// 添加路径
void addPath(Path path, Offset offset, {Float64List? matrix4});
/// 添加子路径
void extendWithPath(Path path, Offset offset, {Float64List? matrix4});
/// 关闭路径
void close();
/// 复位
void reset();
/// 点是否在路径内
bool contains(Offset point);
/// 路径的副本
Path shift(Offset offset);
Path transform(Float64List matrix4);
/// 路径的边界
Rect getBounds();

/// 对路径进行组合
static Path combine(PathOperation operation, Path path1, Path path2) {
    final _NativePath path = _NativePath();
    if (path._op(path1 as _NativePath, path2 as _NativePath, operation.index)) {
      return path;
    }
    throw StateError('Path.combine() failed.  This may be due an invalid path; in particular, check for NaN values.');
  }
/// 多部分的路径轮廓属性,一个Path通常有0到多个轮廓线组成
PathMetrics computeMetrics({bool forceClosed = false});

五、绘制的画笔

Canvas使用Paint描述如何绘制图形,例如颜色、样式、混合模式等,以上我称之为画笔;
isAntiAlias :抗锯齿;
color :填充的颜色;
blendMode :图形混合时合成的模式;
style :是否绘制形状的内部,形状的边缘,或两者;
strokeWidth :线的宽度;
strokeCap :在绘制的线的末端放置的结束类型;
strokeJoin :连接点的类型;
strokeMiterLimit :斜接长度限制;
maskFilter :蒙版滤镜;
filterQuality :控制采样位图时使用的性能和质量权衡;
shader :形状着色器;
colorFilter :颜色滤镜;
imageFilter :图像滤镜;
invertColors:颜色反转。

以上时Flutter中Canvas绘图部分,具体的应用在实际开发中可能是地图线路绘制、AI图像转换、动画绘制等,如需深入还需了解计算机的渲染机制

相关推荐
DU_YULIN10 分钟前
Camera HAL ThreadManager概述
android·camera hal
淡淡的香烟1 小时前
Android中的MQTT通信原理解析
android·物联网
淡淡的香烟1 小时前
Android Camera开发详解
android·音视频
mmsx2 小时前
基于 Android 的校园信息管理系统源码
android·java·okhttp
xcyxiner3 小时前
flutter wsl2安装记录(使用宿主机虚拟机)
前端·flutter
YF02113 小时前
如何进入Android工程模式
android
Kevin Coding4 小时前
JsonConvert:适用于 Android、鸿蒙与 Flutter 的 JSON 转 Model 插件
android·flutter·harmonyos
2601_965798474 小时前
Build a Fast, High-Ranking Restaurant Website with Rolanda Theme
开发语言·ios·swift
极客互动API5 小时前
企业微信 iPad 协议消息接口开发:文本 / 图片 / 群发消息的统一封装
人工智能·ios·微信·机器人·企业微信·ipad
xcLeigh5 小时前
Go入门:基本数据类型全览与选择指南
android·服务器·golang·教程·go热门