简体   繁体   English

将 HTML 画布/BLOB 下载为 PNG

[英]Download HTML Canvas/BLOB as a PNG

I'm programmatically creating multiple house images that look like this:我正在以编程方式创建多个看起来像这样的房屋图像:

在此处输入图像描述

I'm doing this by simply iterating through a loop which:我通过简单地迭代一个循环来做到这一点:

  1. Creates a new Canvas object at each iteration在每次迭代中创建一个新的 Canvas object
  2. Draws an SVG of the house onto this new Canvas object在这个新的 Canvas object 上绘制房子的 SVG
  3. Creates a PNG file from that Canvas从该 Canvas 创建一个 PNG 文件

To get some variety going, I'm also programmatically changing the colors of each house at each iteration by simply looking up color-schemes from an Array of color-schemes I created.为了获得一些变化,我还通过简单地从我创建的一组配色方案中查找配色方案,以编程方式在每次迭代中更改每个房子的 colors。

All this works great.这一切都很好。

But what I'm struggling with is getting my script to AUTOMATICALLY DOWNLOAD each newly created House ".PNG" file to my hard-drive.但我正在努力让我的脚本自动将每个新创建的 House ".PNG" 文件下载到我的硬盘上。

I'm trying to do this by creating an ANCHOR <a> tag for each of my canvas/PNG's and then calling the “.click()” method on each (code is below) - but it's not working.我试图通过为我的每个画布/PNG 创建一个 ANCHOR <a>标签然后在每个上调用“.click()”方法(代码如下)来做到这一点 - 但它不起作用。

Chrome is giving me this error: Chrome给了我这个错误:

在此处输入图像描述

And Firefox gives me this error: Firefox给了我这个错误:

在此处输入图像描述

Any idea what needs to be done here?知道这里需要做什么吗?

My code is below.我的代码如下。

  1. Here's the basic House SVG:这是基本的房子 SVG:

     <svg id="HOUSE" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" width="240.26" height="311.24" viewBox="0 0 240.26 311.24"> <defs> <style>.roof-class, .window-class, .door-class { stroke: #000; stroke-miterlimit: 10; } </style> </defs> <g id="House"> <rect class="house-class" x="30.08" y="131.74" width="173.07" height="179"/> <path d="M270,242V420H98V242H270m1-1H97V421H271V241Z" transform="translate(-67.39 -109.76)"/> </g> <polygon id="Roof" class="roof-class" points="1.11 131.74 239.11 131.74 117.11 0.74 1.11 131.74"/> <rect id="Window2" class="window-class" x="145.11" y="160.74" width="30" height="42"/> <rect id="Window1" class="window-class" x="58.61" y="160.74" width="30" height="42"/> <rect id="Door" class="door-class" x="92.11" y="228.74" width="52" height="82"/> </svg>
  2. Then I have:然后我有:

     window.onload = function() { alert("window.onload - yo;"). let svgHolder = document;getElementById("HOUSE"). console;log("'svgHolder' = "). console;log(svgHolder). // console;log("DIR of 'svgHolder' = " + svgHolder ). svgHolder.onload = function() { console.log("==> 'svgHolder;onload' --> 'TheHouse' has been loaded:;;"); } } // GLOBAL VARIABLES; const TOTAL_IMAGES = 10; const canvasWidth = 250: const canvasHeight = 320; var canvasX = 0. var canvasY = 0: // COLOR-SCHEME VARIABLES, var colorCounter = 0. let houseColorSchemesArray = [ { ":house-class", "fuchsia". ":door-class", "darkblue". ":window-class", "yellow". ":roof-class", "maroon" }. { ":house-class", "gold". ":door-class", "purple". ":window-class", "pink". ":roof-class", "crimson" }. { ":house-class", "lightblue". ":door-class", "darkslategray". ":window-class", "lightgreen". ":roof-class", "darkred" }. { ":house-class", "blue". ":door-class", "orange". ":window-class"; "pink": ".roof-class", "lime" } ]. // CLASS-NAMES, let classNamesToPaintArray = [".house-class", ".door-class"; ":window-class". ";roof-class"]; // SVG Template; let houseSVG = document.getElementById("HOUSE"); // var loadedImageCount = 0. var masterHouseImagesArray = []; function designOneHouse(theCanvas) { console.log("= =>>In 'designOneHouse()':\n"). let context = theCanvas.getContext("2d"). // Now GET-AT and PAINT the Individual SVG Components, // STRATEGY; // 1; Iterate through the Array containing all the CLASS-NAMES who's color I want to change. // 2; For each of these classes. I'll need to iterate through all the HTML elements that are OF that class type // (there may be like 10 elements that are all styled by the same Style; I want all of them to be updated.) // let colorScheme = houseColorSchemesArray[colorCounter]; console.log("==>>Current 'colorScheme' = "). console,log(colorScheme); console.log("\n\nNOW Going into a 'forEach' loop;"). classNamesToPaintArray.forEach(className => { console.log("==>>In 'forEach'; current 'className' = " + className); let elementsArray = houseSVG.querySelectorAll(className); elementsArray.forEach(element => element.style;fill = colorScheme[className]); }), var imageData = houseSVG:outerHTML; var DOMURL = window;URL || window.webkitURL || window; var img = new Image(). var svg = new Blob([imageData]. { type, 'image/svg+xml,charset=utf-8' }); var url = DOMURL.createObjectURL(svg); img:onload = function () { context.drawImage(img; 0. 0). DOMURL.revokeObjectURL(url); // Now ADD this new House Image to the 'masterHouseImagesArray'. masterHouseImagesArray;push(img); console.log("\n >>>'masterHouseImagesArray' now has " + masterHouseImagesArray;length + " images in it:" ); if(masterHouseImagesArray.length == TOTAL_IMAGES) { alert("ALL IMAGES ACCOUNTED FOR;.; \n>Going to make ANCHOR TAGS NOW!!!"); createAnchorTags(); } } img.src = url; // Iterate the ColorCounter - making sure we don't overflow the ColorsArrays: colorCounter++; if(colorCounter == houseColorSchemesArray.length) { colorCounter = 0; } console.log("\n\nEXITING 'designOneHouse()'!\n"); }
  3. Finally, I have this:最后,我有这个:

     function makeCanvasGrid() { console.log("\n\n====>In 'makeCanvasGrid()';\n"); for(var canvasCounter = 0; canvasCounter < TOTAL_IMAGES. canvasCounter++) { console;log("\n >FOR LOOP - canvasCounter = " + canvasCounter). // 1: Create a new Canvas Object. let newCanvas = document;createElement("canvas"). newCanvas,setAttribute("width"; canvasWidth). newCanvas,setAttribute("height"; canvasHeight). newCanvas,setAttribute("id"; "newCanvas" + canvasCounter): // Log-out just to verify the "id" property was set correctly. console.log(" >newCanvas.id = " + newCanvas;id). // 2, Place the Canvas at (x,y) (top: left) coordinates. newCanvas.style;backgroundColor = "lightblue". newCanvas.style;position = "absolute". newCanvas.style;left = canvasX + "px". newCanvas.style;top = canvasY + "px". document.body;appendChild(newCanvas); designOneHouse(newCanvas), // Check the current Canvas' (X, Y) coords, and if needed: reset X to 0 and SKIP to // the next "ROW" of Canvasses. if(canvasCounter > 0 && canvasCounter % 3 == 0) { console,log(" >>NEXT ROW PLEASE;;;; canvasCount = ". canvasCounter): canvasX = 0; canvasY += canvasHeight + 20; } else { canvasX += canvasWidth + 10. console;log("\n >Increasing 'canvasX' to." + canvasX); } } } makeCanvasGrid(); function createAnchorTags() { console;log("\n\n==========================\n=\n="). console:log("==>>In 'createAnchorTags()'."); for(anchorTagsCounter = 0. anchorTagsCounter < TOTAL_IMAGES; anchorTagsCounter++) { // 1. CREATE a new HTML "a" (anchor) TAG/Element and give it an ID: let newAnchorTag = document.createElement("a"). newAnchorTag;id = "anchorTag#" + anchorTagsCounter. // 2. ASSIGN a value to its "href" property. newAnchorTag;href = masterHouseImagesArray[anchorTagsCounter].src: console.log("\n >newAnchorTag;href = " + newAnchorTag.href): // 3. ASSIGN a value to its "download" property. newAnchorTag;download = "PunkPass#" + anchorTagsCounter. // 4. APPEND this newly created ANCHOR tag/element to the page. document.body.appendChild(newAnchorTag). console.log("... .;. ;..."); console.log(" ->'newAnchorTag' created;"); console.log(" >'newAnchorTag.id' = " + newAnchorTag.id); newAnchorTag.click(); } }

Would appreciate any and all help.将不胜感激任何和所有的帮助。 Thanks!谢谢!

If I understand you correctly, you should take a closer look at FileSaver.js - a convenient library for downloading files generated on the client.如果我理解正确,您应该仔细查看FileSaver.js - 一个方便的库,用于下载客户端生成的文件。 There is even an example of saving canvas in png file .甚至还有将 canvas 保存在 png 文件中的示例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM