HTML5 Vector file upload progress bar
In HTML, there are no prompts in many cases during file upload. This is a poor experience. users do not know if the file is being uploaded or uploaded successfully, so today we will introduce how to use the HT for Web vector to implement the HTML5 File Upload progress bar, the application of the setCompType () method in vector Chart embedding HTML5 network topology graph has been described in vector Chart. Today we use setImage () the method makes full use of the vector resources defined in the system to implement the File Upload progress bar. Let's take a look at the following:
You can see that an mp4 file is uploaded to the server and the current upload progress is displayed at the bottom.
Next we will discuss the specific implementation:
First, let's analyze the structure of the progress bar:
1. A background, background
2. You need a current progress value, value
3. You need a foreground, foreground, which is used to draw a foreground based on the current progress value and overlay the background.
The structure is so simple, so the next step is the specific implementation. Check the Code:
Ht. default. setImage ('progress', {width: 150, height: 12, comps: [// draw background {type: 'rect ', rect: {x: 0, y: 0, width: 115, height: 12}, background: {func: function (data) {return data. a ('background') ;}}, // draw foreground {rect: {x: 0, y: 0, width: 115, height: 12}, type: function (g, rect, comp, data, view) {var width = rect. width, height = rect. height, value = data. getValue (), foreWidth = width/100 * value; g. fillStyle = data. a ('foreground '); g. fillRect (0, 0, foreWidth, height) ;}}]});
We define a vector object named progress. The vector object consists of two parts: the background and the foreground.
The background is drawn using the data binding method and the data's background attribute. the foreground is drawn using a custom type method, which is an abbreviation of the setCompType () method, drawing is to calculate the drawing width based on the value in data.
The general design of the vector has been completed, so we can use it to see how it works.
var dataModel = new ht.DataModel(), node = new ht.Node();node.setValue(0);node.setImage('progress');node.a('background', '#5F6870');node.a('foreground', '#58B6DA');node.p(85, 87);dataModel.add(node);var graphView = new ht.graph.GraphView(dataModel);graphView.addToDOM();graphView.layout({x : 0, y : 80, width : 170, height : 30});
We have created a node, set the image attribute of the node to the defined vector, and create a graphView component to display the node in the graphView network topology.
Next we will simulate the File Upload progress and let the progress bar move.
function setProgressValue(node) { var value = node.getValue(); if (value !== 100) { node.setValue(value + 1); var second = Math.round(Math.random() * 500); setTimeout(setProgressValue, second, node); }}
We use the setTimeout () method to continuously set the value of node. However, when the code runs, you will find that the progress bar is not moving at all, and the consistency is in the initial state. When we scale graphView, the progress bar is changing. Why? In fact, the reason is very simple. When we modify the value, graphView is not notified to be updated, so the progress bar will not change because of the value change of node, so how do we notify graphView update? The method is simple. After modifying the value of node, You can dispatch a propertyChange event. After creating the node Code, add the following code:
node.getValue = function() { return this._value;};node.setValue = function(value) { var self = this, oV = self._value; self._value = value; self.fp('value', oV, value);};
In the code, the fp () method is used to distribute the propertyChange event, so that the progress bar can work normally and change with the value of node, as shown below:
However, there are still some shortcomings. Although the progress bar is running, we still do not know the current progress value. We can only estimate the current progress value by comparing the progress bar, can we add a text on the progress bar to display the current progress value? The answer is yes. We only need to add the following code to the comps of the vector:
// Draw the text {rect: {x: 118, y: 0, width: 32, height: 12}, type: 'text', text: {func: function (data) {return data. getValue () + '%'; }}, font: '12px arial, sans-ferif ', color: 'black '}
The Code also applies to binding the current value of the node. The details are as follows:
The progress bar is different from the final result. How can we achieve the rounded corner? In fact, it is not difficult. You only need to draw a rounded rectangle and use the clip () method to cut out the part beyond the rounded rectangle area. clip () for details about the method, see the introduction in MDN.
1. First, we need to create a method for creating a lingering rounded rectangle:
/***** Draw a circular edge rectangle * @ param ctx brush * @ param x coordinate x * @ param y coordinate y * @ param width * @ param height * @ param radius rounded corner radius */function roundRect (ctx, x, y, width, height, radius) {ctx. beginPath (); ctx. moveTo (x, y + radius); ctx. lineTo (x, y + height-radius); ctx. quadraticCurveTo (x, y + height, x + radius, y + height); ctx. lineTo (x + width-radius, y + height); ctx. quadraticCurveTo (x + width, y + height, x + width, y + height-radius); ctx. lineTo (x + width, y + radius); ctx. quadraticCurveTo (x + width, y, x + width-radius, y); ctx. lineTo (x + radius, y); ctx. quadraticCurveTo (x, y, x, y + radius );}
2. Use a custom method, call the roundRect () method, draw a rectangular area of the rounded corner, and then call the clip () method to cut off the area outside the rectangle of the rounded corner. Note that the content intercepted by the clip () method is only valid for the content drawn after the method is called. The content drawn before the method is called is not truncated. Therefore, the following code must be placed before the code that draws the background.
// Draw the rounded rectangle {rect: {x: 0, y: 0, width: 115, height: 12}, type: function (g, rect, comp, data, view) {var width = rect. width, height = rect. height; roundRect (g, 0, 0, width, height, height/2); g. clip ();}}
See how it works
Now, the progress bar design is complete. Next, let's take a look at how the progress bar is combined with file upload:
1. first, we need a server to receive files. In addition to conventional web servers, the server can be used (for simple configuration of web servers, refer: HT for Web HTML5 tree component delay loading technology implementation), also uses the formidable module, the following is the server code:
Var express = require ('express '), app = express (), server = require ('http '). createServer (app), io = require ('socket. io ') (server), path = require ('path'), root = path. join (_ dirname ,'.. /.. /.. /'), formidable = require ('formidable'); // io listens for connection event io. on ('connection', function (socket) {// define the socket name socket. join ('upload') ;}); // sets the server's working Path app. use (express. static (root); app. post ('/', function (req, res ) {Var form = new formidable. IncomingForm (); form. on ('end', function () {res. end ('upload complete! ');}); Form. on ('progress', function (bytesReceived, bytesExpected) {var percent = Math. floor (bytesReceived/bytesExpected * 100); // obtain the specified socket and dispatch the event io. sockets. in ('upload '). emit ('progress', percent) ;}); form. parse (req) ;}); // The server listens to port 4000 of the server. listen (3000, function () {console. log ('server is listening at port 3000 ');});
2. Secondly, we need to design a file upload form:
3. furthermore, we need to combine ajax to upload files to the server without refreshing, and listen to server events with socket technology. for details about how to use socket in a browser, refer to: Implementation of the HTML5 tree component delay loading technology of HT for Web.
var fileForm = document.forms.namedItem('fileForm');fileForm.addEventListener('submit', function(e) { var httpRequest; if (window.XMLHttpRequest) { // Mozilla, Safari, IE7+ ... httpRequest = new XMLHttpRequest(); } else if (window.ActiveXObject) { // IE 6 and older httpRequest = new ActiveXObject("Microsoft.XMLHTTP"); } httpRequest.open('POST', '/', true); httpRequest.send(new FormData(fileForm)); socket.on('progress', function(val) { progress.setValue(val); }); e.preventDefault();}, false);
In this way, the page design and code design for implementing the HTML5 File Upload progress bar based on the HT for Web custom class are all completed. Due to the length, fromidable is rarely discussed. I hope you will forgive me, I will attach the complete code below. If you are interested, you can download the study.
Click to download source code