You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

iOS涂色应用低透明度下画笔痕迹明显,如何优化线条流畅度?

嘿,这个低透明度下显露出单个画笔点的问题我之前做涂色应用时也碰到过!本质原因是你当前的实现应该是在touchesMoved里逐点绘制或者画很短的线段,低透明度下这些独立的绘制单元叠加后,就会显露出一个个点的轮廓——而不透明时因为颜色完全覆盖,所以看不出来。

给你一套解决思路和修改后的代码,亲测有效:

核心优化方向

  • 连贯的路径替代逐点绘制,让线条成为一个整体,而不是一堆独立的点
  • 优化笔触样式,让线条边缘更顺滑
  • 统一控制透明度,避免独立绘制单元的叠加问题

修改后的完整实现

首先在你的视图类里添加几个属性,用来管理绘制路径、画笔参数:

@property (nonatomic, strong) UIBezierPath *drawingPath;
@property (nonatomic, assign) CGFloat brushOpacity;
@property (nonatomic, assign) CGFloat brushWidth;
@property (nonatomic, strong) UIColor *brushColor;

然后在初始化方法(比如viewDidLoad或者自定义视图的initWithFrame:)里做基础设置:

- (void)viewDidLoad {
    [super viewDidLoad];
    // 初始化绘制路径
    self.drawingPath = [UIBezierPath bezierPath];
    // 设置画笔样式:圆角笔触+圆角连接,避免生硬的棱角
    self.drawingPath.lineCapStyle = kCGLineCapRound;
    self.drawingPath.lineJoinStyle = kCGLineJoinRound;
    // 画笔参数示例
    self.brushWidth = 6.0;
    self.brushOpacity = 0.3; // 你的低透明度需求
    self.brushColor = [UIColor blueColor];
}

接下来修改触摸事件的处理逻辑,把触摸点添加到连贯路径里:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch *touch = [touches anyObject];
    CGPoint startPoint = [touch locationInView:self];
    // 把路径起点移动到触摸开始的位置
    [self.drawingPath moveToPoint:startPoint];
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch *touch = [touches anyObject];
    CGPoint nextPoint = [touch locationInView:self];
    // 把当前触摸点连接到路径上
    [self.drawingPath addLineToPoint:nextPoint];
    // 触发重绘,让新的线条显示出来
    [self setNeedsDisplay];
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    // 触摸结束时再触发一次重绘,确保最后一段线条显示完整
    [self setNeedsDisplay];
}

最后实现drawRect方法,用统一的透明度绘制整个连贯路径:

- (void)drawRect:(CGRect)rect {
    CGContextRef context = UIGraphicsGetCurrentContext();
    // 设置透明度
    CGContextSetAlpha(context, self.brushOpacity);
    // 设置画笔颜色和宽度
    [self.brushColor setStroke];
    self.drawingPath.lineWidth = self.brushWidth;
    // 绘制完整路径
    [self.drawingPath stroke];
}

为什么这样能解决问题?

之前的逐点绘制相当于在画布上画了一堆独立的小圆圈(或方块),低透明度下每个小单元的alpha会叠加,导致点与点之间的边界显形。而用UIBezierPath连贯绘制后,整个线条是一个连续的图形,透明度是统一应用在整个路径上的,自然就看不到单个画笔点了。

如果需要支持多图层或者撤销功能,还可以把每个完成的路径保存到数组里,在drawRect里循环绘制所有路径就行。

内容的提问来源于stack exchange,提问作者Swick

火山引擎 最新活动