मेश ग्रेडिएंट

मेश ग्रेडिएंट, पैच के 2D ग्रिड का इस्तेमाल करके, कई दिशाओं में कलर ट्रांज़िशन बनाते हैं. लीनियर या रेडियल ग्रेडिएंट के उलट, मेश ग्रेडिएंट 2D ग्रिड में रंगों को आसानी से इंटरपोलेट करते हैं. अपने यूज़र इंटरफ़ेस में फ़्लूइड, ऑर्गैनिक या मल्टी-पॉइंट बैकग्राउंड बनाते समय, कई radialGradient या linearGradient ब्रश को स्टैक करने के बजाय, मेश ग्रेडिएंट का इस्तेमाल करें.

मेश ग्रेडिएंट का उदाहरण, जिसमें इसके मौजूदा मेश ग्रेडिएंट पॉइंट दिखाए गए हैं.
पहली इमेज. मेश ग्रेडिएंट का उदाहरण, जिसमें इसके मौजूदा मेश ग्रेडिएंट पॉइंट दिखाए गए हैं.

मुख्य सिद्धांत

मेश ग्रेडिएंट बनाने के लिए, ग्रिड के डाइमेंशन, वर्टिसेस, और पॉइंट के बीच कलर ट्रांज़िशन तय करें:

  • ग्रिड डाइमेंशन: मेश को वर्टिकल और हॉरिज़ॉन्टल ऐक्सिस के साथ पैच में बांटा जाता है. rows और columns के ग्रिड में (पंक्तियां+1)×(कॉलम+1) वर्टिसेस होते हैं. उदाहरण के लिए, 1×1 मेश में चार वर्टिस होते हैं, जो एक पैच बनाते हैं.
  • नॉर्मलाइज़्ड कोऑर्डिनेट: सभी वर्टेक्स पोज़िशन, नॉर्मलाइज़्ड कोऑर्डिनेट सिस्टम का इस्तेमाल करती हैं. इसमें (0f, 0f), ड्रॉइंग बाउंड के सबसे ऊपर बाईं ओर और (1f, 1f), सबसे नीचे दाईं ओर मौजूद होता है.
  • बेज़ियर कंट्रोल पॉइंट (टैंजेंट): हर वर्टेक्स में ज़्यादा से ज़्यादा चार वैकल्पिक बेज़ियर कंट्रोल पॉइंट होते हैं. ये टेंजेंट, आस-पास के वर्टिसेस के बीच के किनारे के घुमाव को तय करते हैं. Offset.Unspecified का इस्तेमाल करने पर, Compose टेंजेंट का अनुमान लगाता है, ताकि पैच के बीच आसानी से ट्रांज़िशन हो सके. चार वर्टिसेस और उनके कंट्रोल पॉइंट से बनने वाला हर ग्रिड सेल, एक बेज़ियर पैच जनरेट करता है.
  • कलर इंटरपोलेशन: फ़्रेमवर्क, मुख्य वर्टिसेस के बीच के रंगों को कैलकुलेट करता है. रंगों को आसानी से बदलने के लिए, hasBicubicColor को true पर सेट करें. इससे कैटमुल-रोम इंटरपोलेशन चालू हो जाएगा. इसके अलावा, बाइलीनियर इंटरपोलेशन के लिए, false पर सेट करें.

MeshGradientPainter की मदद से ड्रॉइंग बनाएं

Jetpack Compose में, मेश ग्रेडिएंट को रेंडर करने के लिए, MeshGradientPainter का इस्तेमाल करें. MeshGradientPainter कैनवस पर ड्रॉ करता है.

एक आसान मेश ग्रेडिएंट बनाना

एक बेसिक स्टैटिक मेश ग्रेडिएंट बनाने के लिए, MeshGradientPainter को शुरू करें. इसके लिए, उसके डाइमेंशन तय करें और कॉन्फ़िगरेशन ब्लॉक में setVertex फ़ंक्शन का इस्तेमाल करें. इससे, कॉर्नर पॉइंट को पोज़िशन किया जा सकता है और उन्हें रंग असाइन किए जा सकते हैं.

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)
)

बेसिक मेश ग्रेडिएंट, जिसमें हर कोने पर चार रंग तय किए गए हैं
दूसरी इमेज. चार रंगों वाला एक बेसिक मेश ग्रेडिएंट, जिसमें हर कोने पर चार में से एक रंग सेट किया गया है.

बेज़ियर कंट्रोल पॉइंट का इस्तेमाल करना

डिफ़ॉल्ट रूप से, मेश जनरेटर मुश्किल कैलकुलेशन को हैंडल करता है, ताकि ग्रिड ट्रांज़िशन आसानी से हो सके. हालांकि, किसी एक वर्टेक्स पर टेंजेंट को अपनी पसंद के मुताबिक बनाया जा सकता है. ऐसा तब किया जा सकता है, जब आपको रंग के कुछ सेक्शन को चुनिंदा तरीके से पुश करना हो, खींचना हो या शार्प पिंच करना हो.

कंट्रोल ऑफ़सेट को होस्ट वर्टेक्स की पोज़िशन के हिसाब से मेज़र किया जाता है.

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)
)

मेश ग्रेडिएंट, जिसमें सबसे ऊपर बाईं ओर कर्व वाला पॉइंट है.
तीसरी इमेज. बेज़ियर कंट्रोल पॉइंट की मदद से, सबसे ऊपर बाईं ओर मौजूद वर्टेक्स को घुमावदार बनाएं.

ऐडवांस ग्रिड बनाना

इस उदाहरण में 3 गुणा 3 का ग्रिड दिखाया गया है. इसका मतलब है कि इसमें 16 पॉइंट तय करने होंगे. साथ ही, बीच के पॉइंट अलग-अलग ऑफ़सेट के साथ सेट किए गए हैं:

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)
        // ...
)

बेज़ियर कंट्रोल पॉइंट और वेव कलर के साथ मेश ग्रेडिएंट. इसके ऊपर मेश पॉइंट दिखाए गए हैं.
चौथी इमेज. बेज़ियर कंट्रोल पॉइंट और वेव कलर के साथ मेश ग्रेडिएंट. साथ ही, इसके ऊपर मेश पॉइंट दिखाए गए हैं.

मेश ग्रेडिएंट को ऐनिमेट करना

MeshGradientPainter का block लैम्डा पैरामीटर, DrawScope में लागू होता है. इसलिए, यह बदली जा सकने वाली स्थिति को पढ़ सकता है और उस पर नज़र रख सकता है. शेडर या बिटमैप को फिर से असाइन किए बिना, समय के साथ पोज़िशन या रंगों को ऐनिमेट किया जा सकता है.

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)
)

पांचवीं इमेज. ऐनिमेशन दिखाने के लिए, पॉइंट के साथ ऐनिमेटेड मेश ग्रेडिएंट.