2009-08-20 14 views
22

मुझे पता है कि एक सरल रेखा खींचना:कोर ग्राफिक्स/आईफोन के साथ एक ढाल रेखा (लुप्तप्राय/बाहर) कैसे आकर्षित करें?

CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0); 
CGContextMoveToPoint(context, x, y); 
CGContextAddLineToPoint(context, x2, y2); 
CGContextStrokePath(context); 

और मैं कैसे एक ढाल आयत, i.g .:

CGColorSpaceRef myColorspace=CGColorSpaceCreateDeviceRGB(); 
size_t num_locations = 2; 
CGFloat locations[2] = { 1.0, 0.0 }; 
CGFloat components[8] = { 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0 }; 

CGGradientRef myGradient = CGGradientCreateWithColorComponents(myColorspace, components, locations, num_locations); 

CGPoint myStartPoint, myEndPoint; 
myStartPoint.x = 0.0; 
myStartPoint.y = 0.0; 
myEndPoint.x = 0.0; 
myEndPoint.y = 10.0; 
CGContextDrawLinearGradient (context, myGradient, myStartPoint, myEndPoint, 0); 

क्या करना है लेकिन यह कैसे मैं एक ढाल, आई जी के साथ एक रेखा खींच सकता है काले से सफेद में लुप्त हो जाना (और शायद दूसरी तरफ काले रंग में बाहर निकलना)?

+1

