The author: Ziven27

This article is produced by a member of YFE, please respect the original, please contact the public account (ID: yuewen_YFE) for authorization to reprint, and indicate the author, source and link.

Background introduction

Inkstone is a creative platform for original writers and translators from overseas. A large number of authors and works mean a large number of book cover production requirements. Before this is the need for designers to invest energy, or spend money to buy to solve, taobao’s 5 yuan book seal, said cheap is not cheap, and users upload their book seal, do not guarantee that there is no problem in copyright, there are all kinds of risks. At this time, the browser end book seal production system has become a big tool to solve this demand. All you have to do is log on to our Inkstone Platform for Overseas Writers and create a beautiful copyrighted book cover in just a few steps.

The overseas book seal system is mainly divided into two lines: solid color background and picture background. It takes four steps for a solid color background and five steps for a picture background to complete our book cover.

All this has already realized the Chinese version of the book cover production system under the leadership of zhang Xinxu, the writer’s assistant in China last year. We have the same idea in overseas testing as in China, but there are still many difficulties in non-Chinese system that need to be made extra efforts.

As for the Chinese version of book seal system, Mr. Zhang Xinxu has introduced a lot of relevant content to you on his blog. This paper will focus on the difference between the domestic book seal several points to introduce to you:

  1. Book seal layering logic
  2. Image filter caching mechanism
  3. English font
  4. English branch
  5. English line height
  6. English alignment
  7. Text color

One, book seal hierarchical logic

When we first got this requirement, our first reaction was to map different layers into our DOM layers, and then directly export the processed DOM as images. Although the text processing by DOM operation is much better than Canvas, Canvas has a higher possibility in image processing. For example, to achieve a text that needs to overlay image texture and background color at the same time, I don’t seem to have found a reasonable solution based on DOM.

So the hierarchical pattern shown in the figure above was chosen. The background layer is the Base64 image after the Canvas overlay filter, the middle layer is the text “title + author name” drawn directly with Canvas, and the top layer is the LOGO and watermark picture. When the user clicks the upload button, Canvas will be used to superimpose the three layers into the book cover we want and submit it to our server.

2. Image filter caching mechanism

For image filter processing related technical solutions we can go to Zhang Xinxu teacher blog search keywords: filter. This will focus on filter cache optimization mechanism to introduce to you.

In order to reflect the quality of the filter effect, and the domestic book seal is the same choice of movie level 3D LUT filter. However, with this level of filters, most files are close to 1M in size, and if the user clicks the button every time before loading the corresponding file and rendering, the total wait time is very long. And to my surprise, rendering the filter is a process that can take longer than loading.

The size of the book cover that the overseas front end needs to generate is 8101080, which corresponds to 874, 800 pixels, and this 3D LUT filter needs to process almost every pixel, which can be imagined as a huge amount of calculation. In fact, the size of the book cover in the preview state is only 240,320. When the user clicks to switch the filter, it does not mean that he will definitely use this picture, but may really just look at it.

Unit: ms

So the processing scheme here is in the preview state, will only deal with the size of 480*640 “2x map” book seal. As you can see from the chart above, our overall average load time decreased by nearly 63%.

When the user actually clicks upload, the original size of the image is filtered. At this point, because the filter file is already loaded, it only takes the filter rendering time, killing two birds with one stone.

Then we look at the preloading logic, which by default does not apply the filter when the user enters the page. At this point, the first filter is preloaded to complete the rendering, and the second filter is loaded to complete the rendering. The rendered image is converted to a Base64 URL and placed in the right IMG list, “which is hidden in production.” When the user clicks the “Switch Filter” button, he only needs to take out the URL of the corresponding serial number from the list on the right and replace the URL of the background image in the display area on the left.

This means that we are always two steps ahead of the user, trying to manipulate the image filter effect. Minimize the user waiting time. Even after the user has walked around, switching filters is like swapping urls for two Base64 images, with no loading and no filter processing, perfect.

Three, English font

3.1 Font loading scheme

The processing of Chinese fonts in China is supported by our self-built font service Y-font “Reading Chinese font interface Service”, which can load several characters’ fonts used by book seals as needed. However, overseas and domestic servers are not shared, which leads to our direct inability to use this service. However, compared with Chinese fonts, English fonts are relatively small, and with the help of Google Font, even if the full load will not be too big a problem.

The font list of overseas book cover itself is also related to the category of work selected by the user. At the beginning, I prepared a CSS file to store the font list for each category. When users switch the classification of works, they will switch the corresponding CSS file. However, later I found this was too much.

Font browsers have their own processing logic. Simply put, if you introduce a font @font-face, it will not load if no text on the page has a font set. The font file is not loaded until you have specified a font family for the text. When the font file is loaded successfully, the text with the corresponding font family is redrawn.

So I ended up combining the font files of different categories into one, because the fonts of different categories overlap, which makes the overall font CSS file smaller. Subsequently, font loading is controlled by setting font-family for the text.

As you can see, I’m going to print a list of fonts under the user’s selected category directly on the page, and I’m going to set font-family only for the first five words, which means I’ve pre-loaded them. Because the user selects categories in step 1 and switches fonts in step 1, by the time the user reaches step 5, the five fonts may have already been preloaded.

When the user switches font, I will start from the font serial number selected by the user and set font-family for the last five words, which means that when the user switches font, only one font is loaded and “four have been preloaded”. However, the user will hardly feel the font loading during the whole process of switching fonts. This preloading logic is the same as before with filters.

More importantly, this approach eliminates the logic of not knowing when the font file has successfully loaded.

3.2 Font rendering optimization

We all know the text in the DOM tag. If it is a dynamically loaded font, when the font file is loaded, the font with the relevant font-family set will be automatically rerendered to the corresponding font.

However, text drawn in Canvas needs to be manually rendered after the font file is loaded. The tricky question is, how do we know if a font file has loaded successfully? There is a library called “Web Font Loader” to solve this problem. However, when we use the logic of pre-loading five fonts, the library doesn’t make much sense. When the user switches fonts, the next font may already have been loaded, so the current font will not be dynamically loaded.

Of course, there are some extreme cases where the user clicks the button multiple times while switching fonts, which is faster than we can preload 5 font files. Or in some areas where the Internet is not as good, Google Font loads slowly. At this time, the current font does not correspond to the “default font will be displayed”. The way we deal with this problem is not to deal with it.

Because users actually do not know which font number corresponds to which font, even if there is a mismatch between font number and font, it is difficult for users to find out, and they may think that the font number is very similar to the default font. When the user clicks around and comes back, the font will most likely be loaded.

English branch

4.1 Canvas text drawing method

context.fillText(text, x, y [, maxWidth]);
Copy the code

Canvas text drawing API

  • text: Text to draw
  • x: The horizontal coordinate to start drawing
  • y: Specifies the ordinate from which to start drawing
  • maxWidth: Text display width (horizontal compression will occur if the text does not fit)

Text drawn on Canvas does not wrap itself when it is out of line like DOM tags. To implement line wrapping, you need to calculate manually and then draw after the line. For example, if you have a line of text you are my Little Apple, the size of the text is 16px, the line height is 24px, and the width of the Canvas is 4 × 16px. You need to draw a line by line group of up to 4 words per line.

context.font = '16px STheiti, SimHei';
context.fillText('You are mine', 0, 0);
context.fillText('Little Apple', 0, 24);
Copy the code

4.2 Text newline scheme

Figure 1 / Figure 2 / Figure 3

The biggest difference between domestic and overseas book seals is the processing of characters. The reason for this difference comes from the differences between Chinese and English. To put it simply, Chinese can handle a idiom, while English needs a whole sentence.

So most of the time, the author’s title line won’t fit. Therefore, we can only think backwards and dynamically calculate the text size based on the width of the canvas and the number of lines of text.

Size = round (canvas width/number of words in a line);Copy the code

When the user clicks on the bottom space to add a line break, the line with the most words is chosen as the dividend of our formula, which is used to calculate our base size, and the other lines are drawn based on this size.

Of course, the size we calculate cannot be infinite, so we will give a maximum size for the base size. When the calculated base size exceeds this maximum size, we will use this maximum size as our base size “Figure 3”.

Another problem, however, is that most English book titles are displayed on a single line, and the dynamically computed text has a smaller font size. As a direct result, most users will see this unelegant state “Figure 1” when they first enter the page.

To solve this problem, when the user first enters a text typeset page, a line break is automatically added to the nearest space in the middle of the text by default. It’s not a perfect solution, but at least it ensures the readability of the text “Figure 2” that most users enter for the first time. We can also tell the user that our interaction takes the form of a line wrap with the bottom space, which is a way to kill two birds with one stone.

Five, English proficiency

Single line of text starting point ordinate = datum starting point ordinate + line number * line height;Copy the code

As mentioned above, when drawing Canvas text, we also need to provide the horizontal and vertical coordinates of the starting point. In the case of the same size, the ordinate of our starting point can be achieved only by using the formula above.

Line height = font size * 1.5;Copy the code

The original idea was to use this formula to deal with the line height of text. “This is the most commonly used method for line height on web pages.” Yet in the complexity of English fonts, this formula pales.

Because English is not boxy like Chinese, it has a “L” that is visually up, and a “G” that is visually down. Even if the font is the same size and the line is the same size, you can see that the text in the first column is overlapping, and the second column is fine. So in the case of mixed case, it is difficult to give a specific row height to avoid this problem.

Now, if you’re careful, you might notice that the last two columns seem to be much better because they’re all capitalized. So we made an appointment with the designer that the title would be capitalized by default, but the problem wasn’t over yet.

Because our font users are freely interchangeable. Even when all else is equal, the user may still see a wide variety of results.

Line height = type * 1;Copy the code

After many adjustments and visual comparison, we finally chose this formula as our calculation method of row height. Of course, this also trouble designers to abandon some particularly incompatible fonts.

6. English alignment

Originally, this alignment is not worth talking about if there are only three ways left, middle and right. Because the Canvas Text-align API comes with all three.

The difficulty lies in the alignment of the third AUTO, which is actually a kind of artistic expression technique commonly used in posters. The above four figures are all in AUTO mode, only the line feeding of the text is adjusted. As you can see, the effect is much more vivid than the three normal ways of “thumbs up for good designers”.

I believe you can also see the logic through the diagram above. The size of each line is calculated separately based on the formula described in the previous section. Simply put, the smaller the number of words per line, the larger the font size, “of course there is a maximum.”

The ordinate of the starting point of a single line of text = the ordinate of the starting point of the reference point + the height of each previous line;Copy the code

But now, because each line is calculated separately, each line has a different type and corresponding line height, so you have to record all the line heights and draw them line by line. So in AUTO mode the ordinate of the starting point of the text becomes the formula above.

7. Text color

7.1 Color scheme

Figure 1 / Figure 2

For text colors, AT first I thought I just needed the designer to give me a list of text colors. However, the reality is still too simple.

For example, the first color in the color list given to me by the designer is white. When the user chooses the background inclined to pure white as shown in Figure 2, it will be almost impossible to see if white is still used as the color of our text. So we need to have a logic to switch the default text color for different backgrounds.

The library I recommend here is Color Thief. As shown above, give the library’s API an image and it will return you the color scheme for that image. And the length of the color scheme can be customized.

Const isWhite= (r + g + b) / 3 < 128*1.3?false: true;
Copy the code

How do we determine if a background image is too dark or too light based on this library? Very simply, we take the first color in the color scheme, which is the dominant color in this image. Then, take an average value of the RGB color value of this color, and if the average value is less than 128*1.3, we will approximately consider this graph to be dark. You might ask, isn’t 128 half of 256? Why do we have to multiply by 1.3 here.

In fact, this is very easy, when the RGB average is around 128, white and black text is actually legible. But at this edge, we want the user to see white text. As for the reason of 1.3, we actually tried it one by one, and probably thought that under this threshold value, it was more in line with our expectations.

Here Color Thief’s calculation of the image Color table is similar to the previous filter logic, that is, the larger the size of the image we provide, the longer the calculation time will be. Originally we wanted an obscure value here, so we provided Color Thief with a thumbnail.

7.2 Color List

At this point, we’ve only roughly solved the problem of default font colors for the user font Settings page. There is also the question of how to set the entire color list.

Text color list = Black + White +8 matching colors +4 matching colorsCopy the code

We use Color Thief to get 9 Color matching of the whole image, and then use the first Color as our standard to judge whether the default text Color is black or white. Then add the remaining 8 matching colors and 4 matching colors given by the designer to form our text color list.

You may wonder why we used the background color as our text color. This plan is proposed by Teacher Zhang Xinxu in the domestic book seal project.

It is not difficult to understand that the color inside the picture match and the picture itself will not have too much sense of violation. Other colors might look good on their own, but look strange in a mismatched background. Therefore, the colors given by the designers behind are also chosen to be more versatile colors.

conclusion

I’ve highlighted a few technical difficulties that I think are worth sharing. Another thing I want to share with you is a little bit of experience.

When I first got the project, what I was most worried about was the overlay of image filter and image texture, and I didn’t know how to achieve it. Because this part was blank in my previous project experience. However, when I actually use it, this part is basically equivalent to calling the API. Of course, this has a lot to do with the support of Teacher Zhang Xinxu. Almost all the problems in this aspect can be found in his blog. The real challenge is to improve the user experience.

At the beginning, due to my established thinking, I mistakenly thought that it would be much easier to process English than Chinese on the browser side. After all, Chinese fonts tend to be file sizes of several megabytes. However, in the actual development, because of the Characteristics of the English language, there will be a lot of pits for this kind of delicate processing. Simply put, in a certain font, your entire logic can be overturned. At this point, you might want to be a little less technical and talk to the designer to see if you can get rid of fonts like this.

Technology is always just A tool to get you from point A to POINT B. Getting to point B is your core purpose.

For more sharing, please pay attention to the Official account of China Literature Front End Team:

To learn more about the team, check it outwebsiteOh ~ 😄