pic vom selbstgeschriebenen server holen und darstellen
bearbeitet von 1unitedpowerDoppelpost, wird hier weiter diskutiert: <https://forum.selfhtml.org/self/2017/sep/10/pic-refreshen/1705320#m1705320>
pic vom selbstgeschriebenen server holen und darstellen
bearbeitet von 1unitedpowerHallo xharx,
ich habe das Code-Beispiel mal aus deinem anderen Beitrag hierüber kopiert. Über die farbliche Hervorhebung später mehr.
~~~javascript
imgData=0;
canvas=0;
canvasheight=480;
canvaswidth=640;
function render() {
~~~
~~~javascript, good
var myAjax = new XMLHttpRequest();
myAjax.responseType="arraybuffer";
if (myAjax.response==0) console.log("network error");
myAjax.onreadystatechange=function(){
~~~
~~~js, bad
if (myAjax.readyState==4 && myAjax.status==200){
if (!canvas) {
canvas=document.getElementById("canvasid");
console.log("canvasneu");
context=canvas.getContext('2d');
if (context) {
if (!imgData) {
imgData=context.getImageData(0,0,canvaswidth,canvasheight);
}
}
}
else {
responsearray=new Uint8Array(myAjax.response);
i=responsearray.length;
while (i--) imgData.data[i]=responsearray[i];
responsearray=null;
context.putImageData(imgData, 0, 0);
}
}
~~~
~~~js,good
};
myAjax.open("GET", "canvasdata", true);
myAjax.send();
~~~
~~~js
}
function animate() {
render();
requestAnimationFrame(animate);
}
animate();
~~~
Ich fürchte du wirst dein Ziel auf diesem Wege nicht erreichen können. Du peilst 60 Bilder pro Sekunde an und für jedes Bild startest du eine einzelne http-Anfrage an den Server. Jede Frage-Antwort-Runde an den Server hat damit gerade mal ein Zeitfenster von 16,67ms und da ist die clientseitige Weiterverarbeitung noch gar nicht berücksichtigt, die nimmt auch nochmal Zeit in Anspruch. Du müsstest auch noch berücksichtigen, dass die Server-Antworten nicht zwingend in der Reihenfolge eintreffen, in der du sie angefragt hast. Du müsstest die Antworten also noch ordnen und ggf. alle überholten Anfragen abbrechen, um die Netzwerk-Auslastung nicht unkontrolliert in die Höhe zu treiben. Und dann hast du noch ein Problem in deinem Rendering-Loop: Bei jedem Aufruf von `requestAnimationFrame` wird jeweils nur der grün markierte Code ausgeführt. In diesem Bereich sendest du die http-Anfragen ab, gezeichnet wird da gar nichts. Das kann nämlich erst passieren, wenn die Server-Antwort eintrifft, also in dem rot-markierten Bereich, aber bis dahin hat der Browser den Frame längst gezeichnet. Dann trifft irgendwann die Server-Antwort ein, du zeichnest tatsächlich etwas auf das Canvas und unterbrichst dann trotzdem den Browser bei seinem aktuellen Zeichenvorgang. Das Skelett, für deinen Rendering-Loop, sollte also eher so aussehen:
~~~js
function fetchBitmap() {
const request = new XMLHttpRequest()
request.open("GET", "canvasdata")
request.addEventListener("load", onLoad)
}
function onLoad (response) {
// … verarbeite response weiter zu imgData …
requestAnimationFrame(() => render(imgData))
}
function render (imgData) {
context.putImageData(imgData, 0, 0)
fetchBitmap()
}
~~~
Letzten Endes bleibt aber das Problem, dass jeder Frame auch eine http-Anfrage voraussetzt und dafür zu wenig Zeit bleibt. Ich rate dir auf jeden Fall dazu, serverseitig ein richtiges Video zu generieren und keine Einzelbilder. Der Unterschied ist in etwa der zwischen einem HD-Kino und einem Daumenkino.