রচনায় গ্রাফিক্স

অনেক অ্যাপের স্ক্রিনে ঠিক কী আঁকা হচ্ছে তা সঠিকভাবে নিয়ন্ত্রণ করতে সক্ষম হওয়া প্রয়োজন। এটি স্ক্রিনে সঠিক জায়গায় একটি বাক্স বা একটি বৃত্ত স্থাপন করার মতো ছোট হতে পারে, অথবা এটি বিভিন্ন স্টাইলে গ্রাফিক উপাদানগুলির একটি বিস্তৃত বিন্যাস হতে পারে।

মডিফায়ার এবং DrawScope সহ মৌলিক অঙ্কন

Compose-এ কাস্টম কিছু আঁকার মূল উপায় হল মডিফায়ার ব্যবহার করা, যেমন Modifier.drawWithContent , Modifier.drawBehind , এবং Modifier.drawWithCache

উদাহরণস্বরূপ, আপনার কম্পোজেবলের পিছনে কিছু আঁকতে, আপনি drawBehind মডিফায়ার ব্যবহার করে অঙ্কন কমান্ড কার্যকর করতে পারেন:

Spacer(
    modifier = Modifier
        .fillMaxSize()
        .drawBehind {
            // this = DrawScope
        }
)

যদি আপনার কেবল একটি কম্পোজেবলের প্রয়োজন হয় যা অঙ্কন করে, তাহলে আপনি Canvas কম্পোজেবল ব্যবহার করতে পারেন। Canvas কম্পোজেবল হল Modifier.drawBehind চারপাশে একটি সুবিধাজনক মোড়ক। আপনি আপনার লেআউটে Canvas একইভাবে রাখেন যেভাবে আপনি অন্য যেকোনো কম্পোজ UI উপাদানের সাথে করেন। Canvas মধ্যে, আপনি তাদের স্টাইল এবং অবস্থানের উপর সুনির্দিষ্ট নিয়ন্ত্রণ সহ উপাদানগুলি আঁকতে পারেন।

সকল অঙ্কন সংশোধক একটি DrawScope প্রকাশ করে, একটি স্কোপড অঙ্কন পরিবেশ যা তার নিজস্ব অবস্থা বজায় রাখে। এটি আপনাকে গ্রাফিকাল উপাদানগুলির একটি গ্রুপের জন্য প্যারামিটার সেট করতে দেয়। DrawScope বেশ কয়েকটি দরকারী ক্ষেত্র প্রদান করে, যেমন size , একটি Size অবজেক্ট যা DrawScope এর বর্তমান মাত্রা নির্দিষ্ট করে।

কিছু আঁকতে, আপনি DrawScope এর অনেকগুলি draw ফাংশনের একটি ব্যবহার করতে পারেন। উদাহরণস্বরূপ, নিম্নলিখিত কোডটি স্ক্রিনের উপরের বাম কোণে একটি আয়তক্ষেত্র আঁকে:

Canvas(modifier = Modifier.fillMaxSize()) {
    val canvasQuadrantSize = size / 2F
    drawRect(
        color = Color.Magenta,
        size = canvasQuadrantSize
    )
}

সাদা পটভূমিতে আঁকা গোলাপী আয়তক্ষেত্র যা স্ক্রিনের এক চতুর্থাংশ দখল করে।
চিত্র ১। কম্পোজে ক্যানভাস ব্যবহার করে আয়তক্ষেত্র আঁকা।

বিভিন্ন অঙ্কন সংশোধক সম্পর্কে আরও জানতে, গ্রাফিক্স সংশোধক ডকুমেন্টেশন দেখুন।

স্থানাঙ্ক ব্যবস্থা

স্ক্রিনে কিছু আঁকতে হলে, আপনার আইটেমের অফসেট ( x এবং y ) এবং আকার জানতে হবে। DrawScope এর অনেক ড্র পদ্ধতিতে, অবস্থান এবং আকার ডিফল্ট প্যারামিটার মান দ্বারা প্রদান করা হয়। ডিফল্ট প্যারামিটারগুলি সাধারণত ক্যানভাসের [0, 0] বিন্দুতে আইটেমটিকে স্থাপন করে এবং একটি ডিফল্ট size প্রদান করে যা পুরো অঙ্কন এলাকাটি পূরণ করে, যেমন উপরের উদাহরণে - আপনি দেখতে পাচ্ছেন যে আয়তক্ষেত্রটি উপরের বাম দিকে অবস্থিত। আপনার আইটেমের আকার এবং অবস্থান সামঞ্জস্য করতে, আপনাকে Compose-এর স্থানাঙ্ক সিস্টেমটি বুঝতে হবে।

