iOS石英绘图应用程序

3

更新:下面展示了正确的绘制矩形方法

- (void)drawRect:(CGRect)rect {
    CGContextRef context = UIGraphicsGetCurrentContext();

    if(layer == nil)
    {
        float scale = [UIScreen mainScreen].scale;
        CGRect bounds = CGRectMake(0, 0, rect.size.width *scale, rect.size.height *scale);
        layer = CGLayerCreateWithContext(context, bounds.size, NULL);
        layerContext = CGLayerGetContext(layer);
        CGContextScaleCTM(layerContext, scale, scale);
        viewRect = CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height);
    }

    UIBezierPath *bezierPath = path.bezierPath;
    CGContextAddPath(layerContext, bezierPath.CGPath);
    CGContextSetLineWidth(layerContext, path.width);
    CGContextSetStrokeColorWithColor(layerContext, path.color.CGColor);
    CGContextSetLineCap(layerContext, kCGLineCapRound);
    CGContextStrokePath(layerContext);

    CGContextDrawLayerInRect(context, viewRect, layer);
    self.empty = NO;
}

更新:我已经按照建议将路径添加到数组中,并按照下面的方式绘制到CGLayer中。然而,当绘制大量路径时,性能会降低。我有做错什么吗?
    - (void)pan:(UIPanGestureRecognizer *)pan
{
    CGPoint velocity = [pan velocityInView:self];

    previousPoint2 = previousPoint1;
    previousPoint1 = currentPoint;
    currentPoint = [pan locationInView:self];

    float velocityMagnitude = sqrtf(velocity.x * velocity.x + velocity.y * velocity.y);

    float clampedVelocityMagnitude = clamp(VELOCITY_CLAMP_MIN, VELOCITY_CLAMP_MAX, velocityMagnitude);
    float normalizedVelocity = (clampedVelocityMagnitude - VELOCITY_CLAMP_MIN) / (VELOCITY_CLAMP_MAX - VELOCITY_CLAMP_MIN);

    float lowPassFilterAlpha = STROKE_WIDTH_SMOOTHING;
    float newThickness = (STROKE_WIDTH_MAX - STROKE_WIDTH_MIN) * normalizedVelocity + STROKE_WIDTH_MIN;
    self.lineWidth = self.lineWidth * lowPassFilterAlpha + newThickness * (1 - lowPassFilterAlpha);

    CGPoint mid1 = midPoint(previousPoint1, previousPoint2);
    CGPoint mid2 = midPoint(currentPoint, previousPoint1);
    CGMutablePathRef subpath = CGPathCreateMutable();
    CGPathMoveToPoint(subpath, NULL, mid1.x, mid1.y);
    CGPathAddQuadCurveToPoint(subpath, NULL, previousPoint1.x, previousPoint1.y, mid2.x, mid2.y);
    CGRect bounds = CGPathGetBoundingBox(subpath);

    Path *path = [[Path alloc] init];
    path.width = self.lineWidth;
    path.color = [UIColor redColor];
    path.bezierPath = [UIBezierPath bezierPathWithCGPath:subpath];
    [pathArray addObject:path];
    CGPathRelease(subpath);

    CGRect drawBox = bounds;
    drawBox.origin.x -= self.lineWidth * 2.0;
    drawBox.origin.y -= self.lineWidth * 2.0;
    drawBox.size.width += self.lineWidth * 4.0;
    drawBox.size.height += self.lineWidth * 4.0;

    [self setNeedsDisplayInRect:drawBox];

    if (pan.state == UIGestureRecognizerStateEnded | pan.state == UIGestureRecognizerStateCancelled)
    {
        self.lineWidth = STROKE_WIDTH_MIN;
    }
}

- (void)drawRect:(CGRect)rect {
    [self.backgroundColor set];
    UIRectFill(rect);

    CGContextRef context = UIGraphicsGetCurrentContext();

    if(layer == nil)
    {
        float scale = [UIScreen mainScreen].scale;
        CGRect bounds = CGRectMake(0, 0, rect.size.width * scale, rect.size.height * scale);
        layer = CGLayerCreateWithContext(context, bounds.size, NULL);
        layerContext = CGLayerGetContext(layer);
    }

    for(int i = 0; i < [pathArray count]; i++)
    {
        Path *path = [pathArray objectAtIndex:i];
        UIBezierPath *bezierPath = path.bezierPath;
        CGContextAddPath(layerContext, bezierPath.CGPath);
        CGContextSetLineWidth(layerContext, path.width);
        CGContextSetStrokeColorWithColor(layerContext, path.color.CGColor);
        CGContextSetLineCap(layerContext, kCGLineCapRound);
        CGContextStrokePath(layerContext);
    }

    CGContextDrawLayerAtPoint(context, CGPointZero, layer);

    self.empty = NO;
}

