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 correctifs. 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. Utilisez des dégradés de maillage pour créer des éléments esthétiques fluides et organiques 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 un 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 correctifs le long des axes vertical et horizontal. Une grille de rows et de columns contient (rows+1)×(columns+1) sommets. Par exemple, un maillage 1×1 est composé de quatre sommets formant un correctif.
  • Coordonnées normalisées : toutes les positions des sommets utilisent un système de coordonnées normalisé où (0f, 0f) représente le coin supérieur gauche et (1f, 1f) le coin inférieur droit des limites de dessin.
  • 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 correctifs. Chaque cellule de grille formée par quatre sommets et leurs points de contrôle génère un correctif 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. Dégradé de maillage de base avec quatre couleurs, chaque angle étant défini sur l'une des quatre.

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

Par défaut, le générateur de maillage gère des 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 fortement certaines sections de couleur de manière sélective.

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 incurvé en haut à gauche.
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 3x3, ce qui signifie qu'il existe 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 Bézier et des couleurs d'onde, et les points de maillage illustrés au-dessus.
Figure 4. Dégradé de maillage avec des points de contrôle de Bézier et des couleurs d'onde, et les points de maillage illustrés au-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 mutable. 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 afficher l'animation.