কম্পোজে আকার

রচনার মাধ্যমে, আপনি বহুভুজ থেকে তৈরি আকৃতি তৈরি করতে পারেন। উদাহরণস্বরূপ, আপনি নিম্নলিখিত ধরণের আকার তৈরি করতে পারেন:

অঙ্কন এলাকার কেন্দ্রে নীল ষড়ভুজ
চিত্র 1 । বিভিন্ন আকারের উদাহরণ যা আপনি গ্রাফিক্স-আকৃতি লাইব্রেরি দিয়ে তৈরি করতে পারেন

রচনায় একটি কাস্টম বৃত্তাকার বহুভুজ তৈরি করতে, আপনার app/build.gradlegraphics-shapes নির্ভরতা যোগ করুন :

implementation "androidx.graphics:graphics-shapes:1.0.0-rc01"

এই লাইব্রেরি আপনাকে বহুভুজ থেকে তৈরি আকৃতি তৈরি করতে দেয়। যদিও বহুভুজ আকারের শুধুমাত্র সোজা প্রান্ত এবং তীক্ষ্ণ কোণ রয়েছে, এই আকারগুলি ঐচ্ছিক গোলাকার কোণগুলির জন্য অনুমতি দেয়। এটি দুটি ভিন্ন আকারের মধ্যে রূপান্তর করা সহজ করে তোলে। নির্বিচারে আকারের মধ্যে মরফিং করা কঠিন, এবং এটি একটি ডিজাইন-টাইম সমস্যা হতে থাকে। কিন্তু এই লাইব্রেরিটি অনুরূপ বহুভুজ কাঠামোর সাথে এই আকারগুলির মধ্যে পরিবর্তন করে এটিকে সহজ করে তোলে।

বহুভুজ তৈরি করুন

নিচের স্নিপেটটি অঙ্কন এলাকার কেন্দ্রে 6 পয়েন্ট সহ একটি মৌলিক বহুভুজ আকৃতি তৈরি করে:

Box(
    modifier = Modifier
        .drawWithCache {
            val roundedPolygon = RoundedPolygon(
                numVertices = 6,
                radius = size.minDimension / 2,
                centerX = size.width / 2,
                centerY = size.height / 2
            )
            val roundedPolygonPath = roundedPolygon.toPath().asComposePath()
            onDrawBehind {
                drawPath(roundedPolygonPath, color = Color.Blue)
            }
        }
        .fillMaxSize()
)

অঙ্কন এলাকার কেন্দ্রে নীল ষড়ভুজ
চিত্র ২ । অঙ্কন এলাকার কেন্দ্রে নীল ষড়ভুজ।

এই উদাহরণে, লাইব্রেরি একটি RoundedPolygon তৈরি করে যা অনুরোধ করা আকৃতির প্রতিনিধিত্ব করে জ্যামিতি ধারণ করে। একটি কম্পোজ অ্যাপে সেই আকৃতিটি আঁকতে, আপনাকে অবশ্যই এটি থেকে একটি Path অবজেক্ট পেতে হবে যাতে আকৃতিটিকে একটি ফর্মে পরিণত করতে হয় যা কম্পোজ কীভাবে আঁকতে জানে।

বহুভুজের কোণে বৃত্তাকার

বহুভুজের কোণগুলিকে বৃত্তাকার করতে, CornerRounding প্যারামিটার ব্যবহার করুন। এর জন্য দুটি প্যারামিটার লাগে, radius এবং smoothing । প্রতিটি বৃত্তাকার কোণ 1-3 ঘন বক্ররেখা দ্বারা গঠিত, যার কেন্দ্রে একটি বৃত্তাকার চাপের আকৃতি রয়েছে যখন দুটি দিক ("ফ্ল্যাঙ্কিং") বক্ররেখা আকৃতির প্রান্ত থেকে কেন্দ্রের বক্ররেখায় স্থানান্তরিত হয়।

ব্যাসার্ধ

radius হল একটি শীর্ষবিন্দুকে বৃত্তাকার করতে ব্যবহৃত বৃত্তের ব্যাসার্ধ।

উদাহরণস্বরূপ, নিম্নলিখিত বৃত্তাকার কোণার ত্রিভুজটি নিম্নরূপ তৈরি করা হয়েছে:

বৃত্তাকার কোণ সহ ত্রিভুজ
চিত্র 3 । বৃত্তাকার কোণ সহ ত্রিভুজ।
বৃত্তাকার ব্যাসার্ধ r বৃত্তাকার কোণগুলির বৃত্তাকার বৃত্তাকার আকার নির্ধারণ করে
চিত্র 4 । বৃত্তাকার ব্যাসার্ধ r বৃত্তাকার কোণগুলির বৃত্তাকার বৃত্তাকার আকার নির্ধারণ করে।

স্মুথিং

মসৃণকরণ একটি ফ্যাক্টর যা নির্ধারণ করে যে কোণার বৃত্তাকার গোলাকার অংশ থেকে প্রান্তে যেতে কতক্ষণ সময় লাগে। 0-এর একটি স্মুথিং ফ্যাক্টর (আনমসুথ, CornerRounding জন্য ডিফল্ট মান) সম্পূর্ণরূপে বৃত্তাকার কোণার বৃত্তাকারে পরিণত হয়। একটি অশূন্য স্মুথিং ফ্যাক্টর (সর্বোচ্চ 1.0 পর্যন্ত) এর ফলে কোণটি তিনটি পৃথক বক্ররেখা দ্বারা বৃত্তাকার হয়।

0 এর একটি স্মুথিং ফ্যাক্টর (আনমসুথড) একটি একক ঘনবক্ররেখা তৈরি করে যা পূর্বের উদাহরণের মতো নির্দিষ্ট বৃত্তাকার ব্যাসার্ধ সহ কোণার চারপাশে একটি বৃত্ত অনুসরণ করে
চিত্র 5 । 0 এর একটি স্মুথিং ফ্যাক্টর (আনমসুথড) একটি একক ঘন বক্ররেখা তৈরি করে যা পূর্বের উদাহরণের মতো নির্দিষ্ট বৃত্তাকার ব্যাসার্ধ সহ কোণার চারপাশে একটি বৃত্ত অনুসরণ করে।
একটি অশূন্য স্মুথিং ফ্যাক্টর শীর্ষবিন্দুকে বৃত্তাকার করতে তিনটি ঘন বক্ররেখা তৈরি করে: অভ্যন্তরীণ বৃত্তাকার বক্ররেখা (আগের মতো) এবং দুটি ফ্ল্যাঙ্কিং বক্ররেখা যা অভ্যন্তরীণ বক্ররেখা এবং বহুভুজ প্রান্তগুলির মধ্যে স্থানান্তরিত হয়।
চিত্র 6 । একটি অশূন্য স্মুথিং ফ্যাক্টর শীর্ষবিন্দুকে বৃত্তাকার করতে তিনটি ঘন বক্ররেখা তৈরি করে: অভ্যন্তরীণ বৃত্তাকার বক্ররেখা (আগের মতো) এবং দুটি ফ্ল্যাঙ্কিং বক্ররেখা যা অভ্যন্তরীণ বক্ররেখা এবং বহুভুজ প্রান্তগুলির মধ্যে স্থানান্তরিত হয়।

উদাহরণ স্বরূপ, নিচের স্নিপেটটি 0 বনাম 1:

Box(
    modifier = Modifier
        .drawWithCache {
            val roundedPolygon = RoundedPolygon(
                numVertices = 3,
                radius = size.minDimension / 2,
                centerX = size.width / 2,
                centerY = size.height / 2,
                rounding = CornerRounding(
                    size.minDimension / 10f,
                    smoothing = 0.1f
                )
            )
            val roundedPolygonPath = roundedPolygon.toPath().asComposePath()
            onDrawBehind {
                drawPath(roundedPolygonPath, color = Color.Black)
            }
        }
        .size(100.dp)
)
তে স্মুথিং সেট করার সূক্ষ্ম পার্থক্যকে চিত্রিত করে

দুটি কালো ত্রিভুজ স্মুথিং প্যারামিটারে পার্থক্য দেখাচ্ছে।
চিত্র 7 । দুটি কালো ত্রিভুজ স্মুথিং প্যারামিটারে পার্থক্য দেখাচ্ছে।

আকার এবং অবস্থান

