làm thế nào để lưu canvas dưới dạng hình ảnh png?


80

Tôi có một phần tử canvas với hình vẽ trong đó và tôi muốn tạo một nút mà khi nhấp vào, nó sẽ lưu hình ảnh dưới dạng tệp png. Vì vậy, nó sẽ mở hộp thoại lưu, mở, đóng ...

Tôi làm điều đó bằng cách sử dụng mã này

var canvas = document.getElementById("myCanvas");
window.open(canvas.toDataURL("image/png"));

Nhưng khi tôi kiểm tra nó trong IE9, một cửa sổ mới mở ra thông báo "không thể hiển thị trang web" và url của nó là:

dữ liệu: image / png; base64,iVBORw0KGgoAAAANSUhEUgAAAmAAAABpCAYAAACd + 58xAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAADRwSURBVHhe7V0HgBVF0q7ZJSlJwRxAPUFRD39RFLN34qGnnomoqIjhzBlFPROIgsoZzogR5AQEzJ4BPFAUEUwgJjgQkCQKooggaf / 6el6 / 6ZnpSW / zUn237u5MdXX1172 + z6rqaqeEG6VsJet + PDW / vkdrfx3H3yfT2tVzaP26X6hkw1q / BoeI / 280 / 29JwznZxJPUyXtBQBAQBAQBQaBcECjefmi56BWlZYtAeqajx / WokfrJYEqOIikOFRfXoVq161PtOk2odu0t + ectqKiojnrntWhC46QhYOtXfUarl79Ivy9 / ldau + h + TX / 8b2SbjJ07pWFQy2Uqnp2yXSrQJAoKAICAICALJCAgBS8ao8iTi / UvpSZlBxiwqwWOKimsxCWtEdettR3XqbEfFtRonkrBYArZh3fe0 + senadWyEbRm1UzasP53K45ZiFc84RKyVXkbVUYWBAQBQUAQyIqAELCsiFW2fDQpSyZk8UQMMysqKmaPWCOqt8mOVK / eTuQU1YuccCQBW7dyIq38 / j5a / Fn / ad3a5QGXmqsvLfGKJl0ZCFdONEOPyl5lGV8QEAQEAUGghiMgBKzqLHCeHqVOrILtduF4MpZExEqoVq167A3bmjap34J / bmoFqcj2dM3Pr9GK + b1p5bJXmXz9nEC + 3FiorYF4hcmXlo + gUrk + um / + e + QoVWfxxRJBQBAQBAQBQUAQqBwE8uzCwiMiaEqOWYR5jJ2 / 6Hl58nYHk0Pr1v1Ov62cTytXfE5r1yyyc6RgDhjI16 + L + tLqFZ9xnteGUKc0Xi876YpYkFDCfpqFEz9YGpRERhAQBAQBQaB8ERAPWPnim157JreX6 / eK7eJ / Ge0RS8oPc9gT1pTqN2jFocltfdPxecBU2HHxgBTky + 71CjPGCO + YyU4j0TU9ZcGf0y + JSAoCgoAgIAgIAoJATUcgG2dQ0jpKZ / Xp + PlLtEcs3huGQhO / r17K3rBvuGrEUt8i5HPAkHC / Yt6lKuwYKiuRM9TtGbY0rcerTBLwC / KY1fSNJ / MTBAQBQUAQqAwExANWGaiHx0z2aJl9CknET + MRc2XsVSKKaNP6O1CDhvtwYn5dJZf3gOG0IxLuS0e + LB4vw9sVhiwmHywmF6xqLLdYIQgIAoKAICAICAJVAQHTo2XmkNtzv6K5R7RXLOwRs3MaW + 47SNkG9oRxZQmun6qbImCo84VSE + 5pR3 / zvFZJni / 7e8tTHiCeqCkAqsKKig2CgCAgCAgCgoAgUG0RCBKzMLmwkzHdL4pk4XlUAn7Uu3XrVtPqVfO4lurPSq0KQa5cdAv9snBgqM5XFPlKSsSPM8o3mcxES2hZtf0rEMMFAUFAEKiBCEgIsqotavpk / OiwZViHPQk / LgHfHo5EnbCGjVpxeYo9yNmw9oeSn2YeTatWTPNzozzX8ZOeWPJlJVRJnrOoxUtJtmLEUmqoartH7BEEBAFBQBCoJggIASu / hUqkUokC2rZkwSSCBU12wpadhNXbpAk13vwwKlJ3O / L1QmYrxPNlDxuGyVtyIn6K8KSZHwY3XsRX + W0L0VyTEPjwM6KuFxN1uiB6Vkv48MpdjxLt9ieieQvscuvWE13eh2jnQ9zv + F2aICAICAKCQGEIRH22559H5IqnDTMGeU / SgUJ7WNLjOVH9g8 / Xrv2Fa4P9SM6K7y4t + WXRw76sfVc42fPV936iJ5 + LKrbqTU0P3rA + 0dZbEh20L9HJHYj23I2oVrHFT5U5NFnY4m6svUA0Pvo8efbvjCBqtr0nN + IVot4Dkvv1v5aoy / HJcpUpsfI3olffdknV0uWuJfv9kWjkw55VIFAfM073PE4EkqZbEBf9HMTs8C6e3KhHiPbdqzJnKWMLAoJAeSMgHrDyRrj0 + rOEGvVoYY9Y0inIeE + YqQ + cqGGj3dgDtvJjC / mKm7BHmG68lGjO + 0T

