मेश ग्रेडिएंट, पैच के 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) )