Pertanyaan JavaScript memuat kemajuan gambar


Apakah ada cara di JS untuk mendapatkan kemajuan dari memuat gambar saat gambar sedang dimuat? Saya ingin menggunakan tag Kemajuan baru HTML5 untuk menunjukkan progres pemuatan gambar.

Saya berharap ada sesuatu seperti:

var someImage = new Image()
someImage.onloadprogress = function(e) { progressBar.value = e.loaded / e.total };
someImage.src = "image.jpg";

42
2018-01-08 15:39


asal


Jawaban:


Coba gunakan pendekatan yang dijelaskan dalam ini artikel Juga ada a sampel hidup. Seperti yang saya mengerti bahwa Anda sedang mencari.


-3
2018-01-09 16:08



Dengan ini, Anda menambahkan 2 fungsi baru pada objek Image ():

 Image.prototype.load = function(url){
        var thisImg = this;
        var xmlHTTP = new XMLHttpRequest();
        xmlHTTP.open('GET', url,true);
        xmlHTTP.responseType = 'arraybuffer';
        xmlHTTP.onload = function(e) {
            var blob = new Blob([this.response]);
            thisImg.src = window.URL.createObjectURL(blob);
        };
        xmlHTTP.onprogress = function(e) {
            thisImg.completedPercentage = parseInt((e.loaded / e.total) * 100);
        };
        xmlHTTP.onloadstart = function() {
            thisImg.completedPercentage = 0;
        };
        xmlHTTP.send();
    };

    Image.prototype.completedPercentage = 0;

Dan di sini Anda menggunakan fungsi beban dan menambahkan gambar pada div.

var img = new Image();
img.load("url");
document.getElementById("myDiv").appendChild(img);

Selama status pemuatan, Anda dapat memeriksa persentase kemajuan menggunakan img.completedPercentage.


39
2018-03-23 16:53



Jawaban Sebastian sangat bagus, yang terbaik yang pernah saya lihat untuk pertanyaan ini. Namun demikian, ada beberapa kemungkinan perbaikan. Saya menggunakan kodenya yang dimodifikasi seperti ini:

Image.prototype.load = function( url, callback ) {
    var thisImg = this,
        xmlHTTP = new XMLHttpRequest();

    thisImg.completedPercentage = 0;

    xmlHTTP.open( 'GET', url , true );
    xmlHTTP.responseType = 'arraybuffer';

    xmlHTTP.onload = function( e ) {
        var h = xmlHTTP.getAllResponseHeaders(),
            m = h.match( /^Content-Type\:\s*(.*?)$/mi ),
            mimeType = m[ 1 ] || 'image/png';
            // Remove your progress bar or whatever here. Load is done.

        var blob = new Blob( [ this.response ], { type: mimeType } );
        thisImg.src = window.URL.createObjectURL( blob );
        if ( callback ) callback( this );
    };

    xmlHTTP.onprogress = function( e ) {
        if ( e.lengthComputable )
            thisImg.completedPercentage = parseInt( ( e.loaded / e.total ) * 100 );
        // Update your progress bar here. Make sure to check if the progress value
        // has changed to avoid spamming the DOM.
        // Something like: 
        // if ( prevValue != thisImage completedPercentage ) display_progress();
    };

    xmlHTTP.onloadstart = function() {
        // Display your progress bar here, starting at 0
        thisImg.completedPercentage = 0;
    };

    xmlHTTP.onloadend = function() {
        // You can also remove your progress bar here, if you like.
        thisImg.completedPercentage = 100;
    }

    xmlHTTP.send();
};

Terutama saya menambahkan tipe mime dan beberapa detail kecil. Gunakan sebagai Sebastian menjelaskan. Bekerja dengan baik.


14
2018-05-16 19:32



Hanya untuk menambah perbaikan, saya telah memodifikasi jawaban Julian (yang pada gilirannya memodifikasi Sebastian). Saya telah memindahkan logika ke fungsi alih-alih memodifikasi Image obyek. Fungsi ini mengembalikan a Promise yang menyelesaikan dengan objek URL, yang hanya perlu dimasukkan sebagai src atribut dari suatu image menandai.

/**
 * Loads an image with progress callback.
 *
 * The `onprogress` callback will be called by XMLHttpRequest's onprogress
 * event, and will receive the loading progress ratio as an whole number.
 * However, if it's not possible to compute the progress ratio, `onprogress`
 * will be called only once passing -1 as progress value. This is useful to,
 * for example, change the progress animation to an undefined animation.
 *
 * @param  {string}   imageUrl   The image to load
 * @param  {Function} onprogress
 * @return {Promise}
 */
