Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/84.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 在画布上呈现svg图像_Javascript_Html_Canvas_Svg_Web - Fatal编程技术网

Javascript 在画布上呈现svg图像

Javascript 在画布上呈现svg图像,javascript,html,canvas,svg,web,Javascript,Html,Canvas,Svg,Web,我试图在画布上呈现SVG图像。图像一次绘制一个以填充给定行,下面是相同的代码片段: 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. *

我试图在画布上呈现SVG图像。图像一次绘制一个以填充给定行,下面是相同的代码片段:

  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;
  };

问题是我可以看到我不想要的部分填充行,有没有办法一次填充整行?

是的。首先将整排瓷砖绘制到屏幕外的画布上。完成后,您可以在主画布上绘制屏幕外画布

比如:

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);

我就是这样做的,虽然我不确定它是否能满足您的需要,因为我在渲染时文档中有图像,但它只是隐藏的

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

下面的解决方案对我来说很好:

 /**
   * @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;
  };
/**
*@param{canvasrendingcontext2d}ctx
*@param{!Array}tiles
*/
功能drawTiles(ctx、tiles){
var canvas=document.createElement('canvas');
var宽度=瓦片长度*瓦片宽度;
var高度=瓷砖高度;
var y=tiles[0].y;
canvas.width=tiles.length*TILE\u width;
canvas.height=瓷砖高度;
var context=canvas.getContext(“2d”);
tiles.forEach(函数(tile,索引){
RenderFile(上下文、平铺、函数(){
如果(tiles.length==索引+1){
ctx.drawImage(画布,0,y);
}
});
});
//TODO:以下代码用于测试目的。
var temp=document.createElement('div');
临时附件(画布);
文件.正文.附件(临时);
};
/**
*在给定上下文上呈现svg磁贴。
*@param{canvasrendingcontext2d}ctx
*@param{!Tile}平铺要渲染的平铺。
*@param{function()}在加载映像后调用的回调。
*@抛出错误
*/
函数renderFile(ctx、平铺、回调){
var img=新图像();
img.onload=函数(){
试一试{
ctx.drawImage(这个,tile.x,0,tile.width,tile.height);
ctx.imageSmoothingEnabled=假;
ctx.mozImageSmoothingEnabled=false;
revokeObjectURL(tile.svgURL);
回调();
}捕获(e){
抛出新错误('无法呈现图像'+e);
}
};
img.src=tile.svgURL;
};

否,svg是动态生成的。那么,恐怕它无法工作,除非您愿意将动态生成的svg文件添加到文档中的图像中,在这种情况下,它可以工作。我不确定ctx.drawImage是否接受非元素图像,您可以尝试,因为您使用的是相同的方法。此外,您实际上不必将元素附加到页面,只要它已被创建和引用。您是否尝试过此操作,因为我以前尝试过此操作,但未成功。添加了工作演示(尽管使用普通位图图像)。在Chrome和Firefox.LGTM中测试!我会自己试试。这不起作用,而且只有在你的测试中才起作用,因为你的映像缓存(事实上你使用的是一个映像)OP的方法是异步的。他必须预装他的照片。是的,你说得对。我假设图像已经被缓存了。我的示例更多的是演示如何一次渲染一行。这是OPs最初的请求。只需等待所有图像预加载,然后绘制它。顺便说一句,在调用drawImage之前应该设置imageSmoothingEnabled,并避免在循环中设置它。@kaido的可能重复不完全是我尝试了建议的解决方案,但在我的情况下它不起作用,可能是因为每行有大量图像。理论上,它应该可以工作,但实际上不行,您可以看到示例。o_o为什么要通过svg?你知道画布有一些画法吗?您的代码会更简单。@kaido因为我们开发人员遇到的同样问题,是的,这就是需求。