2016-04-02 14 views
0

Ich versuche, einen Canvas-Verweis in einem globalen Objekt zu speichern und diesen Verweis dann auf ein Element anzuwenden, anstatt den Canvas neu zu generieren. Hier ist mein bestehender Code. Ich hoffe das ergibt Sinn. Danke im Voraus!Vorhandenen Verweis auf CanvasRendingContext2D auf ein Element anwenden

waveformCache wird angenommen, dass ein globales

var cL = document.getElementById('track' + trackId + 'WaveformL'); 
var cR = document.getElementById('track' + trackId + 'WaveformR'); 

if (waveformCache.hasOwnProperty(track.path)) 
{ 
    var waveformCacheItem = waveformCache[track.path]; 

    if (waveformCacheItem.hasOwnProperty('left')) 
    { 
     // restore canvas data here to cL element 
    } 
} 
else 
{ 
    waveformCache[track.path] = {}; 

    var left = track.data.getChannelData(0); 

    var ctx1 = cL.getContext('2d'); 
    ctx1.save(); 
    ctx1.strokeStyle = 'rgb(49,73,11)'; 
    ctx1.translate(0, 55/2); //centers where the line drawing starts horizontally 

    for(var i = 0; i < left.length; i += 200) { 
     var x1 = Math.floor(track.waveformLength * i/left.length); //first parameter affects the length of the drawn waveform #ZOOM 
     var y1 = left[i] * 55/2; 

     ctx1.beginPath(); 
     ctx1.moveTo(x1, 0); 
     ctx1.lineTo(x1 + 1, y1); 
     ctx1.stroke(); 
    } 
    ctx1.restore(); 

    waveformCache[track.path].left = ctx1; 
} 
+0

Und was ist dein Problem? – Kaiido

+0

@Kaiido Ich bin mir nicht sicher, wie ich die Leinwand erneut auf das Element anwenden kann, wenn ich das CanvasRendingContext2D-Objekt vom "waveformCache" abrufe. '// canvas data hier zu cL element' wiederherstellen –

+0

Sie meinen das Canvas Element? Es ist in der .canvas -Eigenschaft des Kontexts gespeichert – Kaiido

Antwort

1

Ein Überblick über sein wie einen html5 Leinwand

CanvasRendingContext2D serialisiert

die Leinwand Kontext (CanvasRendingContext2D) hält die Leinwand Eigenschaften (Styling, aktuelle Transformation, usw.).

Wichtig! Der Kontext enthält nicht alle ausgeführten Zeichenbefehle, die den Canvas-Inhalt erstellt haben. Eigenschaften Kontext:

  • Färbung: stroke, fillStyle (1), globalAlpha,

  • Linienstile: linewidth, Linecap, lineJoin, miterLimit,

  • Textstile: Schriftart, TextAlign, TextBaseline,

  • Compositing: global,

  • Shadowing: shadow, shadowBlur, shadowOffsetX, shadowOffsetY

(1) fillStyle ist in der Regel ein String ('# ff0000'), aber es kann Halte alternativ einen Verweis auf ein Farbverlaufsobjekt oder ein Musterobjekt. Um den fillStyle des Kontextes zu speichern, müssen Sie entweder Gradienten/Muster ignorieren oder die Gradienten-/Mustereigenschaften serialisieren.

Hier ist, wie Kontexteigenschaften in ein Objekt

var properties=['strokeStyle','lineWidth','font','globalAlpha', 
    'globalCompositeOperation','shadowColor','shadowBlur', 
    'shadowOffsetX','shadowOffsetY','lineCap','lineJoin', 
    'miterLimit','textAlign','textBaseline']; 

var serializedContext={} 

for(var i=0;i<properties.length;i++){ 
    var prop=properties[i]; 
    serializedContext[prop]=context[prop]; 
} 

// fillStyle can be a headache 
if(typeof context.fillStyle === 'string'){ 
    serializedContext['fillStyle']=context.fillStyle; 
}else{ 
    // do lots more work to serialize gradient or pattern :-O 
} 