我使用以下代码绘制具有可变宽度的线条,根据用户的手势速度。 它可以正常工作,但是当我接近或超过以前绘制过的线时,其线宽会更改以匹配当前手势和线的速度。 请问如何确保绘制的线保持最初绘制时的粗细?
- (void)pan:(UIPanGestureRecognizer *)pan
{
    CGPoint velocity = [pan velocityInView:self];

    previousPoint2 = previousPoint1;
    previousPoint1 = currentPoint;
    currentPoint = [pan locationInView:self];

    float velocityMagnitude = sqrtf(velocity.x * velocity.x + velocity.y * velocity.y);

    float clampedVelocityMagnitude = clamp(VELOCITY_CLAMP_MIN, VELOCITY_CLAMP_MAX, velocityMagnitude);
    float normalizedVelocity = (clampedVelocityMagnitude - VELOCITY_CLAMP_MIN) / (VELOCITY_CLAMP_MAX - VELOCITY_CLAMP_MIN);

    float lowPassFilterAlpha = STROKE_WIDTH_SMOOTHING;
    float newThickness = (STROKE_WIDTH_MAX - STROKE_WIDTH_MIN) * normalizedVelocity + STROKE_WIDTH_MIN;
    self.lineWidth = self.lineWidth * lowPassFilterAlpha + newThickness * (1 - lowPassFilterAlpha);

    CGPoint mid1 = midPoint(previousPoint1, previousPoint2);
    CGPoint mid2 = midPoint(currentPoint, previousPoint1);
    CGMutablePathRef subpath = CGPathCreateMutable();
    CGPathMoveToPoint(subpath, NULL, mid1.x, mid1.y);
    CGPathAddQuadCurveToPoint(subpath, NULL, previousPoint1.x, previousPoint1.y, mid2.x, mid2.y);
    CGRect bounds = CGPathGetBoundingBox(subpath);

    CGPathAddPath(path, NULL, subpath);
    CGPathRelease(subpath);

    CGRect drawBox = bounds;
    drawBox.origin.x -= self.lineWidth * 2.0;
    drawBox.origin.y -= self.lineWidth * 2.0;
    drawBox.size.width += self.lineWidth * 4.0;
    drawBox.size.height += self.lineWidth * 4.0;

    if (pan.state == UIGestureRecognizerStateEnded | pan.state == UIGestureRecognizerStateCancelled)
    {
        self.lineWidth = STROKE_WIDTH_MIN;
    }
    else
    {
         [self setNeedsDisplayInRect:drawBox];
    }
}

- (void)drawRect:(CGRect)rect {
    [self.backgroundColor set];
    UIRectFill(rect);

    CGContextRef context = UIGraphicsGetCurrentContext();

    CGContextAddPath(context, path);
    CGContextSetLineCap(context, kCGLineCapRound);

    CGContextSetLineWidth(context, self.lineWidth);
    CGContextSetStrokeColorWithColor(context, self.lineColor.CGColor);

    CGContextStrokePath(context);

    self.empty = NO;
}
1个回答

0
每次线条宽度变化时,您需要开始一个新路径。您需要将所有这些路径存储到数组(或类似)中,并在调用drawRect:时绘制它们中的每一个。这将保持绘制时的线条宽度。 当前发生的情况是,您总是在绘制单个路径,因此您始终会重置整个路径的线条宽度。只是您使用视图刷新drawBox,所以您实际上只看到更新的那一部分。
随着添加更多行的性能将变差,因此您可能需要开始查看使用CGLayer来缓存先前绘制的路径,并在drawRect:中将图层呈现到上下文中,而不是迭代路径。

请查看我的问题,其中包含进一步的进展。这看起来正确吗?谢谢。 - Simon
1
在drawrect中,思路是绘制层和“当前”路径,而不是所有路径。该层应该包含预渲染的所有“保存”的路径。 - Wain
谢谢Wain,感激不尽。 - Simon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接