In the early days of front-end requirements development, the UI would be sketched and exported to us as a zip package for page annotations; In the future, the company used Blue Lake, and instead of sending us a labeled ZIP package, the designer simply sent us a link. At that time, when I contacted “Blue Lake”, I was amazed by it. It was so convenient and easy to use. I never thought that I would write a similar one later. Back in the early days of zip packages, let’s look at the directory structure inside. It’s simple:
.├ ── assets ├─ index.html ├─ links ├─Copy the code
Click on index. HTML to see the annotations for the page. How is this annotation generated? Sketch-measure is used, which can export all sketchboards of Sketch. Each sketchboard page contains detailed “annotation data”, which can be simply understood as a collection of layers. Each layer can also be viewed simply as an HTML tag (div, span, img), and each layer has its size and placement (using absolute positioning, centered at the top left corner of the artboard (0,0)). In the annotation file exported by Sketch – Measure, this part of data is stored in the head of index. HTML. You can see “annotation data” by searching SMApp.The data we use here is extracted from a plug-in of Sketch (called “Magic Brush”) developed by ourselves. The magic brush is responsible for extracting and parsing Sketch data, optimizing data, processing icon pictures and other work. Magic Brush Ma Liang is a relatively large system, and the annotation function in this paper is only one of the function points of Ma Liang. If you want to know more, please refer to previous articles:Explore the development and practice of intelligent code platform Magic Brush. However, annotation is relatively independent, and the “annotation data” structure used is not too different from that derived by Sketch – Measure (PS). Json data extracted from the Sketch file.
Copy this data (actually json) and format it to see the data structure:In its structureartboardsThe storage is all the sketchboards in the current Sketch (the sketchboards are ≈ pages for easy understanding here), in a specific sketchboardWidth, height,Mark the width and height,imagePathThis is the preview image of this artboard.layersThis is all the layers (HTML tags) contained in the artboard (page). aboutlayerOne thing that needs to be emphasized here, every one of themlayerThey’re all rectangles. The structure inside each layer is as follows, of which we are concernedrectandcssThese two fields. rectIt shows the absolute position of the layer and its width and height,cssAre some CSS properties of their own. By now, the data is available and the structure of the data is understood. The next step is to display and process these layers:To do a simple loop, we can add a 1px border to each layer to see how it looks:Here we see the basic skeleton of the page, sort of like a skeleton screen. I mentioned it earlier when I introduced data structuresimagePathThis field, let’s takeimagePathThe corresponding preview renderings are pasted as a background, and the feeling is that there are some taste.It looks so much better. Then we optimized the border of these layers. We didn’t want it to be displayed all the time (after all, it wasn’t pretty) and only displayed when I mouse over it, so we needed to use the hover pseudo-class:The effect here can be directly imagined, not above, the basic appearance is there. Then, we also want to keep improving, others have we also have 🤔.
When the mouse is over, we also see the effect shown belowReference line.How do you do that? Here we can switch gears, we don’t have to actually draw lines, you can see that these four lines can be the intersection of two long rectangles.The reference line you see in the figure is actually the border (border-style: dashed module) of the two rectangles. If the background of the rectangle is set to transparent, it has achieved the desired effect.
After we finish dealing with the hover of the mouse, we need to consider the effect of clicking/selecting a certain layer (as shown below ⬇️).What I’m doing here is listening for the onClick event of the outer div, getting the layer of the object clicked in the click event, and dynamically adding and deleting styles.The data shown at the top and right of the layer (red background and 35px/20px) is implemented using the before&After elements.The content shown (35px/20px) relies on the Content property to take the data-width and data-height data from the current clickdiv layer property. Ps. These two data have been brought together in the previous circular layering (as shown below).At this point in the article, a simple Sketch annotation feature is about as good as it gets, but we need to do a few more things: when selecting a layer, moving the mouse over the other layers helps me measure the distance between the two layers, like ⬇️ :The line here is supposed to be an orange line, but it’s really a line (not a rectangular border). There are two ways of thinking about it: ① if we know where the two ends of a line are, we can draw the line; ② if we know where one end of the line is and how long the line is, we can draw it. With CSS, you need to calculate the distance between two points and the Angle of inclination. Set a line with a height of 1px and a width of the distance between the two, and then rotate it around a point to the Angle of inclination.Thinking ② has certain limitations, can only be horizontal or vertical direction. Set the height to 1px for the horizontal direction and the width to 1px for the vertical direction.In combination with the actual use scenario, we adopt scheme ② here; The reason is that we only need horizontal or vertical lines to write less code. The scheme is determined, then we need to determine the starting point of each line, from each reference point (starting point) to calculate the line length (distance from each edge of the distance).
Before we decide on the reference point, we need to be clear that if we want to show distance data, we need to have at least two layers. One layer is our selected- layer (marked with a solid orange border). The other is the hover- layer (marked with a solid blue border) to which we moved the mouse. Since the hover- layer is variable, it is a little more complicated to calculate the starting point based on it, so we choose the selected-layer to calculate the reference point. The position of the reference point, as shown in the renderings, is the midpoint of each side of the selected layer. When traversing to generate each layer, we already have the upper-left corner position (x1, y1) and width and height (w, H) of each layer. We can easily calculate the center point position of the edge of the layer, and there will be 4 points in total.We’re going to skip the calculation, and once we’ve got each starting point, the next step is to figure out the length of each line. Taking the left distance as an example, the distance between selected-layer and hover-layer is the distance between the left X-axis of the two layers, and the distance can be obtained as: X1 – X2. Other edges are similar in length:So now that we have all this data, we’re going to start drawing lines, horizontal lines, we’re going to make height=1, width is the calculated length, vertical lines are going to do the opposite, width=1, height is the calculated length. (Data -* + content:attr) : data-* + content:attrWe find that the left and top lines do not show what we want. After thinking about it, we find the problem. Since our reference point is the selected- layer, the distance between the corresponding edges of the two layers is positive, so they will extend to the right and down respectively when “drawing lines”. How do we fix this? We use translateX/translateY. When calculating the length, we take the left and top sides as negative numbers (x1-x2 becomes -(x1-x2), and y-y2 becomes -(y1-y2)). Add a logical judgment to the line style, shift it if it is negative, and do the same for the other lines.In the follow-up self-test, it was also found that there was the following situation:In this case, there is no crossover and no inclusion between the two layers. Here, we can carry out special treatment for this caseSince the IF condition is union, it is also compatible with upper left, upper right, lower left and lower right. At this point, the basic functionality is almost complete. Behind the implementation of more extended functions, including view annotated CSS style, n-fold map size, mouse zoom, two finger drag and so on, here will not be described one by one. If you are interested in this or have better suggestions, please leave them in the comments section.
🔗 : How to realize the annotation function of Ma Liang