Dégradés de maillage

Les dégradés de maillage créent des transitions de couleurs complexes et multidirectionnelles à l'aide d'une grille 2D de patchs. Contrairement aux dégradés linéaires ou radiaux, les dégradés de maillage interpolent les couleurs de manière fluide sur une grille 2D. Utilisez des dégradés de maillage au lieu d'empiler plusieurs pinceaux radialGradient ou linearGradient lorsque vous créez des arrière-plans fluides, organiques ou multipoints dans votre interface utilisateur.

Exemple de dégradé de maillage avec affichage de ses points de dégradé de maillage actuels.
Figure 1. Exemple de dégradé de maillage avec affichage de ses points de dégradé de maillage actuels.

Concepts clés

Pour créer un dégradé de maillage, définissez les dimensions de la grille, les sommets et les transitions de couleur entre les points :

  • Dimensions de la grille : le maillage est divisé en patchs le long des axes vertical et horizontal. Une grille de rows et columns contient (lignes+1)×(colonnes+1) sommets. Par exemple, un maillage 1 x 1 se compose de quatre sommets formant un patch.
  • Coordonnées normalisées : toutes les positions des sommets utilisent un système de coordonnées normalisé où (0f, 0f) représente l'angle supérieur gauche et (1f, 1f) l'angle inférieur droit des limites de tracé.
  • Points de contrôle de Bézier (tangentes) : chaque sommet contient jusqu'à quatre points de contrôle de Bézier facultatifs. Ces tangentes spécifient la courbure des bords entre les sommets voisins. Si vous utilisez Offset.Unspecified, Compose déduit les tangentes pour assurer des transitions fluides entre les patchs. Chaque cellule de la grille formée par quatre sommets et leurs points de contrôle génère un patch de Bézier.
  • Interpolation des couleurs : le framework calcule les couleurs entre les sommets principaux. Définissez hasBicubicColor sur true pour l'interpolation Catmull-Rom afin d'obtenir des changements de couleur plus fluides, ou sur false pour l'interpolation bilinéaire.

Dessiner avec MeshGradientPainter

Dans Jetpack Compose, utilisez MeshGradientPainter pour afficher un dégradé de maillage. MeshGradientPainter dessine sur le canevas.

Créer un dégradé de maillage simple

Pour créer un dégradé de maillage statique de base, initialisez un MeshGradientPainter en spécifiant ses dimensions et en utilisant la fonction setVertex dans le bloc de configuration pour positionner vos points d'angle et leur attribuer des couleurs.

val rows = 1
val columns = 1

val gradientPainter = remember {
    MeshGradientPainter(rows, columns) {
        // Parameters: row, column, position, color
        setVertex(0, 0, Offset(0f, 0f), Color.Red)     // Top-Left
        setVertex(0, 1, Offset(1f, 0f), Color.Blue)    // Top-Right
        setVertex(1, 0, Offset(0f, 1f), Color.Green)   // Bottom-Left
        setVertex(1, 1, Offset(1f, 1f), Color.Yellow)  // Bottom-Right
    }
}

Box(
    modifier = modifier
        .aspectRatio(16/9f)
        .fillMaxWidth()
        .paint(gradientPainter)
)

Dégradé de maillage de base avec quatre couleurs définies à chaque angle
Figure 2. Un dégradé de maillage de base avec quatre couleurs, chaque angle étant défini sur l'une des quatre couleurs.

Utiliser des points de contrôle de Bézier spécifiques

Par défaut, le générateur de maillage gère les calculs complexes pour que les transitions de la grille restent fluides. Toutefois, vous pouvez personnaliser explicitement les tangentes sur n'importe quel sommet si vous souhaitez pousser, tirer ou pincer de manière sélective certaines sections de couleur.

Les décalages de contrôle sont mesurés par rapport à la position du sommet hôte.

val customTangentPainter = remember {
    MeshGradientPainter(rows = 1, columns = 1) {
        // Tweak the top-left vertex to curve outwards to the right and bottom
        setVertex(
            row = 0,
            column = 0,
            position = Offset(0f, 0f),
            color = Color.Magenta,
            rightControlPoint = Offset(0.4f, 0.1f),
            bottomControlPoint = Offset(0.1f, 0.4f)
        )

        // Other points can remain unspecified to use default inferred fallback tangents
        setVertex(0, 1, Offset(1f, 0f), Color.Cyan)
        setVertex(1, 0, Offset(0f, 1f), Color.Blue)
        setVertex(1, 1, Offset(1f, 1f), Color.Black)
    }
}
Box(
    modifier = modifier
        .aspectRatio(16/9f)
        .fillMaxWidth()
        .paint(customTangentPainter)
)

Dégradé de maillage avec un point supérieur gauche incurvé.
Figure 3. Courbez le sommet supérieur gauche avec un point de contrôle de Bézier.

Créer des grilles avancées

Cet exemple montre une grille de 3 par 3, ce qui signifie qu'il y a 16 points à spécifier, les points du milieu étant définis avec des décalages différents :

