/// <summary>Draw a pie meter</summary> private void PaintPie(SKImageInfo info, SKCanvas canvas, bool handles = false) { float arcWidth = (info.Width / 15.0F) * 1.0F; // always draw a background ring using (SKPath path = new SKPath()) { path.AddArc(this.OuterRect, 0, 360); canvas.DrawPath(path, new SKPaint() { Color = _disabled, StrokeWidth = this.ArcLineWidth, Style = SKPaintStyle.Stroke, IsAntialias = true }); } // calc the sum float total = this.Value1 + this.Value2; // bail if both are 0 if (total <= 0.0) { return; } // calc the sweep angle float sweep = (this.Value1 / total) * 360.0F; // calc the angles, 0 is to the right, start from overhead float rewardSweep = (sweep > 360.0) ? 360.0F : sweep; float bonusStartAngle = QuickCalc.Revolution(270.0F + rewardSweep); // draw arc 1 using (SKPath path = new SKPath()) { using (SKPaint arcPaint = new SKPaint { Style = SKPaintStyle.Stroke, Color = this.ArcColor1.ToSKColor(), StrokeWidth = this.ArcLineWidth, IsAntialias = true }) { path.AddArc(this.OuterRect, 270, rewardSweep); canvas.DrawPath(path, arcPaint); } } // draw arc 2 using (SKPath path = new SKPath()) { using (SKPaint arcPaint = new SKPaint { Style = SKPaintStyle.Stroke, Color = this.ArcColor2.ToSKColor(), StrokeWidth = this.ArcLineWidth, IsAntialias = true }) { path.AddArc(this.OuterRect, bonusStartAngle, 360 - rewardSweep); canvas.DrawPath(path, arcPaint); } } if (!handles) { return; } // draw handles using (SKPaint handlePaint = new SKPaint() { Color = this.ArcColor1.ToSKColor(), StrokeCap = SKStrokeCap.Round, StrokeWidth = this.ArcLineWidth * 2, IsAntialias = true }) { canvas.DrawPoint(this.VerticalCenter, this.OuterRect.Top, handlePaint); // where's the other handle? float rad = QuickCalc.Deg2Rad(QuickCalc.Revolution(360 - rewardSweep + 90)); Tuple <float, float> pt = QuickCalc.Transform(rad, this.OuterRect.Width / 2.0F); handlePaint.Color = this.ArcColor2.ToSKColor(); canvas.DrawPoint(pt.Item1 + info.Rect.MidX, info.Rect.MidY - pt.Item2, handlePaint); } }
/// <summary>Draw a progress meter</summary> /// <remarks> /// Value 1 is the part and Value 2 is the total possible /// Value 1 can exceed value 2 for mutiple revolutions /// </remarks> private void PaintProgress(SKImageInfo info, SKCanvas canvas) { // set up the gradient colors SKColor[] colors = new SKColor[2] { this.ArcColor1.ToSKColor(), this.ArcColor2.ToSKColor() }; // sweep is in DEG -> normalize the sweep angle between 0 and 360 //float sweep = QuickCalc.Revolution( ( this.Value1 / this.Value2 ) * 360.0F ); //sweep = ( sweep > 360.0 ) ? 360.0F : sweep; float sweep = (this.Value1 % this.Value2 / this.Value2) * 360.0F; // we have to roate the drawing canvas 90 degrees CCW canvas.RotateDegrees(-90, info.Width / 2, info.Height / 2); // no value if (this.Value1 <= 0.0) { // draw background ring using (SKPath path = new SKPath()) { using (SKPaint bkgPaint = new SKPaint() { Color = _disabled, StrokeWidth = this.ArcLineWidth, Style = SKPaintStyle.Stroke, IsAntialias = true }) { path.AddArc(this.OuterRect, 0, 360.0F); canvas.DrawPath(path, bkgPaint); } } } // less than 1 revolution else if (this.Value1 < this.Value2) { // draw background ring using (SKPath path = new SKPath()) { using (SKPaint bkgPaint = new SKPaint() { Color = _disabled, StrokeWidth = this.ArcLineWidth, Style = SKPaintStyle.Stroke, IsAntialias = true }) { path.AddArc(this.OuterRect, 0, 360.0F); canvas.DrawPath(path, bkgPaint); } } // draw the partial arc using (SKPath path = new SKPath()) { using (SKPaint arcPaint = new SKPaint { Style = SKPaintStyle.Stroke, Color = this.ArcColor1.ToSKColor() }) { arcPaint.StrokeWidth = this.ArcLineWidth; arcPaint.StrokeCap = SKStrokeCap.Butt; arcPaint.IsAntialias = true; arcPaint.Shader = SKShader.CreateSweepGradient(this.Origin, colors, new Single[] { 0, 1 }, SKShaderTileMode.Clamp, 0, sweep); // create an arc to sweep along path.AddArc(this.OuterRect, 0, sweep); canvas.DrawPath(path, arcPaint); } } } else // 1 or more revolution { // draw background ring using (SKPath path = new SKPath()) { using (SKPaint bkgPaint = new SKPaint() { Color = this.ArcColor1.ToSKColor(), StrokeWidth = this.ArcLineWidth }) { bkgPaint.Style = SKPaintStyle.Stroke; bkgPaint.IsAntialias = true; path.AddArc(this.OuterRect, 0, 360.0F); canvas.DrawPath(path, bkgPaint); } } // rotate the canvas by the sweep angle so we always start at 0 canvas.RotateDegrees(sweep - 180, info.Width / 2, info.Height / 2); // draw the partial gradiant arc using (SKPath path = new SKPath()) { using (SKPaint arcPaint = new SKPaint { Style = SKPaintStyle.Stroke }) { arcPaint.Color = this.ArcColor2.ToSKColor(); arcPaint.StrokeWidth = this.ArcLineWidth; arcPaint.StrokeCap = SKStrokeCap.Butt; arcPaint.IsAntialias = true; // sweep gradient uses start angle to end angle arcPaint.Shader = SKShader.CreateSweepGradient(this.Origin, colors, new Single[] { 0, 1 }, SKShaderTileMode.Clamp, 0, 180); // create an arc to sweep along - uses start angle and then how many degrees to rotate from start path.AddArc(this.OuterRect, 0, 180); canvas.DrawPath(path, arcPaint); } } canvas.RotateDegrees(-(sweep - 180), info.Width / 2, info.Height / 2); } // calc pts for the trailing handle Tuple <float, float> pt1 = QuickCalc.Transform(QuickCalc.Deg2Rad(sweep + (this.ArcLineWidth * 0.075F)), this.OuterRect.Width / 2.0F); Tuple <float, float> pt2 = QuickCalc.Transform(QuickCalc.Deg2Rad(sweep), this.OuterRect.Width / 2.0F); // draw the trailing point with shadow using (SKPaint handlePaint = new SKPaint() { Color = this.BackgroundColor.ToSKColor() }) { handlePaint.StrokeCap = SKStrokeCap.Round; handlePaint.StrokeWidth = this.ArcLineWidth * 2; handlePaint.IsAntialias = true; // shadow canvas.DrawPoint(pt1.Item1 + info.Rect.MidX, info.Rect.MidY + pt1.Item2, handlePaint); // change color handlePaint.Color = this.ArcColor2.ToSKColor(); // handle canvas.DrawPoint(pt2.Item1 + info.Rect.MidX, info.Rect.MidY + pt2.Item2, handlePaint); } // rotate it all back canvas.RotateDegrees(90, info.Width / 2, info.Height / 2); }