2012-06-20 9 views
10

कोर ग्राफिक्स का उपयोग करके, मैं एक रेखा खींचने की कोशिश कर रहा हूं, जब मैं छाया जोड़ने की कोशिश करता हूं तो लाइन के अंदर लिन और बुलबुले बनाता है, छवि देखें, मैं नहीं हूं इस मुद्दे को हल करने में सक्षम। कृपयासमस्या: बुलबुले दिखाए गए हैं

-(void)drawRect:(CGRect)rect 
{ 

    [curImage drawAtPoint:CGPointMake(0, 0)]; 
    CGPoint mid1 = midPoint(previousPoint1, previousPoint2); 
    CGPoint mid2 = midPoint(currentPoint, previousPoint1); 

    CGContextRef context = UIGraphicsGetCurrentContext(); 

    [self.layer renderInContext:context]; 

    CGContextMoveToPoint(context, mid1.x, mid1.y); 
    CGContextAddQuadCurveToPoint(context, previousPoint1.x, previousPoint1.y, mid2.x, mid2.y); 
    CGContextSetLineCap(context, kCGLineCapRound); 
    CGContextSetLineWidth(context, self.lineWidth); 
    CGContextSetStrokeColorWithColor(context, self.lineColor.CGColor); 

    CGContextSetShadow(context, CGSizeMake(-16.00, -5.0f), 5.0f); 

    CGContextStrokePath(context); 

    [super drawRect:rect]; 

    [curImage release]; 

} 

नीचे touchesMoved विधि नीचे मेरा कोड पाएं।

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event 
{ 

    UITouch *touch = [touches anyObject]; 

    previousPoint2 = previousPoint1; 
    previousPoint1 = [touch previousLocationInView:self]; 
    currentPoint = [touch locationInView:self]; 

    // calculate mid point 
    CGPoint mid1 = midPoint(previousPoint1, previousPoint2); 
    CGPoint mid2 = midPoint(currentPoint, previousPoint1); 

    CGMutablePathRef path = CGPathCreateMutable(); 
    CGPathMoveToPoint(path, NULL, mid1.x, mid1.y); 
    CGPathAddQuadCurveToPoint(path, NULL, previousPoint1.x, previousPoint1.y, mid2.x, mid2.y); 
    CGRect bounds = CGPathGetBoundingBox(path); 
    CGPathRelease(path); 

    CGRect drawBox = bounds; 

    //Pad our values so the bounding box respects our line width 
    drawBox.origin.x  -= self.lineWidth * 2; 
    drawBox.origin.y  -= self.lineWidth * 2; 
    drawBox.size.width  += self.lineWidth * 4; 
    drawBox.size.height  += self.lineWidth * 4; 

    UIGraphicsBeginImageContext(drawBox.size); 
    [self.layer renderInContext:UIGraphicsGetCurrentContext()]; 
    curImage = UIGraphicsGetImageFromCurrentImageContext(); 
    [curImage retain]; 
    UIGraphicsEndImageContext(); 
    [self setNeedsDisplayInRect:drawBox]; 

} 

CGPoint midPoint(CGPoint p1, CGPoint p2) 
{ 
    return CGPointMake((p1.x + p2.x) * 0.5, (p1.y + p2.y) * 0.5); 
} 


-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 
{ 

    UITouch *touch = [touches anyObject]; 

    previousPoint1 = [touch previousLocationInView:self]; 
    previousPoint2 = [touch previousLocationInView:self]; 
    currentPoint = [touch locationInView:self]; 

    [self touchesMoved:touches withEvent:event]; 
} 

यहाँ मुद्दा आता है जब मैं पहले से लाइन

CGContextSetShadow(context, CGSizeMake(-16.00, -5.0f), 5.0f); 

Issue image

कृपया मुझे इस मुद्दे से मदद बाहर, धन्यवाद जोड़ने के लिए प्रयास करें। विधियों के साथ संपादन प्रश्न देखें।

उत्तर

8

ऐसा लगता है कि आप क्वाड वक्र के रूप में सेगमेंट की एक श्रृंखला तैयार कर रहे हैं। बुलबुले होंगे जहां पिछले खंड और वर्तमान खंड ओवरलैप होगा। चूंकि आपकी सेगमेंट लाइन एक ठोस लाल है, इसलिए आप ओवरलैप नहीं देखते हैं, लेकिन यह छाया में गहरे क्षेत्रों के रूप में दिखाई देता है।

अपने स्ट्रोक रंग को 0.5 (या कुछ ऐसे पारदर्शिता) के अल्फा को सेट करने का प्रयास करें। मुझे लगता है (पता है) आप देखेंगे कि ओवरलैपिंग सेगमेंट भी छाया के समान प्रभाव दिखाएंगे।

इसे हल करने के लिए, आप सेगमेंट को प्रत्येक पंक्ति के लिए एक सतत पथ के रूप में आकर्षित करना चाहते हैं। मुझे लगता है कि आप लाइनों के अंक प्राप्त करने के लिए touchesBegan:withEvent:/touchesMoved:withEvent/touchesEnded:withEvent: का उपयोग कर रहे हैं?

उस स्थिति में, जब touchesBegan:withEvent: कहा जाता है, तो अपना नया मार्ग शुरू करें। touchesMoved:withEvent के दौरान वर्तमान छवि पर नया पथ प्रस्तुत करें। touchesEnded:withEvent: में UIImage के पथ को प्रतिबद्ध करें। इस बिंदु पर आप touchesBegan:withEvent: तक पथ को तब तक त्याग सकते हैं जब अगले स्ट्रोक के साथ फिर से कॉल किया जाता है।

अद्यतन

अपने कोड के टुकड़े में आप पूरे दृश्य प्रतिपादन तीन बार हर रन पाश अंत। यह बहुत अधिक ड्राइंग ओवरहेड है। मैंने जल्दी से कुछ कोड एक साथ रखा जो दर्शाता है कि मैं ऊपर क्या बात कर रहा हूं। यह कोड परीक्षण किया जाता है नहीं, लेकिन यह ज्यादातर सही होना चाहिए: 2

मैं समय का एक सा लिख ​​सकते हैं और कुछ कोड है कि आप मेरी नवीनतम दो टिप्पणी के आधार पर मांग कर रहे हैं कि क्या करना होगा परीक्षण करने के लिए किया था

अद्यतन । यह कोड व्यू कंट्रोलर से दृश्य के बजाय है, लेकिन थोड़ा बदलाव के साथ, यदि आप चाहें तो दृश्य में स्थानांतरित कर सकते हैं। इस तरह, मैंने छवि 0 को पकड़ने और प्रदर्शित करने के लिए जेनेरिक UIView के उप-दृश्य के रूप में UIImageView जोड़ा (और दृश्य नियंत्रक में संदर्भ बनाए रखा), और टच इवेंट प्राप्त करने के लिए व्यू कंट्रोलर को पहला प्रतिसादकर्ता बना दिया। हार्ड कोडित मूल्यों के बहुत सारे है कि आप को साफ कर सकते हैं जब अपनी परियोजना में एकीकृत:

static 
UIImage *CreateImage(CGRect rect, NSArray *paths) 
{ 
    UIGraphicsBeginImageContextWithOptions(rect.size, NO, 1.0); 
    CGContextRef context = UIGraphicsGetCurrentContext(); 

    CGFloat colorComponents[4] = {0.0,0.0,0.0,0.0}; 
    CGContextSetFillColor(context, colorComponents); 
    CGContextFillRect(context, rect); 

    for (id obj in paths) { 
     CGPathRef path = (CGPathRef)obj; 
     CGContextAddPath(context, path); 
    }  
    CGContextSetStrokeColorWithColor(context, [[UIColor redColor] CGColor]); 
    CGContextSetLineCap(context, kCGLineCapRound); 
    CGContextSetLineWidth(context, 5.0); 
    CGContextSetShadow(context, (CGSize){-8.0,40}, 5.0); 
    CGContextBeginTransparencyLayer(context, NULL); 

    CGContextDrawPath(context, kCGPathStroke); 

    CGContextEndTransparencyLayer(context); 

    UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 
    return image; 
} 

static 
CGPoint MidPoint(CGPoint pt1, CGPoint pt2) 
{ 
    return (CGPoint){(pt1.x+pt2.x)/2.0,(pt1.y+pt2.y)/2.0}; 
} 

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 
{ 
    [super touchesBegan:touches withEvent:event]; 
    CGPoint location = [[touches anyObject] locationInView:self.view]; 
    myPath = CGPathCreateMutable(); 
    CGPathMoveToPoint(myPath, NULL, location.x, location.y); 

    [self.paths addObject:(id)myPath]; 
} 

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event 
{ 
    [super touchesMoved:touches withEvent:event]; 
    UITouch *touch = [touches anyObject]; 
    CGPoint previousLocation = [touch previousLocationInView:self.view]; 
    CGPoint location = [touch locationInView:self.view]; 
    CGPoint midPoint = MidPoint(previousLocation, location); 
    CGPathAddQuadCurveToPoint(myPath, NULL, midPoint.x, midPoint.y, location.x, location.y); 

    self.imageView.image = CreateImage(self.view.bounds, self.paths); 
} 

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event 
{ 
    [super touchesEnded:touches withEvent:event]; 
    UITouch *touch = [touches anyObject]; 
    CGPoint previousLocation = [touch previousLocationInView:self.view]; 
    CGPoint location = [touch locationInView:self.view]; 
    CGPoint midPoint = MidPoint(previousLocation, location); 
    CGPathAddQuadCurveToPoint(myPath, NULL, midPoint.x, midPoint.y, location.x, location.y); 

    self.imageView.image = CreateImage(self.view.bounds, self.paths); 

    CGPathRelease(myPath); 
    myPath = nil; 
} 
+0

सहायता के लिए धन्यवाद, लेकिन मैं बिल्कुल आपकी बात नहीं कर पा रहा हूं। क्योंकि यह मेरे लिए बिल्कुल नया विषय है। –

+1

पर्याप्त मेला। चूंकि उपयोगकर्ता अपनी उंगली को समग्र स्ट्रोक बना देता है, इसलिए अंक की एक श्रृंखला दर्ज की जाती है (प्रत्येक रन लूप चक्र)। आप स्पष्ट रूप से केवल अपने नए 'UIImage' में रिकॉर्ड करने के लिए पिछले और वर्तमान बिंदु को रिकॉर्ड करते हैं। इसके बजाय, 'स्पर्शों के बीच उत्पन्न सभी बिंदुओं को समेकित करें: साथ:' संदेश और 'स्पर्श करें: साथ: साथ:' संदेश, उन्हें पथ (या तो एक CGPath या UIBezierPath) में कनवर्ट करें ** ** ** उपयोगकर्ता ने अपनी उंगली उठाई है ('स्पर्श किया गया: साथ:'), और अपने नए 'UIImage' पर पूर्ण स्ट्रोक प्रतिबद्ध करें। पारदर्शिता परतों के बारे में @ relikd की टिप्पणियां भी अच्छी है। – gschandler

+0

कोड सहायता के लिए धन्यवाद, आपका कोड उचित है लेकिन यह टच एंड पर ड्रॉइंग बनाएगा, और मुझे उंगली के उपयोगकर्ता के आंदोलन के साथ रेखा खींचनी होगी, इसलिए मैं कोड डेन को बदलने की कोशिश कर रहा हूं, आपको बताएं कि क्या है परिणाम। –

4

समस्या आप कई पंक्तियों जो एक दूसरे के ऊपर झूठ है। तो दोनों ओवरलैप की छायाएं और आपको एक गहरा रंग मिलता है।

अपनी रेखा रेखाचित्रों की तरह आसान कुछ के लिए आप बस पूरे ड्राइंग कोड की प्रतिलिपि बना सकते हैं और एक अलग रंग और दृश्य पिक्सेल ऑफ़सेट (छाया के बजाय) के साथ फिर से तैयार कर सकते हैं। जैसे आप वक्र को एक सरणी में सहेजते हैं और बाद में उन्हें अलग-अलग खींचते हैं।

संपादित करें:
ठीक @gschandler समस्या का भी वर्णन करता है।

लेकिन आप Transparency Layer दस्तावेज़ीकरण को भी देखना चाहते हैं। तत्वों को एक साथ समूहित करें और समूह के लिए छाया लागू करें।

2

यह करने के लिए एक और तरीका है दौर स्पर्श कदम घटनाओं पर अंक की एक सरणी बनाने के लिए, और फिर उन्हें आकर्षित करने के लिए है ..

अंक की एक सरणी बनाएँ:

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 
{ 
[pointArray release]; pointArray = nil; 
pointArray=[[NSMutableArray alloc] init]; 
UITouch *touch = [touches anyObject]; 
[bufferArray removeAllObjects]; 

previousPoint1 = [touch previousLocationInView:self]; 
previousPoint2 = [touch previousLocationInView:self]; 
currentPoint = [touch locationInView:self]; 

} 


-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event 
{ 
UITouch *touch = [touches anyObject]; 
previousPoint2 = previousPoint1; 
previousPoint1 = [touch previousLocationInView:self]; 
currentPoint = [touch locationInView:self]; 
[pointArray addObject: [NSValue valueWithCGPoint:previousPoint2]]; 
[pointArray addObject:[NSValue valueWithCGPoint:previousPoint1]]; 
[pointArray addObject:[NSValue valueWithCGPoint:currentPoint]]; 
[self setNeedsDisplay]; 
} 

-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event 
{ 

} 


-(void)drawRect:(CGRect)rect 
{ 
CGContextRef context = UIGraphicsGetCurrentContext(); 
CGContextSetLineCap(context, kCGLineCapRound); 
CGContextSetLineWidth(context, self.lineWidth); 
CGContextSetStrokeColorWithColor(context, self.lineColor.CGColor); 

CGContextSetShadow(context, CGSizeMake(-16.00, -5.0f), 5.0f); 

for(int i = 1 ; i < [pointArray count]-1;i++) 
{ 
CGPoint mid1 = midPoint([pointArray objectAtIndex:i+1], [pointArray objectAtIndex:i]); 
CGPoint mid2 = midPoint([pointArray objectAtIndex:i+2], [pointArray objectAtIndex:i+1]); 


CGContextMoveToPoint(context, mid1.x, mid1.y); 
CGContextAddQuadCurveToPoint(context, previousPoint1.x, previousPoint1.y, mid2.x, mid2.y); 
i+=2; 
} 
CGContextStrokePath(context); 

} 

आप के साथ कई लाइनों प्रबंधन कर सकते हैं एकाधिक आयामी सरणी :)

+0

हाय डिंपल, उत्तर के लिए धन्यवाद, लेकिन कोड लूप के लिए क्रैश हो रहा है, मध्य 2 बिंदु, सूचकांक मान कुछ तार्किक मुद्दा होने लगता है। जब मैंने डीबग के साथ प्रयास किया, तो यह [पॉइंटएरे ऑब्जेक्ट एट इंडेक्स: i + 2] पर क्रैश हो गया क्योंकि उस इंडेक्स पर ऑब्जेक्ट नहीं था, कृपया साझा करें कि यह हिस्सा कैसे काम कर रहा है !! –

+0

कृपया लूप में i + = 2 जोड़ें, क्योंकि हम एक समय में 4 अंक का उपयोग कर रहे हैं, हमें इसकी आवश्यकता है। – DivineDesert

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

  • कोई संबंधित समस्या नहीं^_^