【问题标题】:How to set constant width of strokes from PKInkingTool in PencilKit如何从 PencilKit 中的 PKInkingTool 设置恒定的笔划宽度
【发布时间】:2020-08-27 17:07:54
【问题描述】:

当使用 PencilKit API 使用手指/铅笔在屏幕上绘图时,我想将笔画的宽度设置为常数。目前,say PKInkingTool 中的宽度设置仅设置用手指或铅笔绘制时的基线宽度,如果用手指/铅笔进行慢速或快速描边,宽度会有所不同。

我不确定如何设置最小示例,有很多代码可以让 PencilKit 视图正常工作。您可以使用 Apple 的 this example 来设置一个简单的绘图应用程序。

这是我选择默认绘图工具的代码:

canvas.tool = PKInkingTool(.pen, color: .white, width: 10)

其中canvasPKCanvasView 对象。每个 InkType (link to docs) 中都有一个 validWidthRange 属性,但我不确定这是否可以帮助我实现我想要的。

【问题讨论】:

  • 你解决了吗?我也有同样的问题
  • @RoiMulia 我有,希望我下面的回答对你也有帮助。

标签: ios swift pencilkit


【解决方案1】:

我找到了解决方案(感谢Will Bishop),但我不确定它是否适合所有人。我通过在以恒定宽度完成笔画后重新绘制笔画来解决它。 Apple 在 WWDC2020 上为 iOS 14 发布了 PKStrokePKStrokePoint 的新 API。这是我的代码的相关部分(newDrawing 是具有恒定笔划宽度的新绘图,而 canvasView 是指我的 @ 上的当前绘图987654328@):

var newDrawingStrokes = [PKStroke]()
    for stroke in canvasView.drawing.strokes {
        var newPoints = [PKStrokePoint]()
        stroke.path.forEach { (point) in
        let newPoint = PKStrokePoint(location: point.location, 
                                     timeOffset: point.timeOffset, 
                                     size: CGSize(width: 5,height: 5), 
                                     opacity: CGFloat(1), force: point.force,
                                     azimuth: point.azimuth, altitude: point.altitude)
        newPoints.append(newPoint)
        }
        let newPath = PKStrokePath(controlPoints: newPoints, creationDate: Date())
        newDrawingStrokes.append(PKStroke(ink: PKInk(.pen, color: UIColor.white), path: newPath))
     }
let newDrawing = PKDrawing(strokes: newDrawingStrokes)

这是我整理的一些初步代码,如果您发现任何错误/错误,请告诉我!

【讨论】:

  • 是的,PKStroke 和 PKStrokePoint 在新的测试版中。我会将其添加到我的答案中。
  • 你把代码放在哪里了?我尝试放入 canvasViewDidEndUsingTool 委托方法,但是在我分配 canvasView.drawing = newDrawing 时的最后一行,它会引发警告并恢复我的笔画。任何帮助将不胜感激!
  • 好吧,我把它放在canvasViewDrawingDidChange 委托方法中,但那是特定于我的用例的。关于您的错误,我不确定您是否可以像这样重新分配画布绘图 - 我使用 newDrawing 进行一些后台处理,但我不会更改画布绘图显示本身。
  • 啊,我明白了 :( 我想修改 cavas 本身的绘图,当使用 canvasViewDrawingDidChange 时,它​​会触发递归。我可能不得不使用自定义解决方案而不是 PencilKit。谢谢你的回应!
【解决方案2】:

有一种方法可以通过混合 UITouch forcetimestamp 方法来修复它。

您可以在项目中添加此 Objective-C 类别:

#import <objc/runtime.h>

@implementation UITouch (UITouch_Overrides)

+ (void)load {
    [super load];

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        [self swizzleForce];
        [self swizzleTimestamp];
    });
}

+ (void)swizzleForce {
    [self swizzle:@selector(force) with:@selector(ed_force)];
}

+ (void)swizzleTimestamp {
    [self swizzle:@selector(timestamp) with:@selector(ed_timestamp)];
}

+ (void)swizzle:(SEL)originalSelector with:(SEL)swizzledSelector {
    Class class = [self class];
    
    Method originalMethod = class_getInstanceMethod(class, originalSelector);
    Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
    BOOL didAddMethod =
        class_addMethod(class,
            originalSelector,
            method_getImplementation(swizzledMethod),
            method_getTypeEncoding(swizzledMethod));
    if (didAddMethod) {
        class_replaceMethod(class,
            swizzledSelector,
            method_getImplementation(originalMethod),
            method_getTypeEncoding(originalMethod));
    } else {
        method_exchangeImplementations(originalMethod, swizzledMethod);
    }
}

- (CGFloat)ed_force {
    return 1.0;
}

- (NSTimeInterval)ed_timestamp {
    return 0;
}

@end

【讨论】:

  • 每次应用启动时只调用一次加载函数,以后我无法将宽度动态更改为原始 PKInkingTool 样式。如何根据 swift 的常量变量在常量宽度和默认 PKInkingTool 行为之间动态切换?
猜你喜欢
  • 1970-01-01
  • 2017-08-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-29
  • 2022-10-04
  • 2015-02-16
  • 1970-01-01
相关资源
最近更新 更多