ডিফল্টরূপে, কেন্দ্রের ( 0, 0 ) চারপাশে 1 ব্যাসার্ধের সাথে একটি আকৃতি তৈরি করা হয়। এই ব্যাসার্ধটি বহুভুজের কেন্দ্র এবং বাহ্যিক শীর্ষবিন্দুগুলির মধ্যে দূরত্বকে প্রতিনিধিত্ব করে যার উপর ভিত্তি করে আকৃতিটি তৈরি হয়। লক্ষ্য করুন যে কোণগুলিকে বৃত্তাকার করার ফলে একটি ছোট আকৃতি হয় কারণ বৃত্তাকার কোণগুলি শীর্ষবিন্দুগুলির চেয়ে কেন্দ্রের কাছাকাছি হবে। বহুভুজের আকার দিতে, radius মান সামঞ্জস্য করুন। অবস্থান সামঞ্জস্য করতে, বহুভুজের centerX বা centerY পরিবর্তন করুন। বিকল্পভাবে, DrawScope#translate() এর মতো স্ট্যান্ডার্ড DrawScope ট্রান্সফরমেশন ফাংশন ব্যবহার করে অবজেক্টের আকার, অবস্থান এবং ঘূর্ণন পরিবর্তন করতে রূপান্তর করুন।

রূপের আকার

একটি Morph অবজেক্ট একটি নতুন আকৃতি যা দুটি বহুভুজ আকারের মধ্যে একটি অ্যানিমেশন উপস্থাপন করে। দুটি আকারের মধ্যে রূপান্তর করতে, দুটি RoundedPolygons এবং একটি Morph বস্তু তৈরি করুন যা এই দুটি আকার নেয়। শুরু এবং শেষ আকারের মধ্যে একটি আকৃতি গণনা করতে, শুরু (0) এবং শেষ (1) আকারের মধ্যে এটির ফর্ম নির্ধারণ করতে শূন্য এবং একের মধ্যে একটি progress মান প্রদান করুন:

Box(
    modifier = Modifier
        .drawWithCache {
            val triangle = RoundedPolygon(
                numVertices = 3,
                radius = size.minDimension / 2f,
                centerX = size.width / 2f,
                centerY = size.height / 2f,
                rounding = CornerRounding(
                    size.minDimension / 10f,
                    smoothing = 0.1f
                )
            )
            val square = RoundedPolygon(
                numVertices = 4,
                radius = size.minDimension / 2f,
                centerX = size.width / 2f,
                centerY = size.height / 2f
            )

            val morph = Morph(start = triangle, end = square)
            val morphPath = morph
                .toPath(progress = 0.5f).asComposePath()

            onDrawBehind {
                drawPath(morphPath, color = Color.Black)
            }
        }
        .fillMaxSize()
)

উপরের উদাহরণে, অগ্রগতি দুটি আকারের (বৃত্তাকার ত্রিভুজ এবং একটি বর্গক্ষেত্র) মধ্যে ঠিক অর্ধেক, নিম্নলিখিত ফলাফল তৈরি করে:

একটি বৃত্তাকার ত্রিভুজ এবং একটি বর্গক্ষেত্রের মধ্যে পথের 50%
চিত্র 8 । একটি বৃত্তাকার ত্রিভুজ এবং একটি বর্গক্ষেত্রের মধ্যে পথের 50%।

বেশিরভাগ পরিস্থিতিতে, একটি অ্যানিমেশনের অংশ হিসাবে মরফিং করা হয়, এবং শুধুমাত্র একটি স্ট্যাটিক রেন্ডারিং নয়। এই দুটির মধ্যে অ্যানিমেট করার জন্য, আপনি সময়ের সাথে অগ্রগতির মান পরিবর্তন করতে রচনাতে স্ট্যান্ডার্ড অ্যানিমেশন API ব্যবহার করতে পারেন। উদাহরণস্বরূপ, আপনি নিম্নরূপ এই দুটি আকারের মধ্যে অসীমভাবে রূপকে অ্যানিমেট করতে পারেন:

val infiniteAnimation = rememberInfiniteTransition(label = "infinite animation")
val morphProgress = infiniteAnimation.animateFloat(
    initialValue = 0f,
    targetValue = 1f,
    animationSpec = infiniteRepeatable(
        tween(500),
        repeatMode = RepeatMode.Reverse
    ),
    label = "morph"
)
Box(
    modifier = Modifier
        .drawWithCache {
            val triangle = RoundedPolygon(
                numVertices = 3,
                radius = size.minDimension / 2f,
                centerX = size.width / 2f,
                centerY = size.height / 2f,
                rounding = CornerRounding(
                    size.minDimension / 10f,
                    smoothing = 0.1f
                )
            )
            val square = RoundedPolygon(
                numVertices = 4,
                radius = size.minDimension / 2f,
                centerX = size.width / 2f,
                centerY = size.height / 2f
            )

            val morph = Morph(start = triangle, end = square)
            val morphPath = morph
                .toPath(progress = morphProgress.value)
                .asComposePath()

            onDrawBehind {
                drawPath(morphPath, color = Color.Black)
            }
        }
        .fillMaxSize()
)

একটি বর্গক্ষেত্র এবং একটি বৃত্তাকার ত্রিভুজের মধ্যে অসীমভাবে রূপান্তর করা
চিত্র 9 । একটি বর্গক্ষেত্র এবং একটি বৃত্তাকার ত্রিভুজের মধ্যে অসীমভাবে রূপান্তর করা।

ক্লিপ হিসাবে বহুভুজ ব্যবহার করুন

একটি কম্পোজেবল কীভাবে রেন্ডার করা হয় তা পরিবর্তন করতে এবং ক্লিপিং এলাকার চারপাশে আঁকা ছায়াগুলির সুবিধা নিতে কম্পোজে clip মডিফায়ার ব্যবহার করা সাধারণ:

fun RoundedPolygon.getBounds() = calculateBounds().let { Rect(it[0], it[1], it[2], it[3]) }
class RoundedPolygonShape(
    private val polygon: RoundedPolygon,
    private var matrix: Matrix = Matrix()
) : Shape {
    private var path = Path()
    override fun createOutline(
        size: Size,
        layoutDirection: LayoutDirection,
        density: Density
    ): Outline {
        path.rewind()
        path = polygon.toPath().asComposePath()
        matrix.reset()
        val bounds = polygon.getBounds()
        val maxDimension = max(bounds.width, bounds.height)
        matrix.scale(size.width / maxDimension, size.height / maxDimension)
        matrix.translate(-bounds.left, -bounds.top)

        path.transform(matrix)
        return Outline.Generic(path)
    }
}

তারপরে আপনি বহুভুজটিকে একটি ক্লিপ হিসাবে ব্যবহার করতে পারেন, যেমনটি নিম্নলিখিত স্নিপেটে দেখানো হয়েছে:

val hexagon = remember {
    RoundedPolygon(
        6,
        rounding = CornerRounding(0.2f)
    )
}
val clip = remember(hexagon) {
    RoundedPolygonShape(polygon = hexagon)
}
Box(
    modifier = Modifier
        .clip(clip)
        .background(MaterialTheme.colorScheme.secondary)
        .size(200.dp)
) {
    Text(
        "Hello Compose",
        color = MaterialTheme.colorScheme.onSecondary,
        modifier = Modifier.align(Alignment.Center)
    )
}

এর ফলে নিম্নলিখিত হয়:

কেন্দ্রে `হ্যালো কম্পোজ` লেখা সহ ষড়ভুজ।
চিত্র 10 । কেন্দ্রে "হ্যালো কম্পোজ" লেখা সহ ষড়ভুজ।

এটি আগে যা রেন্ডার করা হয়েছিল তার থেকে আলাদা নাও দেখতে পারে, তবে এটি রচনায় অন্যান্য বৈশিষ্ট্যগুলিকে ব্যবহার করার অনুমতি দেয়৷ উদাহরণস্বরূপ, এই কৌশলটি একটি চিত্র ক্লিপ করতে এবং ক্লিপ করা অঞ্চলের চারপাশে একটি ছায়া প্রয়োগ করতে ব্যবহার করা যেতে পারে:

val hexagon = remember {
    RoundedPolygon(
        6,
        rounding = CornerRounding(0.2f)
    )
}
val clip = remember(hexagon) {
    RoundedPolygonShape(polygon = hexagon)
}
Box(
    modifier = Modifier.fillMaxSize(),
    contentAlignment = Alignment.Center
) {
    Image(
        painter = painterResource(id = R.drawable.dog),
        contentDescription = "Dog",
        contentScale = ContentScale.Crop,
        modifier = Modifier
            .graphicsLayer {
                this.shadowElevation = 6.dp.toPx()
                this.shape = clip
                this.clip = true
                this.ambientShadowColor = Color.Black
                this.spotShadowColor = Color.Black
            }
            .size(200.dp)

    )
}

