Today we have easy to difficult divided into three parts. In the first part, we will draw the corresponding graph, and the graph can be dragged for each point, and in the process of dragging, we will redraw it. The second part will undrag and use the UIView animation to transform itself. You can also use Timer or GCD’s TimerSource to make it move. The third part is an upgrade of the second part, and we make some improvements on the basis of the second part. In this part, we use DispatchSourceTimer to make each point move. In the third part we connect points of local scope, that is, in the process of motion, we need to find out what points are within the specified range of the current point, and then connect these points.

The contents of the above three parts will be introduced in detail below, and the corresponding running results will be attached. So let’s move on to our theme.

First, the drawing of the graph

In the first part of this blog, we will draw the graph according to the requirements. We will randomly generate several coordinate points, and then add View on these coordinate points, and then connect these coordinate points using Bezier. Of course, when we join, we use the adjacency matrix to record the relationship between each two points. During the drawing process, we randomly assign colors to each point and edge.

When the corresponding graph is drawn, we need to add Move events for each point. When dragging each point, we will redraw the relationship of the whole graph in time. Below is the operation effect of the content we want to achieve in this part, as follows:

It is not difficult to achieve this effect if you understand the construction of graphs in data structures. Let’s take a look at the core code to achieve the above effect.

1. Packaging of View node of graph

First of all, we will encapsulate the node View of the above graph. Of course, the packaging of this node View is relatively simple. The core is to add a TouchesMoved event to each node View, and then when the TouchesMoved event executes, set the move point of the touch to the Center of the current View. So we can drag each node View. When dragging a node View, we also need to call back the drag event to the parent View of the node View to let the parent View know which View the current user is dragging. Let’s take a look at the core code of the node View.

The upper part of the code below is a closure type that we define to call back the node View’s touch events to the parent View. This closure type requires passing a single parameter, the current View’s Tag, so that the superview knows which node the current user is dragging.

The randomColor() function is used to randomly generate the color, using the UIColor object randomly generated by the function below.

The bottom section is the ‘TouchesMoved’ event of the node View. In this event, we get the coordinate point of the current user’s touch move, assign that point to the Center of the node View, and call the closure callback object that updates the parent View. As follows:

2. Diagram View encapsulation

Now we’re going to implement the drawing View, which is the superview of the node View above. The main job of the parent View is to create the above node View and then connect each node using Bezier. Of course, the current diagram needs to be redrawn as the user drags the corresponding View.

The method below is to add the corresponding node view to the parent view, and after the node view is initialized, to set up a closure callback that moves the redrawing of the diagram. In the closure callback, we call the drawLine() method. Of course, when we create the node View, we also create the corresponding BezierPath object. Each node corresponds to a BezierPath object, which is used to draw the line of the nodes to which the node is connected. The specific code is as follows:

The relationship of our whole graph is stored in the adjacency matrix, so we need to create the adjacency matrix, and initialize the adjacency matrix during the redrawing. Below is the code for creating and initializing the adjacency matrix. I won’t say much about the adjacency matrix here. Please refer to the previous blog for details.

With the node View and adjacency matrix ready, it’s time to draw lines. Below is the core code for drawing lines. Before drawing lines, we need to remove the points on the corresponding BezierPath object, and then add new points. Finally, we need to redraw. When we add points to the BezierPath object, we record the relationship of the nodes in the adjacency matrix. If the lines are drawn between the two points, we set the contents of the adjacency matrix to true, and the undrawn nodes to false. The specific code is shown below.

After the above method calls the setNeedsDisplay() method, the View’s draw() method is executed, where we draw the line. Of course, the following code is relatively simple, so I won’t go into too much detail here.

The code above is the core of the renderings shown in this section. For a complete example, check out the Github share at the end of this blog post.

2. Automatic transformation of graphs

In the previous section, we manually dragged the created graph to transform, and now we modify the above code to transform it automatically. When the dot moves automatically, if it hits the edge of the screen, we let it bounce back and move on. Below is what we want to achieve in this section.

Of course, with the first part as the base, we can achieve this part of the effect is not complicated. What we need to do is randomly generate the direction in which each node moves. And then we decide if we’re moving out of the screen, and if we’re moving out of the screen we need to modify the direction of motion to move in the opposite direction. In this section we only need to modify the node View, and the parent View of the node View is not modified.

The following code slice is designed to transform the implemented method automatically. The two methods below will replace the ‘TouchesMoved’ method of the first part. The randomIncrement() method below is used to generate the x and Y offsets of the current View. An offset of x of 1 means a move to the right, and -1 means a move to the left. Y offset of 1 is going down, -1 is going up.

The changePoint() below is a method that continually modifies the coordinates of the current node View based on the offsets of x and y. For simplicity, we use Animate, which comes with UIView. When changing the x and y values, determine whether the screen is beyond the edge of the screen, and if so, move in the opposite direction. To keep the point moving, we need to keep calling the changePoint() method, as shown below. Of course, every time we call the changePoint() method, we need to call the redrawn callback. The specific code is shown below.

3. Draw a map in a specific area

So what we’re going to do is we’re going to continue to do a few things in the above. In the process of automatic node movement, we do not connect all the points. What we want to do in this part is that when the point moves, we delimit a region with the center of the change point. If there are other points in this region, we connect the points in this region. If the point moves beyond the defined range, we remove the line we drew earlier. The effect is as follows:

The main modification of this part is the parent View of the node View, the core is to calculate the distance between the current point and the surrounding point, if the distance is less than the distance we specify, then we draw a line, otherwise we do not draw a line. The code snippet below is the core code for this section. It’s basically a distance judgment when you add a point to a Bezier. The countDistance() function below is used to calculate the straight-line distance between two points, and is called in areaPoints() to determine the points in the current region. The core code is as follows:

4. Click Add Node

This section will also be updated on the code in the above section. What this section does is click on the screen to add a new node to the screen. This point is relatively simple to implement on the basis of the above. Just add a new node to the parent View of the node. Below is the effect to be achieved in section 4. Every time the screen is clicked, a node will be generated where the screen is clicked, and the node will move. The specific effect is shown below.

To achieve this, below is the code snippet we modified. Just add a ‘TouchesEnded’ event to the superview and generate a node View where it is clicked. The details are as follows:

Any questions? The correct? Please add our communication groupClick here to enter the communication groupTo communicate or post your questions, comments or feedback.

Thanks for reading ~ click “like” and then go! 🚀

Author: Qingyu Fu Case

Reference: www.cnblogs.com/ludashi/

The copyright of this article belongs to the author and the common blog park, welcome to reprint, but without the consent of the author must retain this statement, and give the original link in the obvious position of the article page, otherwise reserve the right to pursue legal responsibility.