function loadImage(imageUrl, onprogress) {
  return new Promise((resolve, reject) => {
    var xhr = new XMLHttpRequest();
    var notifiedNotComputable = false;

    xhr.open('GET', imageUrl, true);
    xhr.responseType = 'arraybuffer';

    xhr.onprogress = function(ev) {
        if (ev.lengthComputable) {
          onprogress(parseInt((ev.loaded / ev.total) * 100));
        } else {
          if (!notifiedNotComputable) {
            notifiedNotComputable = true;
            onprogress(-1);
          }
        }
    }

    xhr.onloadend = function() {
      if (!xhr.status.toString().match(/^2/)) {
        reject(xhr);
      } else {
        if (!notifiedNotComputable) {
          onprogress(100);
        }

        var options = {}
        var headers = xhr.getAllResponseHeaders();
        var m = headers.match(/^Content-Type\:\s*(.*?)$/mi);

        if (m && m[1]) {
          options.type = m[1];
        }

        var blob = new Blob([this.response], options);

        resolve(window.URL.createObjectURL(blob));
      }
    }

    xhr.send();
  });
}

/*****************
 * Example usage
 */

var imgContainer = document.getElementById("imgcont");
var progressBar = document.getElementById("progress");
var imageUrl = "https://placekitten.com/g/2000/2000";

loadImage(imageUrl, (ratio) => {
  if (ratio == -1) {
    // Ratio not computable. Let's make this bar an undefined one.
    // Remember that since ratio isn't computable, calling this function
    // makes no further sense, so it won't be called again.
    progressBar.removeAttribute("value");
  } else {
    // We have progress ratio; update the bar.
    progressBar.value = ratio;
  }
})
.then(imgSrc => {
  // Loading successfuly complete; set the image and probably do other stuff.
  imgContainer.src = imgSrc;
}, xhr => {
  // An error occured. We have the XHR object to see what happened.
});
<progress id="progress" value="0" max="100" style="width: 100%;"></progress>

<img id="imgcont" />


8
2018-02-13 04:39



Sebenarnya, di chrome terbaru Anda bisa menggunakannya.

$progress = document.querySelector('#progress');

var url = 'https://placekitten.com/g/2000/2000';

var request = new XMLHttpRequest();
request.onprogress = onProgress;
request.onload = onComplete;
request.onerror = onError;

function onProgress(event) {
  if (!event.lengthComputable) {
    return;
  }
  var loaded = event.loaded;
  var total = event.total;
  var progress = (loaded / total).toFixed(2);

  $progress.textContent = 'Loading... ' + parseInt(progress * 100) + ' %';

  console.log(progress);
}

function onComplete(event) {
  var $img = document.createElement('img');
  $img.setAttribute('src', url);
  $progress.appendChild($img);
  console.log('complete', url);
}

function onError(event) {
  console.log('error');
}


$progress.addEventListener('click', function() {
  request.open('GET', url, true);
  request.overrideMimeType('text/plain; charset=x-user-defined');
  request.send(null);
});
<div id="progress">Click me to load</div>


3
2018-06-09 00:00



untuk pemeriksaan xmlhttpreq v2, gunakan:

var xmlHTTP = new XMLHttpRequest();
if ('onprogress' in xmlHTTP) {
 // supported 
} else {
 // isn't supported
}

1
2017-10-01 06:35



Berikut ini adalah pembaruan kecil kode Julian Jensen agar dapat menggambar gambar di Canvas setelah dimuat:

xmlHTTP.onload = function( e ) {
        var h = xmlHTTP.getAllResponseHeaders(),
            m = h.match( /^Content-Type\:\s*(.*?)$/mi ),
            mimeType = m[ 1 ] || 'image/png';
            // Remove your progress bar or whatever here. Load is done.

        var blob = new Blob( [ this.response ], { type: mimeType } );
        thisImg.src = window.URL.createObjectURL( blob );

         thisImg.onload = function()
            {
                if ( callback ) callback( this );
            };
    };

0
2017-08-31 10:05



Jika Anda ingin memproses gambar yang dimuat, daripada Anda harus menambahkan satu fungsi lagi, karena

thisImg.src = window.URL.createObjectURL(blob)

baru mulai memproses gambar sebagai utas.

Anda harus menambahkan fungsi baru ke tubuh prototipe beban, seperti

  this.onload = function(e)
  {
    var canvas = document.createElement('canvas')

    canvas.width = this.width
    canvas.height = this.height

    canvas.getContext('2d').drawImage(this, 0, 0)
   }

Ini membuat saya pusing untuk menyadari :)


0
2018-02-13 15:07