需要一个可以为 .NET Maui 实现的扫描梯度算法

问题描述 投票:0回答:1

我正在为 .NET Maui 开发一个需要扫描渐变的绘制自定义控件。 Maui 提供线性和径向渐变,但不提供扫描渐变。我知道 SkiaSharp 和 Android 提供扫描渐变,但我不想依赖第三方库,并且我需要一个跨平台的实现。如果我有渲染扫描渐变的基本逻辑,我可以自己实现它,但我无法在任何地方找到这样的逻辑。有人可以为我提供解决方案吗?

我在网上搜索过,没有发现任何适用的内容。我查看了 Skia 代码,但发现它几乎无法破译。我本来希望找到一种可以使用的算法,但到目前为止还没有成功。

graphics maui gradient
1个回答
0
投票

这并不是真正的解决方案(.net maui 的实际库将于今年晚些时候发布),但您可以在自定义控件中使用一些代码。下面的Xaml只是为了演示一个用例,这是扫一个自动速度表的尾部(0.933->1.0,#CB6235->#00CB6235),而整个仪表被涂成纯色(0->0.933, #CB6235):

 <draw:SkiaShape.StrokeGradient>

                <draw:SkiaGradient Type="Sweep">
                    <draw:SkiaGradient.Colors>
                        <Color>#CB6235</Color>
                        <Color>#CB6235</Color>
                        <Color>#00CB6235</Color>
                    </draw:SkiaGradient.Colors>
                    <draw:SkiaGradient.ColorPositions>
                        <x:Double>0.0</x:Double>
                        <x:Double>0.933</x:Double>
                        <x:Double>1.0</x:Double>
                    </draw:SkiaGradient.ColorPositions>
                </draw:SkiaGradient>

            </draw:SkiaShape.StrokeGradient>

绘图背后的代码正在创建一个着色器,您可以将其添加到 SKPaint 中并用它绘制形状。平铺默认为

SKShaderTileMode.Clamp

public SKShader CreateGradientAsShader(SKRect destination, SkiaGradient gradient)
  {
      if (gradient != null && gradient.Type != GradientType.None)
      {
          var colors = new List<SKColor>();
          foreach (var color in gradient.Colors.ToList())
          {
              var usingColor = color;
              if (gradient.Light < 1.0)
              {
                  usingColor = usingColor.MakeDarker(100 - gradient.Light * 100);
              }
              else if (gradient.Light > 1.0)
              {
                  usingColor = usingColor.MakeLighter(gradient.Light * 100 - 100);
              }

              var newAlpha = usingColor.Alpha * gradient.Opacity;
              usingColor = usingColor.WithAlpha(newAlpha);
              colors.Add(usingColor.ToSKColor());
          }

          float[] colorPositions = null;
          if (gradient.ColorPositions?.Count == colors.Count)
          {
              colorPositions = gradient.ColorPositions.Select(x => (float)x).ToArray();
          }

          switch (gradient.Type)
          {
          case GradientType.Sweep:
              return SKShader.CreateSweepGradient(
               new SKPoint(destination.Left + destination.Width / 2.0f,
                  destination.Top + destination.Height / 2.0f),
              colors.ToArray(),
              colorPositions,
              gradient.TileMode, (float)Value1, (float)(Value1 + Value2));

          case GradientType.Circular:
          return SKShader.CreateRadialGradient(
              new SKPoint(destination.Left + destination.Width / 2.0f,
                  destination.Top + destination.Height / 2.0f),
              Math.Max(destination.Width, destination.Height) / 2.0f,
              colors.ToArray(),
              colorPositions,
              gradient.TileMode);

          case GradientType.Linear:
          default:
          return SKShader.CreateLinearGradient(
              new SKPoint(destination.Left + destination.Width * gradient.StartXRatio,
                  destination.Top + destination.Height * gradient.StartYRatio),
              new SKPoint(destination.Left + destination.Width * gradient.EndXRatio,
                  destination.Top + destination.Height * gradient.EndYRatio),
              colors.ToArray(),
              colorPositions,
              gradient.TileMode);
          break;
          }

      }

      return null;
  }
© www.soinside.com 2019 - 2024. All rights reserved.