วิธีบันทึก Canvas เป็นรูปภาพด้วย canvas.toDataURL ()


141

ขณะนี้ฉันกำลังสร้างแอพพลิเคชั่นบนเว็บ HTML5 และแอพพื้นเมืองของ Phonegap และฉันไม่สามารถหาวิธีการบันทึกผืนผ้าใบของฉันเป็นรูปภาพcanvas.toDataURL()ได้ ใครสามารถช่วยฉันออก

นี่คือรหัสมีอะไรผิดปกติกับมัน?

// ผ้าใบของฉันชื่อ "canvasSignature"

JavaScript:


function putImage()
{
  var canvas1 = document.getElementById("canvasSignature");        
  if (canvas1.getContext) {
     var ctx = canvas1.getContext("2d");                
     var myImage = canvas1.toDataURL("image/png");      
  }
  var imageElement = document.getElementById("MyPix");  
  imageElement.src = myImage;                           

}  

HTML5:


<div id="createPNGButton">
    <button onclick="putImage()">Save as Image</button>        
</div>

4
คำถามของ OP ยังไม่ได้รับคำตอบ เขาบอกอย่างชัดเจนว่านี่สำหรับ Phonegap / iPad คำตอบที่ให้ไว้สำหรับการบันทึกบนเบราว์เซอร์เดสก์ท็อป
tshm001

1
ไม่แน่ใจเกี่ยวกับ PhoneGap แต่ฉันได้กระทำนี้จากรอยขีดข่วนใน iOS พื้นเมืองโดยใช้ JavaScript ในส่วนอื่น ๆ ผมเก็บข้อมูลที่มี.toDataURL()แล้วใช้ window.location appname://[data url]ที่จะชี้ให้เบราว์เซอร์ ในตอนท้ายของแอพ UIWebView มีวิธีมอบสิทธิ์ที่ระบุว่าควรโหลดเพจหรือไม่ ฉันฟังappname://และทำลายมันเมื่อมันเข้ามาปฏิเสธการโหลดหน้าเว็บและจับข้อมูล URL ในสตริงดั้งเดิม ... คุณคุ้นเคยกับรหัส iOS / Objective C จริงหรือไม่
Doug

คำตอบ:


121

นี่คือรหัสบางส่วน ไม่มีข้อผิดพลาดใด ๆ

var image = canvas.toDataURL("image/png").replace("image/png", "image/octet-stream");  // here is the most important part because if you dont replace you will get a DOM 18 exception.


window.location.href=image; // it will save locally

1
ยกเว้นในโหมดมาตรฐาน IE9: "เนื้อหาหรือไฟล์บางอย่างในหน้าเว็บนี้ต้องการโปรแกรมที่คุณไม่ได้ติดตั้ง" Internet Explorer 8 ขึ้นไปรองรับเฉพาะ URI ของข้อมูลสำหรับรูปภาพใน CSS, <link> และ <img>: developer.mozilla.org/en-US/docs/data_URIs
Cees Timmerman

45
ทำงานได้ดี ฉันจะเปลี่ยนชื่อไฟล์ที่ดาวน์โหลดได้อย่างไร กำลังมาเพียงแค่ "ดาวน์โหลด" และไม่มีส่วนขยาย ขอบคุณ!
Leabdalla

1
ใน Chrome นี่ขัดข้องเบราว์เซอร์ หากฉันแสดงภาพในแท็กรูปภาพจะใช้งานได้ แต่เมนูคลิกขวานั้นเป็นสีเทา - ดังนั้นฉันจึงยังไม่สามารถบันทึกภาพได้
Kokodoko

มันใช้งานได้ดี ... แต่ใน Android (เบราว์เซอร์เริ่มต้นใน Galaxy S3) มันไม่ดาวน์โหลดภาพ แต่ฉันได้รับข้อความ "กำลังดาวน์โหลด ... " ตลอดไป
Habrashat

ฉันมีปัญหาเกี่ยวกับการบันทึกบางอย่างสามารถช่วยให้ฉันเห็นลิงค์นี้: stackoverflow.com/questions/25131763/ …
Ramesh S

36

วิธีนี้ช่วยให้คุณเปลี่ยนชื่อไฟล์ที่ดาวน์โหลด:

HTML:

<a id="link"></a>

javascript:

  var link = document.getElementById('link');
  link.setAttribute('download', 'MintyPaper.png');
  link.setAttribute('href', canvas.toDataURL("image/png").replace("image/png", "image/octet-stream"));
  link.click();

ขอบคุณสำหรับสิ่งนี้มันช่วยฉันได้มาก!
Mike Moon

22

คุณสามารถใช้canvas2imageเพื่อแจ้งให้ทำการดาวน์โหลด

ฉันมีปัญหาเดียวกันต่อไปนี้เป็นตัวอย่างง่ายๆที่ทั้งสองเพิ่มรูปภาพในหน้าเว็บและบังคับให้เบราว์เซอร์ดาวน์โหลด:

