2017-08-18 3 views
0
//image sequence functions 
//preload array 
/** 
* Preload images in a directory. 
* @param {string} baseurl 
* @param {string} extension 
* @return {Promise} resolve an Array<Image>. 
*/ 
function preloadImages(baseurl, extension, starter) { 
    return new Promise(function (res) { 
     var i = starter; 
     var images = []; 
     // Inner promise handler 
     var handler = function (resolve, reject) { 
      var img = new Image; 
      var source = baseurl + i + '.' + extension; 
      img.onload = function() { 
       i++; 
       resolve(img); 
      } 
      img.onerror = function() { 
       reject('Rejected after ' + i + 'frames.'); 
      } 
      img.src = source; 
     } 
     // Once you catch the inner promise you resolve the outer one. 
     var _catch = function() { 
      res(images) 
     } 
     var operate = function (value) { 
      if (value) images.push(value); 
      // Inner recursive promises chain. 
      // Stop with the catch resolving the outer promise. 
      new Promise(handler).then(operate).catch(_catch); 
     } 
     operate(); 
    }) 
} 

/** 
* Draw an Array of images on a canvas. 
* @param {Canvas} canvas 
* @param {Array<Image>} imagelist 
* @param {number} refreshRate 
*/ 
function play(canvas, imagelist, refreshRate, frameWidth, frameHeight, percentage) { 
    // Since we're using promises, let's promisify the animation too. 
    return new Promise(function (resolve) { 
     // May need to adjust the framerate 
     // requestAnimationFrame is about 60/120 fps depending on the browser 
     // and the refresh rate of the display devices. 
     var ctx = canvas.getContext('2d'); 
     var ts, i = 0, 
      delay = 1000/refreshRate; 
     var roll = function (timestamp) { 
      if (!ts || timestamp - ts >= delay) { 
       // Since the image was prefetched you need to specify the rect. 
       ctx.drawImage(imagelist[i], 0, 0, frameWidth, frameHeight); 
       i++; 
       ts = timestamp; 
      } 
      if (i < imagelist.length * percentage) 
       requestAnimationFrame(roll); 
      else 
       resolve(i); 
     } 
     roll(); 
    }) 
} 
//combine preload and play into one 
function preloadAndPlay(ID, actor, event, percentage) { 
    var preload = preloadImages('/static/videos/' + actor + '/Clip_' + event + '/', 'png', 1); 
    preload.then(function (value) { 
     //console.log('starting play'); 
     //canvas html5 object with ID 
     var canvas = document.getElementById(ID); 
     play(canvas, value, 30, 960, 540, percentage) // ~30fps 
      .then(function (frame) { 
       console.log('roll finished after ' + frame + ' frames.') 
      }) 
    }); 
} 



$.when(preloadAndPlay('myImage', actor, event, percentage)).done(function(){ 
     $('.data').click(function() { 
      if ($(this).is(':checked')) { 
       $(this).removeClass('hidden'); 
       $(that).addClass('hidden'); 
      } 
      that = this; 
     }); 
     $('.data').change(function() { 
      if (('input[name=b]:checked').length) { 
       $('#trial_next').prop('disabled', false); 
       cbChecked = document.querySelector('[name="b"]:checked').value; 
       debug(cbChecked); 
      } 
     }); 
    }); 

getan ausgeführt würde ich die .change und .click jquery mag erst nach preloadAndPlay aktiviert werden JavaScript-Funktion ausgeführt wird vollständig durchgeführt. JQuery ist erlaubt Radio-Buttons zu erlauben, die ausgewählt werden können. preloadAndPlay ist eine Funktion, die eine Reihe von Bildern lädt und sie dann mit html5-Canvas anzeigt, so dass es wie ein Video/eine Animation erscheint. Siehe oben für die preloadAndPlay-Funktion, die Versprechen und Rekursion verwendet. Der Code funktioniert, ich möchte nicht, dass die Leute eine Auswahl treffen, bevor das Video endet. Oben ist der Code, den ich ausprobiert habe.aktivieren JQuery Erst nach Javascript rekursive Funktion

+1

zeigen Bitte geben Sie die 'preloadAndPlay()' Funktion. Ich nehme an, dass es einen asynchronen Prozess auslöst? Wenn Sie es mit '$ .when()' verwenden möchten, sollte es eine Zusage zurückgeben, die Sie erfüllen, wenn der asynchrone Prozess abgeschlossen ist. (Beachten Sie, dass, wenn die Funktion alle synchron ist, Sie '$ .when()' nicht benötigen und rekursiv wäre.) – nnnnnn

