Interaction with a complex figure in iOS

I need to be able to interact with the view galvanizing, in which there are many different parts. When users click on the small rectangles, I need to display a popover associated with a specific part (form).

The following image shows a realistic 3D approach. But, I repeat, I need to solve the problem, 3d is not required (it would be really cool). Enough performance satisfying functional needs.

Information about the parts for creating the drawing comes from the API (size, position, etc.)

enter image description here

I do not need this to be realistic. The simplest approximation would be to show the cylinder in the 2d view as a rectangle made of interactive small rectangles.

So, as I mentioned, I think that there are (as I see) two opposing approaches: Realistic or simplified

Is there a way to achieve a good solution in the middle? What libraries, components, frameworks that I should pay attention to?

My research led me to SceneKit, but I still don't know if I can interact with it. Interaction is a very important part as I need to display a popover when the user clicks on the small rectangle above the cylinder.

thanks

+5
source share
4 answers

You do not need a special framework to achieve this interaction. This effect can be achieved using standard UIKit and UIView and small trigonometry. You can draw exactly your example image using 2D math and drawing. My answer is not an exact formula, but involves thinking about how the shapes are defined and break the problem down into manageable steps.

The cylinder may be defined by two offset circles representing end parts connected along their radii. I will use a spelling projection, meaning that the cylinder does not get smaller as the depth passes in the background (but you can adapt to perspective if necessary). You can do this with CoreGraphics in a UIView drawRect .

The square cut is the angular part of the circle, offset by an amount shorter than the length of the cylinder, but in the same direction as in the following diagram (sorry for the inaccurate drawing).

enter image description here

This square fragment that interests you is the area highlighted in solid red, outside the radius of the first circle and inside the radius of the imaginary second circle (which is simply offset from the first circle by any length, slice).

To draw this area, you just need to draw the path of the outline of each arc and connect the end points.

To check if a touch is inside one of these square slices:

  • Check if the tangent point is between the angle a from the origin at a .
  • Check if the touch point is outside the radius of the inner circle.
  • Check if the touch point is inside the radius of the outer circle. (Note that this means if the circles are larger than the radius.)

To find the point to display the popover, you can average the end points on the slice or find the average angle between two edges and the offset by half the distance.

+2
source
Theoretically, doing this in a scene set using SpriteKit or UIKit Popovers is ideal.

However, the Scene Kit (and the Sprite Kit) seems to be in a stream state in which no one at Apple communicates with users about the many problems that people are currently facing with both. From the relatively stable and experienced Sprite suite in iOS 8.4 to the many lost features in iOS 9, it seems commonplace. The Scene Kit simply does not seem complete, and as a result, the documentation and the community almost do not exist.

That said ... the theory is this:

Material identifiers are used in traditional 3D applications to identify areas of an object with different materials. Somehow, these material identifiers are called "elements" in SceneKit. I could not find much more about this.

It should be possible to detect an “element” that is under the touch of an object and react accordingly. You can even change the state / nature of the material on this element to indicate it at the current moment.

If you need a smooth, well-rounded cylinder according to your example, start with a cylinder consisting of just enough segments to describe / define the material identifiers that you need for your “rectangular” sections to be touched.

You can later add a smoothing operation to the cylinder to make it round, and all the additional smoothing geometry in each quadrant of the unique material identifier should respond, regardless of how you add this additional detail to smooth the cylinder view.

+1
source

Idea for a "simplified" version:

If this view is okey, you can use UICollectionView. Each cell can have a specific size due to

 collectionView:layout:sizeForItemAtIndexPath: 

Then each cell in the collection can be a small rectangle representing the tangible part of the cylinder.

and using

 collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath 

To touch.

This will help you display the popover in the right place:

 CGRect rect = [collectionView layoutAttributesForItemAtIndexPath:indexPath].frame; 

Finally, you can choose the appropriate popover (if the application should work on the iPhone) here: https://www.cocoacontrols.com/search?q=popover

Not perfect, but I think it is effective!

+1
source

Yes, SceneKit.

When the user executes a touch event, it means that you knew the two-dimensional coordinate on the screen, so your only decision is to overlap the view or not, even the three-dimensional model does not exist.

First, we can logically divide the requirement into two parts, define a touching segment, displaying the correct “color” in each segment.

I think the use of the 3D model is to determine how much of the data will be displayed in your case, if I'm not mistaken. In this case, the SCNView test method will do most of the work for you. What you have to do is perform a hit test, take out the node hit and the local three-dimensional coordinate of this node, you can calculate which segment came under this touch and make a decision.

Now, how to draw a cylinder surface will be the only question on the left, right? There are various ways to do it, for example, just draw each image that you need and programmatically, and attach it to the material of the cylinder or put the image files on the disc and use as material for the cylinder ...

I think the problem will be mostly resolved.

0
source

Source: https://habr.com/ru/post/1232547/


All Articles