মেশ গ্রেডিয়েন্ট প্যাচের একটি ২ডি গ্রিড ব্যবহার করে জটিল ও বহু-দিকনির্দেশক রঙের রূপান্তর তৈরি করে। লিনিয়ার বা রেডিয়াল গ্রেডিয়েন্টের মতো নয়, মেশ গ্রেডিয়েন্ট একটি গ্রিড জুড়ে মসৃণভাবে রঙগুলোকে বিন্যস্ত করে। আপনার ইউজার ইন্টারফেসে সাবলীল ও স্বাভাবিক নান্দনিক উপাদান তৈরি করতে মেশ গ্রেডিয়েন্ট ব্যবহার করুন।

মূল ধারণা
একটি মেশ গ্রেডিয়েন্ট তৈরি করতে, গ্রিডের মাত্রা, শীর্ষবিন্দু এবং বিন্দুগুলোর মধ্যে রঙের পরিবর্তন নির্ধারণ করুন:
- গ্রিডের মাত্রা: মেশটি উল্লম্ব এবং অনুভূমিক অক্ষ বরাবর বিভিন্ন অংশে বিভক্ত থাকে।
rowsএবংcolumnsএকটি গ্রিডে (সারি+১)×(কলাম+১) টি শীর্ষবিন্দু থাকে। উদাহরণস্বরূপ, একটি ১×১ মেশ ৪টি শীর্ষবিন্দু নিয়ে গঠিত যা একটি অংশ তৈরি করে। - নর্মালাইজড স্থানাঙ্ক: সকল ভার্টেক্স পজিশন একটি নর্মালাইজড স্থানাঙ্ক ব্যবস্থা ব্যবহার করে, যেখানে
(0f, 0f)অঙ্কন সীমার উপরের-বাম এবং(1f, 1f)নীচের-ডান দিককে নির্দেশ করে। - বেজিয়ার কন্ট্রোল পয়েন্ট (ট্যানজেন্ট): প্রতিটি ভার্টেক্সে সর্বোচ্চ চারটি ঐচ্ছিক বেজিয়ার কন্ট্রোল পয়েন্ট থাকে। এই ট্যানজেন্টগুলো প্রতিবেশী ভার্টেক্সগুলোর মধ্যে প্রান্তের বক্রতা নির্দিষ্ট করে। আপনি যদি
Offset.Unspecifiedব্যবহার করেন, তাহলে Compose প্যাচগুলোর মধ্যে মসৃণ রূপান্তর নিশ্চিত করতে ট্যানজেন্টগুলো অনুমান করে নেয়। ৪টি ভার্টেক্স এবং তাদের কন্ট্রোল পয়েন্ট দ্বারা গঠিত প্রতিটি গ্রিড সেল একটি বেজিয়ার প্যাচ তৈরি করে। - কালার ইন্টারপোলেশন: ফ্রেমওয়ার্কটি প্রধান ভার্টেক্সগুলোর মধ্যে রঙ গণনা করে। মসৃণ রঙ পরিবর্তনের জন্য ক্যাটমুল-রম ইন্টারপোলেশন পেতে
hasBicubicColortrue, অথবা বাইলিনিয়ার ইন্টারপোলেশনের জন্য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) )

উন্নত গ্রিড তৈরি করুন
এই উদাহরণটিতে একটি ৩ বাই ৩ গ্রিড দেখানো হয়েছে, অর্থাৎ এখানে ১৬টি বিন্দু নির্দিষ্ট করতে হবে, যেখানে মধ্যবর্তী বিন্দুগুলো ভিন্ন ভিন্ন অফসেট দিয়ে সেট করা হয়েছে:
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) )