Screenshot

绘制完美的压力感应手绘线条。

? 这是 perfect-freehand JavaScript 库的移植。 试试这个演示

? 是否在商业产品中使用此库?请考虑 成为赞助者

目录

用法

此包导出一个名为 getStroke 的函数,该函数

  • 接受一个点数组和若干选项
  • 返回一个笔画轮廓作为点数组

import 'package:perfect_freehand/perfect_freehand.dart';

List<Point> myPoints = [
  Point(0, 0),
  Point(1, 2),
  // etc...
];

final stroke = getStroke(myPoints);

您也可以提供命名参数作为选项

final stroke = getStroke(
  myPoints,
  size: 16,
  thinning: 0.7,
  smoothing: 0.5,
  streamline: 0.5,
  taperStart: 0.0,
  taperEnd: 0.0,
  capStart: true,
  capEnd: true,
  simulatePressure: true,
  isComplete: false,
);

要使用真实的压力,请将每个点的压力作为第三个参数提供。

List<Point> myPoints = [
  Point(0, 0, 0.2),
  Point(1, 2, 0.3),
  Point(2, 4, 0.4),
  // etc...
];

final stroke = getStroke(myPoints, simulatePressure: false);

选项

可选参数为

属性 类型 默认值 描述
size 双精度 16 笔画的基础尺寸(直径)。
细化 双精度 .5 压力对笔画尺寸的影响。
平滑 双精度 .5 对笔画边缘进行柔化处理的程度。
流线化 双精度 .5 从输入点中去除变化的程度。
起始锥度 双精度 0 线开始处锥形的程度。
结束锥度 双精度 0 线结束处锥形的程度。
isComplete boolean 笔画是否完整。
simulatePressure boolean 是根据点之间的距离模拟压力,还是使用提供的点的压力。

注意:last 属性为 true 时,线条的末端将绘制在最后一个输入点处,而不是稍稍靠后。

注意:taper 大于零时,cap 属性无效。

提示:要创建具有稳定线条的笔画,请将 thinning 选项设置为 0

提示:要创建一条随着压力变细而不是变粗的笔画,请将 thinning 选项设置为负数。

渲染

虽然 getStroke 返回一个表示笔画轮廓的点数组,但如何渲染这些点由您决定。请查看 **示例项目**,了解如何在 Flutter 中使用 CustomPainter 绘制这些点。

import 'package:flutter/material.dart';
import 'package:perfect_freehand/perfect_freehand.dart';

class StrokePainter extends CustomPainter {
  final List<Point> points;

  StrokePainter({ required this.points });

  @override
  void paint(Canvas canvas, Size size) {
    Paint paint = Paint() ..color = Colors.black;

    // 1. Get the outline points from the input points
    final outlinePoints = getStroke(points);

    // 2. Render the points as a path
    final path = Path();

    if (outlinePoints.isEmpty) {
      // If the list is empty, don't do anything.
      return;
    } else if (outlinePoints.length < 2) {
      // If the list only has one point, draw a dot.
      path.addOval(Rect.fromCircle(
          center: Offset(outlinePoints[0].x, outlinePoints[0].y), radius: 1));
    } else {
      // Otherwise, draw a line that connects each point with a bezier curve segment.
      path.moveTo(outlinePoints[0].x, outlinePoints[0].y);

      for (int i = 1; i < outlinePoints.length - 1; ++i) {
        final p0 = outlinePoints[i];
        final p1 = outlinePoints[i + 1];
        path.quadraticBezierTo(
            p0.x, p0.y, (p0.x + p1.x) / 2, (p0.y + p1.y) / 2);
      }
    }

    // 3. Draw the path to the canvas
    canvas.drawPath(path, paint);
  }

  @override
  bool shouldRepaint(StrokePainter oldDelegate) {
    return true;
  }
}

高级用法

对于高级用法,该库还导出了 getStroke 用于生成其轮廓点的较小函数。

getStrokePoints

一个接受点数组并返回 StrokePoints 集合的函数。路径的总长度将是数组中最后一个点的 runningLength。与 getStroke 一样,此函数也接受上面列出的任何 可选命名参数

List<Point> myPoints = [
  Point(0, 0),
  Point(1, 2),
  // etc...
];

final strokePoints = getStrokePoints(myPoints, size: 16);

getOutlinePoints

一个接受笔画点数组(即 getStrokePoint 的输出)并返回定义笔画轮廓的点数组的函数。与 getStroke 一样,此函数也接受上面列出的任何 可选命名参数

List<Point> myPoints = [
  Point(0, 0),
  Point(1, 2),
  // etc...
];

final myStrokePoints = getStrokePoints(myPoints, size: 16);

final myOutlinePoints = getStrokeOutlinePoints(myStrokePoints, size: 16)

注意:在内部,getStroke 函数将 getStrokePoints 的结果传递给 getStrokeOutlinePoints,正如本示例所示。这意味着,在此示例中,myOutlinePoints 的结果将与 myPoints 列表传递给 getStroke 的结果相同。

支持

打开一个 issue 以获得支持。

讨论

有想法或想随意提问?请访问 讨论页面

作者

GitHub

https://github.com/stowers/perfect-freehand-dart