স্থানাঙ্ক ব্যবস্থার উৎপত্তি ( [0,0] ) অঙ্কন ক্ষেত্রের উপরের বাম দিকের পিক্সেলটিতে। ডানদিকে সরানোর সাথে সাথে x বৃদ্ধি পায় এবং নীচের দিকে সরানোর সাথে সাথে y বৃদ্ধি পায়।

একটি গ্রিড যেখানে স্থানাঙ্ক ব্যবস্থা দেখানো হচ্ছে যা উপরের বাম দিকে [0, 0] এবং নীচে ডান দিকে [প্রস্থ, উচ্চতা] দেখাচ্ছে।
চিত্র ২। অঙ্কন স্থানাঙ্ক ব্যবস্থা / অঙ্কন গ্রিড।

উদাহরণস্বরূপ, যদি আপনি ক্যানভাস এলাকার উপরের-ডান কোণ থেকে নীচে-বাম কোণে একটি তির্যক রেখা আঁকতে চান, তাহলে আপনি DrawScope.drawLine() ফাংশন ব্যবহার করতে পারেন এবং সংশ্লিষ্ট x এবং y অবস্থানের সাথে একটি শুরু এবং শেষ অফসেট নির্দিষ্ট করতে পারেন:

Canvas(modifier = Modifier.fillMaxSize()) {
    val canvasWidth = size.width
    val canvasHeight = size.height
    drawLine(
        start = Offset(x = canvasWidth, y = 0f),
        end = Offset(x = 0f, y = canvasHeight),
        color = Color.Blue
    )
}

মৌলিক রূপান্তর

ড্রয়িং কমান্ডগুলি কোথায় বা কীভাবে কার্যকর করা হয় তা পরিবর্তন করার জন্য DrawScope রূপান্তর অফার করে।

স্কেল

আপনার অঙ্কন ক্রিয়াকলাপের আকার একটি ফ্যাক্টর দ্বারা বাড়াতে DrawScope.scale() ব্যবহার করুন। scale() মতো ক্রিয়াকলাপগুলি সংশ্লিষ্ট ল্যাম্বডার মধ্যে সমস্ত অঙ্কন ক্রিয়াকলাপের ক্ষেত্রে প্রযোজ্য। উদাহরণস্বরূপ, নিম্নলিখিত কোডটি scaleX 10 গুণ এবং scaleY 15 গুণ বৃদ্ধি করে:

Canvas(modifier = Modifier.fillMaxSize()) {
    scale(scaleX = 10f, scaleY = 15f) {
        drawCircle(Color.Blue, radius = 20.dp.toPx())
    }
}

একটি বৃত্ত অসমভাবে স্কেল করা হয়েছে
চিত্র ৩. ক্যানভাসের একটি বৃত্তে স্কেল অপারেশন প্রয়োগ করা।

অনুবাদ করুন

আপনার অঙ্কন ক্রিয়াকলাপগুলিকে উপরে, নীচে, বামে বা ডানে সরাতে DrawScope.translate() ব্যবহার করুন। উদাহরণস্বরূপ, নিম্নলিখিত কোডটি অঙ্কনটিকে 100 px ডানে এবং 300 px উপরে সরায়:

Canvas(modifier = Modifier.fillMaxSize()) {
    translate(left = 100f, top = -300f) {
        drawCircle(Color.Blue, radius = 200.dp.toPx())
    }
}

কেন্দ্র থেকে সরে যাওয়া একটি বৃত্ত
চিত্র ৪. ক্যানভাসের একটি বৃত্তে একটি অনুবাদ অপারেশন প্রয়োগ করা হচ্ছে।

ঘোরান

একটি পিভট পয়েন্টের চারপাশে আপনার অঙ্কন ক্রিয়াকলাপ ঘোরানোর জন্য DrawScope.rotate() ব্যবহার করুন। উদাহরণস্বরূপ, নিম্নলিখিত কোডটি একটি আয়তক্ষেত্রকে 45 ডিগ্রি ঘোরায়:

Canvas(modifier = Modifier.fillMaxSize()) {
    rotate(degrees = 45F) {
        drawRect(
            color = Color.Gray,
            topLeft = Offset(x = size.width / 3F, y = size.height / 3F),
            size = size / 3F
        )
    }
}

স্ক্রিনের মাঝখানে ৪৫ ডিগ্রি ঘোরানো একটি আয়তক্ষেত্রাকার ফোন
চিত্র ৫। আমরা বর্তমান অঙ্কন স্কোপে ঘূর্ণন প্রয়োগ করতে rotate() ব্যবহার করি, যা আয়তক্ষেত্রটিকে ৪৫ ডিগ্রি ঘোরায়।

ইনসেট

বর্তমান DrawScope এর ডিফল্ট প্যারামিটারগুলি সামঞ্জস্য করতে, অঙ্কনের সীমানা পরিবর্তন করতে এবং সেই অনুযায়ী অঙ্কনগুলি অনুবাদ করতে DrawScope.inset() ব্যবহার করুন:

Canvas(modifier = Modifier.fillMaxSize()) {
    val canvasQuadrantSize = size / 2F
    inset(horizontal = 50f, vertical = 30f) {
        drawRect(color = Color.Green, size = canvasQuadrantSize)
    }
}

এই কোডটি কার্যকরভাবে অঙ্কন কমান্ডগুলিতে প্যাডিং যোগ করে:

একটি আয়তক্ষেত্র যা এর চারপাশে প্যাড করা হয়েছে
চিত্র 6. অঙ্কন কমান্ডগুলিতে একটি ইনসেট প্রয়োগ করা।

একাধিক রূপান্তর

আপনার অঙ্কনে একাধিক রূপান্তর প্রয়োগ করতে, DrawScope.withTransform() ফাংশনটি ব্যবহার করুন, যা আপনার সমস্ত পছন্দসই পরিবর্তনগুলিকে একত্রিত করে একটি একক রূপান্তর তৈরি করে এবং প্রয়োগ করে। withTransform() ব্যবহার করা পৃথক রূপান্তরগুলিতে নেস্টেড কল করার চেয়ে বেশি কার্যকর, কারণ সমস্ত রূপান্তরগুলি একক অপারেশনে একসাথে সম্পাদিত হয়, কম্পোজের পরিবর্তে প্রতিটি নেস্টেড রূপান্তর গণনা এবং সংরক্ষণ করার প্রয়োজন হয়।

উদাহরণস্বরূপ, নিম্নলিখিত কোডটি আয়তক্ষেত্রে অনুবাদ এবং ঘূর্ণন উভয়ই প্রয়োগ করে:

Canvas(modifier = Modifier.fillMaxSize()) {
    withTransform({
        translate(left = size.width / 5F)
        rotate(degrees = 45F)
    }) {
        drawRect(
            color = Color.Gray,
            topLeft = Offset(x = size.width / 3F, y = size.height / 3F),
            size = size / 3F
        )
    }
}

স্ক্রিনের পাশে ঘোরানো আয়তক্ষেত্রাকার একটি ফোন স্থানান্তরিত হয়েছে
চিত্র ৭। আয়তক্ষেত্রটি ঘোরানো এবং বাম দিকে স্থানান্তরিত করে ঘূর্ণন এবং অনুবাদ উভয়ই প্রয়োগ করতে withTransform ব্যবহার করুন।

সাধারণ অঙ্কন ক্রিয়াকলাপ

টেক্সট আঁকুন

Compose-এ টেক্সট আঁকতে, আপনি সাধারণত Text composable ব্যবহার করতে পারেন। তবে, যদি আপনি DrawScope এ থাকেন অথবা আপনি কাস্টমাইজেশনের মাধ্যমে ম্যানুয়ালি আপনার টেক্সট আঁকতে চান, তাহলে আপনি DrawScope.drawText() পদ্ধতি ব্যবহার করতে পারেন।

টেক্সট আঁকতে, rememberTextMeasurer ব্যবহার করে একটি TextMeasurer তৈরি করুন এবং পরিমাপক দিয়ে drawText কল করুন:

val textMeasurer = rememberTextMeasurer()

Canvas(modifier = Modifier.fillMaxSize()) {
    drawText(textMeasurer, "Hello")
}

ক্যানভাসে আঁকা একটি হ্যালো দেখানো হচ্ছে
চিত্র ৮। ক্যানভাসে লেখা আঁকা।

টেক্সট পরিমাপ করুন