+0

_ "Ich möchte, dass die .change- und .click jquery nur nach aktiviert werden Die JavaScript-Funktion preloadAndLoad wird vollständig ausgeführt. "_, _" Beachten Sie, dass preloadAndPlay eine rekursive Funktion ist. "_ Was ist der Rückgabewert des Funktionsaufrufs' preloadAndLoad'? Siehe https://stackoverflow.com/help/mcve – guest271314

+0

@nnnnnn fertig. Ich fügte weitere Details und Erklärungen hinzu. Danke, dass du mir wieder geholfen hast. –

Antwort

0

Es gibt mehrere Probleme bei Code in Frage. Bei preloadImages Funktion wird der Parameter an der Funktion übergeben an Promise Konstruktor res genannt, obwohl resolve() wird innerhalb der Funktion bei load Ereignis aufgerufen, obwohl resolve ist innerhalb der Funktion undefined. handler wird nicht angerufen und erreicht nicht den Aufruf von undefined resolve(). operate Funktion innerhalb Promise Konstruktor ist nicht erforderlich. Kein Wert ist return ed von operate, siehe Why is value undefined at .then() chained to Promise?.

Sie können Promise.all() verwenden, um ein iterable Objekt zu übergeben, wo .then() gekettet sollte aufgerufen werden, wenn alle der Werte oder Promise gebenen Werte erfüllt sind.

Nicht sicher, was der erwartete Effekt von play() Aufruf ist, noch wird dieser Teil des Codes als Teil der ursprünglichen Anfrage erwähnt. Angepasster Code bei staccksnippets, um requestAnimationFrame für jedes Bild aufzurufen.

const baseurl = "https://lorempixel.com/50/50/"; 
 

 
const data = ["cats", "nature", "city"]; 
 

 
const canvas = document.querySelector("canvas"); 
 

 
function preloadImages(image) { 
 
    return new Promise(function(resolve) { 
 
    var img = new Image; 
 
    var source = baseurl + image; 
 
    img.onload = function() { 
 
     resolve(img); 
 
    } 
 
    img.onerror = function() { 
 
     reject('Rejected after ' + i + 'frames.'); 
 
    } 
 
    img.src = source; 
 
    }) 
 
} 
 

 
function play(canvas, imagelist, refreshRate, frameWidth, frameHeight, percentage) { 
 
    // Since we're using promises, let's promisify the animation too. 
 
    return new Promise(function(resolve) { 
 
    // May need to adjust the framerate 
 
    // requestAnimationFrame is about 60/120 fps depending on the browser 
 
    // and the refresh rate of the display devices. 
 
    var ctx = canvas.getContext('2d'); 
 
    var ts, i = 0, 
 
     delay = 1000/refreshRate; 
 
    var roll = function(timestamp) { 
 
     if (!ts || timestamp - ts >= delay) { 
 
     // Since the image was prefetched you need to specify the rect. 
 
     ctx.drawImage(imagelist[i], 0, 0, frameWidth, frameHeight); 
 
     i++; 
 
     ts = timestamp; 
 
     } 
 
     if (i < imagelist.length /* * percentage */) 
 
     requestAnimationFrame(roll); 
 
     else 
 
     resolve(i); 
 
    } 
 
    roll(); 
 
    }) 
 
} 
 

 
function preloadAndPlay(percentage) { 
 
    var preload = Promise.all(data.map(preloadImages)) 
 
    .then(function(images) { 
 
     console.log("preloadImages complete, images:", images); 
 
     images.forEach(function(img) { 
 
     document.body.appendChild(img) 
 
     }); 
 
     return images 
 
    }) 
 
    .catch(function(err) { 
 
     console.error(err); 
 
     throw err; 
 
    }); 
 
    return preload.then(function(value) { 
 
    console.log("preload complete, value:", value); 
 
    return play(canvas, value, 30, 960, 540, percentage) // ~30fps 
 
     .then(function(frame) { 
 
     console.log('roll finished after ' + frame + ' frames.'); 
 
     return "done"; 
 
     }) 
 
    }); 
 
} 
 

 
preloadAndPlay() 
 
.then(function(data) { 
 
    console.log(data); 
 
}) 
 
    .catch(function(err) { 
 
    console.error(err) 
 
    })
<canvas></canvas>

Verwandte Themen