在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;
然后你可以在startPt
和endPt
之间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
或其他选择一个。 也许还可以切换颜色。 等等。
上一篇: Drawing a Speedometer with Core Graphics on OSX in NSView