ড্রয়িং টেক্সট অন্যান্য ড্রয়িং কমান্ড থেকে একটু আলাদাভাবে কাজ করে। সাধারণত, আপনি ড্রয়িং কমান্ডকে আকৃতি/ছবি আঁকার জন্য আকার (প্রস্থ এবং উচ্চতা) দেন। টেক্সটের ক্ষেত্রে, কিছু প্যারামিটার রয়েছে যা রেন্ডার করা টেক্সটের আকার নিয়ন্ত্রণ করে, যেমন ফন্ট সাইজ, ফন্ট, লিগ্যাচার এবং অক্ষরের ব্যবধান।

কম্পোজের সাহায্যে, আপনি উপরের বিষয়গুলির উপর নির্ভর করে টেক্সটের পরিমাপিত আকারে অ্যাক্সেস পেতে একটি TextMeasurer ব্যবহার করতে পারেন। যদি আপনি টেক্সটের পিছনে একটি পটভূমি আঁকতে চান, তাহলে আপনি টেক্সটটি যে জায়গাটি দখল করে তার আকার পেতে পরিমাপিত তথ্য ব্যবহার করতে পারেন:

val textMeasurer = rememberTextMeasurer()

Spacer(
    modifier = Modifier
        .drawWithCache {
            val measuredText =
                textMeasurer.measure(
                    AnnotatedString(longTextSample),
                    constraints = Constraints.fixedWidth((size.width * 2f / 3f).toInt()),
                    style = TextStyle(fontSize = 18.sp)
                )

            onDrawBehind {
                drawRect(pinkColor, size = measuredText.size.toSize())
                drawText(measuredText)
            }
        }
        .fillMaxSize()
)

এই কোড স্নিপেটটি টেক্সটের উপর একটি গোলাপী পটভূমি তৈরি করে:

একাধিক লাইনের লেখা পুরো এলাকার ⅔ অংশ দখল করে, পটভূমিতে একটি আয়তক্ষেত্র রয়েছে
চিত্র ৯। একাধিক লাইনের লেখা পুরো এলাকার ⅔ অংশ দখল করে, একটি পটভূমি আয়তক্ষেত্র সহ।

সীমাবদ্ধতা, ফন্টের আকার, অথবা পরিমাপ করা আকারকে প্রভাবিত করে এমন যেকোনো বৈশিষ্ট্য সামঞ্জস্য করলে একটি নতুন আকার রিপোর্ট করা হয়। আপনি width এবং height উভয়ের জন্য একটি নির্দিষ্ট আকার সেট করতে পারেন, এবং টেক্সটটি তারপর সেট TextOverflow অনুসরণ করে। উদাহরণস্বরূপ, নিম্নলিখিত কোডটি কম্পোজেবল এলাকার উচ্চতার ⅓ এবং প্রস্থের ⅓ অংশে টেক্সট রেন্ডার করে এবং TextOverflow কে TextOverflow.Ellipsis এ সেট করে:

val textMeasurer = rememberTextMeasurer()

Spacer(
    modifier = Modifier
        .drawWithCache {
            val measuredText =
                textMeasurer.measure(
                    AnnotatedString(longTextSample),
                    constraints = Constraints.fixed(
                        width = (size.width / 3f).toInt(),
                        height = (size.height / 3f).toInt()
                    ),
                    overflow = TextOverflow.Ellipsis,
                    style = TextStyle(fontSize = 18.sp)
                )

            onDrawBehind {
                drawRect(pinkColor, size = measuredText.size.toSize())
                drawText(measuredText)
            }
        }
        .fillMaxSize()
)

লেখাটি এখন সীমাবদ্ধতার মধ্যে আঁকা হয়েছে এবং শেষে একটি উপবৃত্ত রয়েছে:

গোলাপী পটভূমিতে লেখাটি আঁকা হয়েছে, উপবৃত্তাকারে লেখাটি কেটে ফেলা হয়েছে।
চিত্র ১০। TextOverflow.Ellipsis টেক্সট পরিমাপের ক্ষেত্রে নির্দিষ্ট সীমাবদ্ধতা সহ উপবৃত্ত।

ছবি আঁকুন

DrawScope ব্যবহার করে একটি ImageBitmap আঁকতে, ImageBitmap.imageResource() ব্যবহার করে ছবিটি লোড করুন এবং তারপর drawImage কল করুন:

val dogImage = ImageBitmap.imageResource(id = R.drawable.dog)

Canvas(modifier = Modifier.fillMaxSize(), onDraw = {
    drawImage(dogImage)
})

ক্যানভাসে আঁকা একটি কুকুরের ছবি
চিত্র ১১। ক্যানভাসে একটি ImageBitmap আঁকা।

মৌলিক আকার আঁকুন

DrawScope তে অনেকগুলি আকৃতি অঙ্কন ফাংশন রয়েছে। একটি আকৃতি আঁকতে, পূর্বনির্ধারিত draw ফাংশনগুলির মধ্যে একটি ব্যবহার করুন, যেমন drawCircle :

val purpleColor = Color(0xFFBA68C8)
Canvas(
    modifier = Modifier
        .fillMaxSize()
        .padding(16.dp),
    onDraw = {
        drawCircle(purpleColor)
    }
)

এপিআই

আউটপুট

drawCircle()

বৃত্ত আঁকুন

drawRect()

সোজা আঁকুন

drawRoundedRect()

গোলাকার আয়তক্ষেত্র আঁকুন

drawLine()

রেখা আঁকুন

drawOval()

ডিম্বাকৃতি আঁকুন

drawArc()

চাপ আঁকুন

drawPoints()

পয়েন্ট আঁকুন

পথ আঁকুন

পাথ হলো গাণিতিক নির্দেশাবলীর একটি সিরিজ যা একবার কার্যকর করার পরে একটি অঙ্কন তৈরি করে। DrawScope DrawScope.drawPath() পদ্ধতি ব্যবহার করে একটি পাথ আঁকতে পারে।

উদাহরণস্বরূপ, ধরুন আপনি একটি ত্রিভুজ আঁকতে চেয়েছিলেন। আপনি অঙ্কন এলাকার আকার ব্যবহার করে lineTo() এবং moveTo() এর মতো ফাংশন ব্যবহার করে একটি পাথ তৈরি করতে পারেন। তারপর, একটি ত্রিভুজ পেতে এই নতুন তৈরি পাথ দিয়ে drawPath() কল করুন।

Spacer(
    modifier = Modifier
        .drawWithCache {
            val path = Path()
            path.moveTo(0f, 0f)
            path.lineTo(size.width / 2f, size.height / 2f)
            path.lineTo(size.width, 0f)
            path.close()
            onDrawBehind {
                drawPath(path, Color.Magenta, style = Stroke(width = 10f))
            }
        }
        .fillMaxSize()
)

কম্পোজে আঁকা একটি উল্টো বেগুনি পথের ত্রিভুজ
চিত্র ১২। কম্পোজে একটি Path তৈরি এবং অঙ্কন করা।

Canvas অবজেক্ট অ্যাক্সেস করা হচ্ছে

DrawScope ব্যবহার করে, আপনার সরাসরি Canvas অবজেক্টে অ্যাক্সেস নেই। আপনি DrawScope.drawIntoCanvas() ব্যবহার করে Canvas অবজেক্টে অ্যাক্সেস পেতে পারেন যেখানে আপনি ফাংশন কল করতে পারেন।

উদাহরণস্বরূপ, যদি আপনার কাছে একটি কাস্টম Drawable থাকে যা আপনি ক্যানভাসে আঁকতে চান, তাহলে আপনি ক্যানভাস অ্যাক্সেস করতে পারেন এবং Canvas অবজেক্টটি পাস করে Drawable#draw() কল করতে পারেন:

val drawable = ShapeDrawable(OvalShape())
Spacer(
    modifier = Modifier
        .drawWithContent {
            drawIntoCanvas { canvas ->
                drawable.setBounds(0, 0, size.width.toInt(), size.height.toInt())
                drawable.draw(canvas.nativeCanvas)
            }
        }
        .fillMaxSize()
)

একটি ডিম্বাকৃতি কালো আকৃতির, পূর্ণ আকার ধারণ করছে, যা অঙ্কনযোগ্য।
চিত্র ১৩। একটি Drawable আঁকতে ক্যানভাস অ্যাক্সেস করা।

আরও জানুন

কম্পোজে অঙ্কন সম্পর্কে আরও তথ্যের জন্য, নিম্নলিখিত সংস্থানগুলি দেখুন:

{% অক্ষরে অক্ষরে %} {% এন্ডভারব্যাটিম %} {% অক্ষরে অক্ষরে %} {% এন্ডভারব্যাটিম %}