hier zu speichern, wie gespeicherte Kontexteigenschaften in einen neuen Kontext kopieren:

var context=myOtherCanvas.getContext('2d'); 

for(var i=0;i<properties.length;i++){ 
    var prop=properties[i]; 
    context[prop]=serializedContext[prop]; 
} 

// fillStyle can be a headache 
if(typeof context.fillStyle === 'string'){ 
    serializedContext['fillStyle']=context.fillStyle; 
}else{ 
    // do lots more work to re-establish gradient or pattern :-O 
} 

Re-Ausführung der Zeichnungen

Wenn y Wenn Sie alle Zeichnungsbefehle erneut ausführen möchten, müssen Sie die Befehle und ihre Argumente speichern.

Von Ihrem Beispiel-Code, es sieht aus wie Ihre Zeichnungen Liniensegmente (moveTo & lineTo) beinhalten, so können Sie jedes Segment als Segment-Objekt in einem Array von Segment-Objekten speichern.

var segments=[]; 

segments.push({moveX:10, moveY:20, lineX:100, lineY:35}); 

... and push all the other line segments 

Und dann können Sie „replay“ das Line-Segment Zeichenbefehle, nachdem Sie alle Kontexteigenschaften zurückgesetzt haben:

// redraw every line segment 
ctx.beginPath() 
for(var i=0;i<segments.length;i++){ 
    var s=segments[i]; 
    ctx.moveTo(s.moveX,s.moveY); 
    ctx.lineTo(s.lineX,s.lineY); 
} 
ctx.stroke(); 

Sie können auch serialisiert und Wiedergabe aller gängigen Zeichenbefehle (arc , beginPath, bezierCurveTo, clearRect, clip, closePath, füllen, fillRect, fillText, lineTo, moveTo, quadraticCurveTo, rect, wiederherstellen, drehen, speichern, skalieren, setTransform, stroke, strokeRect, strokeText, transformieren, übersetzen). Speichern Sie jeden Befehlsnamen & zugeordneten Argumente in einem Objekt und speichern Sie alle diese Befehlsobjekte in einem Array.

Diese Befehle geben Werte zurück, damit Sie sie benötigen, um mehr Arbeit zu handhaben: measureText, getImageData (putImageData), toDataURL, isPointInPath, isPointInStroke, create, createLinearGradient, createRadialGradient, create. Glücklicherweise werden diese Befehle seltener verwendet als die gebräuchlicheren (einfacheren) Befehle.

Über Portabilität

Wenn Sie diese Methode des Sparens alle Eigenschaften verwenden & Zeichnung in Objekt-Arrays Befehle, können Sie sie alle in JSON-Strings mit JSON.stringify leicht serialisiert werden können und man kann sie leicht in Objekt-Arrays deserialisieren zurück mit JSON.parse.

Wenn Sie Ihre Canvas-Eigenschaften & Zeichnungsbefehle serialisiert in Strings haben, können Sie sie einfach zum Speichern auf einen Server transportieren und sie dann zur Wiedergabe abrufen.

0

Sie können Path2D object verwenden, um Ihre Pfadbefehle zu speichern. Speichern Sie dann den Pfad in Ihrem globalen Objekt. Wenn Sie den Pfad erneut anwenden müssen, streichen oder füllen Sie ihn einfach mit dem gespeicherten Pfadobjekt.

Zum Beispiel:

var path = new Path2D(); 

... 
path.moveTo(.. , ..); 
path.lineTo(.. , ..); 
etc. 

Später, wenn Sie den Pfad erinnern müssen.

ctx.stroke(path); 

(Ein Bonus ist, dass Sie es SVG paths mit initialisieren Das bedeutet, Sie können einfach definieren Ihr Pfad verwendet SVG-Befehle und speichert diese als einzelne Zeichenfolge. Wenden Sie den Pfad von Path2D zu einem geringen Preis an, um die Leistung bei der Initialisierung zu verringern.)

Path2D kann polyfilled für Browser sein, die es noch nicht unterstützen (siehe Hinweise für Sonderfälle).

Verwandte Themen