I want to zoom a CAlayer placed on UIView, and this view is on UISCrollview. I'm using scrollviews delegate methods for zooming. It zooms but it blurs. How to remove blur and improve zooming?
I have tried with CATiledLayer but I don't want to show tiling effect. So how can I improve zooming using CALayer?
I had a similar experience when zooming in content. When a UIScrollView is zooming, it takes a snapshot of the View, and zooms in on that picture. This is the reason it gets blocky when zooming. When the zooming/panning is complete, use the delegate to re-render the content according to your zoom level. The content then should be 'crisp'.
Warning: do not zoom in too far, the memory used by the snapshot will soon be larger than your available memory.
I didn't use images, but CAShapeLayers and paths. I put together a demo project and explanation here : http://simplicate.weebly.com/1/post/2013/06/fixing-blocky-paths-in-ios.html
I hope that helps.
Related
I'm making simple number coloring game (like sandbox, pixel art, unicorn, etc) and came across a problem. I tried various methods of filling rects in the screen.
At first i created a backgroundView(a simple UIView) which had 2500 subviews(also UIViews), each one had size = (CGSize){50,50}. Added a tap gesture recognizer, detected which view should be filled, and simply changed the background color of that view. But when i placed the backgroundView in the scrollView, the scroll and zooming were awful.
Tried same thing but this time each rectangle was a CALayer. So a backgroundView, which had 2500 sublayers(each was a CALayer with 50,50 size) - zoom and scroll was also awful.
Tired to use custom drawing with overriding drawRect method in UIView subclass or drawInContext in CALayer subclass(i was filling rects with CGContext), this time problem was also caused by the zooming and scrolling. Because i needed to update every rect when user zooms, it was triggering a lot of drawRect calls, and performance was also bad.
Any thoughts how can i fill rects in the screen ?
Explanation
Yup! Adding 2,500 tiny UIViews to a scroll view can destroy performance. I wouldn't use that approach, but if you do, at least make sure that subview_N.opaque = YES; on all subviews to disable compositing.
The CALayer approach that you described is basically the same as the UIView approach because views are backed by CoreAnimation layers (see -[UIView layer]).
The best options for drawing thousands of rectangles to the screen on iOS without decimating frame rate, is to use one of the following approaches:
Draw directly using CoreGraphics
Draw directly using OpenGL (extremely involved)
Use a layout engine such as UICollectionViewLayout
Now, you said you had tried overriding -[UIView drawRect:], but you didn't provide any example code for us to checkout. Please update your question with actual code for method #3 if you want more specific feedback. It's very likely that something is wrong with the drawRect code you created. CoreGraphics can definitely draw thousands of squares on screen without dragging frame rate down that badly.
One Solution
I recently released a project, YMTreeMap, that draws thousands of rectangles into a UIView to create financial TreeMaps. It's in Swift, not Objective-C, but the underlying concepts are the same. For this, I created a custom UICollectionViewLayout that lets Apple's well tested UICollectionView class handle the nitty gritty of selective drawing, zooming and animation.
The example UIViewController code in the YMTreeMap project shows how to draw thousands of colored rectangles to the screen if all you know is their location and size. This sounds like what you are doing. Since you're also scrolling and zooming, this solution might be perfect for you because UICollectionView has native support for both of those.
I have a simple metal setup which draw image in the middle of MTKView. I wish I could add pinch zoom and other functionality as we have in scroll views, so i can zoom image and move it around with some thresholds.
I also don't want to implement it myself since my app will live in both Mac OS and iOS and this is twice more code to support and write.
Is there a way I could use default scroll view controlls to manipulate my projection? I mean set scroll view somehow on top of my view and get some data in delegate manner or whatever.
Any help would be appreciated!
You may want to try Metal2DScrollable sample code. The idea is that:
place MTKView behind (not a subview) UIScrollView,
Place dummy content view as a subview of UIScrollView
Make the dummy content view to be the target of zooming
Set up UIScrollView properly such as contentSize, contentInset etc.
Make both UIScrollView and dummy content view to be transparent
Calculate transform from dummy content view's bounds -> MTKView's coordinate -> device coordinate
Apply that transform when rendering with Metal
So, MTKView is not in the UIScrollView, but this tricks fools user's eyes.
https://github.com/codelynx/Metal2DScrollable
The same technique may work with macOS with some tweaks, but I haven't tried.
I am going through the sample code (https://github.com/vfr/Reader), and tried to add the same zooming effect in all the pages at the same time. for ex: if the user increase the zoom effect in 2nd page it will set the same zoom effect in all the pages. Not getting any idea how to do this...Edit:
In Short,how to resize all the subviews of UIScrollView according to the zoomin / zoomout.
The reader you are using provides zoom in and zoom out options by default. If that doesn't work just check if you have allowed multiple touches.
I have an UIScrollView. My most of the operations are on the zoom level of UIScrollView. I test using instruments, at normal zoom level (i.e 1) its taking less memory but when I zoom its taking too much memory and crashing also.
Detailed scenario:
I took UIView as subview of UIScrollView. I am drawing some shapes on it.
I have to show information in these shapes when the UIScrollView zoomed. So I am adding information view on UIScrollView when zoomed and remove it when zoomed out.
I need to know, whether UIScrollView takes more memory on zoom or my approach is wrong?
UIScrollView itself does not define drawRect: so it takes only small amount memory for storing its properties.
When zooming UIScrollView applies scale transform to the contents view returned from viewForZoomingInScrollView:. This does not change amount of memory consumed by the contents view, just changes its visible rectangle. So if your app crashes when zooming look at the code you execute when/after zooming.
I need to implement an "infinite scrolling" timeline, where the pinch-to-zoom will change the scale of the timeline rather than zoom on the underlying view, almost exactly like the scroll view of the app iStreamer (see below). I don't think I can do this with UIScrollView and am considering implementing a custom UIView that draws the timeline and its contents.
Are there any classes/formulas/constants that can provide the physics simulation behind the "glass on liquid" effect of inertial scrolling?
iStreamer (above) has overlapping touchable elements and inertial scrolling. They might be doing this with a regular UIScrollView, but I don't know how to achieve the same effect. I need to add elements that could span very wide stretches (years or decades on a timeline).
Just use a UIScrollView, and don't allow zooming on the scrollview. Instead, add a pinch gesture recognizer which implements the desired behaviour for the pinch behaviour.
Use UIGestureRecognizer as jer suggested, otherwise this might help: http://macresearch.org/dynamics-scrolling