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