I have been coding for MacOs for months and now exploring iOS. It's a bit confusing.
In MacOS, I have a NSImageView I can rotate using setFrameCenterRotation. One outlet, one call, and the work is done.
I suppose there is an equivalent in iOS but I could only find code examples using animation and a lot of calculation (certainly to make "nice" game-like features on this tiny screen).
I don't want any animation, just my ...UIImageView to rotate in one block from a given number of degrees.
Can it be done?
Any suggestion really welcome!
Regards,
B.
You probably want to set the view's transform property to a rotation transform. Example:
CGFloat radians = degrees * M_PI / 180;
myImageView.transform = CGAffineTransformMakeRotation(radians);
UIImageView inherits the transform property from UIView, so you will need to consult the UIView Class Reference for documentation.
Related
Is it possible to rotate UILabels or similar about a clockface?
For example, if I had an array of numbers from one to twelve, it would render as such in a circular manner. However, with a touch event I could move the labels about the face of the clock i.e. I could move 12 in a rightward motion until it reached 6, with all other numbers remaining in their positions.
I have considered UIPicker, but that follows a 'top to bottom' approach. I need a solution to move the label about a point while maintaining the order of the other labels.
It's simply a matter of opposing rotation transforms. Rotate the clock face while at the same time rotating all the subview numbers the same amount in the opposite direction.
Recommended:
1 Clock without small & Big handle (As Image) set it in ImageView.
2 Another two image view one for Small hand another one for Big hand.
3 Rotate the hands(UIImageView) by using the below code as you needed.
#define DEGREES_TO_RADIANS(angle) ((angle) / 180.0 * M_PI)
UIImageView *smallHand = set your smallHand image view here;
UIImageView *bigHand = set your bigHand image view here;
// Small hand
CGAffineTransform smallHandTransform = CGAffineTransformRotate(self.transform, (DEGREES_TO_RADIANS(1)));
// Big hand
CGAffineTransform bigHandTransform = CGAffineTransformRotate(self.transform, (DEGREES_TO_RADIANS(1*0.60)));
// Apply rotation
smallHand.transform = smallHandTransform;
bigHand.transform = bigHandTransform;
I knew that question was rotating the label, if you need it apply this transform on UILabel.
I hope somebody will make use of this idea. Good luck :)
Here is the example project
I am working on a writing application, My writing is working fine, but what I want to implement is variable stroke width, so that the writing is very realistic and intuitive, as done by "BAMBOO" and "PENULTIMATE" application.
Firstly I want to tell you what I have tried.
1) In iOS, their is no pressure detection, or velocity detection according to my research. For velocity detection, I have to use OPENGL.
2) Due to these limitations, I tried using the method given in this tutorial which is pretty straight forward.Here is the link http://mobile.tutsplus.com/tutorials/iphone/ios-sdk-advanced-freehand-drawing-techniques/
3) This works fine, But here what happens is that, the width increases as I move faster and decreases, as I move slower. But I want is the opposite effect, that is the width should increase as I move slower and when I move fast, the thickness should only be seen only at the edges and for the whole line.
Here are the screenshot of the BAMBOO app and my app.
1)BAMBOO app
In the above image, the line is drawn with speed and you will see that the thickness is only at edges.
2) MY APP
Here you will see that the line is thinner at edges and thick every where else.
So, here are my doubts
1) Is their any better approach to fulfil my requirement, other than what I have tried.
2) If what I have tried, is correct approach to tackle the problem, then what changes I need to make to achieve the desired effect.
Regards
Ranjit
The answer to how to reverse the width behaviour and (and even the same question as yours) is right there in the link that you posted. All I did was to search for the word "width"
The question (my highlighting is not part of the quote):
The final version of this seems to work opposite of the first version. I would like to have the line thicker as the user moves slower and not thinner. Where do I change the code to inverse the final varying thickness to perform or like a pen? Meaning the slower the user moves the thicker or more ink the pen puts down... Thanks! Great tutorials, btw...
And the answer:
thanks for the great tutorial!
with these changes i got the opposite line width cahnge effect:
#define CAPACITY 100
#define FF 20.0
#define LOWER 0.01
#define UPPER 1.5
float frac1 = clamp(FF/len_sq(pointsBuffer[i], pointsBuffer[i+1]), LOWER, UPPER); // ................. (4)
float frac2 = clamp(FF/len_sq(pointsBuffer[i+1], pointsBuffer[i+2]), LOWER, UPPER);
float frac3 = clamp(FF/len_sq(pointsBuffer[i+2], pointsBuffer[i+3]), LOWER, UPPER);
Another search in the same link for the text "float frac1 =" shows that this change should be applied to lines 76-78 (somewhere inside touchesMoved:withEvent: in the code from the article)
In your touchesBegan: method, UItouch is supplied.
UITouch has below instance functions,
– locationInView:
– previousLocationInView:
And below property
#property(nonatomic, readonly) NSTimeInterval timestamp
From the above, i think you can easily calculate velocity.I didn't go through any of mentioned links.I just want to give you an idea of how to calculate velocty based on touch object.
Since I saw this menu drag concept, I have really been interested to find out how to accomplish it.
So I am wondering how I would go about dragging with a cloth-effect in a UIView?
I know how to drag items, but how do you give them the ripple effect?
(Better image: http://dribbble.com/shots/899177-Slide-Concept/attachments/98219)
In short: it’s really, really hard. The old Classics app achieved something along those lines using a series of pre-rendered smooth paper images under a simple transform of their view content, but as you can see from those screenshots (and the one below—note that the text at the bottom is still making a straight line, since it’s getting a basic perspective transform), the effect was fairly limited.
The effect shown in that Dribbble design is much more complicated, since it’s actually doing a scrunching-up warp of the view’s content, not just skewing it as Classics did; the only way I can think of to do that exact effect on iOS at present would be to drop into OpenGL and distort the content with a mesh there.
A simpler option would be to use UIPageViewController, which will at least you the nice iBooks-style curling paper effect—it ain’t fabric, but it’s a lot easier than the GL option.
There is an open source reimplementation of this already.
This blog post: Mesh Transforms covers the private CAMeshTransform. Rather than treating a CALayer as a simple quad, it allows CALayers to be turned into a mesh of connected faces. This class is how Apple has been able to implement the page curl and iBooks page turning effects.
However, the API doesn't tolerate malformed input at all well and Apple has kept it a private API.
If you keep reading that blog post though you'll come to this section just after the bit about it being private API.
In the spirit of CAMeshTransform I created a BCMeshTransform which copies almost every feature of the original class.
...
Without direct, public access to Core Animation render server I was forced to use OpenGL for my implementation. This is not a perfect solution as it introduces some drawbacks the original class didn’t have, but it seems to be the only currently available option.
In effect he renders the content view into an OpenGL texture and then displays that. This lets him mess around with it however he likes.
Including like this...
I encourage you to check out the demo app I made for BCMeshTransformView. It contains a few ideas of how a mesh transform can be used to enrich interaction, like my very simple, but functional take on that famous Dribbble.
What famous Dribbble? This one:
Here is what the example looks like:
Open source project: https://github.com/Ciechan/BCMeshTransformView
Example Implementation of the curtain effect: BCCurtainDemoViewController.m
How does it work?
It sets the BCMeshTransformView up with some lighting and perspective.
// From: https://github.com/Ciechan/BCMeshTransformView/blob/master/Demo/BCMeshTransformViewDemo/BCCurtainDemoViewController.m#L59
self.transformView.diffuseLightFactor = 0.5;
CATransform3D perspective = CATransform3DIdentity;
perspective.m34 = -1.0/2000.0;
self.transformView.supplementaryTransform = perspective;
Then using a UIPanGestureRecognizer it tracks the touches and uses this method to build a new mesh transform every time the users finger moves.
// From: https://github.com/Ciechan/BCMeshTransformView/blob/master/Demo/BCMeshTransformViewDemo/BCCurtainDemoViewController.m#L91
self.transformView.meshTransform = [BCMutableMeshTransform curtainMeshTransformAtPoint:CGPointMake(point.x + self.surplus, point.y) boundsSize:self.transformView.bounds.size];
// From: https://github.com/Ciechan/BCMeshTransformView/blob/master/Demo/BCMeshTransformViewDemo/BCMeshTransform%2BDemoTransforms.m#L14
+ (instancetype)curtainMeshTransformAtPoint:(CGPoint)point boundsSize:(CGSize)boundsSize
{
const float Frills = 3;
point.x = MIN(point.x, boundsSize.width);
BCMutableMeshTransform *transform = [BCMutableMeshTransform identityMeshTransformWithNumberOfRows:20 numberOfColumns:50];
CGPoint np = CGPointMake(point.x/boundsSize.width, point.y/boundsSize.height);
[transform mapVerticesUsingBlock:^BCMeshVertex(BCMeshVertex vertex, NSUInteger vertexIndex) {
float dy = vertex.to.y - np.y;
float bend = 0.25f * (1.0f - expf(-dy * dy * 10.0f));
float x = vertex.to.x;
vertex.to.z = 0.1 + 0.1f * sin(-1.4f * cos(x * x * Frills * 2.0 * M_PI)) * (1.0 - np.x);
vertex.to.x = (vertex.to.x) * np.x + vertex.to.x * bend * (1.0 - np.x);
return vertex;
}];
return transform;
}
I use a lot of CCEase* functionalities in Cocos2D described here. iOS 7 Sprite Kit also have SKActionTimingMode. However only simple modes. How can I get CCEaseElasticIn or CCEaseBounceIn like effects using Sprite Kit?
Sprite Kit left easing (or tweening) intentionally limited with the expectation that the developer would take control of the specifics of the motion of the sprites. Basically, what you need to do is make a custom action and apply an easing curve to the parameter before changing the property (rotation, position, scale, etc) of the sprite. Here's an example.
CGFloat initialScale = mySprite.xScale;
SKAction *scaleAction = [SKAction customActionWithDuration:duration actionBlock:^(SKNode *node, CGFloat elapsedTime) {
CGFloat t = elapsedTime/duration;
CGFloat p = t*t;
CGFloat s = initialScale*(1-p) + scale * p;
[node setScale:s];
}];
[mySprite runAction:scaleAction];
The part of this that determines the easing is p = t*t. So, p is a function of t such that :
when t is 0, p is 0
when t is 1, p is 1
That means that you will start at the beginning and end at the end but the shape of the curve in between will determine how you get there. Easing functions can be simple, like the one shown here, which is basically an ease-in, or quite complex such as elastic or bounce. To generate your own, try this : http://www.timotheegroleau.com/Flash/experiments/easing_function_generator.htm
Or take a more detailed look at Robert Penner's equations: http://www.robertpenner.com/easing/
For arbitrary easing, Kardasis' answer says it all.
If you're looking for an easy way to add a bouncing effect to your animations, that is consistent with the way things are done in UIKit, I have something for you.
Apple introduced spring animations in UIKit a couple years ago, by letting you set a spring damping and initial velocity when performing a UIView animation. Unfortunately they didn't implement that in SpriteKit, so I made my own library that does just that.
It's a set of extensions on SKAction that replicate most factory methods, adding the damping and velocity parameters.
The code is on GitHub, feel free to use it: https://github.com/ataugeron/SpriteKit-Spring
When I use either of the following pieces of code, the button rotates in 3D rather than 2D (flat against the screen). How can I avoid the 3D behavior? Here's what the button looks like during the rotation:
CGAffineTransform rotationTransform = CGAffineTransformIdentity;
rotationTransform = CGAffineTransformRotate(rotationTransform, (offset/(180.0 * M_PI)));
button.transform = rotationTransform;
.
button.transform = CGAffineTransformRotate(CGAffineTransformIdentity, (offset/(180.0 * M_PI)));
.
button.transform = CGAffineTransformMakeRotation(offset/(180.0 * M_PI));
Here's the answer from an Apple employee:
When you set a transform the frame becomes less well-defined, to the
point that you should no longer use it to size or position a view. Try
using the center property instead, your probably not getting a 3D
rotation, but a distortion due to the compounding effect of setting
the frame and trnsform.
I met the same problem which is really annoying, and I got it settled at last, though still have no idea why.
I got unexpected 3D rotations when I tried to perform a 2D rotation in "viewDidLayoutSubviews" method with
double radius = (degree / 180.0) * M_PI;
uiImageView.transform = CGAffineTransformMakeRotation(radius);
My solution is to perform transforming elsewhere other than "viewDidLayoutSubviews" and it is working perfectly.
Interestingly, when the annoying 3D rotation happens, and I keep orienting my iPhone for a while, the 3D rotation will disappear suddenly and 2D rotation will come back and take the place, but the image stays at a distorted shape. I guess maybe iOS is doing some internal transforming in "viewDidLayoutSubviews" and things get messed up if we impose additional transforming on it. However, my guess cannot explain why it disappears after a while. I also tried to NSLog the members of "uiImageView.transform", say, "a, b, c, d, tx, ty" in "viewDidLayoutSubviews" but got no clue.
SOLUTION: Check your code to see if you are performing the rotation in "viewDidLayoutSubviews" or some similar method, and if yes, try to move it out to elsewhere and cross fingers.