Below is the introduction to the functions of the picture I wrote myself:
You can use the mouse to drag and create a cropping box
Can change the size of the crop box
Click OK to return to crop data
principle
There are two ways to complete the cropping:
1. Add drag event drag drop, etc. using HTML5
2. Traditional methods, using mouse events, mousedown, mousemove, etc.
Here we adopt Method 2.
Formation of cropped areas
To cut, we must first form a cropping area. The formation of this cropping area can be associated with the distance the mouse moves. The farther the mouse moves, the larger the crop area. As shown in the figure below:
As shown in the above figure, the horizontal movement distance of the mouse and the vertical movement distance together form the width and height of the cropping area.
And how to calculate the distance between horizontal and vertical movement? When we click the mouse, we can obtain the mouse click position through event event object, and when we move the mouse, we can also obtain the mouse position through event . Through two changes in the mouse position, we can obtain the mouse movement distance.
The attributes to obtain the mouse position are clientX and clientY
Shaded area formation
Next is to draw the shadow area. The part of the cropped image except the cropped area belongs to the shadow part, and the area can also be not drawn. This area is drawn to allow the user to see the cropped area more clearly.
I divided the area into four parts: upper, lower, left and right, see the distribution of the figure below:
So what if this area is calculated? At this time, the offset value of the Dom element needs to be used. The left offset value of the clipping area is subtracted from the left offset value of the picture itself is the width of the left shadow. The upper offset value of the clipping area is subtracted from the upper offset value of the picture is equal to the height value of the upper shadow. As shown in the figure below:
After obtaining the values of the left shadow and the upper shadow, the properties of the other shadows can be calculated through these two.
There are two ways to get the offset value of the picture
1. Disadvantages of using offsetLeft and offsetTop values If the dom element has border margin equivalent values, these values will be calculated in
2. The disadvantages of obtaining the css attribute of dom are predefined css related to predefined css if left top is not defined.
Both methods have their own disadvantages and are used according to different circumstances
Cropping out of bounds
The calculation of the crop area is calculated by the moving distance of the mouse, so the crop area will be out of bounds, and this situation is divided into two types:
1. Cross the boundaries during the cutting process
2. Go beyond the boundary when moving the crop area
So let’s talk about how to prevent crossing the line.
Cropping over the line
What is cross-border when cutting? The mouse drag area exceeds the image and forms an out-of-bounds, as shown in the following figure:
For such out-of-bounds, it is necessary to judge that the right side of the crop area relative to the left side of the browser cannot exceed the right side of the image and the position on the left side of the browser; at the same time, the position on the bottom of the crop area relative to the top of the browser cannot exceed the position on the top of the browser corresponding to the top of the image. Or to illustrate:
When TX >= PX , force the value of TX to a fixed value.
The calculation method of TX and PX, assuming that the cropping area is oTailor , the picture area oPicture :
TX = oTailor.offsetWidth + oTailor.offsetLeft;PX = oPicture.offsetWidth + oPicture.offsetLeft;
Similarly, the above method can be used to limit the left side crossing, the upper side crossing, and the lower side crossing, so I will not go into details.
Move across the boundaries
Moving out-of-bounds means that the cropping area has been formed, but the cross-of-bounds occur when moving the cropping area through the mouse. This understanding is relatively simple, so I won’t introduce it if I draw pictures. This kind of cross-border limit is consistent with the dom drag-and-drop cross-border limit, and is judged by judging whether the mouse moves beyond the image area.
The principle and problem have been solved, and now we will start to complete the actual function.
Preparation
Before doing it, do some preparation work first, sharpen the knife and chop the wood without delaying the work of chopping wood.
Web page layout preparation
The key codes for web page layout are as follows:
<img src="./images/img_2.jpg"><div> <div></div> <div></div> <div></div> <div></div> <div id="box_1"></div> <div id="box_2"></div> <div id="box_3"></div> <div id="box_4"></div> <div id="box_5"></div> <div id="box_6"></div> <div id="box_7"></div> <div id="box_8"></div><!-- left--><div></div><!-- top--> <div></div><!-- right--> <div></div><!-- Next-> <div></div><button>Confirm</button>
where img_box represents the crop area, outer represents the shadow area, and the div in img_box is the border of the crop area
Style controls are as follows:
* { padding:0; margin:0;}body { background: #454545; } .main { width: 500px; margin:50px auto;}.main img { width: 500px; position: absolute; left: 450px; top: 50px;}.img_box { overflow: hidden; position: absolute; top:0px; left: 0px; z-index: 2;}.outer { overflow: hidden; background: #000; opacity: 0.4; position: absolute; top:0px; left: 0px; z-index: 0;}.box_border1 ,.box_border2 ,.box_border3 ,.box_border4 { opacity: 0.5;}.box_border1 { background: url(./images/border-anim-v.gif) repeat-y left top;} .box_border2 { background: url(./images/border-anim-h.gif) repeat-x left top;}.box_border3 { background: url(./images/border-anim-v.gif) repeat-y right top;} .box_border4 { background: url(./images/border-anim-h.gif) repeat-x right bottom;} .box_handle { background: #fff; border: 1px solid #000; opacity: 0.5;}.confrim { width: 80px; height: 35px;}The layout effect is as follows:
General functions
After completing the image cropping, through the above principle, we can know that we need to obtain a large number of tag objects and the tag's css attributes, etc., so we can write general functions to better obtain these values. as follows:
Dom gets the function
/* Get */function $(dom) { function getDom(dom) { var str = dom.charAt(0); switch( str ) { case '.' : this.ele = document.getElementsByClassName(dom.substring(1))||null; break; case '#' : this.ele = document.getElementById(dom.substring(1)) || null; break; default : if(document.getElementsByTagName(dom).length) { this.ele = document.getElementsByTagName(dom); } else if(document.getElementsByName(dom).length) { this.ele = document.getElementsByName(dom); } else { this.ele = null; } } return this; }; getDom.prototype.get = function(num) { return this.ele[num]||this.ele; } getDom.prototype.insert = function(value , num) { this.ele[num].innerHTML = value; } return new getDom(dom);}Css attribute obtaining function
The acquisition of Css attributes is divided into two types. One is IE, using currentStyle ; the other is other mainstream browsers, using getComputedStyle , and the following are compatible versions:
/* Css get*/function getCss(o, key){ return o.currentStyle? o.currentStyle[key] : document.defaultView.getComputedStyle(o,false)[key]; };Assignment function
When writing, I often encounter the assignment of Dom styles. For convenience, I specially wrote a function for assignment:
/** - Assign function - @param : obj Assigned object - @param : operation performed by option - @parma : value Assign content*/function setAssign(obj , option , value) { switch(option) { case 'width': obj.style.width = value; break; case 'height': obj.style.height = value; break; case 'top': obj.style.top = value; break; case 'left': obj.style.left = value; break; case 'position': obj.style.position = value; break; case 'cursor': obj.style.cursor = value; }}The preparations have been basically completed, and now the writing has officially started.
Complete crop area drawing by clicking and moving events
Set mousedown and mousemove event monitoring for images, as follows:
// Mouse clicks on the image to trigger oPicture.onmousedown = function(ev) { // Event object var oEvent = ev || window.event; // Initial mouse position var tempX = oEvent.clientX; var tempY = oEvent.clientY; // Adjust the crop area position oTailor.style.left = oEvent.clientX + 'px'; oTailor.style.top = oEvent.clientY + 'px'; // Mouse moves the clipping area to draw the crop area shadow area document.onmousemove = function(ev) { // Mouse moves the event object var oEvent = ev || window.event; // The current mouse position minus the mouse position before the mouse is equal to the distance of the mouse movement var sLeft = oEvent.clientX - tempX; var sTop = oEvent.clientY - tempY; // Cropping the limit of the out-of-bounds only requires limiting the right and lower sides if((oTailor.offsetLeft+oTailor.offsetWidth) >= (oPicture.offsetLeft+oPicture.offsetWidth)) { sLeft = oPicture.offsetLeft+oPicture.offsetWidth - oTailor.offsetLeft; } if((oTailor.offsetTop+oTailor.offsetHeight) >= (oPicture.offsetTop+oPicture.offsetHeight)) { sTop = oPicture.offsetTop+oPicture.offsetHeight - oTailor.offsetTop; } // Crop area drawing oTailor.style.width = sLeft + 'px'; oTailor.style.height = sTop + 'px'; // Crop area display oTailor.style.display = 'block'; // Shadow area display for (var i = 0; i < oShadow.length; i++) { oShadow[i].style.display = 'block'; } // Shadow area drawing shadow(oPicture , oTailor , oShadow); // Add crop border tailorBorder(oDiv , oHandle , oTailor); // Block the default event oEvent.preventDefault(); }; // Release the mouse to cancel the movement event document.onmouseup = function(ev) { var oEvent = ev || window.event; // Move event cancel document.onmousemove = null; // Block the default event oEvent.preventDefault(); }; // Block the default event oEvent.preventDefault();}Shadow area drawing
/** * @param: oPicture picture dom object* @param: oTailor crop area dom object* @param: oShadow shadow area dom object*/ function shadow(oPicture , oTailor , oShadow) { // left shadow area setAssign(oShadow[0] , 'width' , (parseInt(getCss(oTailor , 'left')) - parseInt(getCss(oPicture , 'left'))) + 'px'); setAssign(oShadow[0] , 'height' , parseInt(getCss(oPicture , 'left'))) + 'px'); setAssign(oShadow[0] , 'height' , parseInt(getCss(oPicture , 'height')) + 'px'); setAssign(oShadow[0] , 'left' , parseInt(getCss(oPicture, 'left')) + 'px') setAssign(oShadow[0] , 'top' , parseInt(getCss(oPicture, 'top')) + 'px') //The shadow area on the right is setAssign(oShadow[2] , 'width' , (parseInt(getCss(oPicture, 'width')) - parseInt(getCss(oTailor, 'width')) - parseInt(getCss(oShadow[0] , 'width')) + 'px'); setAssign(oShadow[2] , 'height' , parseInt(getCss(oPicture, 'height')) + 'px'); setAssign(oShadow[2] , 'left' , (parseInt(getCss(oTailor, 'left'))) + parseInt(getCss(oTailor, 'width'))) + 'px'); setAssign(oShadow[2] , 'top' , parseInt(getCss(oPicture, 'top')) + 'px'); // upper shadow area setAssign(oShadow[1] , 'width' , parseInt(getCss(oTailor, 'width')) + 'px'); setAssign(oShadow[1] , 'height' , (parseInt(getCss(oTailor, 'top')) - parseInt(getCss(oPicture, 'top'))) + 'px'); setAssign(oShadow[1] , 'left' , (parseInt(getCss(oPicture, 'left'))) + parseInt(getCss(oShadow[0] , 'width'))) + 'px'); setAssign(oShadow[1] , 'top' , parseInt(getCss(oPicture, 'top')) + 'px'); // The lower shadow area setAssign(oShadow[3] , 'width' , parseInt(getCss(oTailor, 'width')) + 'px'); setAssign(oShadow[3] , 'height' , (parseInt(getCss(oPicture, 'height')) - parseInt(getCss(oTailor, 'height')) - parseInt(getCss(oShadow[1] , 'height'))) + 'px'); setAssign(oShadow[3] , 'left' , (parseInt(getCss(oPicture , 'left' )) + parseInt(getCss(oShadow[0] , 'width'))) + 'px'); setAssign(oShadow[3] , 'top' , (parseInt(getCss(oTailor, 'top' )) + parseInt(getCss(oTailor, 'height'))) + 'px');}Note that in actual use of web pages, if there is no left or top attribute in the picture css in the layout, then the above code will generate an error. OffsetLeft and offsetTop should be used instead.
Add crop border
In the layout diagram released, you can see the edge of the crop, and each of the four corners and four sides has a small square shape. The addition is not only to distinguish between the cutting area and the non-cut area, but also to provide convenience for the next step of adding the stretched cutting area. Let's start writing the code:
/** * Crop border drawing* @param : oDIv All border objects* @param : oHandle dotted edge* @param : oTailor crop object*/function tailorBorder(oDiv, oHandle, oTailor) { // Initialize the border for (var i = 0; i < oDiv.length; i++) { setAssign(oDiv[i] , 'position' , 'absolute'); setAssign(oDiv[i] , 'top' , '0px'); setAssign(oDiv[i] , 'left' , '0px'); setAssign(oDiv[i] , 'left' , '0px'); setAssign(oDiv[i] , 'width' , parseInt(getCss(oTailor, 'width')) + 'px'); setAssign(oDiv[i] , 'height' , parseInt(getCss(oTailor, 'height')) + 'px'); } /* Dot-like edge drawing*/ // Four-corner dot-like edge drawing for (var i = 0; i < 4; i++) { // Dot-like drawing setAssign(oHandle[i] , 'position' , 'absolute'); setAssign(oHandle[i] , 'width' , '5px'); setAssign(oHandle[i] , 'height' , '5px'); // 0 2 means the left dot-like if(i % 2 == 0) { setAssign(oHandle[i] , 'left' , '0px'); setAssign(oHandle[i] , 'top' , (i == 0?'0px' : (parseInt(getCss(oTailor, 'height')) - 8) + 'px')); } else { // right dot-like setAssign(oHandle[i] , 'left' , ( parseInt(getCss(oTailor, 'width')) - 6) + 'px'); setAssign(oHandle[i] , 'top' , (i == 1?'0px' : parseInt(getCss(oTailor, 'height')) - 8 ) + 'px'); } } // Four-sided dotted border for (var i = 4; i < oHandle.length; i++) { setAssign(oHandle[i] , 'position' , 'absolute'); setAssign(oHandle[i] , 'width' , '5px'); setAssign(oHandle[i] , 'height' , '5px'); // 4 6 Indicates upper and lower dotted border if(i % 2 == 0) { setAssign(oHandle[i] , 'left' , parseInt(getCss(oTailor, 'width')) / 2 + 'px'); setAssign(oHandle[i] , 'top' , (i == 4 ? '0px' : (parseInt(getCss(oTailor, 'height')) - 8) + 'px')); } else { // left and right dot setAssign(oHandle[i] , 'top' , parseInt(getCss(oTailor, 'height')) / 2 + 'px'); setAssign(oHandle[i] , 'top' , parseInt(getCss(oTailor, 'height')) / 2 + 'px'); setAssign(oHandle[i] , 'left' ,(i == 5 ? '0px' : parseInt(getCss(oTailor, 'width')) - 8 ) + 'px'); } }} In the layout, the first four divs with the clipping area class name box_handle represent dots at four corners, and the last four represent dots at the middle of the edge, all distributed clockwise. After completion, the effect is as follows:
Monitor shadowed areas
The crop area and shadow area are drawn. Now add a small function to cancel the crop area when the mouse clicks on the non-cropped area (i.e., the shadow area).
// Set time for shadow area setting, when the crop area disappears, the shadow area disappears for (var i = 0; i < oShadow.length; i++) { oShadow[i].index = i; oShadow[i].onmousedown = function() { oTailor.style.display = 'none'; oTailor.style.width = '0px'; oTailor.style.hegiht = '0px'; for (var i = 0; i < oShadow.length; i++) { oShadow[i].style.display = 'none'; oShadow[i].style.left = '0px'; oShadow[i].style.top = '0px'; } }}Monitor the mouse movement position
Next, add the function of cropping area stretching, which gives different effects when the mouse moves to the dot-shaped border on the edge.
Add mouse display effect
// Pointed border monitoring settings corresponding operations oTailor.onmousemove = function(ev) { var oTarget = oEvent.target; switch(oTarget.id) { case 'box_1': // upper left setAssign(oTailor , 'cursor' , 'nw-resize'); break; case 'box_2': // upper right setAssign(oTailor , 'cursor' , 'ne-resize'); break; case 'box_3': // lower left setAssign(oTailor , 'cursor' , 'sw-resize'); break; case 'box_4': // lower right setAssign(oTailor , 'cursor' , 'se-resize'); break; case 'box_5': // upper setAssign(oTailor , 'cursor' , 'n-resize'); break; case 'box_6': // left setAssign(oTailor , 'cursor' , 'w-resize'); break; case 'box_7': // lower left setAssign(oTailor , 'cursor' , 's-resize'); break; case 'box_8': // right setAssign(oTailor , 'cursor' , 's-resize'); break; case 'box_8': // right setAssign(oTailor , 'cursor' , 'e-resize'); break; default : // The crop area displays a movable prompt setAssign(oTailor, 'cursor' , 'move'); break; }}Since there are many divs to monitor, it is added by event delegation, which is inconvenient for demonstration. Interested students can test it themselves.
Add stretching effect
Code
// Move event in the crop area oTailor.onmousedown = function(ev) { // event event object var oEvent = ev || window.event; // Get cursor status var oCur = getCss(oTailor , 'cursor'); // initial mouse position var sTmpX = oEvent.clientX; var sTmpY = oEvent.clientY; // Get the attributes of the crop area to save them with an object to facilitate calling oAttrs.left = getCss(oTailor , 'left'); oAttrs.top = getCss(oTailor , 'top'); oAttrs.width = getCss(oTailor , 'width'); oAttrs.height = getCss(oTailor , 'height'); document.onmousemove = function(ev) { // Move event object var oEvent = ev || window.event; // Current mouse position minus the initial mouse position equals the distance of the mouse movement var sLeftT = oEvent.clientX - sTmpX; var sTopT = oEvent.clientY - sTmpY ; // Indicates the distance of the mouse movement var oTmpHeight = ''; var oTmpTop = ''; var oTmpWidth = ''; var oTmpLeft = ''; switch(oCur) { case 'nw-resize' : // upper left oTmpWidth = parseInt(oAttrs.width) - sLeftT ; oTmpHeight = parseInt(oAttrs.height) - sTopT ; oTmpLeft = parseInt(oAttrs.left) + sLeftT ; oTmpTop = parseInt(oAttrs.top) + sTopT ; break; case 'ne-resize' : // upper right// At this time, width cannot subtract the mouse movement distance because the movement distance at this time is a positive value oTmpWidth = parseInt(oAttrs.width) + sLeftT ; oTmpHeight = parseInt(oAttrs.height) - sTopT ; // No left value is required to move the upper right corner because the default sound is moved right oTmpTop = parseInt(oAttrs.top) + sTopT ; break; case 'sw-resize' : // Lower left// The same as the upper right height must be added to the mouse movement distance oTmpWidth = parseInt(oAttrs.width) - sLeftT ; oTmpHeight = parseInt(oAttrs.height) + sTopT ; oTmpLeft = parseInt(oAttrs.left) + sLeftT ; break; case 'se-resize' : // Lower right// Combination of the lower left and upper right at the same time remove left and top oTmpWidth = parseInt(oAttrs.width) + sLeftT ; oTmpHeight = parseInt(oAttrs.height) + sTopT ; break; case 'n-resize' : // Top oTmpHeight = parseInt(oAttrs.height) - sTopT; oTmpTop = parseInt(oAttrs.top) + sTopT; break; case 'w-resize' : // Left oTmpWidth = parseInt(oAttrs.width) - sLeftT ; oTmpLeft = parseInt(oAttrs.left) + sLeftT; break; case 's-resize' : // Under oTmpHeight = parseInt(oAttrs.height) + sTopT; break; case 'e-resize' : // Right var oTmpWidth = parseInt(oAttrs.width) + sLeftT; break; default : // Otherwise it is the moving crop area tailorMove(oEvent , oTailor , oPicture , oShadow); break; } // pull up to the boundary if(parseInt(getCss(oTailor, 'top')) <= oPicture.offsetTop) { oTmpHeight = parseInt(getCss(oPicture,'height')) - (oPicture.offsetTop+parseInt(getCss(oPicture,'height')))-parseInt(getCss(oTailor,'top')))); oTmpTop = oPicture.offsetTop; }else if(oPicture.offsetTop+parseInt(getCss(oPicture,'height')) <= (parseInt(getCss(oTailor,'top')))+parseInt(getCss(oTailor,'height')))){ // Pull down to the boundary oTmpHeight = oPicture.offsetTop+parseInt(getCss(oPicture,'height'))) - parseInt(getCss(oTailor,'top')); } // Pull left to the boundary if((parseInt(getCss(oTailor,'left'))) <= oPicture.offsetLeft) { oTmpWidth = parseInt(getCss(oPicture,'width')) - (oPicture.offsetLeft+parseInt(getCss(oPicture),'width')-parseInt(getCss(oTailor,'left'))) oTmpLeft = oPicture.offsetLeft; } else if(parseInt(getCss(oTailor,'left')) + parseInt(getCss(oTailor,'left')) >= (oPicture.offsetLeft+oPicture.offsetWidth)) { // Pull right to the boundary oTmpWidth = oPicture.offsetLeft+oPicture.offsetWidth - parseInt(getCss(oTailor,'left')); } // Assign if(oTmpWidth){ setAssign(oTailor,'width', oTmpWidth + 'px'); } if(oTmpHeight) { setAssign(oTailor,'height', oTmpHeight + 'px'); } if (oTmpLeft) { setAssign(oTailor , 'left' , oTmpLeft + 'px'); } if (oTmpTop) { setAssign(oTailor , 'top' , oTmpTop + 'px'); } // Shadow area drawing shadow(oPicture , oTailor , oShadow); // Add crop border tailorBorder(oDiv , oHandle , oTailor); }; // When releasing the mouse, please note that you cancel the movement event document.onmouseup = function(ev) { // event event object var oEvent = ev || window.event; document.onmousemove = null; oEvent.preventDefault(); } oEvent.preventDefault(); };Pay attention to the calculation of the moving distance when stretching, especially when moving upward and leftward. Pay attention to changing the left and top values of the cropped area at the same time, otherwise it will only increase downward and rightward. Let’s talk about how to calculate in detail:
principle
Taking the mouse stretching to the upper left corner as an example, the moving distance of the mouse is consistent with what was mentioned above, but at this time, please note that the calculated value is a negative number. Therefore, when calculating the added value of the crop area, the value should be subtracted by the width or height of the original crop area. At the same time, as much as the width is increased, the left offset value of the crop area should be subtracted. Otherwise, the displayed effect is that the crop area increases to the right, as shown in the figure below:
In the above figure, the green area is the cropping area after the width and height are added when stretched. If the offset adjustment is not performed, the yellow area is the cropping area after the offset jump, and the two superimposed areas are the original cropping area.
This is stretching at the upper left corner, and the stretching at the lower left corner is similar to other things. You can put it in the upper direction according to the upper direction.
And the other key is that stretching and crossing the boundary has been mentioned above, so I will not describe it anymore.
Movement of cropped areas
Now let’s talk about the last function, the movement of the crop area. When the mouse moves inside the crop area, a movement event will be triggered. At this time, the crop area can be moved. The code is as follows:
/* Movement of crop area*/function tailorMove(ev ,oTailor ,oPicture ,oShadow) { var oEvent = ev || window.event; var oTmpx = oEvent.clientX - oTailor.offsetLeft; var oTmpy = oEvent.clientY - oTailor.offsetTop; document.onmousemove = function(ev) { var oEvent = ev || window.event; oLeft = oEvent.clientX - oTmpx; oTop = oEvent.clientY - oTmpy; if(oLeft < oPicture.offsetLeft ) { oLeft = oPicture.offsetLeft ; } else if(oLeft > (oPicture.offsetLeft + oPicture.offsetWidth - oTailor.offsetWidth)) { oLeft = oPicture.offsetLeft + oPicture.offsetWidth - oTailor.offsetWidth; } if(oTop < oPicture.offsetTop) { oTop = oPicture.offsetTop; } else if (oTop > (oPicture.offsetTop + oPicture.offsetHeight - oTailor.offsetHeight)) { oTop = oPicture.offsetTop + oPicture.offsetHeight - oTailor.offsetHeight; } oTailor.style.left = (oLeft)+ 'px'; oTailor.style.top = (oTop) + 'px'; shadow(oPicture , oTailor , oShadow); }}Get the position of the crop
The function of the cropping effect is basically completed, so you need to obtain the position of the crop. First of all, you need to know which properties you need to obtain. According to PHP 's GD library operation, you need to know the starting point coordinates of the crop and the width and height of the crop. I use a function to get this data and encapsulate it and return:
function getEle() { var oPicture = $('img').get(0); var oTailor = $('.img_box').get(0); oAttrs.LeftX = (parseInt(getCss(oTailor,'left'))) - oPicture.offsetLeft); oAttrs.LeftY = (parseInt(getCss(oTailor,'top'))) - oPicture.offsetTop); oAttrs.Twidth = (parseInt(getCss(oTailor,'width'))); oAttrs.Theight = (parseInt(getCss(oTailor,'height'))); return oAttrs;}There is another problem. If the pictures on the web page are compressed using css, the position obtained here will be different from the crop size than you imagined. The range of the cropped image may become larger (the original image is larger), or it may become smaller (the original image is smaller).
If the size of the original image can be obtained, you can crop according to the ratio of the compressed image to the original image, so that the correct cropping image can be obtained.
OK, a simple image cropping function is completed, and you can use ajax to pass it to the background for processing.
The content of this article ends here. If you have any questions, please leave a message to discuss. I hope this article will be helpful to everyone in learning JavaScript.