मान लीजिए कि हमारे पास दो UIBezierPaths, path1 और path2... (जो पहले से ही रनटाइम पर सीमा देखने के सापेक्ष परिभाषित किए गए हैं और पहले से ही एक ही दृश्य के गुणों के रूप में मौजूद हैं)।
हम UIBezierPath, पथ 3 का एक नया पथ प्राप्त करना चाहते हैं, जो पथ 1 से पथ 2 घटाने का परिणाम है:
इसे करने का तरीका (जैसा कि यहां देखा गया है) यह करना है:
path1.append(path2.reversing())
लेकिन, यह केवल उन परिस्थितियों के लिए काम करता प्रतीत होता है जहां पथ 1 पूरी तरह से पथ 2 को शामिल करता है।
उदाहरण के लिए, उस मामले पर विचार करें जहां केवल एक आंशिक प्रतिच्छेदन है - पथ 1 पथ 2 को पूरी तरह से शामिल नहीं करता है। यदि हम ऊपर दी गई विधि को लागू करते हैं तो ऐसा होता है:
Android में, उत्तर है:
path1.op(path2, Path.Op.DIFFERENCE);
तो ... क्या आईओएस में एक समान सरल ऑपरेशन है?
यदि नहीं, तो क्या कोई ऐसा कार्य है जिसे इस प्रकार लिखा जा सकता है:
func returnPath2CutOutOfPath1(path1: UIBezierPath, path2: UiBezierPath) -> UIBezierPath {
// the mystery lies within these here parts. :)
}
2 जवाब
आईओएस पर एक नए पथ के रूप में UIBezierPaths के अंतर प्राप्त करने का कोई सीधा तरीका नहीं है।
टेस्टकेस
private func path2() -> UIBezierPath {
return UIBezierPath(rect: CGRect(x: 100, y: 50, width: 200, height: 200))
}
private func path1() -> UIBezierPath {
return UIBezierPath(rect: CGRect(x: 50, y: 100, width: 200, height: 200))
}
प्रारंभिक बिंदु: केवल यह दिखाने के लिए कि कौन सा पथ किसका प्रतिनिधित्व करता है: पथ 1 पीला है और पथ 2 हरा है:
संभावना 1
आप शायद इस संभावना को पहले ही देख चुके हैं: आपने अपने प्रश्न में जिस लिंक का उल्लेख किया है, उसमें एक चतुर समाधान भी है यदि आपको केवल एक भरण ऑपरेशन करना है।
कोड इस उत्तर से लिया गया था (आपके द्वारा पोस्ट किए गए लिंक से) https://stackoverflow.com/a/8860341 - केवल रूपांतरित स्विफ्ट करने के लिए:
func fillDifference(path2: UIBezierPath, path1: UIBezierPath) {
let clipPath = UIBezierPath.init(rect: .infinite)
clipPath.append(path2)
clipPath.usesEvenOddFillRule = true
UIGraphicsGetCurrentContext()?.saveGState()
clipPath.addClip()
path1.fill()
UIGraphicsGetCurrentContext()?.restoreGState()
}
तो यह एक पथ भरता है, लेकिन UIBezierPath वापस नहीं करता है, जिसका अर्थ है कि आप रूपरेखा, पृष्ठभूमि, समोच्च चौड़ाई इत्यादि लागू नहीं कर सकते हैं, क्योंकि परिणाम UIBezierPath नहीं है।
यह इस तरह दिख रहा है:
संभावना 2
आप किसी तृतीय-पक्ष लाइब्रेरी का उपयोग कर सकते हैं, उदा। एडम वूल्फ़ नाम के एक लेखक से एक यहाँ: https://github.com/adamwulf/ClippingBezier।
पुस्तकालय उद्देश्य-सी में लिखा गया है, लेकिन इसे स्विफ्ट से बुलाया जा सकता है।
स्विफ्ट में, यह इस तरह दिखेगा:
override func draw(_ rect: CGRect) {
let result = self.path1().difference(with: self.path2())
for p in result ?? [] {
p.stroke()
}
}
यदि आप इस पुस्तकालय का उपयोग करना चाहते हैं, तो आपको एक छोटा संकेत नोट करना होगा: प्रोजेक्ट सेटिंग्स में अन्य लिंकर फ़्लैग्स में, जैसा कि रीडमी द्वारा वर्णित है, "-ObjC++ -lstdc++" जोड़ा जाना चाहिए, अन्यथा इसे बिना किसी शिकायत के बनाया जाएगा, लेकिन चुपचाप फ्रेमवर्क लोड नहीं करेगा और अंततः क्रैश हो जाएगा, क्योंकि UIBEzierPath श्रेणियां नहीं मिली हैं।
परिणाम इस तरह दिखता है:
तो यह वास्तव में आपका वांछित परिणाम देगा, लेकिन आपको किसी तृतीय पक्ष लाइब्रेरी का उपयोग करना होगा।
मैंने आपको वांछित समाधान प्राप्त कर लिया है, लेकिन मैंने 200x200 आकार के स्थिर दृश्य के लिए कोड बनाया है।
मैं आपको दिखाता हूं कि मैंने क्या प्रयास किया है और मुझे बताएं कि आपके लिए कितना उपयोगी है।
सबसे पहले, मैंने कस्टम व्यू का वर्ग बनाया है जहां मैंने दृश्य बनाने के लिए कोड लिखा है। निम्नलिखित कोड देखें:
class MyCustomView: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setup()
}
func setup() {
// Create a CAShapeLayer
let shapeLayer = CAShapeLayer()
let path1 = self.path1()
let path2 = self.path2()
// Append path2 to path1
path1.append(path2.reversing())
// Set true of Even Odd Fill Rule
path1.usesEvenOddFillRule = true
// Call this method to add clip in path
path1.addClip()
shapeLayer.path = path1.cgPath
// Apply other properties related to the path
shapeLayer.strokeColor = UIColor.blue.cgColor
shapeLayer.fillColor = UIColor.black.cgColor
shapeLayer.lineWidth = 1.0
shapeLayer.position = CGPoint(x: 0, y: 0)
// Add the new layer to our custom view
self.layer.addSublayer(shapeLayer)
}
//-----------------------------------------------------
// This is static code as I have already told you first.
// Create First UIBezierPath,
func path1() -> UIBezierPath {
let path = UIBezierPath()
path.move(to: CGPoint(x: 0, y: 0))
path.addLine(to: CGPoint(x: 0, y: 200))
path.addLine(to: CGPoint(x: 200, y: 200))
path.addLine(to: CGPoint(x: 200, y: 0))
path.close()
return path
}
// Create Second UIBezierPath
func path2() -> UIBezierPath {
let path = UIBezierPath()
path.move(to: CGPoint(x: 50, y: -50))
path.addLine(to: CGPoint(x: 50, y: 150))
path.addLine(to: CGPoint(x: 250, y: 150))
path.addLine(to: CGPoint(x: 250, y: -50))
path.close()
return path
}
}
जैसा कि आपने चित्र 4 में बताया है, यह कस्टम वर्ग कोड आपके वास्तविक परिणाम के साथ साझा परत बनाएगा।
अब इस वर्ग का उपयोग करने के लिए मैंने निश्चित ऊंचाई और चौड़ाई के साथ उपरोक्त वर्ग का उदाहरण बनाया है।
override func viewDidLoad() {
super.viewDidLoad()
// Create a new UIView and add it to the view controller
let myView = MyCustomView()
// Must set clipsToBounds true to remove extra layer which are display out side of view as like your **actual** result in figure 4.
myView.clipsToBounds = true
myView.frame = CGRect(x: 50, y: 100, width: 200, height: 200)
myView.backgroundColor = UIColor.orange
view.addSubview(myView)
}
यह अनुसरण के रूप में दृश्य प्रदर्शित करेगा जो आपका वांछित परिणाम है।
मुझे उम्मीद है कि यह आपकी मदद करेगा, अगर आपके पास कोई प्रश्न है तो मुझे अभी भी बताएं।
संबंधित सवाल
जुड़े हुए प्रश्न
नए सवाल
ios
iOS, Apple iPhone, iPod टच और iPad पर चलने वाला मोबाइल ऑपरेटिंग सिस्टम है। IOS प्लेटफॉर्म पर प्रोग्रामिंग से संबंधित प्रश्नों के लिए इस टैग [ios] का उपयोग करें। उन प्रोग्रामिंग भाषाओं के लिए विशिष्ट मुद्दों के लिए संबंधित टैग [उद्देश्य-सी] और [स्विफ्ट] का उपयोग करें।