Bất cứ ai cũng biết làm thế nào để sửa lỗi này?


Câu trả lời:


66

thử cái này:

var c=document.getElementById("alpha");
var d=c.toDataURL("image/png");
var w=window.open('about:blank','image from canvas');
w.document.write("<img src='"+d+"' alt='from canvas'/>");

Điều này hiển thị hình ảnh từ canvas trên trang mới, nhưng nếu bạn đã open popup in new tabcài đặt, nó sẽ hiển thị about:blanktrong thanh địa chỉ.

CHỈNH SỬA: - mặc dù window.open("<img src='"+ c.toDataURL('image/png') +"'/>")không hoạt động trong FF hoặc Chrome, các hoạt động sau đây mặc dù kết xuất hơi khác với những gì được hiển thị trên canvas, tôi nghĩ rằng vấn đề là tính minh bạch:

window.open(c.toDataURL('image/png'));

nó bị treo trên lệnh này: var w = window.open ('about: blank', 'image from canvas');
lén lút

4
tôi đã thay đổi nó thành thế này: var w = window.open ('about: blank') ;, và bây giờ hình ảnh mở ra trong một cửa sổ mới, nhưng làm cách nào để lấy nó để nó trở thành hộp đóng lưu, tôi không muốn phải kích chuột phải vào hình ảnh và nhấn Save As ...
lén lút

31

FileSaver.js sẽ có thể giúp bạn ở đây.

var canvas = document.getElementById("my-canvas");
// draw to canvas...
canvas.toBlob(function(blob) {
    saveAs(blob, "pretty image.png");
});

13
Có rất nhiều lỗi không hoạt động trong IE9 :-( Có thể khắc phục được khá nhiều lỗi với polyfills nhưng tôi e rằng điều này vượt quá mức đó. Nếu bạn có thể, tôi đề nghị sử dụng Google Chrome Frame cho người dùng sử dụng IE.
Maurice

@VagueExplanation toBlob () không được hỗ trợ trên Safari. Nhưng bạn có thể tìm thấy một polyfill đơn giản tại đây: developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/…
Maurice

18

Tôi đã sử dụng giải pháp này để đặt tên tệp :

HTML:

<a href="#" id="downloader" onclick="download()" download="image.png">Download!</a>
<canvas id="canvas"></canvas>

JavaScript:

function download(){
    document.getElementById("downloader").download = "image.png";
    document.getElementById("downloader").href = document.getElementById("canvas").toDataURL("image/png").replace(/^data:image\/[^;]/, 'data:application/octet-stream');
}

12

Tôi gặp sự cố này và đây là giải pháp tốt nhất mà không cần bất kỳ thư viện tập lệnh bên ngoài hoặc bổ sung nào: Trong thẻ hoặc tệp Javascript, hãy tạo hàm này: Ở đây chúng tôi giả định rằng canvas là canvas của bạn:

function download(){
        var download = document.getElementById("download");
        var image = document.getElementById("canvas").toDataURL("image/png")
                    .replace("image/png", "image/octet-stream");
        download.setAttribute("href", image);

    }

Trong phần nội dung của HTML, hãy chỉ định nút:

<a id="download" download="image.png"><button type="button" onClick="download()">Download</button></a>

Điều này đang hoạt động và liên kết tải xuống trông giống như một nút. Đã thử nghiệm trên Firefox và Chrome.


1
Thật không may, trong IE 11 nó xóa màn hình và thay đổi url để: Dữ liệu: image / octet-stream; base64, iVBORw
Mike

10

Để tích lũy cả ba điểm:

  • cái nút
  • lưu hình ảnh dưới dạng tệp png
  • mở hộp thoại lưu, mở, đóng

Hộp thoại tệp là một cài đặt trong trình duyệt.

Đối với phần nút / lưu, hãy chỉ định chức năng sau, được tổng hợp từ các câu trả lời khác, cho các nút của bạn khi nhấp vào:

function DownloadCanvasAsImage(){
    let downloadLink = document.createElement('a');
    downloadLink.setAttribute('download', 'CanvasAsImage.png');
    let canvas = document.getElementById('myCanvas');
    let dataURL = canvas.toDataURL('image/png');
    let url = dataURL.replace(/^data:image\/png/,'data:application/octet-stream');
    downloadLink.setAttribute('href', url);
    downloadLink.click();
}

Ví dụ trên Codepen

Một cách tiếp cận khác, có phần gọn gàng hơn là sử dụng Canvas.toBlob () :

function DownloadCanvasAsImage(){
    let downloadLink = document.createElement('a');
    downloadLink.setAttribute('download', 'CanvasAsImage.png');
    let canvas = document.getElementById('myCanvas');
    canvas.toBlob(function(blob) {
      let url = URL.createObjectURL(blob);
      downloadLink.setAttribute('href', url);
      downloadLink.click();
    });
}

Ví dụ trên Codepen

Không giải pháp nào tương thích 100% với nhiều trình duyệt, vì vậy hãy kiểm tra ứng dụng khách


Sau rất nhiều thời gian tìm kiếm giải pháp, ĐÂY là giải pháp phù hợp với tôi. Trên Firefox 76.0.1 (64-bit), đó là những gì tôi đang sử dụng. Tôi nên kiểm tra các trình duyệt khác nhưng tôi chắc chắn hy vọng rằng mọi thứ cập nhật sẽ vẫn hoạt động.
Alan Stewart

4

Tôi có thể đã khám phá ra một cách tốt hơn để không buộc người dùng nhấp chuột phải và "lưu hình ảnh thành". Trực tiếp vẽ mã canvas base64 vào hrefliên kết và sửa đổi nó để quá trình tải xuống sẽ tự động bắt đầu. Tôi không biết liệu nó có tương thích với trình duyệt toàn cầu hay không, nhưng nó sẽ hoạt động với các trình duyệt chính / mới .

var canvas = document.getElementById('your-canvas');
    if (canvas.getContext) {
        var C = canvas.getContext('2d');
    }

$('#your-canvas').mousedown(function(event) {
    // feel free to choose your event ;) 

    // just for example
    // var OFFSET = $(this).offset();
    // var x = event.pageX - OFFSET.left;
    // var y = event.pageY - OFFSET.top;

    // standard data to url
    var imgdata = canvas.toDataURL('image/png');
    // modify the dataUrl so the browser starts downloading it instead of just showing it
    var newdata = imgdata.replace(/^data:image\/png/,'data:application/octet-stream');
    // give the link the values it needs
    $('a.linkwithnewattr').attr('download','your_pic_name.png').attr('href',newdata);

});

Bạn có thể quấn <a>quanh bất cứ thứ gì bạn muốn.


0

Thử cái này:

jQuery('body').after('<a id="Download" target="_blank">Click Here</a>');

var canvas = document.getElementById('canvasID');
var ctx = canvas.getContext('2d');

document.getElementById('Download').addEventListener('click', function() {
    downloadCanvas(this, 'canvas', 'test.png');
}, false);

function downloadCanvas(link, canvasId, filename) {
    link.href = document.getElementById(canvasId).toDataURL();
    link.Download = filename;
}

Bạn chỉ có thể đặt mã này trong bảng điều khiển trong firefox hoặc chrom và sau khi thay đổi ID thẻ canvas của bạn trong tập lệnh trên và chạy tập lệnh này trong bảng điều khiển.

Sau khi thực thi đoạn mã này, bạn sẽ thấy liên kết dưới dạng văn bản "bấm vào đây" ở cuối trang html. nhấp vào liên kết này và mở bản vẽ canvas dưới dạng hình ảnh PNG trong cửa sổ mới lưu hình ảnh.


0

Gửi biểu mẫu có chứa đầu vào có giá trị canvas toDataURL ('image / png'), ví dụ:

// JAVASCRIPT

    var canvas = document.getElementById("canvas");
    var url = canvas.toDataUrl('image/png');

Chèn giá trị của url vào đầu vào ẩn của bạn trên phần tử biểu mẫu.

// PHP

    $data = $_POST['photo'];
    $data = str_replace('data:image/png;base64,', '', $data);
    $data = base64_decode($data);
    file_put_contents("i".  rand(0, 50).".png", $data);

Điều này hoạt động tốt, ngoại trừ hàm JavaScript canvas.toDataUrl(...)nên được canvas.toDataURL(...).
Brannon

0

Mã HTML hoạt động đầy đủ . Cắt + Dán vào tệp .HTML mới:

Chứa hai ví dụ:

  1. Canvas trong tệp HTML.
  2. Canvas được tạo động bằng Javascript.

Đã thử nghiệm trong:

  1. Trình duyệt Chrome
  2. trình duyệt web IE
  3. * Cạnh (tên tiêu đề không hiển thị)
  4. Firefox
  5. Opera

<!DOCTYPE HTML >
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title> #SAVE_CANVAS_TEST# </title>
    <meta 
        name   ="author" 
        content="John Mark Isaac Madison"
    >
    <!-- EMAIL: J4M4I5M7 -[AT]- Hotmail.com -->
</head>
<body>

<div id="about_the_code">
    Illustrates:
    <ol>
    <li>How to save a canvas from HTML page.     </li>
    <li>How to save a dynamically created canvas.</li>
    </ol>
</div>

<canvas id="DOM_CANVAS" 
        width ="300" 
        height="300"
></canvas>

<div id="controls">
    <button type="button" style="width:300px;"
            onclick="obj.SAVE_CANVAS()">
        SAVE_CANVAS ( Dynamically Made Canvas )
    </button>

    <button type="button" style="width:300px;"
            onclick="obj.SAVE_CANVAS('DOM_CANVAS')">
        SAVE_CANVAS ( Canvas In HTML Code )
    </button>
</div>

<script>
var obj = new MyTestCodeClass();
function MyTestCodeClass(){

    //Publically exposed functions:
    this.SAVE_CANVAS = SAVE_CANVAS;

    //:Private:
    var _canvas;
    var _canvas_id = "ID_OF_DYNAMIC_CANVAS";
    var _name_hash_counter = 0;

    //:Create Canvas:
    (function _constructor(){
        var D   = document;
        var CE  = D.createElement.bind(D);
        _canvas = CE("canvas");
        _canvas.width = 300;
        _canvas.height= 300;
        _canvas.id    = _canvas_id;
    })();

    //:Before saving the canvas, fill it so
    //:we can see it. For demonstration of code.
    function _fillCanvas(input_canvas, r,g,b){
        var ctx = input_canvas.getContext("2d");
        var c   = input_canvas;

        ctx.fillStyle = "rgb("+r+","+g+","+b+")";
        ctx.fillRect(0, 0, c.width, c.height);
    }

    //:Saves canvas. If optional_id supplied,
    //:will save canvas off the DOM. If not,
    //:will save the dynamically created canvas.
    function SAVE_CANVAS(optional_id){

        var c = _getCanvas( optional_id );

        //:Debug Code: Color canvas from DOM
        //:green, internal canvas red.
        if( optional_id ){
            _fillCanvas(c,0,255,0);
        }else{
            _fillCanvas(c,255,0,0);
        }

        _saveCanvas( c );
    }

    //:If optional_id supplied, get canvas
    //:from DOM. Else, get internal dynamically
    //:created canvas.
    function _getCanvas( optional_id ){
        var c = null; //:canvas.
        if( typeof optional_id == "string"){
            var id = optional_id;
            var  d = document;
            var c  = d.getElementById( id );
        }else{
            c = _canvas; 
        }
        return c;
    }

    function _saveCanvas( canvas ){
        if(!window){ alert("[WINDOW_IS_NULL]"); }

        //:We want to give the window a unique
        //:name so that we can save multiple times
        //:without having to close previous
        //:windows.
        _name_hash_counter++              ; 
        var NHC = _name_hash_counter      ;
        var URL = 'about:blank'           ;
        var name= 'UNIQUE_WINDOW_ID' + NHC;
        var w=window.open( URL, name )    ;

        if(!w){ alert("[W_IS_NULL]");}

        //:Create the page contents,
        //:THEN set the tile. Order Matters.
        var DW = ""                        ;
        DW += "<img src='"                 ;
        DW += canvas.toDataURL("image/png");
        DW += "' alt='from canvas'/>"      ;
        w.document.write(DW)               ;
        w.document.title = "NHC"+NHC       ;

    }

}//:end class

</script>

</body>
<!-- In IE: Script cannot be outside of body.  -->
</html>

0

Tôi thực sự thích câu trả lời của Tovask nhưng nó không hoạt động do chức năng có tên download( câu trả lời này giải thích tại sao). Tôi cũng không thấy điểm trong việc thay thế "data: image / ..." bằng "data: application / ...".

Đoạn mã sau đã được thử nghiệm trong Chrome và Firefox và dường như hoạt động tốt trên cả hai.

JavaScript:

function prepDownload(a, canvas, name) {
    a.download = name
    a.href = canvas.toDataURL()
}

HTML:

<a href="#" onclick="prepDownload(this, document.getElementById('canvasId'), 'imgName.png')">Download</a>
<canvas id="canvasId"></canvas>

-1
var canvasId = chart.id + '-canvas';
var canvasDownloadId = chart.id + '-download-canvas';
var canvasHtml = Ext.String.format('<canvas id="{0}" width="{1}" height="{2}"></canvas><a id="{3}"/>',
canvasId,
chart.getWidth(),
chart.getHeight(),
canvasDownloadId);
var canvasElement = reportBuilder.add({ html: canvasHtml });

var canvas = document.getElementById(canvasId);

var canvasDownload = document.getElementById(canvasDownloadId);
canvasDownload.href = chart.getImage().data;
canvasDownload.download = 'chart';

canvasDownload.click();
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.