2016-07-12 1 views
1

Je suis en train de rendre les images SVG sur une toile les images sont tirées une à la fois pour remplir une ligne donnée, ci-dessous est l'extrait de code du même:rendu des images svg sur une toile

function createSVGUrl(svg) { 
    var svgBlob = new Blob([svg], {type: 'image/svg+xml;charset=utf-8'}); 
    return DOMURL.createObjectURL(svgBlob); 
    }; 

/** 
    * Renders svg tile on the given context. 
    * @param {CanvasRenderingContext2D} ctx 
    * @param {SVGElement} svg The svg tile. 
    * @param {{x: number, y:number}} pos The position to draw the svg tile on. 
    * @throws Error 
    */ 
    function renderSVGTile(ctx, svg, pos) { 
    var img = new Image(); 
    var url = createSVGUrl(svg); 
    img.onload = function() { 
     try { 
     ctx.drawImage(img, pos.x, pos.y); 
     ctx.imageSmoothingEnabled = false; 
     ctx.mozImageSmoothingEnabled = false; 
     DOMURL.revokeObjectURL(url); 
     } catch (e) { 
     throw new Error('Could not render image' + e); 
     } 
    }; 
    img.src = url; 
    }; 

Le le problème est que je peux voir les rangées partiellement remplies que je ne veux pas, est-il possible de remplir toute la rangée à la fois?

+0

Attendez pour toute l'image ont une pré-chargée, puis dessiner. Btw, imageSmoothingEnabled doit être défini avant d'appeler drawImage et éviter de le définir en boucle. – Kaiido

+0

Copie possible de [Comment fonctionnent les préchargeurs d'images?] (Http://stackoverflow.com/questions/30578521/how-do-image-preloaders-work) – Kaiido

+0

@Kaiido pas exactement j'ai essayé la solution suggérée mais elle ne fonctionne pas travailler dans mon cas, peut-être en raison du très grand nombre d'images par ligne. Théoriquement, cela devrait fonctionner mais ce n'est pas le cas, [ici] (http://codereview.stackexchange.com/q/133964/58341) vous pouvez voir l'exemple. – CodeYogi

Répondre

1

Oui. Dessinez votre rangée entière de tuiles à une toile hors écran d'abord. Lorsque cela est fait, vous pouvez peindre cette toile hors écran sur votre canevas principal.

Quelque chose comme:

var offscreenCanvas = document.createElement('canvas'); 
offscreenCanvas .width = <whatever>; 
offscreenCanvas .height = <whatever>; 
var offscreenContext = offscreenCanvas.getContext('2d'); 

// Draw all your tiles 
renderSVGTile(offscreenContext, svg, pos); 
//... loop through all tiles etc 

// When finished... 
mainCanvasContext.drawImage(offscreenCanvas, 0, 0); 

Démo:

var canvas = document.getElementById("canvas"); 
 
var ctx = canvas.getContext("2d"); 
 
var image = document.getElementById("source"); 
 

 
var offscreenCanvas = document.createElement("canvas"); 
 
offscreenCanvas.width = 300; 
 
offscreenCanvas.height = 150; 
 
var offscreenContext = offscreenCanvas.getContext("2d"); 
 

 
offscreenContext.drawImage(image, 33, 71, 104, 124, 21, 20, 87, 104); 
 
offscreenContext.drawImage(image, 33, 71, 104, 124, 108, 20, 87, 104); 
 

 
ctx.drawImage(offscreenCanvas, 0, 0);
<canvas id="canvas"></canvas> 
 
<div style="display:none;"> 
 
    <img id="source" src="http://placekitten.com/300/227" 
 
     width="300" height="227"> 
 
</div>

+0

DId vous essayez ceci, parce que j'ai essayé cela avant mais a échoué. – CodeYogi

+0

Démonstration de travail ajoutée (bien qu'avec des images bitmap normales). Testé dans Chrome et Firefox. –

+0

LGTM! Je vais essayer moi-même. – CodeYogi

0

Voici comment je le fais, mais je ne suis pas sûr si elle servira votre but que je l'image dans le document au moment du rendu, il est juste caché.

var ctx = document.getElementById("canvasID").getContext("2d"); 
ctx.drawImage(document.getElementById("imageID"), x,y,w,h); 
+0

Non, les svg sont générés dynamiquement. – CodeYogi

+0

Ensuite, je crains que cela ne fonctionne pas, sauf si vous êtes prêt à ajouter un fichier SVG généré dynamiquement à une image dans le document, auquel cas cela fonctionnera. Je ne suis pas sûr si ctx.drawImage accepterait une image de non-élément, vous pourriez essayer puisque vous employez la même méthode. De plus, vous n'avez pas besoin d'avoir un élément attaché à la page, tant qu'il est créé et référencé. – Dellirium

0

La solution ci-dessous fonctionne très bien pour moi:

/** 
    * @param {CanvasRenderingContext2D} ctx 
    * @param {!Array<!SVGTile>} tiles 
    */ 
    function drawTiles(ctx, tiles) { 
    var canvas = document.createElement('canvas'); 
    var width = tiles.length * TILE_WIDTH; 
    var height = TILE_HEIGHT; 
    var y = tiles[0].y; 
    canvas.width = tiles.length * TILE_WIDTH; 
    canvas.height = TILE_HEIGHT; 
    var context = canvas.getContext("2d"); 
    tiles.forEach(function(tile, index) { 
     renderTile(context, tile, function() { 
     if (tiles.length === index + 1) { 
      ctx.drawImage(canvas, 0, y); 
     } 
     }); 
    }); 
    // TODO: Below code is for testing purpose. 
    var temp = document.createElement('div'); 
    temp.appendChild(canvas); 
    document.body.appendChild(temp); 
    }; 


    /** 
    * Renders svg tile on the given context. 
    * @param {CanvasRenderingContext2D} ctx 
    * @param {!Tile} tile The tile to render. 
    * @param {function()} callback To be called after image is loaded. 
    * @throws Error 
    */ 
    function renderTile(ctx, tile, callback) { 
    var img = new Image(); 
    img.onload = function() { 
     try { 
     ctx.drawImage(this, tile.x, 0, tile.width, tile.height); 
     ctx.imageSmoothingEnabled = false; 
     ctx.mozImageSmoothingEnabled = false; 
     DOMURL.revokeObjectURL(tile.svgURL); 
     callback(); 
     } catch (e) { 
     throw new Error('Could not render image' + e); 
     } 
    }; 
    img.src = tile.svgURL; 
    };