एक त्वरित नोट - वर्तमान में चयनित उत्तर यहां गलत है। ** एक ढाल ** के साथ मनमानी पथों को स्ट्रोक करना संभव है [इस उत्तर] (http://stackoverflow.com/a/25034854/2547229) दिखाता है। – Benjohn

उत्तर

20

कई प्रयासों के बाद मुझे अब यकीन है कि ग्रेडियेंट स्ट्रोक को प्रभावित नहीं करता है, इसलिए मुझे लगता है कि CGContextStrokePath() के साथ ढाल लाइनों को आकर्षित करना असंभव है। क्षैतिज और ऊर्ध्वाधर रेखाओं के लिए समाधान CGContextAddRect() का उपयोग करना है, जो सौभाग्य से मुझे चाहिए। मैं

CGContextSaveGState(context); 
CGContextAddRect(context, CGRectMake(x, y, width, height)); 
CGContextClip(context); 
CGContextDrawLinearGradient (context, gradient, startPoint, endPoint, 0); 
CGContextRestoreGState(context); 

साथ

CGContextMoveToPoint(context, x, y); 
CGContextAddLineToPoint(context, x2, y2); 
CGContextStrokePath(context); 

प्रतिस्थापित और सब कुछ ठीक काम करता है। महत्वपूर्ण संकेत के लिए ब्रैड लार्सन का धन्यवाद।

+0

मुझे बिल्कुल वही चीज़ मिल गई है। ऐसा लगता है कि ग्रेडियेंट्स को पहले ग्राफिक्स संदर्भ पर लागू होने के लिए क्लिप पथ (या आयताकार) की आवश्यकता होती है। शायद ऐसा इसलिए है क्योंकि मार्ग (या आयताकार) सीमा के बजाय संलग्न क्षेत्र में ग्रेडियेंट प्रदान किए जाते हैं? – Dalmazio

+0

यह एक ढलान लाइन प्रस्तुत नहीं कर सकता है? – AntiMoron

8

आप कोर एनिमेशन परतों का उपयोग कर सकते हैं। आप सेटिंग्स के अनुसार अपनी लाइन के लिए CAShaperLayer का उपयोग कर सकते हैं और फिर आप अपनी आकृति परत पर एक परत मास्क के रूप में CAGradientLayer का उपयोग कर सकते हैं जो लाइन को फीका कर देगा।

अपने CGContext को बदलें ... CGPath को कॉल के साथ कॉल ... लाइन पथ बनाने के लिए कॉल करें। उस पथ का उपयोग कर परत पर पथ फ़ील्ड सेट करें।

[gradientLayer setMask:lineLayer]; 

क्या ढाल परत के बारे में अच्छी बात यह है कि आप की अनुमति देता है है: तो फिर अपने ढाल परत में, इस तरह लाइन परत होने के लिए रंग आप उपयोग करना (शायद सफेद करने के लिए काले) निर्दिष्ट और फिर सेट मुखौटा उन स्थानों की एक सूची निर्दिष्ट करने के लिए जहां ढाल बंद हो जाएगा, ताकि आप फीका और फीका कर सकें। यह केवल रैखिक ग्रेडियेंट का समर्थन करता है, लेकिन ऐसा लगता है कि आपकी आवश्यकताओं के अनुरूप हो सकता है।

मुझे स्पष्टीकरण की आवश्यकता होने पर मुझे बताएं।

संपादित करें: अब जब मैं इसके बारे में सोचता हूं, तो केवल एक ही कैग्राइडेंट लेयर बनाएं जो आपकी इच्छित रेखा की चौड़ाई/ऊंचाई है। ढाल रंगों (काला से सफेद या काले रंग को साफ़ करने के लिए काला) निर्दिष्ट करें और स्टार्टपॉइंट और एंडट पॉइंट्स और यह आपको जो चाहिए उसे आपको देना चाहिए।

+0

आप सही हैं, यह मेरी आवश्यकताओं को पूरी तरह से फिट करेगा, लेकिन दुर्भाग्य से यह केवल आईफोन ओएस के संस्करण 3 के साथ उपलब्ध है और मैं कम से कम 2.2 का उपयोग करना चाहता हूं। फिर भी धन्यवाद... – Walchy

+1

मुझे लगता है कि आप का मतलब है [gradientLayer setMask: LineLayer]; - सही? आप CASHAPLLer के साथ CAGradientLayer को मुखौटा करते हैं। – Palimondo

+0

शानदार। यह बहुत कुछ सीख लिया। – Ian1971

8

के बाद आप रेखा खींचना, आप

CGContextClip(context); 

अपनी लाइन क्षेत्र के लिए ड्राइंग आगे क्लिप करने के लिए कह सकते हैं। यदि आप ढाल खींचते हैं, तो अब इसे लाइन क्षेत्र के भीतर निहित होना चाहिए। ध्यान दें कि यदि आप केवल ढाल दिखाना चाहते हैं, और इसके नीचे की रेखा नहीं है तो आपको अपनी लाइन के लिए एक स्पष्ट रंग का उपयोग करने की आवश्यकता होगी।

संभावना है कि आपके ढाल के लिए एक रेखा बहुत पतली होगी, इस मामले में आप एक मोटे क्षेत्र को परिभाषित करने के लिए CGContextAddRect() का उपयोग कर सकते हैं।

मैं अपने उत्तर here में इस संदर्भ क्लिपिंग का उपयोग करने का एक और विस्तृत उदाहरण प्रस्तुत करता हूं।

+1

मैंने आपके सुझाव की कोशिश की: \t CGContextSetLineWidth (संदर्भ, 10.0); // पर्याप्त मोटा होना चाहिए \t CGContextSetRGBStrokeColor (संदर्भ, 0.0, 0.0, 0.0, 0.0); \t CGContextMoveToPoint (संदर्भ, 50,50); \t CGContextAddLineToPoint (संदर्भ, 100,100); \t CGContextStrokePath (संदर्भ); \t CGContextClip (संदर्भ); \t CGContextDrawLinearGradient (संदर्भ, myGradient, myStartPoint, myEndPoint, 0); लेकिन यह : डिकक्लिप: खाली पथ। प्रलेखन का कहना है कि CGContextStrokePath (संदर्भ); पथ को साफ़ करता है - इस विधि के बिना कोई त्रुटि नहीं फेंक दी जाती है, लेकिन कुछ भी नहीं खींचा जाता है। कोई विचार? – Walchy

0
CGContextMoveToPoint(context, frame.size.width-200, frame.origin.y+10); 
CGContextAddLineToPoint(context, frame.size.width-200, 100-10); 
CGFloat colors[16] = { 0,0, 0, 0, 
    0, 0, 0, .8, 
    0, 0, 0, .8, 
    0, 0,0 ,0 }; 
CGColorSpaceRef baseSpace = CGColorSpaceCreateDeviceRGB(); 
CGGradientRef gradient = CGGradientCreateWithColorComponents(baseSpace, colors, NULL, 4); 

CGContextSaveGState(context); 
CGContextAddRect(context, CGRectMake(frame.size.width-200,10, 1, 80)); 
CGContextClip(context); 
CGContextDrawLinearGradient (context, gradient, CGPointMake(frame.size.width-200, 10), CGPointMake(frame.size.width-200,80), 0); 
CGContextRestoreGState(context); 

मेरे लिए यह काम।

25

मनमाने ढंग से पथ को ढाल के साथ स्ट्रोक करना संभव है, या पैटर्न के साथ किसी अन्य भरने के प्रभाव को स्ट्रोक करना संभव है।

जैसा कि आपने पाया है, स्ट्रोक किए गए पथ वर्तमान ढाल के साथ प्रस्तुत नहीं किए जाते हैं। केवल भरे पथ केवल ढाल का उपयोग करते हैं (जब आप उन्हें एक क्लिप में बदलते हैं और फिर ढाल खींचते हैं)।

हालांकि, कोर ग्राफिक्स आश्चर्यजनक शांत प्रक्रिया CGContextReplacePathWithStrokedPath है कि एक रास्ता है कि है बराबर जब भरा करने के लिए स्ट्रोक के लिए पथ आप का इरादा बदल दिया है।

दृश्यों के पीछे, CGContextReplacePathWithStrokedPath आपके स्ट्रोक पथ के चारों ओर एक किनारे बहुभुज बनाता है और आपके द्वारा परिभाषित पथ के लिए स्विच करता है। मैं अनुमान लगाता हूं कि कोर ग्राफिक्स रेंडरिंग इंजन शायद पर CGContextStrokePath पर कॉल में करता है।

यहाँ इस पर एप्पल के प्रलेखन है:

क्वार्ट्ज एक stroked पथ वर्तमान ग्राफिक्स संदर्भ के मापदंडों का उपयोग कर बनाता है। नया पथ बनाया गया है ताकि इसे भरने से मूल पथ को घुमाने के समान पिक्सल खींचे। आप इस पथ का उपयोग उसी तरह से कर सकते हैं जैसे आप किसी संदर्भ के पथ का उपयोग करते हैं। उदाहरण के लिए, आप फ़ंक्शन CGContextClip पर कॉल के बाद इस फ़ंक्शन को कॉल करके पथ के स्ट्रोक किए गए संस्करण पर क्लिप कर सकते हैं।

तो, कुछ आप भर सकते हैं करने के लिए अपना रास्ता परिवर्तित, बारी एक क्लिप करने के लिए है कि, और तो अपने ढाल आकर्षित। प्रभाव ऐसा होगा जैसे आपने ढाल के साथ पथ को दबा दिया था।

कोड

यह कुछ इस तरह दिखाई देंगे ...

// Get the current graphics context. 
    // 
    const CGContextRef context = UIGraphicsGetCurrentContext(); 

    // Define your stroked path. 
    // 
    // You can set up **anything** you like here. 
    // 
    CGContextAddRect(context, yourRectToStrokeWithAGradient); 

    // Set up any stroking parameters like line. 
    // 
    // I'm setting width. You could also set up a dashed stroke 
    // pattern, or whatever you like. 
    // 
    CGContextSetLineWidth(context, 1); 

    // Use the magical call. 
    // 
    // It turns your _stroked_ path in to a **fillable** one. 
    // 
    CGContextReplacePathWithStrokedPath(context); 

    // Use the current _fillable_ path in to define a clipping region. 
    // 
    CGContextClip(context); 

    // Draw the gradient. 
    // 
    // The gradient will be clipped to your original path. 
    // You could use other fill effects like patterns here. 
    // 
    CGContextDrawLinearGradient(
     context, 
     yourGradient, 
     gradientTop, 
     gradientBottom, 
     0 
    ); 

इसके अलावा नोटों

यह ऊपर प्रलेखन का हिस्सा बल के लायक है:

क्वार्ट्ज एक stroked पथ बनाता है वर्तमान ग्राफिक्स संदर्भ के पैरामीटर का उपयोग कर

स्पष्ट पैरामीटर लाइन चौड़ाई है। हालांकि, सभी लाइन ड्राइंग राज्य का उपयोग किया जाता है, जैसे स्ट्रोक पैटर्न, मिटर सीमा, लाइन जॉइन, कैप्स, डैश पैटर्न इत्यादि। यह दृष्टिकोण को बेहद शक्तिशाली बनाता है।

अतिरिक्त जानकारी के लिए this answerthis S.O. question देखें।

संबंधित मुद्दे