val points = remember {
    listOf(
        Offset(0.0f, 0.0f), Offset(0.3f, 0.0f), Offset(0.7f, 0.0f), Offset(1.0f, 0.0f),
        Offset(0.0f, 0.3f), Offset(0.2f, 0.4f), Offset(0.7f, 0.2f), Offset(1.0f, 0.3f),
        Offset(0.0f, 0.7f), Offset(0.3f, 0.8f), Offset(0.7f, 0.6f), Offset(1.0f, 0.7f),
        Offset(0.0f, 1.0f), Offset(0.3f, 1.0f), Offset(0.7f, 1.0f), Offset(1.0f, 1.0f)
    )
}

val gradientPainter = remember {
    MeshGradientPainter(rows = 3, columns = 3) {
        // Row 0
        setVertex(0, 0, points[0], yellow)
        setVertex(0, 1, points[1], orange)
        setVertex(0, 2, points[2], yellow)
        setVertex(0, 3, points[3], purple)

        // Row 1
        setVertex(1, 0, points[4], pink)
        setVertex(1, 1, points[5], yellow)
        setVertex(1, 2, points[6], pink)
        setVertex(1, 3, points[7], purple)

        // Row 2
        setVertex(2, 0, points[8], indigo)
        setVertex(2, 1, points[9], pink)
        setVertex(2, 2, points[10], purple)
        setVertex(2, 3, points[11], indigo)

        // Row 3
        setVertex(3, 0, points[12], purple)
        setVertex(3, 1, points[13], indigo)
        setVertex(3, 2, points[14], pink)
        setVertex(3, 3, points[15], yellow)
    }
}

Box(
    modifier = modifier.padding(32.dp)
        .aspectRatio(16 / 9f)
        .fillMaxWidth()
        .paint(gradientPainter)
        // ...
)

Dégradé de maillage avec des points de contrôle de Bézier et des couleurs de vagues, et les points de maillage illustrés par-dessus.
Figure 4. Dégradé de maillage avec des points de contrôle de Bézier et des couleurs de vagues, et les points de maillage illustrés par-dessus.

Animer un dégradé de maillage

Étant donné que le paramètre lambda block de MeshGradientPainter est exécuté dans un DrawScope, il peut lire et observer l'état modifiable. Vous pouvez animer des positions ou des couleurs au fil du temps sans réallouer de nuanceurs ni de bitmaps.

val infiniteTransition = rememberInfiniteTransition(label = "meshMovement")
val animatedOffset by infiniteTransition.animateFloat(
    initialValue = -0.1f,
    targetValue = 0.1f,
    animationSpec = infiniteRepeatable(
        animation = tween(2500, easing = LinearEasing),
        repeatMode = RepeatMode.Reverse
    ),
    label = "offset"
)

val coral = Color(255, 90, 90)
val peach = Color(255, 139, 90)
val amber = Color(255, 169, 90)
val sunshine = Color(255, 212, 90)
val indigo = Color(0xFF5856D6)
val pink = Color(0xFFFF2D55)


val gradientPainter = remember {
    MeshGradientPainter(rows = 3, columns = 3) {
        // Row 0
        setVertex(0, 0, Offset(0.0f, 0.0f), indigo)
        setVertex(0, 1, Offset(0.3f, 0.0f), peach)
        setVertex(0, 2, Offset(0.7f, 0.0f), amber)
        setVertex(0, 3, Offset(1.0f, 0.0f), sunshine)
        // Row 1
        setVertex(1, 0, Offset(0.0f, 0.3f), pink)
        setVertex(1, 1, Offset(0.2f, 0.4f) + Offset(animatedOffset, animatedOffset), coral)
        setVertex(1, 2, Offset(0.7f, 0.2f) + Offset(animatedOffset, animatedOffset), peach)
        setVertex(1, 3, Offset(1.0f, 0.3f), indigo)

        // Row 2
        setVertex(2, 0, Offset(0.0f, 0.7f), coral)
        setVertex(2, 1, Offset(0.3f, 0.8f) + Offset(animatedOffset, 0f), pink)
        setVertex(2, 2, Offset(0.7f, 0.6f) + Offset(animatedOffset, 0f), sunshine)
        setVertex(2, 3, Offset(1.0f, 0.7f), amber)

        // Row 3
        setVertex(3, 0, Offset(0.0f, 1.0f), sunshine)
        setVertex(3, 1, Offset(0.3f, 1.0f), amber)
        setVertex(3, 2, Offset(0.7f, 1.0f), pink)
        setVertex(3, 3, Offset(1.0f, 1.0f), indigo)
    }
}


Box(
    modifier = modifier.padding(32.dp)
        .safeContentPadding()
        .aspectRatio(16 / 9f)
        .fillMaxWidth()
        .paint(gradientPainter)
)

Figure 5. Dégradé de maillage animé avec des points pour montrer l'animation.