在NSView的OSX中用Core Graphics绘制车速表

我试图在OSX上使用Core Graphics绘制Speed Gauge的元素。 我几乎可以得到它,但需要一些关于仪表内部中心刻度的帮助。 这是我想要做的事情的形象:

在这里输入图像描述

这是迄今为止我所得到的图像:

在这里输入图像描述

我知道如何绘制圆环以及如何绘制基于测量仪中心的线段,如下所示:

- (void)drawOuterGaugeRingsInRect:(CGContextRef)contextRef rect:(NSRect)rect {


    CGContextSetLineWidth(contextRef,self.gaugeRingWidth);

    CGContextSetStrokeColorWithColor(contextRef, [MyColors SpeedGaugeOuterRingGray].CGColor);
    CGFloat startRadians = 0;
    CGFloat endRadians =  M_PI*2;
    CGFloat radius = self.bounds.size.width/2 - 5;

    CGContextAddArc(contextRef, CGRectGetMidX(rect),CGRectGetMidY(rect),radius,startRadians,endRadians,YES);
    //Render the outer gauge
    CGContextStrokePath(contextRef);

    //Draw the inner gauge ring.
    radius -= self.gaugeRingWidth;
    CGContextSetStrokeColorWithColor(contextRef, [MyColors SpeedGaugeInnerRingGray].CGColor);
    CGContextAddArc(contextRef, CGRectGetMidX(rect),CGRectGetMidY(rect),radius,startRadians,endRadians,YES);

    //Render the inner gauge
    CGContextStrokePath(contextRef);

    radius -= self.gaugeRingWidth;

    //Draw and fill the gauge background

    CGContextSetFillColorWithColor(contextRef, [MyColors SpeedGaugeCenterFillBlack ].CGColor);
    CGContextSetStrokeColorWithColor(contextRef, [MyColors SpeedGaugeCenterFillBlack].CGColor);
    CGContextAddArc(contextRef, CGRectGetMidX(rect),CGRectGetMidY(rect),radius,startRadians,endRadians,YES);

    //Render and fill the gauge background
    CGContextDrawPath(contextRef, kCGPathFillStroke);


    /*BLUE CIRCULAR DIAL */
    //Prepare to draw the blue circular dial.
    radius -= self.gaugeRingWidth/2;

    //Adjust gauge ring width
    CGContextSetLineWidth(contextRef,self.gaugeRingWidth/2);

    CGContextSetStrokeColorWithColor(contextRef, [MyColors SpeedGaugeBlue].CGColor);

    CGFloat startingRadians = [MyMathHelper degressToRadians:135];
    CGFloat endingRadians = [MyMathHelper degressToRadians:45];


    CGContextAddArc(contextRef, CGRectGetMidX(rect),CGRectGetMidY(rect),radius,startingRadians,endingRadians,NO);

    //Render the blue gauge line
    CGContextStrokePath(contextRef);
}

上面的代码在我的NSView中的drawRect:方法中调用

关键部分是这里的代码:

- (void)drawInnerDividerLines:(CGContextRef)context rect:(NSRect)rect {

    CGFloat centerX = CGRectGetMidX(rect);
    CGFloat centerY = CGRectGetMidY(rect);


    CGContextSetLineWidth       (context, 3.0);
    CGContextSetRGBStrokeColor  (context, 37.0/255.0, 204.0/255.0, 227.0/255.0, 0.5);



    CGFloat destinationX = centerX + (centerY * (cos((135)*(M_PI/180))));
    CGFloat destinationY = centerY + (centerX * (sin((135)*(M_PI/180))));

    NSPoint destinationPoint = NSMakePoint(destinationX, destinationY);


    CGContextMoveToPoint(context, centerX, centerY);

    CGContextAddLineToPoint(context, destinationPoint.x, destinationPoint.y);

    CGContextStrokePath(context);

}

我理解这里发生了什么,但是我试图解决的问题是绘制细线,离开延伸到视图中心点的内部蓝线,但不要一直画到中心。 我有点不确定如何修改数学和绘图逻辑来实现这一点。 这里是单位圆我基于核心图形绘制的角度。

在这里输入图像描述

我试图解决的主要问题是:

  • 如何定义淡蓝色内线的适当起点作为每个量表刻度的起始点。 现在,我正在绘制从中心到边缘的整条线。

  • 如何控制滴答指示器的长度,因为它指向蓝色线上原点的中心。

  • 任何提示或建议,将指向我在正确的方向来解决这个问题将不胜感激。


    我建议使用矢量。 通过计算,您可以找到一条线,指定给定角度的圆上的任意点:

    dirX = cos(angle);
    dirY = sin(angle);
    startPt.x = center.x + innerRadius * dirX;
    startPt.y = center.y + innerRadius * dirY;
    endPt.x = center.x + outerRadius * dirX;
    endPt.y = center.y + outerRadius * dirY;
    

    然后你可以在startPtendPt之间startPt一条线。


    任何提示或建议,将指向我在正确的方向来解决这个问题将不胜感激。

    给定圆的圆周上某个角度的中心,可以形成一个直角三角形,半径是斜边,其他两边平行于x和y轴(忽略一段时间退化)该点在0,90,180或270度的情况下)。 考虑到sin&cos公式(记住学校的SOHCAHTOA)以及一些基本的数学运算,您可以计算该点的坐标,并使用该坐标绘制从中心到点的半径。

    “刻度”标记的终点只是位于不同半径的圆上,所以相同的数学计算会给出终点,您可以绘制刻度。 您只需要确定这些圆的半径,即沿原始半径的距离应该是刻度的终点。

    HTH


    避免三角函数的另一种方法是旋转变换矩阵,并绘制垂直或水平线。

    // A vertical "line" of width "width" along the y axis at x==0.
    NSRect tick = NSMakeRect(-width / 2.0, innerRadius, width, outerRadius - innerRadius);
    NSAffineTransform* xform = [NSAffineTransform transform];
    // Move the x and y axes to the center of your speedometer so rotation happens around it
    [xform translateXBy:center.x yBy:center.y];
    // Rotate the coordinate system so that straight up is actually at your speedometer's 0
    [xform rotateByDegrees:135];
    [xform concat];
    // Create a new transform to rotate back around for each tick.
    xform = [NSAffineTransform transform];
    [xform rotateByDegrees:-270.0 / numTicks];
    for (int i = 0; i < numTicks; i++)
    {
        NSRectFill(tick);
       [xform concat];
    }
    

    您可能想要将其包装在[NSGraphicsContext saveGraphicsState][NSGraphicsContext restoreGraphicsState]以便在完成后恢复转换矩阵。

    如果你想要两种不同类型的刻度线(主要和次要),然后有两个不同的矩形,并根据i % 10 == 0或其他选择一个。 也许还可以切换颜色。 等等。

    链接地址: http://www.djcxy.com/p/61693.html

    上一篇: Drawing a Speedometer with Core Graphics on OSX in NSView

    下一篇: Omit an edge from a shape in WPF (C# code)?