প্রান্তের চারপাশে প্রয়োগ করা ছায়া সহ ষড়ভুজ কুকুর
চিত্র 11 । কাস্টম আকৃতি ক্লিপ হিসাবে প্রয়োগ করা হয়েছে।

মার্ফ বোতামে ক্লিক করুন

আপনি একটি বোতাম তৈরি করতে graphics-shape লাইব্রেরি ব্যবহার করতে পারেন যা প্রেসে দুটি আকারের মধ্যে রূপ নেয়। প্রথমে, একটি MorphPolygonShape তৈরি করুন যা Shape প্রসারিত করে, স্কেল করে এবং যথাযথভাবে ফিট করার জন্য অনুবাদ করে। অগ্রগতির পাসিং নোট করুন যাতে আকারটি অ্যানিমেটেড করা যায়:

class MorphPolygonShape(
    private val morph: Morph,
    private val percentage: Float
) : Shape {

    private val matrix = Matrix()
    override fun createOutline(
        size: Size,
        layoutDirection: LayoutDirection,
        density: Density
    ): Outline {
        // Below assumes that you haven't changed the default radius of 1f, nor the centerX and centerY of 0f
        // By default this stretches the path to the size of the container, if you don't want stretching, use the same size.width for both x and y.
        matrix.scale(size.width / 2f, size.height / 2f)
        matrix.translate(1f, 1f)

        val path = morph.toPath(progress = percentage).asComposePath()
        path.transform(matrix)
        return Outline.Generic(path)
    }
}

এই মর্ফ আকৃতি ব্যবহার করতে, দুটি বহুভুজ তৈরি করুন, shapeA এবং shapeBMorph তৈরি করুন এবং মনে রাখুন। তারপরে, অ্যানিমেশনের পিছনে চালিকা শক্তি হিসাবে প্রেসে interactionSource ব্যবহার করে ক্লিপ আউটলাইন হিসাবে বোতামে morph প্রয়োগ করুন:

val shapeA = remember {
    RoundedPolygon(
        6,
        rounding = CornerRounding(0.2f)
    )
}
val shapeB = remember {
    RoundedPolygon.star(
        6,
        rounding = CornerRounding(0.1f)
    )
}
val morph = remember {
    Morph(shapeA, shapeB)
}
val interactionSource = remember {
    MutableInteractionSource()
}
val isPressed by interactionSource.collectIsPressedAsState()
val animatedProgress = animateFloatAsState(
    targetValue = if (isPressed) 1f else 0f,
    label = "progress",
    animationSpec = spring(dampingRatio = 0.4f, stiffness = Spring.StiffnessMedium)
)
Box(
    modifier = Modifier
        .size(200.dp)
        .padding(8.dp)
        .clip(MorphPolygonShape(morph, animatedProgress.value))
        .background(Color(0xFF80DEEA))
        .size(200.dp)
        .clickable(interactionSource = interactionSource, indication = null) {
        }
) {
    Text("Hello", modifier = Modifier.align(Alignment.Center))
}

যখন বাক্সটি ট্যাপ করা হয় তখন এটি নিম্নলিখিত অ্যানিমেশনে পরিণত হয়:

দুটি আকারের মধ্যে একটি ক্লিক হিসাবে Morph প্রয়োগ করা হয়েছে
চিত্র 12 । দুটি আকারের মধ্যে একটি ক্লিক হিসাবে Morph প্রয়োগ করা হয়েছে।

অ্যানিমেট আকৃতি অসীম morphing

অন্তহীনভাবে একটি মর্ফ আকৃতি অ্যানিমেট করতে, rememberInfiniteTransition ব্যবহার করুন। নীচে একটি প্রোফাইল ছবির উদাহরণ দেওয়া হল যা সময়ের সাথে সাথে আকার পরিবর্তন করে (এবং ঘোরে)। এই পদ্ধতিটি উপরে দেখানো MorphPolygonShape এ একটি ছোট সমন্বয় ব্যবহার করে:

class CustomRotatingMorphShape(
    private val morph: Morph,
    private val percentage: Float,
    private val rotation: Float
) : Shape {

    private val matrix = Matrix()
    override fun createOutline(
        size: Size,
        layoutDirection: LayoutDirection,
        density: Density
    ): Outline {
        // Below assumes that you haven't changed the default radius of 1f, nor the centerX and centerY of 0f
        // By default this stretches the path to the size of the container, if you don't want stretching, use the same size.width for both x and y.
        matrix.scale(size.width / 2f, size.height / 2f)
        matrix.translate(1f, 1f)
        matrix.rotateZ(rotation)

        val path = morph.toPath(progress = percentage).asComposePath()
        path.transform(matrix)

        return Outline.Generic(path)
    }
}

@Preview
@Composable
private fun RotatingScallopedProfilePic() {
    val shapeA = remember {
        RoundedPolygon(
            12,
            rounding = CornerRounding(0.2f)
        )
    }
    val shapeB = remember {
        RoundedPolygon.star(
            12,
            rounding = CornerRounding(0.2f)
        )
    }
    val morph = remember {
        Morph(shapeA, shapeB)
    }
    val infiniteTransition = rememberInfiniteTransition("infinite outline movement")
    val animatedProgress = infiniteTransition.animateFloat(
        initialValue = 0f,
        targetValue = 1f,
        animationSpec = infiniteRepeatable(
            tween(2000, easing = LinearEasing),
            repeatMode = RepeatMode.Reverse
        ),
        label = "animatedMorphProgress"
    )
    val animatedRotation = infiniteTransition.animateFloat(
        initialValue = 0f,
        targetValue = 360f,
        animationSpec = infiniteRepeatable(
            tween(6000, easing = LinearEasing),
            repeatMode = RepeatMode.Reverse
        ),
        label = "animatedMorphProgress"
    )
    Box(
        modifier = Modifier.fillMaxSize(),
        contentAlignment = Alignment.Center
    ) {
        Image(
            painter = painterResource(id = R.drawable.dog),
            contentDescription = "Dog",
            contentScale = ContentScale.Crop,
            modifier = Modifier
                .clip(
                    CustomRotatingMorphShape(
                        morph,
                        animatedProgress.value,
                        animatedRotation.value
                    )
                )
                .size(200.dp)
        )
    }
}

এই কোড নিম্নলিখিত মজার ফলাফল দেয়:

হৃদয় আকৃতি
চিত্র 13 । একটি ঘূর্ণমান স্ক্যালপড আকৃতি দ্বারা ক্লিপ করা প্রোফাইল ছবি।

কাস্টম বহুভুজ

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

হৃদয় আকৃতি
চিত্র 14 । হৃদয় আকৃতি।

আপনি RoundedPolygon ওভারলোড ব্যবহার করে এই আকৃতির পৃথক শীর্ষবিন্দুগুলি নির্দিষ্ট করতে পারেন যা x, y স্থানাঙ্কের একটি ফ্লোট অ্যারে নেয়।

হৃৎপিণ্ডের বহুভুজকে ভেঙে ফেলার জন্য, লক্ষ্য করুন যে বিন্দু নির্দিষ্ট করার জন্য মেরু স্থানাঙ্ক ব্যবস্থা কার্টেসিয়ান (x,y) স্থানাঙ্ক ব্যবস্থা ব্যবহার করার চেয়ে এটিকে সহজ করে তোলে, যেখানে ডান দিকে শুরু হয় এবং ঘড়ির কাঁটার দিকে 270° দিয়ে এগিয়ে যায়। 12 টার অবস্থান:

হৃদয় আকৃতি
চিত্র 15 । স্থানাঙ্ক সহ হার্ট আকৃতি।

প্রতিটি বিন্দুতে কেন্দ্র থেকে কোণ (𝜭) এবং ব্যাসার্ধ নির্দিষ্ট করে আকৃতিটি এখন সহজ উপায়ে সংজ্ঞায়িত করা যেতে পারে:

হৃদয় আকৃতি
চিত্র 16 । বৃত্তাকার ছাড়া স্থানাঙ্ক সহ হার্টের আকৃতি।

