मेश ग्रेडिएंट, पैच की 2D ग्रिड का इस्तेमाल करके, कई दिशाओं में रंग के ट्रांज़िशन बनाते हैं. लाइनर या रेडियल ग्रेडिएंट के उलट, मेश ग्रेडिएंट, ग्रिड में रंगों को आसानी से इंटरपोलेट करते हैं. मेश ग्रेडिएंट का इस्तेमाल करके, अपने यूज़र इंटरफ़ेस में फ़्लूड और ऑर्गैनिक एस्थेटिक एलिमेंट बनाएं.
मुख्य सिद्धांत
मेश ग्रेडिएंट बनाने के लिए, ग्रिड के डाइमेंशन, वर्टिकल, और पॉइंट के बीच रंग के ट्रांज़िशन तय करें:
- ग्रिड के डाइमेंशन: मेश को वर्टिकल और हॉरिज़ॉन्टल ऐक्सिस के हिसाब से पैच में बांटा जाता है.
rowsऔरcolumnsकी ग्रिड में (rows+1)×(columns+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) )
ऐडवांस ग्रिड बनाना
इस उदाहरण में, 3x3 ग्रिड दिखाया गया है. इसका मतलब है कि 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 lambda पैरामीटर, 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) )