简体   繁体   中英

Save HTML Canvas drawing as jpg error

trying to save a drawing using canvas, the file actually does download but I am hit with these errors when trying to open it PS: "Could not complete your request because a JPEG marker segment length is too short (the file may be truncated or incomplete)." Preview: "The file “my-file-name (5).jpg” could not be opened. It may be damaged or use a file format that Preview doesn't recognize."

Any ideas? Here is the code:

JS:

var canvas, ctx, flag = false,
prevX = 0,
currX = 0,
prevY = 0,
currY = 0,
dot_flag = false;

var x = "black",
y = 2;

function init() {
canvas = document.getElementById('can');
ctx = canvas.getContext("2d");
w = canvas.width;
h = canvas.height;

canvas.addEventListener("mousemove", function (e) {
    findxy('move', e)
}, false);
canvas.addEventListener("mousedown", function (e) {
    findxy('down', e)
}, false);
canvas.addEventListener("mouseup", function (e) {
    findxy('up', e)
}, false);
canvas.addEventListener("mouseout", function (e) {
    findxy('out', e)
}, false);
}

function color(obj) {
switch (obj.id) {
    case "green":
        x = "green";
        break;
    case "blue":
        x = "blue";
        break;
    case "red":
        x = "red";
        break;
    case "yellow":
        x = "yellow";
        break;
    case "orange":
        x = "orange";
        break;
    case "white":
        x = "white";
        break;
    case "black":
        x = "black";
        break;
}
if (x == "black") y = 14;
else y = 3;

}

function draw() {
ctx.beginPath();
ctx.moveTo(prevX, prevY);
ctx.lineTo(currX, currY);
ctx.strokeStyle = x;
ctx.lineWidth = y;
ctx.stroke();
ctx.closePath();
}

function erase() {
var m = confirm("Want to clear");
if (m) {
    ctx.clearRect(0, 0, w, h);
    document.getElementById("canvasimg").style.display = "none";
}
}

function save() {
document.getElementById("canvasimg").style.border = "2px solid";
var dataURL = canvas.toDataURL();
document.getElementById("canvasimg").src = dataURL;
document.getElementById("canvasimg").style.display = "inline";
}

var button = document.getElementById('btn-download');
button.addEventListener('click', function (e) {
var dataURL = canvas.toDataURL('image/jpg');
button.href = dataURL;
});

function findxy(res, e) {
if (res == 'down') {
    prevX = currX;
    prevY = currY;
    currX = e.clientX - canvas.offsetLeft;
    currY = e.clientY - canvas.offsetTop;

    flag = true;
    dot_flag = true;
    if (dot_flag) {
        ctx.beginPath();
        ctx.fillStyle = x;
        ctx.fillRect(currX, currY, 2, 2);
        ctx.closePath();
        dot_flag = false;
    }
}
if (res == 'up' || res == "out") {
    flag = false;
}
if (res == 'move') {
    if (flag) {
        prevX = currX;
        prevY = currY;
        currX = e.clientX - canvas.offsetLeft;
        currY = e.clientY - canvas.offsetTop;
        draw();
    }
}
}


HTML:

<a href="#" class="button" id="btn-download" download="my-file-name.jpg"   style="position:absolute;top:90%;left:23%;">Download</a>
<input type="button" value="save" id="btn" size="30" onclick="save()" style="position:absolute;top:90%;left:31%;">
<input type="button" value="clear" id="clr" size="23" onclick="erase()" style="position:absolute;top:90%;left:36%;">

Update

From the new information in the comment (the file itself) -

The image file uploaded turns out to be an HTML file, the source page itself. Now that I could, coincidentally , see the complete page it became obvious why things doesn't work.

The JavaScript is loaded in the head tag and tries to reference elements on the page which is not initialized yet (a page is always parsed linearly).

This causes the code to fail with addEventListener etc. as the call is invoked on an undefined element. This leads to the a-tag's href to not be updated as well, so it links t the page itself due to the hash-tag ( href="#" ). Since there is a download attribute defined in the html this doesn't become so evident, but results in the page itself being downloaded instead of the data-uri as the latter never gets assigned to the href attribute.

Hex dump:

十六进制转储

Solution

The solution is simple however: By moving the script to the end (before the end body tag) it should work as intended (tested locally).

Alternatively: you wrap also wrap the script inside the following code block if you want to keep it in the header:

window.onload = function() {

    // script here

};

I would recommend the first approach though.

Hope this helps!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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