শীর্ষবিন্দুগুলি এখন তৈরি করা যেতে পারে এবং RoundedPolygon ফাংশনে প্রেরণ করা যেতে পারে:

val vertices = remember {
    val radius = 1f
    val radiusSides = 0.8f
    val innerRadius = .1f
    floatArrayOf(
        radialToCartesian(radiusSides, 0f.toRadians()).x,
        radialToCartesian(radiusSides, 0f.toRadians()).y,
        radialToCartesian(radius, 90f.toRadians()).x,
        radialToCartesian(radius, 90f.toRadians()).y,
        radialToCartesian(radiusSides, 180f.toRadians()).x,
        radialToCartesian(radiusSides, 180f.toRadians()).y,
        radialToCartesian(radius, 250f.toRadians()).x,
        radialToCartesian(radius, 250f.toRadians()).y,
        radialToCartesian(innerRadius, 270f.toRadians()).x,
        radialToCartesian(innerRadius, 270f.toRadians()).y,
        radialToCartesian(radius, 290f.toRadians()).x,
        radialToCartesian(radius, 290f.toRadians()).y,
    )
}

এই radialToCartesian ফাংশন ব্যবহার করে শীর্ষবিন্দুগুলিকে কার্টেসিয়ান স্থানাঙ্কে অনুবাদ করতে হবে:

internal fun Float.toRadians() = this * PI.toFloat() / 180f

internal val PointZero = PointF(0f, 0f)
internal fun radialToCartesian(
    radius: Float,
    angleRadians: Float,
    center: PointF = PointZero
) = directionVectorPointF(angleRadians) * radius + center

internal fun directionVectorPointF(angleRadians: Float) =
    PointF(cos(angleRadians), sin(angleRadians))

পূর্ববর্তী কোডটি আপনাকে হৃদয়ের জন্য কাঁচা শীর্ষবিন্দু দেয়, তবে আপনাকে নির্বাচিত হার্টের আকৃতি পেতে নির্দিষ্ট কোণগুলিকে বৃত্তাকার করতে হবে। 90° এবং 270° কোণে কোন বৃত্তাকার নেই, কিন্তু অন্যান্য কোণে আছে। পৃথক কোণগুলির জন্য কাস্টম রাউন্ডিং অর্জন করতে, perVertexRounding প্যারামিটার ব্যবহার করুন:

val rounding = remember {
    val roundingNormal = 0.6f
    val roundingNone = 0f
    listOf(
        CornerRounding(roundingNormal),
        CornerRounding(roundingNone),
        CornerRounding(roundingNormal),
        CornerRounding(roundingNormal),
        CornerRounding(roundingNone),
        CornerRounding(roundingNormal),
    )
}

val polygon = remember(vertices, rounding) {
    RoundedPolygon(
        vertices = vertices,
        perVertexRounding = rounding
    )
}
Box(
    modifier = Modifier
        .drawWithCache {
            val roundedPolygonPath = polygon.toPath().asComposePath()
            onDrawBehind {
                scale(size.width * 0.5f, size.width * 0.5f) {
                    translate(size.width * 0.5f, size.height * 0.5f) {
                        drawPath(roundedPolygonPath, color = Color(0xFFF15087))
                    }
                }
            }
        }
        .size(400.dp)
)

এর ফলে গোলাপী হৃদয় হয়:

হৃদয় আকৃতি
চিত্র 17 । হার্ট আকৃতির ফলাফল।

যদি পূর্ববর্তী আকারগুলি আপনার ব্যবহারের ক্ষেত্রে কভার না করে, তবে একটি কাস্টম আকৃতি আঁকতে , বা ডিস্ক থেকে একটি ImageVector ফাইল লোড করতে Path ক্লাস ব্যবহার করার কথা বিবেচনা করুন। graphics-shapes লাইব্রেরিটি নির্বিচারে আকারের জন্য ব্যবহারের উদ্দেশ্যে নয়, তবে এটি বিশেষভাবে বৃত্তাকার বহুভুজ এবং তাদের মধ্যে morph অ্যানিমেশন তৈরিকে সহজ করার উদ্দেশ্যে।

অতিরিক্ত সম্পদ

আরও তথ্য এবং উদাহরণের জন্য, নিম্নলিখিত সংস্থানগুলি দেখুন: