दिलचस्प पोस्ट
इनपुट में अप्रत्याशित वर्ण: '\' (एएससीआईआई = 92) राज्य = 1 सीतनिद्रा में होना hbm2ddl.auto संभव मूल्यों और वे क्या करते हैं? आर में चौराहे के बिंदु खोजने JPQL कन्स्ट्रक्टर एक्सप्रेशन – org.hibernate.hql.ast.QuerySyntaxException: तालिका मैप नहीं है सॉफ्टमॅक्स फ़ंक्शन – अजगर jqGrid डेटायूआरएल ड्रॉपडाउन सूची ताज़ा नहीं है फ़ायरफ़ॉक्स में "स्थानीय स्टॉरेज" क्या केवल तभी काम करता है जब पेज ऑनलाइन होता है? सीतनिद्रा में होना और कोई पी.के. RewriteRule अंतिम झंडा काम नहीं कर रहा है? कैसे जाँचें कि क्या तत्व के पास जावास्क्रिप्ट में कोई भी बच्चा है? सी # में इनर क्लासेस का उपयोग करना MySQL 1050 त्रुटि "तालिका पहले से मौजूद है" जब वास्तव में, यह नहीं है SSL सॉकेट के लिए कौन सी साइफर सूट सक्षम है? एक्लिप्स में एंड्रॉइड ऐप: ग्राफिकल लेआउट पर पाठ संपादित नहीं किया जा रहा है जावा "?" निरर्थक जांच करने के लिए ऑपरेटर – यह क्या है? (टर्नरी नहीं!)

Cglayer ड्राइंग के साथ पूर्ववत और पुनः करना करना

मैं एक ड्राइंग ऐप के साथ काम कर रहा हूं, मैं ड्राइंग के लिए सीजीलेर्स का उपयोग कर रहा हूं। छूने पर, मुझे परत से छवि मिलती है और इसे एक अर्रे में संग्रहीत करता है, जो मैं पूर्ववत ऑपरेशन के लिए उपयोग करता हूं।

मेरे स्पर्श ने समारोह समाप्त कर दिया

-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { NSLog(@"Touches ended"); UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, 0.0); CGContextRef context = UIGraphicsGetCurrentContext(); CGContextDrawLayerInRect(context, self.bounds, self.drawingLayer); m_curImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); [m_undoArray addObject: m_curImage]; } 

मेरा ड्राइंग व्यू गतिशील रूप से उपयोगकर्ता की मांग पर फैलता है, तो लगता है कि उपयोगकर्ता ड्रॉ व्हील आकार 200 * 200 के साथ एक पंक्ति कह सकता है, फिर 200 * 300 में विस्तार कर और एक और रेखा खींचना, उसके बाद 200 * 300 में विस्तार करें और एक और रेखा खींचना ।

यहां ऐप की छवि है

तो अब मेरे पास 3 छवियां अंडोअरेरे में अलग-अलग हैं

जब भी मैं कैनवास के आकार को बढ़ाता / decrese मैंने यह कोड लिखा है

ड्राइंग व्यू की वृद्धि और कमी पर, मैं इस फ़ंक्शन को लिख रहा हूं

  (void)increaseDecreaseDrawingView { self.currentDrawingLayer = nil; if(self.permanentDrawingLayer) { rectSize = self.bounds; NSLog(@"Size%@", NSStringFromCGRect(self.bounds)); CGContextRef context = UIGraphicsGetCurrentContext(); //self.newDrawingLayer = CGLayerCreateWithContext(context, self.bounds.size, NULL); CGFloat scale = self.contentScaleFactor; CGRect bounds = CGRectMake(0, 0, self.bounds.size.width * scale, self.bounds.size.height * scale); CGLayerRef layer = CGLayerCreateWithContext(context, bounds.size, NULL); CGContextRef layerContext = CGLayerGetContext(layer); CGContextScaleCTM(layerContext, scale, scale); self.newDrawingLayer = layer; CGContextDrawLayerInRect(layerContext, self.bounds, self.permanentDrawingLayer ); self.permanentDrawingLayer = nil; } 

और वापस करने के लिए मैंने यह कोड लिखा है

 - (void)Undo { //Destroy the layer and create it once again with the image you get from undoArray. self.currentDrawingLayer = Nil; CGContextRef layerContext1 = CGLayerGetContext(self.permanentDrawingLayer ); CGContextClearRect(layerContext1, self.bounds); CGContextRef context = UIGraphicsGetCurrentContext(); for(int i =0; i<[m_rectArrayUndo count];i++) { CGRect rect = [[m_rectArrayUndo objectAtIndex:i]CGRectValue]; CGLayerRef undoLayer = CGLayerCreateWithContext(context, rect.size, NULL); CGContextRef layerContext = CGLayerGetContext(undoLayer ); CGContextTranslateCTM(layerContext, 0.0, rect.size.height); CGContextScaleCTM(layerContext, 1.0, -1.0); CGRect imageFrame; NSDictionary *lineInfo = [m_undoArray objectAtIndex:i]; m_curImage = [lineInfo valueForKey:@"IMAGE"]; imageFrame = CGRectMake(0 ,0,m_curImage.size.width,m_curImage.size.height); CGContextDrawImage(layerContext, imageFrame, m_curImage.CGImage); CGContextDrawLayerInRect(context, rect, undoLayer ); CGContextDrawLayerInRect(layerContext1, rect, undoLayer); } } 

मेरे drawRect फ़ंक्शन में, मैंने यह कोड लिखा है

 - (void)drawRect:(CGRect)rect { CGContextRef context = UIGraphicsGetCurrentContext();//Get a reference to current context(The context to draw) if(self.currentDrawingLayer == nil) { CGLayerRef layer = CGLayerCreateWithContext(context, bounds.size, NULL); self.currentDrawingLayer = layer; } if(self.permanentDrawingLayer == nil) { CGLayerRef layer = CGLayerCreateWithContext(context, bounds.size, NULL); self.permanentDrawingLayer = layer; } if(self.newDrawingLayer == nil) { CGLayerRef layer = CGLayerCreateWithContext(context, bounds.size, NULL); self.newDrawingLayer = layer; } CGPoint mid1 = midPoint(m_previousPoint1, m_previousPoint2); CGPoint mid2 = midPoint(m_currentPoint, m_previousPoint1); CGContextRef layerContext = CGLayerGetContext(self.currentDrawingLayer); CGContextSetLineCap(layerContext, kCGLineCapRound); CGContextSetBlendMode(layerContext, kCGBlendModeNormal); CGContextSetLineJoin(layerContext, kCGLineJoinRound); CGContextSetLineWidth(layerContext, self.lineWidth); CGContextSetStrokeColorWithColor(layerContext, self.lineColor.CGColor); CGContextSetShouldAntialias(layerContext, YES); CGContextSetAllowsAntialiasing(layerContext, YES); CGContextSetAlpha(layerContext, self.lineAlpha); CGContextSetFlatness(layerContext, 1.0f); CGContextBeginPath(layerContext); CGContextMoveToPoint(layerContext, mid1.x, mid1.y);//Position the current point CGContextAddQuadCurveToPoint(layerContext, m_previousPoint1.x, m_previousPoint1.y, mid2.x, mid2.y); CGContextStrokePath(layerContext);//paints(fills) the line along the current path. CGContextDrawLayerInRect(context, self.bounds, self.newDrawingLayer); CGContextDrawLayerInRect(context, self.bounds, self.permanentDrawingLayer); CGContextDrawLayerInRect(context, self.bounds, self.currentDrawingLayer); [super drawRect:rect]; } 

मुझे कुछ संदेह है

  1. क्या यह सही तरीका है? या उनका कोई बेहतर दृष्टिकोण है

  2. यहां क्या होता है कि, पूर्ववत एरे से मेरी छवि रिएक्ट्स का सम्मान नहीं कर रही है और नई परत पर किसी भी यादृच्छिक स्थिति में खींची गई है।

इसलिए मैं जानना चाहता हूं कि हम उन्हें कैसे सही तरीके से आकर्षित कर सकते हैं ताकि छवियों को विशिष्ट स्थिति में सिलवेरों पर ठीक से खींचा जा सके।

Solutions Collecting From Web of "Cglayer ड्राइंग के साथ पूर्ववत और पुनः करना करना"

सबसे पहले, जब से आप परतों के साथ काम कर रहे हैं, मैं सुझाव देता हूं कि drawRect: पर छोड़ दें drawRect: और केवल CALayer रूपांतरण के साथ काम करें।

दूसरा, मेरी राय में, पूर्ववत-फिर से करें संचालन को लागू करने का सबसे अच्छा तरीका हमेशा कमांड-आधारित होगा एक बहुत सरल उदाहरण के रूप में, आप प्रत्येक कमांड के लिए अलग तरीके बना सकते हैं:

 - (void)scaleLayerBy:(CGFloat)scale; - (void)moveLayerByX:(CGFloat)x Y:(CGFloat)y; // etc 

और फिर हर बार जब उपयोगकर्ता एक क्रिया करता है, तो आप एक NSMutableArray एक्शन आईडी और पैरामीटर में जोड़ते हैं:

 [self.actionHistory addObject:@{ @"action": @"move", @"args": @[@10.0f, @20.0f] }]; 

इसके विपरीत, यदि उपयोगकर्ता पूर्ववत को आह्वान करता है, तो उस ऑरेरे में अंतिम ऑब्जेक्ट निकाल दें।

तब जब आपको डिस्प्ले को पुनः लोड करने की आवश्यकता होती है, तो बस सरणी में सभी आदेशों का पुनः मूल्यांकन करें।

 [self resetLayers]; // reset CALayers to their initial state for (NSDictionary *command in self.actionHistory) { NSArray *arguments = command[@"args"]; if ([command[@"action"] isEqualToString:@"move"]) { [self moveLayerByX:[arguments[0] floatValue] Y:[arguments[1] floatValue]]; } // else if other commands } 

प्रत्येक स्पर्श इवेंट के लिए एक इमेज ऑब्जेक्ट एक बुरा विचार आईएमएचओ है, आप राम के माध्यम से फाड़ रहे हैं क्यों नहीं स्पर्श बिंदुओं के सरणी रखें और गतिशील रूप से आकर्षित करें? सस्ते अर्नो ऑपरेशन के लिए उस सरणी के पिछले कुछ तत्वों को निकालने के लिए पर्याप्त आसान है

//// 14 जनवरी 2014 // // संपादित करने के लिए example //

ठीक है, यह एक त्वरित ड्राइंग व्यू उदाहरण है। वहाँ तीन अस्थिरता, _touches, जो सभी पिछले चित्रों के लिए है, _currentTouch, जो वर्तमान ड्राइंग है और केवल स्पर्श घटनाओं के दौरान डेटा शामिल हैं, (स्पर्श के बीच शुरू होता है और छू जाता है) .. और एक फिर से करें सरणी जो डेटा जो पूर्ववत द्वारा हटाया जाता है इसे हटाए जाने की बजाय प्रतिलिपि बनाई गई है (जो आप निश्चित रूप से कर सकते हैं)

का आनंद लें 🙂

 // // JEFdrawingViewExample.m // Created by Jef Long on 14/01/2014. // Copyright (c) 2014 Jef Long / Dragon Ranch. All rights reserved. // #import "JEFdrawingViewExample.h" ///don't worry, the header is empty :) /// this is a subclass of UIView @interface JEFdrawingViewExample() -(UIColor *)colourForLineAtIndex:(int)lineIndex; //swaps the coulour for each line -(void)undo; -(void)redo; @end; @implementation JEFdrawingViewExample { //iVars NSMutableArray *_touches; NSMutableArray *_currentTouch; NSMutableArray *_redoStore; } - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { // Initialization code _touches = [[NSMutableArray alloc]init]; _currentTouch = [[NSMutableArray alloc]init]; _redoStore = [[NSMutableArray alloc]init]; } return self; } #pragma mark - touches -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ UITouch *touch = [touches anyObject]; CGPoint touchPoint = [touch locationInView:self]; [_currentTouch removeAllObjects]; [_currentTouch addObject:NSStringFromCGPoint(touchPoint)]; ///there are other, possibly less expensive ways to do this.. (adding a CGPoint to an NSArray.) // typecasting to (id) doesnt work under ARC.. // two NSNumbers probably not any cheaper.. } -(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{ UITouch *touch = [touches anyObject]; CGPoint touchPoint = [touch locationInView:self]; [_currentTouch addObject:NSStringFromCGPoint(touchPoint)]; [self setNeedsDisplay]; } -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{ UITouch *touch = [touches anyObject]; CGPoint touchPoint = [touch locationInView:self]; [_currentTouch addObject:NSStringFromCGPoint(touchPoint)]; [_touches addObject:[NSArray arrayWithArray:_currentTouch]]; [_currentTouch removeAllObjects]; [self setNeedsDisplay]; } -(void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event{ [_currentTouch removeAllObjects]; [self setNeedsDisplay]; } #pragma mark - drawing - (void)drawRect:(CGRect)rect { //we could be adding a CALayer for each new line, which would be cheaper because you could draw each and basically forget it CGContextRef _context = UIGraphicsGetCurrentContext(); CGContextSetLineWidth(_context, 1.0); //or whatever ///older lines if ([_touches count]) { for (int line = 0; line < [_touches count]; line ++) { NSArray *thisLine = [_touches objectAtIndex:line]; if ([thisLine count]) { CGContextSetStrokeColorWithColor(_context, [self colourForLineAtIndex:line].CGColor); CGPoint start = CGPointFromString([thisLine objectAtIndex:0]); CGContextMoveToPoint(_context, start.x, start.y); for (int touch = 1; touch < [thisLine count]; touch ++) { CGPoint pt = CGPointFromString([thisLine objectAtIndex:touch]); CGContextAddLineToPoint(_context, pt.x, pt.y); } CGContextStrokePath(_context); } } } ///current line if ([_currentTouch count]) { CGPoint start = CGPointFromString([_currentTouch objectAtIndex:0]); CGContextSetStrokeColorWithColor(_context, [self colourForLineAtIndex:[_touches count]].CGColor); CGContextMoveToPoint(_context, start.x, start.y); for (int touch = 1; touch < [_currentTouch count]; touch ++) { CGPoint touchPoint = CGPointFromString([_currentTouch objectAtIndex:touch]); CGContextAddLineToPoint(_context, touchPoint.x, touchPoint.y); } CGContextStrokePath(_context); } } -(UIColor *)colourForLineAtIndex:(int)lineIndex{ return (lineIndex%2 == 0) ? [UIColor yellowColor] : [UIColor purpleColor]; /// you might have a diff colour for each line, eg user might select a pencil from a toolbar etc } #pragma mark - undo mechanism -(void)undo{ if ([_currentTouch count]) { [_redoStore addObject:[NSArray arrayWithArray:_currentTouch]]; [_currentTouch removeAllObjects]; [self setNeedsDisplay]; }else if ([_touches count]){ [_redoStore addObject:[_touches lastObject]]; [_touches removeLastObject]; [self setNeedsDisplay]; }else{ //nothing left to undo } } -(void)redo{ if ([_redoStore count]) { [_touches addObject:[_redoStore lastObject]]; [_redoStore removeLastObject]; [self setNeedsDisplay]; } } @end