<html>
    <head>
        <script src="http://hongru.github.io/proj/canvas2image/canvas2image.js"></script>
        <script>
            function draw(){
                var canvas = document.getElementById("thecanvas");
                var ctx = canvas.getContext("2d");
                ctx.fillStyle = "rgba(125, 46, 138, 0.5)";
                ctx.fillRect(25,25,100,100); 
                ctx.fillStyle = "rgba( 0, 146, 38, 0.5)";
                ctx.fillRect(58, 74, 125, 100);
            }

            function to_image(){
                var canvas = document.getElementById("thecanvas");
                document.getElementById("theimage").src = canvas.toDataURL();
                Canvas2Image.saveAsPNG(canvas);
            }
        </script>
    </head>
    <body onload="draw()">
        <canvas width=200 height=200 id="thecanvas"></canvas>
        <div><button onclick="to_image()">Draw to Image</button></div>
        <image id="theimage"></image>
    </body>
</html>

2
เพิ่งทดลองใช้แล้วมันจะบันทึกไฟล์ที่ไม่มีชื่อหรือนามสกุลใน Chrome
malber

ตามที่กล่าวไว้ที่นี่nihilogic.dk/labs/canvas2imageการตั้งชื่อไฟล์ดูเหมือนจะไม่เป็นไปได้: "มันจะเป็นเรื่องที่เรียบร้อยมาก ๆ ถ้ามีการแนบชื่อไฟล์กับข้อมูล แต่ฉันไม่พบวิธีที่จะทำเช่นนั้น ในตอนนี้คุณต้องระบุชื่อไฟล์ด้วยตัวเอง "
SColvin

1
ลิงก์ที่คุณโพสต์เสียหาย
Oliver Nybroe

9

คุณสามารถลองสิ่งนี้ สร้างจุดยึด HTML dummy และดาวน์โหลดภาพจากที่นั่นเช่น ...

// Convert canvas to image
document.getElementById('btn-download').addEventListener("click", function(e) {
    var canvas = document.querySelector('#my-canvas');

    var dataURL = canvas.toDataURL("image/jpeg", 1.0);

    downloadImage(dataURL, 'my-canvas.jpeg');
});

// Save | Download image
function downloadImage(data, filename = 'untitled.jpeg') {
    var a = document.createElement('a');
    a.href = data;
    a.download = filename;
    document.body.appendChild(a);
    a.click();
}

1
ฉันชอบความจริงที่ว่าทุกอย่างทำใน JS รวมถึงการสร้างองค์ประกอบลิงก์ มันใช้งานได้ดีสำหรับวัตถุประสงค์อัตโนมัติ
Jeromy Adofo

โซลูชั่นที่สมบูรณ์แบบ
Hidayt Rahman

8

ฉันสร้างห้องสมุดขนาดเล็กที่ทำสิ่งนี้ (รวมถึงการแปลงที่มีประโยชน์อื่น ๆ ) มันเรียกว่าreimgและมันใช้ง่ายมาก

ReImg.fromCanvas(yourCanvasElement).toPng()


ห้องสมุดสุดยอด ขอบคุณ มีปัญหาเล็กน้อยในเอกสารตัวอย่างแม้ว่า ฉันเปิดปัญหาเกี่ยวกับ Github เพื่อนำมันมาสู่ความสนใจของคุณ
jmknoll

7

งานนี้สำหรับฉัน: (เฉพาะ Google Chrome)

<html>
<head>
    <script>
            function draw(){
                var canvas = document.getElementById("thecanvas");
                var ctx = canvas.getContext("2d");
                ctx.fillStyle = "rgba(125, 46, 138, 0.5)";
                ctx.fillRect(25,25,100,100);
                ctx.fillStyle = "rgba( 0, 146, 38, 0.5)";
                ctx.fillRect(58, 74, 125, 100);
            }

            function downloadImage()
            {
                var canvas = document.getElementById("thecanvas");
                var image = canvas.toDataURL();

                var aLink = document.createElement('a');
                var evt = document.createEvent("HTMLEvents");
                evt.initEvent("click");
                aLink.download = 'image.png';
                aLink.href = image;
                aLink.dispatchEvent(evt);
            }
    </script>
</head>
<body onload="draw()">
    <canvas width=200 height=200 id="thecanvas"></canvas>
    <div><button onclick="downloadImage()">Download</button></div>
    <image id="theimage"></image>
</body>
</html>

บางทีคุณสามารถอธิบายส่วนของรหัสของคุณที่ตอบคำถามแทนที่จะวางมันโดยไม่ต้องแสดงความคิดเห็น?
Gediminas Masaitis

6

คล้ายกับคำตอบของ 1000Bugyแต่ง่ายกว่าเพราะคุณไม่จำเป็นต้องประกาศข่าวและส่งเหตุการณ์คลิกด้วยตนเอง (รวมถึงการแก้ไข IE)

หากคุณทำให้ปุ่มดาวน์โหลดเป็นจุดยึดคุณสามารถ highjack ได้ทันทีก่อนที่จะใช้งานฟังก์ชันการยึดสมอที่เป็นค่าเริ่มต้น ดังนั้นonAnchorClickคุณสามารถตั้งค่า anchor href เป็น canvas base64 image และ attribute download anchor เป็นสิ่งที่คุณต้องการตั้งชื่อรูปภาพของคุณ

สิ่งนี้ไม่ทำงานใน (ปัจจุบัน) IE เพราะมันไม่ได้ใช้คุณสมบัติการดาวน์โหลดและป้องกันการดาวน์โหลดข้อมูล uris แต่สามารถแก้ไขได้โดยใช้window.navigator.msSaveBlobแทน

ดังนั้นสมอจัดการเหตุการณ์คของคุณจะได้รับการปฏิบัติตาม (ที่anchor, canvasและfileNameมีการค้นหาขอบเขต):

function onClickAnchor(e) {
  if (window.navigator.msSaveBlob) {
    window.navigator.msSaveBlob(canvas.msToBlob(), fileName);
    e.preventDefault();
  } else {
    anchor.setAttribute('download', fileName);
    anchor.setAttribute('href', canvas.toDataURL());
  }
}

นี่คือซอ


1

แทนที่จะเป็นimageElement.src = myImage;คุณควรใช้window.location = myImage;

และแม้กระทั่งหลังจากนั้นเบราว์เซอร์ก็จะแสดงภาพเอง คุณสามารถคลิกขวาและใช้ "Save Link" เพื่อดาวน์โหลดภาพ

ตรวจสอบลิงค์นี้สำหรับข้อมูลเพิ่มเติม


ว้าวขอบคุณที่ช่วยได้มากจริงๆ :) แต่คุณจะได้รับกล่องบันทึกป๊อปอัพได้อย่างไรเพื่อให้บางคนสามารถบันทึกไปยังปลายทางที่ต้องการ (เช่นโฟลเดอร์ภาพ Android ของพวกเขา)
Wardenclyffe

มันขึ้นอยู่กับเบราว์เซอร์ที่เฉพาะเจาะจง เบราว์เซอร์ Android มักจะดาวน์โหลดไฟล์ไปยังโฟลเดอร์เฉพาะโดยตรงเพื่อติดตั้ง
Hakan Serce

ใน Chrome ใช้งานได้ แต่เมนูคลิกขวาเป็นสีเทา เมื่อพยายาม 'ลาก' ภาพออกจากเบราว์เซอร์ Chrome ขัดข้อง
Kokodoko

groups.google.com/a/chromium.org/forum/#!topic/blink-dev/…การเปิด URL ข้อมูลแบบนี้จะถูกปิดกั้นดูเหมือนว่า
KeyOfJ

0

คุณไม่สามารถใช้วิธีที่กล่าวถึงก่อนหน้านี้เพื่อดาวน์โหลดภาพเมื่อทำงานใน Cordova คุณจะต้องใช้Cordova ไฟล์ปลั๊กอิน สิ่งนี้จะช่วยให้คุณเลือกตำแหน่งที่จะบันทึกและใช้ประโยชน์จากการตั้งค่าการคงอยู่ที่แตกต่างกัน รายละเอียดที่นี่: https://cordova.apache.org/docs/en/latest/reference/cordova-plugin-file/

หรือคุณสามารถแปลงภาพเป็น base64 แล้วเก็บสตริงไว้ในlocalStorageแต่จะทำให้โควต้าของคุณเต็มเร็วถ้าคุณมีภาพจำนวนมากหรือความละเอียดสูง


-9

@Wardenclyffe และ @SColvin คุณทั้งสองพยายามบันทึกภาพโดยใช้ Canvas ไม่ใช่โดยใช้บริบทของ Canvas ทั้งคุณควรลอง ctx.toDataURL (); ลองสิ่งนี้:

var canvas1 = document.getElementById("yourCanvasId");  <br>
var ctx = canvas1.getContext("2d");<br>
var img = new Image();<br>
img.src = ctx.toDataURL('image/png');<br>
ctx.drawImage(img,200,150);<br>

นอกจากนี้คุณอาจอ้างถึงลิงค์ต่อไปนี้:

http://tutorials.jenkov.com/html5-canvas/todataurl.html

http://www.w3.org/TR/2012/WD-html5-author-20120329/the-canvas-element.html#the-canvas-element


Uncaught TypeError: Object # <CanvasRenderingContext2D> ไม่มีเมธอด 'toDataURL'
Brandon Aubie

นี้เป็นธรรมเป็นองค์ประกอบบริบทไม่ได้มีtoDataURLฟังก์ชั่น: developer.mozilla.org/en-US/docs/Web/API/... คุณต้องการโทรหาtoDataURLองค์ประกอบ Canvas: developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/…
Crashalot
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.