/// <summary> /// Finds point coordinates of an entry. /// </summary> /// <returns>The point.</returns> /// <param name="value">The value.</param> /// <param name="center">The center.</param> /// <param name="angle">The entry angle.</param> /// <param name="radius">The radius.</param> private SKPoint GetPoint(float value, SKPoint center, float angle, float radius) { var amount = Math.Abs(value - AbsoluteMinimum) / ValueRange; var point = new SKPoint(0, radius * amount); var rotation = SKMatrix.CreateRotation(angle); return(center + rotation.MapPoint(point)); }
private protected SKMatrix CreateTransformMatrix(SKRect bounds) { var transform = SKMatrix.Identity; // Translate to origin if (CenterPoint != Vector2.Zero) { transform = SKMatrix.CreateTranslation(-CenterPoint.X, -CenterPoint.Y); } // Scaling if (Scale != Vector2.One) { transform = transform.PostConcat(SKMatrix.CreateScale(Scale.X, Scale.Y)); } // Rotating if (RotationAngle != 0) { transform = transform.PostConcat(SKMatrix.CreateRotation(RotationAngle)); } // Translating if (Offset != Vector2.Zero) { transform = transform.PostConcat(SKMatrix.CreateTranslation(Offset.X, Offset.Y)); } // Translate back if (CenterPoint != Vector2.Zero) { transform = transform.PostConcat(SKMatrix.CreateTranslation(CenterPoint.X, CenterPoint.Y)); } if (!TransformMatrix.IsIdentity) { transform = transform.PostConcat(TransformMatrix.ToSKMatrix()); } var relativeTransform = RelativeTransformMatrix.IsIdentity ? SKMatrix.Identity : RelativeTransformMatrix.ToSKMatrix(); if (!relativeTransform.IsIdentity) { relativeTransform.TransX *= bounds.Width; relativeTransform.TransY *= bounds.Height; transform = transform.PostConcat(relativeTransform); } return(transform); }
/// <summary> /// 单指操纵 /// </summary> /// <param name="prevPoint"></param> /// <param name="newPoint"></param> /// <param name="pivotPoint"></param> /// <returns></returns> public SKMatrix OneFingerManipulate(SKPoint prevPoint, SKPoint newPoint, SKPoint pivotPoint) { if (Mode == TouchManipulationMode.None) { return(SKMatrix.CreateIdentity()); } SKMatrix touchMatrix = SKMatrix.CreateIdentity(); SKPoint delta = newPoint - prevPoint; if (Mode == TouchManipulationMode.ScaleDualRotate) // One-finger rotation { SKPoint oldVector = prevPoint - pivotPoint; SKPoint newVector = newPoint - pivotPoint; float scale = Magnitude(newVector) / Magnitude(oldVector); // Avoid rotation if fingers are too close to center if (Magnitude(newVector) > 30 && Magnitude(oldVector) > 30) { float prevAngle = (float)Math.Atan2(oldVector.Y, oldVector.X); float newAngle = (float)Math.Atan2(newVector.Y, newVector.X); // Calculate rotation matrix float angle = newAngle - prevAngle; touchMatrix = SKMatrix.CreateRotation(angle, pivotPoint.X, pivotPoint.Y); // Effectively rotate the old vector float magnitudeRatio = Magnitude(oldVector) / Magnitude(newVector); oldVector.X = magnitudeRatio * newVector.X; oldVector.Y = magnitudeRatio * newVector.Y; // Recalculate delta delta = newVector - oldVector; } if (!float.IsNaN(scale) && !float.IsInfinity(scale)) { var tm = SKMatrix.CreateScale(scale, scale, pivotPoint.X, pivotPoint.Y); touchMatrix.PostConcat(tm); } } // Multiply the rotation matrix by a translation matrix touchMatrix.PostConcat(SKMatrix.CreateTranslation(delta.X, delta.Y)); return(touchMatrix); }
/// <summary> /// 2本指での操作 /// </summary> /// <param name="prevPoint"></param> /// <param name="newPoint"></param> /// <param name="pivotPoint"></param> /// <returns></returns> public SKMatrix TwoFingerManipulate(SKPoint prevPoint, SKPoint newPoint, SKPoint pivotPoint) { SKMatrix touchMatrix = SKMatrix.CreateIdentity(); SKPoint oldVector = prevPoint - pivotPoint; SKPoint newVector = newPoint - pivotPoint; if (Mode == TouchManipulationMode.ScaleRotate || Mode == TouchManipulationMode.ScaleDualRotate) { // Find angles from pivot point to touch points float oldAngle = (float)Math.Atan2(oldVector.Y, oldVector.X); float newAngle = (float)Math.Atan2(newVector.Y, newVector.X); // Calculate rotation matrix float angle = newAngle - oldAngle; touchMatrix = SKMatrix.CreateRotation(angle, pivotPoint.X, pivotPoint.Y); // Effectively rotate the old vector float magnitudeRatio = Magnitude(oldVector) / Magnitude(newVector); oldVector.X = magnitudeRatio * newVector.X; oldVector.Y = magnitudeRatio * newVector.Y; } float scaleX = 1; float scaleY = 1; if (Mode == TouchManipulationMode.AnisotropicScale) { scaleX = newVector.X / oldVector.X; scaleY = newVector.Y / oldVector.Y; } else if (Mode == TouchManipulationMode.IsotropicScale || Mode == TouchManipulationMode.ScaleRotate || Mode == TouchManipulationMode.ScaleDualRotate) { scaleX = scaleY = Magnitude(newVector) / Magnitude(oldVector); } if (!float.IsNaN(scaleX) && !float.IsInfinity(scaleX) && !float.IsNaN(scaleY) && !float.IsInfinity(scaleY)) { //SKMatrix.PostConcat(ref touchMatrix, // SKMatrix.CreateScale(scaleX, scaleY, pivotPoint.X, pivotPoint.Y)); touchMatrix = touchMatrix.PostConcat(SKMatrix.CreateScale(scaleX, scaleY, pivotPoint.X, pivotPoint.Y)); } return(touchMatrix); }
private void DrawGrid(SKCanvas canvas, double dx, double dy, double zx, double zy) { float gw = (float)_view.Width; float gh = (float)_view.Height; float cw = 15.0f; float ch = 15.0f; canvas.Save(); canvas.Translate((float)dx, (float)dy); canvas.Scale((float)zx, (float)zy); var hlattice = SKMatrix.CreateScale(cw, ch); hlattice = hlattice.PreConcat(SKMatrix.CreateRotation((float)(Math.PI * 0.0 / 180.0))); var vlattice = SKMatrix.CreateScale(cw, ch); vlattice = vlattice.PreConcat(SKMatrix.CreateRotation((float)(Math.PI * 90.0 / 180.0))); using (var heffect = SKPathEffect.Create2DLine((float)(1.0 / zx), hlattice)) using (var veffect = SKPathEffect.Create2DLine((float)(1.0 / zx), vlattice)) using (var hpaint = new SKPaint()) using (var vpaint = new SKPaint()) { hpaint.IsAntialias = false; hpaint.Color = SKColors.LightGray; hpaint.PathEffect = heffect; canvas.DrawRect(SKRect.Create(0.0f, ch, gw, gh - ch), hpaint); vpaint.IsAntialias = false; vpaint.Color = SKColors.LightGray; vpaint.PathEffect = veffect; canvas.DrawRect(SKRect.Create(cw, 0.0f, gw - cw, gh), vpaint); } using (SKPaint strokePaint = new SKPaint()) { strokePaint.IsAntialias = false; strokePaint.StrokeWidth = (float)(1.0 / zx); strokePaint.Color = SKColors.Red; strokePaint.Style = SKPaintStyle.Stroke; canvas.DrawRect(SKRect.Create(0.0f, 0.0f, gw, gh), strokePaint); } canvas.Restore(); }
protected override RBrush CreateLinearGradientBrush(RRect rect, RColor color1, RColor color2, double angle) { var rotation = (float)(angle / 180.0f * Math.PI); var angleX = (float)(rect.Width / 2); var angleY = (float)(rect.Height / 2); return(new BrushAdapter(new SKPaint { Style = SKPaintStyle.Fill, Shader = SKShader.CreateLinearGradient( new SKPoint((float)rect.Left, (float)rect.Top), new SKPoint((float)rect.Right, (float)rect.Bottom), new[] { Utils.Convert(color1), Utils.Convert(color2) }, new[] { 0.0f, 1.0f }, SKShaderTileMode.Repeat, SKMatrix.CreateRotation(rotation, angleX, angleY)) }, true)); // new LinearGradientBrush(Utils.Convert(rect), Utils.Convert(color1), Utils.Convert(color2), // (float) angle), true); }
protected override void OnDrawSample(SKCanvas canvas, int width, int height) { // load the image from the embedded resource stream using (var stream = new SKManagedStream(SampleMedia.Images.ColorWheel)) using (var source = SKBitmap.Decode(stream)) { var matrix = SKMatrix.CreateRotation(30.0f); // create the shader and paint using (var shader = SKShader.CreateBitmap(source, SKShaderTileMode.Repeat, SKShaderTileMode.Repeat, matrix)) using (var paint = new SKPaint()) { paint.IsAntialias = true; paint.Shader = shader; // tile the bitmap canvas.Clear(SKColors.White); canvas.DrawPaint(paint); } } }
public static SKMatrix CaculateOneFingerDraggedMatrix(SKPoint prevPoint, SKPoint curPoint, SKPoint pivotPoint, TouchManipulationMode mode) { if (mode == TouchManipulationMode.None) { return(SKMatrix.CreateIdentity()); } SKMatrix touchMatrix = SKMatrix.CreateIdentity(); SKPoint delta = curPoint - prevPoint; if (mode == TouchManipulationMode.ScaleDualRotate) // One-finger rotation { SKPoint oldVector = prevPoint - pivotPoint; SKPoint newVector = curPoint - pivotPoint; // Avoid rotation if fingers are too close to center if (Magnitude(newVector) > 25 && Magnitude(oldVector) > 25) { float prevAngle = (float)Math.Atan2(oldVector.Y, oldVector.X); float newAngle = (float)Math.Atan2(newVector.Y, newVector.X); // Calculate rotation matrix float angle = newAngle - prevAngle; touchMatrix = SKMatrix.CreateRotation(angle, pivotPoint.X, pivotPoint.Y); // Effectively rotate the old vector float magnitudeRatio = Magnitude(oldVector) / Magnitude(newVector); oldVector.X = magnitudeRatio * newVector.X; oldVector.Y = magnitudeRatio * newVector.Y; // Recalculate delta delta = newVector - oldVector; } } // Multiply the rotation matrix by a translation matrix touchMatrix = touchMatrix.PostConcat(SKMatrix.CreateTranslation(delta.X, delta.Y)); return(touchMatrix); }
public static void Draw(SKCanvas canvas, IReadOnlyViewport viewport, VectorStyle vectorStyle, IFeature feature, Polygon polygon, float opacity, ISymbolCache?symbolCache = null) { float lineWidth = 1; var lineColor = Color.Black; // default var fillColor = Color.Gray; // default var strokeCap = PenStrokeCap.Butt; // default var strokeJoin = StrokeJoin.Miter; // default var strokeMiterLimit = 4f; // default var strokeStyle = PenStyle.Solid; // default float[]? dashArray = null; // default float dashOffset = 0; // default if (vectorStyle.Outline != null) { lineWidth = (float)vectorStyle.Outline.Width; lineColor = vectorStyle.Outline.Color; strokeCap = vectorStyle.Outline.PenStrokeCap; strokeJoin = vectorStyle.Outline.StrokeJoin; strokeMiterLimit = vectorStyle.Outline.StrokeMiterLimit; strokeStyle = vectorStyle.Outline.PenStyle; dashArray = vectorStyle.Outline.DashArray; dashOffset = vectorStyle.Outline.DashOffset; } if (vectorStyle.Fill != null) { fillColor = vectorStyle.Fill?.Color; } using (var path = polygon.ToSkiaPath(viewport, canvas.LocalClipBounds, lineWidth)) using (var paintFill = new SKPaint { IsAntialias = true }) { // Is there a FillStyle? if (vectorStyle.Fill?.FillStyle == FillStyle.Solid) { paintFill.StrokeWidth = 0; paintFill.Style = SKPaintStyle.Fill; paintFill.PathEffect = null; paintFill.Shader = null; paintFill.Color = fillColor.ToSkia(opacity); canvas.DrawPath(path, paintFill); } else { paintFill.StrokeWidth = 1; paintFill.Style = SKPaintStyle.Stroke; paintFill.Shader = null; paintFill.Color = fillColor.ToSkia(opacity); var scale = 10.0f; using var fillPath = new SKPath(); var matrix = SKMatrix.CreateScale(scale, scale); switch (vectorStyle.Fill?.FillStyle) { case FillStyle.Cross: fillPath.MoveTo(scale * 0.8f, scale * 0.8f); fillPath.LineTo(0, 0); fillPath.MoveTo(0, scale * 0.8f); fillPath.LineTo(scale * 0.8f, 0); paintFill.PathEffect = SKPathEffect.Create2DPath(matrix, fillPath); break; case FillStyle.DiagonalCross: fillPath.MoveTo(scale, scale); fillPath.LineTo(0, 0); fillPath.MoveTo(0, scale); fillPath.LineTo(scale, 0); paintFill.PathEffect = SKPathEffect.Create2DPath(matrix, fillPath); break; case FillStyle.BackwardDiagonal: fillPath.MoveTo(0, scale); fillPath.LineTo(scale, 0); paintFill.PathEffect = SKPathEffect.Create2DPath(matrix, fillPath); break; case FillStyle.ForwardDiagonal: fillPath.MoveTo(scale, scale); fillPath.LineTo(0, 0); paintFill.PathEffect = SKPathEffect.Create2DPath(matrix, fillPath); break; case FillStyle.Dotted: paintFill.Style = SKPaintStyle.StrokeAndFill; fillPath.AddCircle(scale * 0.5f, scale * 0.5f, scale * 0.35f); paintFill.PathEffect = SKPathEffect.Create2DPath(matrix, fillPath); break; case FillStyle.Horizontal: fillPath.MoveTo(0, scale * 0.5f); fillPath.LineTo(scale, scale * 0.5f); paintFill.PathEffect = SKPathEffect.Create2DPath(matrix, fillPath); break; case FillStyle.Vertical: fillPath.MoveTo(scale * 0.5f, 0); fillPath.LineTo(scale * 0.5f, scale); paintFill.PathEffect = SKPathEffect.Create2DPath(matrix, fillPath); break; case FillStyle.Bitmap: paintFill.Style = SKPaintStyle.Fill; var image = GetImage(symbolCache, vectorStyle.Fill.BitmapId); if (image != null) { paintFill.Shader = image.ToShader(SKShaderTileMode.Repeat, SKShaderTileMode.Repeat); } break; case FillStyle.BitmapRotated: paintFill.Style = SKPaintStyle.Fill; image = GetImage(symbolCache, vectorStyle.Fill.BitmapId); if (image != null) { paintFill.Shader = image.ToShader(SKShaderTileMode.Repeat, SKShaderTileMode.Repeat, SKMatrix.CreateRotation((float)(viewport.Rotation * System.Math.PI / 180.0f), image.Width >> 1, image.Height >> 1)); } break; default: paintFill.PathEffect = null; break; } // Do this, because if not, path isn't filled complete using (new SKAutoCanvasRestore(canvas)) { canvas.ClipPath(path); var bounds = path.Bounds; // Make sure, that the brush starts with the correct position var inflate = ((int)path.Bounds.Width * 0.3f / scale) * scale; bounds.Inflate(inflate, inflate); // Draw rect with bigger size, which is clipped by path canvas.DrawRect(bounds, paintFill); } } if (vectorStyle.Outline != null) { using (var paintStroke = new SKPaint { IsAntialias = true }) { paintStroke.Style = SKPaintStyle.Stroke; paintStroke.StrokeWidth = lineWidth; paintStroke.Color = lineColor.ToSkia(opacity); paintStroke.StrokeCap = strokeCap.ToSkia(); paintStroke.StrokeJoin = strokeJoin.ToSkia(); paintStroke.StrokeMiter = strokeMiterLimit; if (strokeStyle != PenStyle.Solid) { paintStroke.PathEffect = strokeStyle.ToSkia(lineWidth, dashArray, dashOffset); } else { paintStroke.PathEffect = null; } canvas.DrawPath(path, paintStroke); } } } }
public static SKMatrix Rotate(this SKMatrix m, float angle) => m.Concat(SKMatrix.CreateRotation(angle));
public override void DrawContent(SKCanvas canvas, int width, int height) { var total = Entries?.Count() ?? 0; if (total > 0) { var captionHeight = Entries.Max(x => { var result = 0.0f; var hasLabel = !string.IsNullOrEmpty(x.Label); var hasValueLabel = !string.IsNullOrEmpty(x.ValueLabel); if (hasLabel || hasValueLabel) { var hasOffset = hasLabel && hasValueLabel; var captionMargin = LabelTextSize * 0.60f; var space = hasOffset ? captionMargin : 0; if (hasLabel) { result += LabelTextSize; } if (hasValueLabel) { result += LabelTextSize; } } return(result); }); var center = new SKPoint(width / 2, height / 2); var radius = ((Math.Min(width, height) - (2 * Margin)) / 2) - captionHeight; var rangeAngle = (float)((Math.PI * 2) / total); var startAngle = (float)Math.PI; DrawBorder(canvas, center, radius); using (var clip = new SKPath()) { clip.AddCircle(center.X, center.Y, radius); for (int i = 0; i < total; i++) { var angle = startAngle + (rangeAngle * i); var entry = Entries.ElementAt(i); int nextIndex = (i + 1) % total; var nextAngle = startAngle + (rangeAngle * nextIndex); var nextEntry = Entries.ElementAt(nextIndex); while (!nextEntry.Value.HasValue) { nextIndex = (nextIndex + 1) % total; nextAngle = startAngle + (rangeAngle * nextIndex); nextEntry = Entries.ElementAt(nextIndex); } canvas.Save(); if (entry.Value.HasValue) { var point = GetPoint(entry.Value.Value * AnimationProgress, center, angle, radius); var nextPoint = GetPoint(nextEntry.Value.Value * AnimationProgress, center, nextAngle, radius); canvas.ClipPath(clip); // Border center bars using (var paint = new SKPaint() { Style = SKPaintStyle.Stroke, StrokeWidth = BorderLineSize, Color = BorderLineColor, IsAntialias = true, }) { var borderPoint = GetPoint(MaxValue, center, angle, radius); canvas.DrawLine(point.X, point.Y, borderPoint.X, borderPoint.Y, paint); } // Values points and lines using (var paint = new SKPaint() { Style = SKPaintStyle.Stroke, StrokeWidth = BorderLineSize, Color = entry.Color.WithAlpha((byte)(entry.Color.Alpha * 0.75f * AnimationProgress)), PathEffect = SKPathEffect.CreateDash(new[] { BorderLineSize, BorderLineSize * 2 }, 0), IsAntialias = true, }) { var amount = Math.Abs(entry.Value.Value - AbsoluteMinimum) / ValueRange; canvas.DrawCircle(center.X, center.Y, radius * amount, paint); } canvas.DrawGradientLine(center, entry.Color.WithAlpha(0), point, entry.Color.WithAlpha((byte)(entry.Color.Alpha * 0.75f)), LineSize); canvas.DrawGradientLine(point, entry.Color, nextPoint, nextEntry.Color, LineSize); canvas.DrawPoint(point, entry.Color, PointSize, PointMode); } canvas.Restore(); // Labels var labelPoint = new SKPoint(0, radius + LabelTextSize + (PointSize / 2)); var rotation = SKMatrix.CreateRotation(angle); labelPoint = center + rotation.MapPoint(labelPoint); var alignment = SKTextAlign.Left; if ((Math.Abs(angle - (startAngle + Math.PI)) < Epsilon) || (Math.Abs(angle - Math.PI) < Epsilon)) { alignment = SKTextAlign.Center; } else if (angle > (float)(startAngle + Math.PI)) { alignment = SKTextAlign.Right; } canvas.DrawCaptionLabels(entry.Label, entry.TextColor, entry.ValueLabel, entry.Color.WithAlpha((byte)(255 * AnimationProgress)), LabelTextSize, labelPoint, alignment, base.Typeface, out var _); } } } }