এতে স্বচ্ছ ছিদ্রযুক্ত ক্যালায়ার


112

আমার একটি সাধারণ ভিউ (ছবির বাম দিক) আছে এবং এই ভিউটিতে আমার একধরণের ওভারলে (ছবির ডান দিক) তৈরি করতে হবে। এই ওভারলেটির কিছুটা অস্বচ্ছতা থাকা উচিত, সুতরাং দৃশ্যটি বেলো এটি এখনও আংশিকভাবে দৃশ্যমান। সর্বাধিক গুরুত্বপূর্ণ এই ওভারলেটির মাঝখানে একটি বৃত্তাকার ছিদ্র থাকা উচিত যাতে এটি দৃশ্যটির কেন্দ্রস্থলে আবৃত হয় না (চিত্রের নমুনা দেখুন)।

আমি সহজেই এর মতো একটি বৃত্ত তৈরি করতে পারি:

int radius = 20; //whatever
CAShapeLayer *circle = [CAShapeLayer layer];

circle.path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0,radius,radius) cornerRadius:radius].CGPath;
circle.position = CGPointMake(CGRectGetMidX(view.frame)-radius,
                              CGRectGetMidY(view.frame)-radius);
circle.fillColor = [UIColor clearColor].CGColor;

এবং এর মতো একটি "পূর্ণ" আয়তক্ষেত্রাকার ওভারলে:

CAShapeLayer *shadow = [CAShapeLayer layer];
shadow.path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, view.bounds.size.width, view.bounds.size.height) cornerRadius:0].CGPath;
shadow.position = CGPointMake(0, 0);
shadow.fillColor = [UIColor grayColor].CGColor;
shadow.lineWidth = 0;
shadow.opacity = 0.5;
[view.layer addSublayer:shadow];

তবে আমি কী জানি না যে আমি কীভাবে এই দুটি স্তরকে একত্রিত করতে পারি যাতে তারা আমার পছন্দসই প্রভাব তৈরি করে। যে কেউ? আমি সত্যিই সব চেষ্টা করেছি ... সাহায্যের জন্য অনেক ধন্যবাদ!

ভাবমূর্তি


আপনি কি এমন একটি বেজিয়ার তৈরি করতে পারেন যার মধ্যে রেকট এবং বৃত্ত রয়েছে এবং তারপরে অঙ্কনের সময় ব্যবহৃত ঘুরানো নিয়ম একটি গর্ত তৈরি করবে (আমি এটি চেষ্টা করি নি)।
ঋক্ষমণ্ডল

আমি জানি না কীভাবে এটি করতে হবে :)
প্রাণী_চিন

রেক্টট দিয়ে তৈরি করুন, তারপরে moveToPoint, পরে বৃত্তাকার রেট যুক্ত করুন। প্রদত্ত পদ্ধতিগুলির জন্য দস্তাবেজগুলি পরীক্ষা করুন UIBezierPath
ঋক্ষমণ্ডল

দেখুন এই যদি অনুরূপ প্রশ্ন ও উত্তর সাহায্যের: [UIView কাটা স্বচ্ছ গর্ত] [1] [1]: stackoverflow.com/questions/9711248/...
dichen

এখানে আমার সমাধান পরীক্ষা করে দেখুন: stackoverflow.com/questions/14141081/... আশা রাখি, এটা কারো সাহায্যে
জেমস Laurenstin

উত্তর:


218

জন স্টেইনমেটজের পরামর্শ নিয়ে আমি এটি সমাধান করতে সক্ষম হয়েছি। কারও যদি চিন্তা থাকে তবে চূড়ান্ত সমাধানটি এখানে:

int radius = myRect.size.width;
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, self.mapView.bounds.size.width, self.mapView.bounds.size.height) cornerRadius:0];
UIBezierPath *circlePath = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, 2.0*radius, 2.0*radius) cornerRadius:radius];
[path appendPath:circlePath];
[path setUsesEvenOddFillRule:YES];

CAShapeLayer *fillLayer = [CAShapeLayer layer];
fillLayer.path = path.CGPath;
fillLayer.fillRule = kCAFillRuleEvenOdd;
fillLayer.fillColor = [UIColor grayColor].CGColor;
fillLayer.opacity = 0.5;
[view.layer addSublayer:fillLayer];

সুইফট 3.x:

let radius = myRect.size.width
let path = UIBezierPath(roundedRect: CGRect(x: 0, y: 0, width: self.mapView.bounds.size.width, height: self.mapView.bounds.size.height), cornerRadius: 0)
let circlePath = UIBezierPath(roundedRect: CGRect(x: 0, y: 0, width: 2 * radius, height: 2 * radius), cornerRadius: radius)
path.append(circlePath)
path.usesEvenOddFillRule = true

let fillLayer = CAShapeLayer()
fillLayer.path = path.cgPath
fillLayer.fillRule = kCAFillRuleEvenOdd
fillLayer.fillColor = Color.background.cgColor
fillLayer.opacity = 0.5
view.layer.addSublayer(fillLayer)

সুইফট 4.2 এবং 5:

let radius: CGFloat = myRect.size.width
let path = UIBezierPath(roundedRect: CGRect(x: 0, y: 0, width: self.view.bounds.size.width, height: self.view.bounds.size.height), cornerRadius: 0)
let circlePath = UIBezierPath(roundedRect: CGRect(x: 0, y: 0, width: 2 * radius, height: 2 * radius), cornerRadius: radius)
path.append(circlePath)
path.usesEvenOddFillRule = true

let fillLayer = CAShapeLayer()
fillLayer.path = path.cgPath
fillLayer.fillRule = .evenOdd
fillLayer.fillColor = view.backgroundColor?.cgColor
fillLayer.opacity = 0.5
view.layer.addSublayer(fillLayer)

2
যুক্ত নমনীয়তার জন্য আপনার ভিউ সাবক্লাসকে "আইবি ডিজাইনেবল" করুন। এটা সত্যিই সহজ! : শুরু করার জন্য, উত্তর আমি এই প্রশ্নের দিলেন মধ্যে উপরের কোড চলা stackoverflow.com/questions/14141081/...
clozach

2
একজন শিক্ষানবিস আইওএস বিকাশকারী হিসাবে আমি কয়েক ঘন্টা ব্যয় করার চেষ্টা করেছি, কেন এই কোডটি উদ্ভট ফলাফল দেয়। পরিশেষে আমি দেখতে পেলাম যে ওভারলে মাস্কটি কোনও পর্যায়ে পুনরায় গণনা করা হলে যোগ করা সাবলেয়ারগুলি অবশ্যই অপসারণ করতে হবে। View.layer.sublayers সম্পত্তি মাধ্যমে এটি সম্ভব। উত্তরের জন্য আপনাকে অনেক ধন্যবাদ!
সার্জাস

আমি কেন এর ঠিক বিপরীতে পাচ্ছি। কালো আধা স্বচ্ছ আকারযুক্ত রঙিন স্তর ??
চঞ্চল ওয়ার্ড

এই মোডটি ব্যবহার করে আমি কীভাবে একটি বৃত্তে স্বচ্ছ পাঠ্য যুক্ত করতে পারি, সম্ভব? আমি কীভাবে তা খুঁজে পাচ্ছি না
দিয়েগো ফার্নান্দো মুরিলো ভ্যালেনসি

প্রায় years বছর, এখনও সহায়তা করে তবে মনে রাখবেন যে ফাঁপা গর্তটি যে স্তরটিকে ধারণ করে এটি সত্যিই 'ঘুষি মারে' না। বলুন, যদি কোনও বোতামের উপর দিয়ে গর্তটি ওভারলে করুন। বোতামটি অ্যাক্সেসযোগ্য নয়, যা আপনি যদি আমার মতো 'গাইডেড টিউটোরিয়াল' তৈরি করার চেষ্টা করছেন তবে এটির প্রয়োজন। @ নিক ইয়্যাপের সরবরাহিত লাইব্রেরিটি আপনার পক্ষে কাজ করবে, যেখানে ফানক পয়েন্টটি (ওভার পয়েন্ট: সিজিপিয়েন্ট, ইভেন্ট সহ: ইউআইইভেন্ট?) -> ইউআইভিউয়ের বুল। R আরও তথ্যের জন্য তাঁর গ্রন্থাগারটি দেখুন। তবে, আপনি যা প্রত্যাশা করছেন তা কেবল 'মুখোশের পিছনে যা রয়েছে তার কাছে দৃশ্যমানতা', এটি একটি বৈধ উত্তর।
অনন্ত_কোডিং

32

এই প্রভাবটি তৈরি করতে, আমি পর্দার ওভারলেল করে একটি সম্পূর্ণ ভিউ তৈরি করা সহজ এবং তারপরে স্তরগুলি এবং ইউআইবিজেয়ারপথগুলি ব্যবহার করে পর্দার অংশগুলি বিয়োগ করে found একটি সুইফ্ট বাস্তবায়নের জন্য:

// Create a view filling the screen.
let overlay = UIView(frame: CGRectMake(0, 0, 
    UIScreen.mainScreen().bounds.width,
    UIScreen.mainScreen().bounds.height))

// Set a semi-transparent, black background.
overlay.backgroundColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.85)

// Create the initial layer from the view bounds.
let maskLayer = CAShapeLayer()
maskLayer.frame = overlay.bounds
maskLayer.fillColor = UIColor.blackColor().CGColor

// Create the frame for the circle.
let radius: CGFloat = 50.0
let rect = CGRectMake(
        CGRectGetMidX(overlay.frame) - radius,
        CGRectGetMidY(overlay.frame) - radius,
        2 * radius,
        2 * radius)

// Create the path.
let path = UIBezierPath(rect: overlay.bounds)
maskLayer.fillRule = kCAFillRuleEvenOdd

// Append the circle to the path so that it is subtracted.
path.appendPath(UIBezierPath(ovalInRect: rect))
maskLayer.path = path.CGPath

// Set the mask of the view.
overlay.layer.mask = maskLayer

// Add the view so it is visible.
self.view.addSubview(overlay)

আমি উপরের কোডটি পরীক্ষা করেছি, এবং ফলাফল এখানে:

এখানে চিত্র বর্ণনা লিখুন

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

টিএওভারলে ভিউ ব্যবহার করে টিউটোরিয়াল

লাইব্রেরিকে টিএওভারলেভিউ বলা হয় এবং এটি অ্যাপাচি ২.০ এর অধীনে উন্মুক্ত উত্স। আশা করি এটি আপনার কাজে লাগবে!


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

1
@ মোগসদাদ আমি স্প্যামি হিসাবে উপস্থিত হতে চাইনি, আমি এই লাইব্রেরিতে খুব ভাল সময় ব্যয় করেছি এবং আমি অনুভব করেছি যে এটি অনুরূপ কাজ করার চেষ্টা করা লোকদের পক্ষে দরকারী হবে। তবে প্রতিক্রিয়ার জন্য ধন্যবাদ, আমি কোড উদাহরণগুলি ব্যবহার করার জন্য আমার উত্তরগুলি আপডেট করব
নিক ইয়াপ

3
ভাল আপডেট, নিক। আমি আপনার কোণে - আমি প্রকাশিত গ্রন্থাগার এবং ইউটিলিটিগুলি নিজেই পেয়েছি এবং আমি বুঝতে পেরেছি যে আমার ডকুমেন্টেশনটি ইতিমধ্যে এটি কভার করলে সম্পূর্ণ উত্তর এখানে দেওয়া অপ্রয়োজনীয় মনে হতে পারে ... তবে ধারণাটি উত্তরগুলি স্ব-অন্তর্ভুক্ত হিসাবে রাখা উচিত যতটুকু সম্ভব. এবং এমন কিছু লোক রয়েছে যা স্প্যাম ব্যতীত আর কিছু পোস্ট করে না, তাই আমি তাদের সাথে লম্পট না হই। আমি ধরে নিয়েছি আপনি একই মনের, সে কারণেই আমি এটি আপনাকে দেখিয়েছি। চিয়ার্স!
মোগসদাদ

আপনার তৈরি পড আমি ব্যবহার করেছি, এর জন্য ধন্যবাদ। তবে ওভারলে এর নীচে আমার মতামত মিথস্ক্রিয়া বন্ধ করে। এতে কী ভুল? এর ভিতরে চিত্রদর্শন সহ আমার একটি স্ক্রোলভিউ রয়েছে।
আম্মার মুজিব

@ আম্মারমুজিব ওভারলে আপনার তৈরি করা "গর্ত" বাদে মিথস্ক্রিয়াটিকে বাধা দেয়। শুঁটির সাথে আমার উদ্দেশ্য হ'ল ওভারলেগুলি যা স্ক্রিনের অংশগুলি হাইলাইট করে এবং কেবল আপনাকে হাইলাইট করা উপাদানগুলির সাথে ইন্টারঅ্যাক্ট করার অনুমতি দেয়।
নিক ইয়াপ

11

স্বীকৃত সমাধান সুইফট 3.0 সামঞ্জস্যপূর্ণ

let radius = myRect.size.width
let path = UIBezierPath(roundedRect: CGRect(x: 0.0, y: 0.0, width: self.mapView.bounds.size.width, height: self.mapView.bounds.size.height), cornerRadius: 0)
let circlePath = UIBezierPath(roundedRect: CGRect(x: 0.0, y: 0.0, width: 2.0*radius, height: 2.0*radius), cornerRadius: radius)
path.append(circlePath)
path.usesEvenOddFillRule = true

let fillLayer = CAShapeLayer()
fillLayer.path = path.cgPath
fillLayer.fillRule = kCAFillRuleEvenOdd
fillLayer.fillColor = UIColor.gray.cgColor
fillLayer.opacity = 0.5
view.layer.addSublayer(fillLayer)

@ ফ্যাটি: আপনার লিঙ্কটি মারা গেছে
র্যান্ডি

10

আমি অ্যানিম্যাল_চিন হিসাবে অনুরূপ পন্থা নিয়েছি, তবে আমি আরও ভিজ্যুয়াল, তাই আমি এর বেশিরভাগ আউটলেট এবং অটো লেআউট ব্যবহার করে ইন্টারফেস বিল্ডারে সেট আপ করেছি।

সুইফটে আমার সমাধানটি এখানে

    //shadowView is a UIView of what I want to be "solid"
    var outerPath = UIBezierPath(rect: shadowView.frame)

    //croppingView is a subview of shadowView that is laid out in interface builder using auto layout
    //croppingView is hidden.
    var circlePath = UIBezierPath(ovalInRect: croppingView.frame)
    outerPath.usesEvenOddFillRule = true
    outerPath.appendPath(circlePath)

    var maskLayer = CAShapeLayer()
    maskLayer.path = outerPath.CGPath
    maskLayer.fillRule = kCAFillRuleEvenOdd
    maskLayer.fillColor = UIColor.whiteColor().CGColor

    shadowView.layer.mask = maskLayer

আমি এই সমাধানটি পছন্দ করি কারণ আপনি সার্কেলপথটিকে ডিজাইনের সময় ঘুরিয়ে নিতে পারেন এবং সময় খুব সহজে চালাতে পারেন।
মার্ক মোয়েকেন্স

এটি আমার পক্ষে কার্যকর হয়নি, যদিও আমি এটি ডিম্বাকৃতির পরিবর্তে একটি সাধারণ রেকট ব্যবহার করার জন্য এটি পরিবর্তন করেছি তবে চূড়ান্ত মুখোশটির চিত্রটি
ভুলই প্রকাশ পাচ্ছে

7

কোড সুইফট 2.0 সামঞ্জস্যপূর্ণ

@Animal_inch উত্তর থেকে শুরু করে, আমি কিছুটা ইউটিলিটি-শ্রেণি কোড করি, আশা করি এটি প্রশংসা করবে:

import Foundation
import UIKit
import CoreGraphics

/// Apply a circle mask on a target view. You can customize radius, color and opacity of the mask.
class CircleMaskView {

    private var fillLayer = CAShapeLayer()
    var target: UIView?

    var fillColor: UIColor = UIColor.grayColor() {
        didSet {
            self.fillLayer.fillColor = self.fillColor.CGColor
        }
    }

    var radius: CGFloat? {
        didSet {
            self.draw()
        }
    }

    var opacity: Float = 0.5 {
        didSet {
           self.fillLayer.opacity = self.opacity
        }
    }

    /**
    Constructor

    - parameter drawIn: target view

    - returns: object instance
    */
    init(drawIn: UIView) {
        self.target = drawIn
    }

    /**
    Draw a circle mask on target view
    */
    func draw() {
        guard (let target = target) else {
            print("target is nil")
            return
        }

        var rad: CGFloat = 0
        let size = target.frame.size
        if let r = self.radius {
            rad = r
        } else {
            rad = min(size.height, size.width)
        }

        let path = UIBezierPath(roundedRect: CGRectMake(0, 0, size.width, size.height), cornerRadius: 0.0)
        let circlePath = UIBezierPath(roundedRect: CGRectMake(size.width / 2.0 - rad / 2.0, 0, rad, rad), cornerRadius: rad)
        path.appendPath(circlePath)
        path.usesEvenOddFillRule = true

        fillLayer.path = path.CGPath
        fillLayer.fillRule = kCAFillRuleEvenOdd
        fillLayer.fillColor = self.fillColor.CGColor
        fillLayer.opacity = self.opacity
        self.target.layer.addSublayer(fillLayer)
    }

    /**
    Remove circle mask
    */


  func remove() {
        self.fillLayer.removeFromSuperlayer()
    }

}

তারপরে, আপনার কোড যেখানেই থাকুন:

let circle = CircleMaskView(drawIn: <target_view>)
circle.opacity = 0.7
circle.draw()
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.