মেশ গ্রেডিয়েন্ট

মেশ গ্রেডিয়েন্ট জটিল, মাল্টি-ডিরেকশনাল কালার ট্রানজিশন তৈরি করে, যার জন্য প্যাচের 2D গ্রিড ব্যবহার করা হয়। লিনিয়ার বা রেডিয়াল গ্রেডিয়েন্টের মতো নয়, মেশ গ্রেডিয়েন্ট মসৃণভাবে 2D গ্রিড জুড়ে রঙ ইন্টারপোলেট করে। আপনার ইউজার ইন্টারফেসে ফ্লুইড, অর্গানিক বা মাল্টি-পয়েন্ট ব্যাকগ্রাউন্ড তৈরি করার সময় একাধিক radialGradient বা linearGradient ব্রাশ স্ট্যাক করার পরিবর্তে মেশ গ্রেডিয়েন্ট ব্যবহার করুন।

একটি মেশ গ্রেডিয়েন্ট উদাহরণ, যার বর্তমান মেশ গ্রেডিয়েন্ট পয়েন্টগুলি দেখানো হয়েছে।
ছবি ১. একটি মেশ গ্রেডিয়েন্ট উদাহরণ, যার বর্তমান মেশ গ্রেডিয়েন্ট পয়েন্টগুলি দেখানো হয়েছে।

মূল ধারণা

মেশ গ্রেডিয়েন্ট তৈরি করতে, গ্রিডের মাপ, ভার্টিসেস এবং পয়েন্টের মধ্যে কালার ট্রানজিশন সংজ্ঞায়িত করুন:

  • গ্রিড ডাইমেনশন: উল্লম্ব ও অনুভূমিক অক্ষ বরাবর মেশকে প্যাচে ভাগ করা হয়। rows এবং columns-এর গ্রিডে (সারি+১)×(কলাম+১) ভার্টিসেস থাকে। যেমন, ১×১ মেশে ৪টি ভার্টিসেস থাকে যা একটি প্যাচ তৈরি করে।
  • নর্মালাইজ করা কোঅর্ডিনেট: সব ভার্টেক্স পজিশন নর্মালাইজ করা কোঅর্ডিনেট সিস্টেম ব্যবহার করে যেখানে (0f, 0f) ড্রয়িং বাউন্ডের উপরে-বাঁদিকে এবং (1f, 1f) নিচে-ডানদিকে দেখায়।
  • বেজিয়ার কন্ট্রোল পয়েন্ট (ট্যানজেন্ট): প্রতিটি ভার্টেক্সে সর্বাধিক চারটি ঐচ্ছিক বেজিয়ার কন্ট্রোল পয়েন্ট থাকে। এইসব স্পর্শক প্রতিবেশী ভার্টিসেসের মধ্যে এজ কার্ভেচার নির্দিষ্ট করে। আপনি Offset.Unspecified ব্যবহার করলে, প্যাচ জুড়ে মসৃণ ট্রানজিশন নিশ্চিত করতে Compose ট্যাঞ্জেন্ট অনুমান করে। ৪টি ভার্টেক্স ও তাদের কন্ট্রোল পয়েন্টের মাধ্যমে তৈরি প্রতিটি গ্রিড সেল একটি বেজিয়ের প্যাচ তৈরি করে।
  • কালার ইন্টারপোলেশন: ফ্রেমওয়ার্কটি প্রধান ভার্টিসেসের মধ্যে রঙ গণনা করে। আরও মসৃণ রঙ পরিবর্তনের জন্য Catmull-Rom ইন্টারপোলেশন-এর জন্য hasBicubicColor-কে true-এ সেট করুন অথবা বিলিনিয়ার ইন্টারপোলেশনের জন্য false-এ সেট করুন।

MeshGradientPainter দিয়ে আঁকুন

Jetpack Compose-এ, মেশ গ্রেডিয়েন্ট রেন্ডার করতে MeshGradientPainter ব্যবহার করুন। MeshGradientPainter ক্যানভাসে আঁকে।

একটি সহজ মেশ গ্রেডিয়েন্ট তৈরি করুন

একটি প্রাথমিক স্ট্যাটিক মেশ গ্রেডিয়েন্ট তৈরি করতে, কনফিগারেশন ব্লকের মধ্যে setVertex ফাংশন ব্যবহার করে এবং এর ডাইমেনশন নির্দিষ্ট করে একটি MeshGradientPainter শুরু করুন যাতে আপনার কর্নার পয়েন্টগুলি পজিশন করা যায় এবং সেগুলিতে রঙ অ্যাসাইন করা যায়।

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

বাঁদিকে উপরে বাঁকানো পয়েন্ট সহ মেশ গ্রেডিয়েন্ট।
ছবি ৩। বেজিয়ার কন্ট্রোল পয়েন্ট দিয়ে উপরের-বাঁদিকের শীর্ষবিন্দু কার্ভ করুন।

উন্নত গ্রিড তৈরি করুন

এই উদাহরণে ৩x৩ গ্রিড দেখানো হয়েছে, অর্থাৎ ১৬টি পয়েন্ট নির্দিষ্ট করতে হবে, যেখানে মাঝের পয়েন্টগুলি আলাদা অফসেট দিয়ে সেট করা হয়েছে:

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

ছবি ৫. অ্যানিমেশন দেখানোর জন্য পয়েন্ট সহ অ্যানিমেটেড মেশ গ্রেডিয়েন্ট।