I'm using https://bitbucket.org/javieralonso/japanoview to create 360 degree panoramic views for an iOS app. What I want to do now is split the view into 2 identical views and use one input for both of them and be able to use it inside google cardboard. Please help. Thank you.
I once used this as inspiration to do the same thing. https://github.com/nicklockwood/ReflectionView
Set reflection to dynamic. View is mirrored but you can fix if by removing values smaller than zero.
Also translate method to make it next to each other. Remove gradient drawing and you are set to go :)
In storyboard add view you want to duplicate on left half of screen and set its Class to ReflectionView.
Reflection view implementation changes will look like this:
- (void)update {
//update instances
CAReplicatorLayer *layer = (CAReplicatorLayer *)self.layer;
layer.shouldRasterize = YES;
layer.rasterizationScale = [UIScreen mainScreen].scale;
layer.instanceCount = 2;
CATransform3D transform = CATransform3DIdentity;
transform = CATransform3DTranslate(transform, layer.bounds.size.width + _reflectionGap, 0.0f, 0.0f);
transform = CATransform3DScale(transform, 1.0f, 1.0f, 0.0f);
layer.instanceTransform = transform;
layer.instanceAlphaOffset = 1.0f;
}
- (void)setUp {
//set default properties
_reflectionGap = 0.0f;
_dynamic = YES;
//update reflection
[self setNeedsLayout];
}
Related
A have an issue with UIProgressView value. I'm trying to embed ProgressView into Table View cell.
This code works - ProgressView fills it's cell. But there's problem with filling ProgressView itself - it's value rounds to 0.5 (e.g. if value is 0.2 then progressView is not filled, if 0.8 - then it filled 100%, see the image bellow)
Can anyone help with making things right?
CGAffineTransform transform = CGAffineTransformMakeScale(cell.frame.size.width, cell.frame.size.height);
cell.attendanceProgress.transform = transform;
[cell.attendanceProgress setAlpha:0.5];
[cell setUserInteractionEnabled:NO];
float progr = (float)attended / (float)classes.count;
if (classes.count == 0) { progr = 0; }
[cell.attendanceProgress setProgress:progr];
Use
cell.attendanceProgress.frame=CGRectMake(0,0,cell.attendanceProgress.frame.size.width, cell.frame.size.height);
CATransform3D transform = CATransform3DScale(cell.attendanceProgress.layer.transform, 1.0f,cell.frame.size.height, 1.0f);
cell.attendanceProgress.layer.transform = transform;
Make sure set frame before transform.
I'm trying to create a "page flip effect" using UIView instead of CALayer due to a project limitation. This requires flipping 1 UIView 180 degrees and essentially "sticking it" to the back of the other UIView. You then rotate the two UIViews simultaneously by rotating the superview in 3D space.
I'm trying to port AFKPageFlipper's "initFlip" method to use UIView instead of UIImage.
Below is a snippet of my attempt to port it. The initial page flip works, but the "front layer" in the code doesn't seem to show up. As if I"m not able to see the backend of the page. When I'm flipping the page, the animation is initially correct (back layer is fine), but then the other side of the page (front layer), I see the inverted view of the first page (backLayer).
Any help would be awesome!
flipAnimationLayer = [[UIView alloc] init];
flipAnimationLayer.layer.anchorPoint = CGPointMake(1.0, 0.5);
flipAnimationLayer.layer.frame = rect;
[self addSubview:flipAnimationLayer];
UIView *backLayer;
UIView *frontLayer;
if (flipDirection == AFKPageFlipperDirectionRight)
{
backLayer = currentViewSnap2;
backLayer.layer.contentsGravity = kCAGravityLeft;
frontLayer = nextViewSnap2;
frontLayer.layer.contentsGravity = kCAGravityRight;
}else
{
backLayer = nextViewSnap2;
backLayer.layer.contentsGravity = kCAGravityLeft;
frontLayer= currentViewSnap2;
frontLayer.layer.contentsGravity = kCAGravityRight;
}
backLayer.frame = flipAnimationLayer.bounds;
backLayer.layer.doubleSided = NO;
backLayer.clipsToBounds = YES;
[flipAnimationLayer addSubview:backLayer];
frontLayer.frame = flipAnimationLayer.bounds;
frontLayer.layer.doubleSided = NO;
frontLayer.clipsToBounds = YES;
frontLayer.layer.transform = CATransform3DMakeRotation(M_PI, 0, 1.0, 0);
[flipAnimationLayer addSubview:frontLayer];
if (flipDirection == AFKPageFlipperDirectionRight)
{
CATransform3D transform = CATransform3DMakeRotation(0.0, 0.0, 1.0, 0.0);
transform.m34 = 1.0f / 2500.0f;
flipAnimationLayer.layer.transform = transform;
currentAngle = startFlipAngle = 0;
endFlipAngle = -M_PI;
} else
{
CATransform3D transform = CATransform3DMakeRotation(-M_PI / 1.1, 0.0, 1.0, 0.0);
transform.m34 = 1.0f / 2500.0f;
flipAnimationLayer.layer.transform = transform;
currentAngle = startFlipAngle = -M_PI;
endFlipAngle = 0;
}
Your code is rotating layers, not views. That's fine.
I would not expect the code you posted to animate, since a layer's backing view doesn't do implicit animation, You could make it animate by using a CABasicAnimation. Or, you could create layers for your front and back views and attach them as sublayers of your view's layers. If you do that than manipulating the transform on the layers will use implicit animations.
What I've done to create my own font-to-back flip as you describe is to fake it.
I animate in 2 steps: First from zero degrees (flat) to 90 degrees (where the layers become invisible.) At that moment I hide the first layer and make the second layer visible, rotated 90 degrees the other way, and then rotate the other layer back to zero. This creates the same visual effect as showing the back face of the rotation.
If you use implicit layer animation to do this you'll need to put the changes to the transform inside a CATransaction block and set the animation timing to linear, or use ease-in for the first half and ease-out for the second half. That's because animations default to ease-in,ease-out timing, and the first animation to 90 degrees will slow down at the end, and then the second 90 degree animation will ease in.
I want to draw a pentagon in iOS with UISliders as the circumradii (a set of five UISliders going in different directions and originating from the center of a pentagon). Currently I have rotated five UISliders using a common anchorPoint (:setAnchorPoint), but they dont seem to originate from a common point.
How can I go about this? Do I need to start working on a custom control? What more from Quartz2D can I use?
Some specific indicators would be useful (please don't just say "Use Quartz2D")
Here is what I have achieved Imgur
And here is what I want to achieve Imgur
I defined the various sliders as an IBOutletCollection, so I can access them as an array in the controller. Then I run the following code in viewWillAppear:
CGPoint viewCenter = self.view.center;
for (NSInteger i = 0, count = self.sliders.count; i < count; ++i) {
UISlider *slider = self.sliders[i];
CGFloat angle = 2.0f * M_PI / count;
CALayer *layer = slider.layer;
layer.anchorPoint = CGPointMake(0.0f, 0.5f);
layer.position = viewCenter;
layer.transform = CATransform3DMakeRotation(i * angle - M_PI_2, 0.0f, 0.0f, 1.0f);
}
Here's a screenshot of the result:
Is this that you want?
I would try just to turn the sliders. The following code should help:
firstSlider.transform=CGAffineTransformRotate(firstSlider.transform,72.0/180*M_PI);
secondSlider.transform=CGAffineTransformRotate(secondSlider.transform,144.0/180*M_PI);
//and so on
The 72.0/180*M_PI is transformation of degrees to radians.
Hope it helps.
P.S. don't have a mac nearby to check if it works
I would like to transform a UIView in way that adds a perspective (with two vanishing points) to it (see below).
The reason why I want to do this with a view is because I want the contents of the transformed view to be the cells of a UITableView.
I am new to this kind of coding but I assume that I would have to change the CALayer that belongs to the subview. However, I believe, the transformation I am interested in cannot be created using CATransform3D.
Does anyone have an idea how to approach this problem?
It seems I have found a way to circumvent/solve the problem:
Using CATransform3D transformations it is possible to approximate the to vantage points by splitting the view into two parts (two independent UITableViews). These should be managed by a UIViewController (not the UITableViewController provided by x code) which implements the necessary and protocols.
Then in the viewDidLayoutSubviews: method use the following code to transform the two tableviews.
- (void) viewDidLayoutSubviews {
CATransform3D rotationAndPerspectiveTransform = CATransform3DIdentity;
// left View
// vantage point
rotationAndPerspectiveTransform.m34 = 1.0 / -150.0;
// Z-rotation of 90°
rotationAndPerspectiveTransform = CATransform3DRotate(rotationAndPerspectiveTransform, 90.0 * M_PI/180.0, 0, 0,1);
// X-rotation of 25°
rotationAndPerspectiveTransform = CATransform3DRotate(rotationAndPerspectiveTransform, -25.0 * M_PI/180.0, 1, 0,0);
// left view
[self.view viewWithTag:1].layer.transform = rotationAndPerspectiveTransform;
//right view
rotationAndPerspectiveTransform = CATransform3DIdentity;
rotationAndPerspectiveTransform.m34 = 1.0 / -150;
// Z-rotation of 90°
rotationAndPerspectiveTransform = CATransform3DRotate(rotationAndPerspectiveTransform, 90.0 * M_PI / 180.0, 0, 0,1);
// X-rotation of 30°
rotationAndPerspectiveTransform = CATransform3DRotate(rotationAndPerspectiveTransform, 25.0 * M_PI / 180.0, 1, 0,0);
// right view
[self.view viewWithTag:2].layer.transform = rotationAndPerspectiveTransform;
}
Once transformed the two tableview can be shifted so that they neatly fit together. The only remaining job is to connect the scrolling of one tv with the other. I haven't figured that one out yet.
Twitter for iPad implements a fancy "pinch to expand paper fold" effect. A short video clip here.
http://www.youtube.com/watch?v=B0TuPsNJ-XY
Can this be done with CATransform3D without OpenGL? A working example would be thankful.
Update: I was interested in the approach or implementation to this animation effect. That's why I offered bounty on this question - srikar
Here's a really simple example using a gesture recognizer and CATransform3D to get you started. Simply pinch to rotate the gray view.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// ...
CGRect rect = self.window.bounds;
view = [[UIView alloc] initWithFrame:CGRectMake(rect.size.width/4, rect.size.height/4,
rect.size.width/2, rect.size.height/2)];
view.backgroundColor = [UIColor lightGrayColor];
[self.window addSubview:view];
CATransform3D transform = CATransform3DIdentity;
transform.m34 = -1/500.0; // this allows perspective
self.window.layer.sublayerTransform = transform;
UIPinchGestureRecognizer *rec = [[UIPinchGestureRecognizer alloc] initWithTarget:self
action:#selector(pinch:)];
[self.window addGestureRecognizer:rec];
[rec release];
return YES;
}
- (void)pinch:(UIPinchGestureRecognizer *)rec
{
CATransform3D t = CATransform3DIdentity;
t = CATransform3DTranslate(t, 0, -self.view.bounds.size.height/2, 0);
t = CATransform3DRotate(t, rec.scale * M_PI, 1, 0, 0);
t = CATransform3DTranslate(t, 0, -self.view.bounds.size.height/2, 0);
self.view.layer.transform = t;
}
Essentially, this effect is comprised of several different steps:
Gesture recognizer to detect when a pinch-out is occurring.
When the gesture starts, Twitter is likely creating a graphics context for the top and bottom portion, essentially creating images from their layers.*
Attach the images as subviews on the top and bottom.
As the fingers flex in and out, use a CATransform3D to add perspective to the images.
Once the view has 'fully stretched out', make the real subviews visible and remove the graphics context-created images.
To collapse the views, do the inverse of the above.
*Because these views are relatively simple, they may not need to be rendered to a graphics context.
The effect is basically just a view rotating about the X axis: when you drag a tweet out of the list, there's a view that starts out parallel to the X-Z plane. As the user un-pinches, the view rotates around the X axis until it comes fully into the X-Y plane. The documentation says:
The CATransform3D data structure
defines a homogenous three-dimensional
transform (a 4 by 4 matrix of CGFloat
values) that is used to rotate, scale,
offset, skew, and apply perspective
transformations to a layer.
Furthermore, we know that CALayer's transform property is a CATransform3D structure, and that it's also animatable. Ergo, I think it's safe to say that the folding effect in question is do-able with Core Animation.