Функции с универсальными типами параметра

Y-answer: Нет, вы можете рисовать текст только на CompositionDrawingSurface, используя Win2d CanvasDrawingSession. Но вы можете получить Visual из XAML TextBlock с помощью ElementCompositionPreview.GetElementVisual(yourTextBlock) и анимировать его с помощью выражений API композиции + цветных раскадровок XAML.

X-answer: Вы можете создать альфа-маску из своего текста CompositionDrawingSurface и применить ее к CompositionColorBrush:

    private void CreateColoredText(string text)
    {
        var compositor = ElementCompositionPreview.GetElementVisual(this).Compositor;
        var graphicsDevice = CanvasComposition.CreateCompositionGraphicsDevice(compositor, CanvasDevice.GetSharedDevice());

        var spriteTextVisual = compositor.CreateSpriteVisual();
        spriteTextVisual.Size = new Vector2(512, 512);

        var maskDrawingSurface = graphicsDevice.CreateDrawingSurface(new Size(512, 512), DirectXPixelFormat.B8G8R8A8UIntNormalized, DirectXAlphaMode.Premultiplied);

        using (var ds = CanvasComposition.CreateDrawingSession(maskDrawingSurface))
        {
            ds.Clear(Colors.Transparent);
            ds.DrawText(text, new Rect(0, 0, 512, 512), Colors.Lime, new CanvasTextFormat
            {
                FontSize = 32,
                FontWeight = FontWeights.Bold,
                VerticalAlignment = CanvasVerticalAlignment.Center,
                HorizontalAlignment = CanvasHorizontalAlignment.Center,
                LineSpacing = 32
            });
        }

        var maskSurfaceBrush = compositor.CreateSurfaceBrush(maskDrawingSurface);
        var surfaceTextBrush = compositor.CreateColorBrush(Colors.DeepPink);
        var maskBrush = compositor.CreateMaskBrush();
        maskBrush.Mask = maskSurfaceBrush;
        maskBrush.Source = surfaceTextBrush;

        var colorAnimation = compositor.CreateColorKeyFrameAnimation();
        colorAnimation.InsertKeyFrame(0.5f, Colors.DeepSkyBlue);
        colorAnimation.InsertKeyFrame(1, Colors.DeepPink);
        colorAnimation.Duration = TimeSpan.FromMilliseconds(1500);
        colorAnimation.IterationBehavior = AnimationIterationBehavior.Forever;

        surfaceTextBrush.StartAnimation("Color", colorAnimation);

        spriteTextVisual.Brush = maskBrush;

        ElementCompositionPreview.SetElementChildVisual(Grid, spriteTextVisual);
    }

Теперь вы можете анимировать цвет и перспективу для своих целей.

46
задан abatishchev 19 March 2014 в 04:15
поделиться

4 ответа

Перегружение обычно является пугалом заключенных типом языков (по крайней мере, когда, как F#, система типов не достаточно мощна для содержания классов типа). Существует много вариантов, которые Вы имеете в F#:

  • Использование, перегружающееся на методах (члены типа), в этом случае перегружая работы во многом как как на других языках .NET (можно для данного случая перегрузить участников, если вызовы может отличить число/тип параметров)
  • "встроенное" Использование, "^", и статические членские ограничения для специальной перегрузки на функциях (это - то, что большинство различных математических операторов, которые должны работать над интервалом/плаванием/и т.д.; синтаксис здесь является странным, это мало-используется кроме библиотеки F#)
  • , Моделируют классы типа путем передачи дополнительного параметра словаря операций (это - то, что INumeric делает в одной из библиотек F# PowerPack для обобщения, различные Математические алгоритмы для произвольных пользовательских типов)
  • Отступают к динамическому контролю типов (передача в 'obj' параметре, сделайте динамическую проверку печатания, выдайте исключение на этапе выполнения для плохого типа)

Для конкретного примера, я, вероятно, просто использовал бы перегрузку метода:

type MathOps =
    static member sqrt_int(x:int) = x |> float |> sqrt |> int
    static member sqrt_int(x:int64) = x |> float |> sqrt |> int64

let x = MathOps.sqrt_int 9
let y = MathOps.sqrt_int 100L
61
ответ дан Brian 26 November 2019 в 20:18
поделиться

Да, это может быть сделано. Смотрите на этот поток hubFS .

В этом случае, решение было бы:

let inline retype (x:'a) : 'b = (# "" x : 'b #)
let inline sqrt_int (n:'a) = retype (sqrt (float n)) : 'a

Протест : никакая проверка типа времени компиляции. Т.е. sqrt_int "blabla" прекрасные компиляции, но Вы получите FormatException во времени выполнения.

14
ответ дан Marcus 26 November 2019 в 20:18
поделиться

Вот другой способ использовать проверки типа выполнения...

let sqrt_int<'a> (x:'a) : 'a = // '
    match box x with
    | :? int as i -> downcast (i |> float |> sqrt |> int |> box)
    | :? int64 as i -> downcast (i |> float |> sqrt |> int64 |> box)
    | _ -> failwith "boo"

let a = sqrt_int 9
let b = sqrt_int 100L
let c = sqrt_int "foo" // boom
9
ответ дан Brian 26 November 2019 в 20:18
поделиться

Уже не отнять у корректных ответов, если, но можно на самом деле использовать ограничения типа в сопоставлении с образцом. Синтаксис:

| :? type ->

Или если Вы хотите объединить проверку типа и бросок:

| :? type as foo ->
2
ответ дан Joel Mueller 26 November 2019 в 20:18
поделиться
Другие вопросы по тегам:

Похожие вопросы: