Parse html and use canvas for rendering

Source: Internet
Author: User

Parse html and use canvas for rendering
When learning html5, canvas is used to parse and render html text, the supported tags include <p>, <I>, <B>, <u>, <ul>, and <li>, and parse irregular html by referring to chrome. The code is thrown on my github ( https://github.com/myhonor2013/gadgets In the html-render-with-canvas directory ). The main function of the program is a loop that parses html text from left to right. wangy points to a valid html '<' position at the beginning of each loop, for example, '<P',' <\ ',' <F', and '<\ x' are all valid, '<P',' <\ ',' <\ x ', and so on are invalid. In short,' <'must be followed by a non-null character, this is a result of chrome parsing. This means that the first similar position must be found at the end of each loop to end the loop. Call the rendering function at the end of each loop to render the canvas. During the loop process, pay attention to whether the html string pointer is out of bounds. if the pointer is out of bounds, the loop is rendered. I. Pre-processing simply replaces the consecutive empty characters (carriage return, tab, indentation) in html text with a single space: var text = data. text. replace (/[\ r \ n \ t]/g, WHITESPACE ). replace (/\ s +/g, WHITESPACE ). trim (); then, start from the html text position to find the first so-called valid tag location, and render the text before this location. In the following example, each loop starts with a valid '<. There are two cases: Effective tag opening and effective tag closing. 2. Effective tag opening: The '<' is not followed by '\', and the regular expression is ^ <[^ \/] + .*. Search for the '<' matched '>' tag and push the tag name to the tagname. Then, based on the tagname, determine the format of the subsequent text, that is, isbold, isitalic, isicon (<li> tag), isunderline, nowrap, uloffset, and other attributes, then, the font attribute values required for drawing the canvas are determined based on isbold and isitalic. Font, isicon, isunderline, nowrap, and uloffset are the real attributes required for canvas rendering. If the tag is supported and the tag name is pushed to tagnames at the same time, the font is pushed to the fontsarr stack. The subsequent loop determines the text format of the scope based on these two attributes. Copy code 1 while (text [index]! = WHITESPACE & text [index]! = RIGHTSYN) {2 tagname. push (text [index ++]); 3 if (index = len) break; 4} 5 if (index = len) return; 6 while (text [index]! = RIGHTSYN) {7 if (index = len) {8 break; 9} 10} 11 var tag = tagname. join (''). toLowerCase (); 12 tagname = []; 13 if (tag = TAGB) {14 isbold = true; 15} 16 else if (tag = TAGI) {17 isitalic = true; 18} 19 else if (tag = TAGLI) {20 isicon = true; 21} 22 else if (tag = TAGU) {23 isunderline = true; 24} 25 if (tag = TAGP | tag = TAGLI | tag = TAGUL) {26 nowrap = false; 27} 28 else {29 nowrap = true; 30} 31 if (tag = TAGUL) {32 uloffset + = ULOFFSET; 33} 34 35 if (isitalic = true & isbold = true) {36 font = ITALICBOLD; 37} 38 else if (isitalic = false & isbold = true) {39 font = BOLD; 40} 41 else if (isitalic = true & isbold = false) {42 font = ITALIC; 43} 44 else {45 font = NORMAL; 46} 47 if (VALIDTAGS. contains (tag) {48 tagnames. push (tag); 49 fontsarr. push (font); 50} copy the code to the back part of the scope text of this loop. The text is placed in texttodraw and canvas rendering is performed before the end. Before the end, clear texttodraw and set isicon to false. 3. Processing of valid Closed tags: The tag '<' followed by '\'. The regular expression is ^ <\/.*. Similarly, find the matched closure '<'. If the last element in the closed Tag Name and tagnames (which stores the names of valid tags in turn, remember?) is the same, the last element of tagnames is output to the stack. If the tag name is ul, The uloffset is indented forward. If the tagnames does not contain the current tag name, the font is processed based on the tag semantics. This is the case of multi-layer nesting. Copy code 1 if (text [index] = "/") {2 var arr = []; 3 while (++ index <len & text [index]! = RIGHTSYN & text [index]! = LEFTSYN) {4 arr. push (text [index]); 5} 6 if (index = len) return; 7 if (text [index] = LEFTSYN) break; 8 var tag = arr. join (''). trim (). toLowerCase (); 9 if (tag = tagnames [tagnames. length-1]) {10 font = fontsarr. pop (); 11 tagnames. pop (); 12 if (tag = TAGUL) {13 uloffset-= ULOFFSET; 14 uloffset = (uloffset> 0 )? Uloffset: 0; 15} 16 if (! Tagnames. contains (tag) {17 if (tag = TAGI) {18 font = font. replace ("italic", 'normal'); 19 isitalic = false; 20} 21 else if (tag = TAGB) {22 font = font. replace ("bold", 'normal'); 23 isbold = false; 24} 25 else if (tag = TAGU) {26 isunderline = false; 27} 28} 29} 30} copy the code and then copy the scope text of this loop, get it, and render it based on the attribute values previously determined. The process is the same as that for tag opening. 4. canvas rendering two global variables xoffset and yoffset are used to identify the position after the last rendering. At the beginning of rendering, the two attributes must be adjusted according to uloffset, nowrap, and other attributes. If the isicon attribute exists, the solid circle corresponding to the <li> label is drawn. The next step is to render the text. After setting the font, extract the text character by character and use measureText to measure whether the row is full. If yes, wrap the text after painting. If you need to draw an underline during rendering, draw it together. This is repeated until all characters are drawn. The complete rendering function is as follows: Copy code 1 var drawtext = function (data) {2 data = data. trim (); 3 var len = data. length; 4 if (len = 0) {5 return; 6} 7 if (! Nowrap & xoffset> MARGIN) {8 xoffset = MARGIN + uloffset; 9 yoffset + = LINEHEIGHT; 10} 11 12 if (isicon) {13 ctx. beginPath (); 14 ctx. arc (MARGIN + uloffset + MARGIN, yoffset-MARGIN, MARGIN, 0, Math. PI * 2, true); 15 ctx. closePath (); 16 ctx. fill (); 17 xoffset + = 30; 18} 19 20 21 var index = 0; 22 var renderindex = 0; 23 ctx. font = font; 24 while (index <len) {25 while (canvaswidth-xoffset> ctx. measureText (data. substring (renderindex, ++ in Dex )). width) {26 if (index = len) {27 break; 28} 29} 30 31 if (index = len) {32 ctx. fillText (data. substring (renderindex, index), xoffset, yoffset); 33 if (isunderline) {34 canvas. strokeStyle = "red"; 35 canvas. lineWidth = 5; 36 ctx. beginPath (); 37 ctx. moveTo (xoffset, yoffset); 38 ctx. lineTo (xoffset + ctx. measureText (data. substring (renderindex, index )). width, yoffset); 39 ctx. closePath (); 40 ctx. stroke (); 41} 42 xoffset + = Ctx. measureText (data. substring (renderindex, index )). width; 43 break; 44} 45 ctx. fillText (data. substring (renderindex, -- index), xoffset, yoffset); 46 if (isunderline) {47 canvas. strokeStyle = "red"; 48 canvas. lineWidth = 5; 49 ctx. beginPath (); 50 ctx. moveTo (xoffset, yoffset); 51 ctx. lineTo (canvaswidth, yoffset); 52 ctx. closePath (); 53 ctx. stroke (); 54} 55 56 57 renderindex = index; 58 xoffset = MARGIN; 59 yoffset + = LINEHEIGHT; 60} 61 return; 62}; do not use recursion when using js to parse html during code copying. This can easily cause stack overflow and performance problems. In addition, the Array contains method in the Code is added to the prototype of the Array to determine whether it contains a string: Array. prototype. contains = function (item) {return new RegExp ("^" + this. join ("|") + "$", "I "). test (item. toString ());}

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.