От json к изображению, используя fabricjs - PullRequest
3 голосов
/ 31 октября 2019

Я сохраняю холст fabricjs в своей базе данных как json. У меня нет намерения изменять его, я просто хочу восстановить его, изменить его размер и, наконец, создать изображение в формате PNG или JPG, которое я добавлю на мою веб-страницу.

На данный момент ясделал следующее:

  • Я создаю HTML-элемент canvas и скрываю его
  • Я загружаю на него де JSON (это работает)
  • Из этого холста яполучить его контекст, я изменяю его размер и получаю dataURL (я получаю очевидный хороший URL)
  • Я создаю HTML-элемент и сопоставляю dataURL с img src

ItВроде работает, но изображение прозрачное. Размер в порядке, но внутри ничего нет. Я хотел бы сделать это без необходимости создавать элемент canvas и скрывать его. Примерно так: создайте сценарий var на js, загрузите на него json, измените его размер, получите dataurl и установите его для элемента.

var exerciseList;

var canvas0 = new fabric.Canvas('canvas0');
var canvas1 = new fabric.Canvas('canvas1');
var canvas2 = new fabric.Canvas('canvas2');
var canvas3 = new fabric.Canvas('canvas3');
var canvas4 = new fabric.Canvas('canvas4');

$(document).ready(function () {
    var login = $.session.get("login");

    $.ajax({
        url: backEndpoint + "usuarios/" + login + "/ejercicios",
        headers: {
            "Content-Type": "application/json"
        },
        method: "GET"
    })
        .done(function (data, textStatus, xhr) {
            exerciseList = data;
            for (var i = 0; i < exerciseList.length; i++) {
                addExercise(exerciseList[i],i);
                loadExercise(exerciseList[i],i);
            }

        })
        .fail(function (xhr, textStatus, errorThrown) {


        });
});
var canvas;

function loadExercise(exercise, idx) {
    switch (idx) {
        case 0:
            canvas = canvas0;
            break;
        case 1:
            canvas = canvas1;
            break;
        case 2:
            canvas = canvas2;
            break;
        case 3:
            canvas = canvas3;
            break;
        case 4:
            canvas = canvas4;
            break;
        default:
            console.log("ERROR")
            break;
    }
    canvas.loadFromJSON(exercise.figura, callbackFunction(idx));
}

function callbackFunction(idx) {
    canvas.renderAll.bind(canvas);
    //canvas.requestRenderAll(); // It doesnt work with anyone
    var $img = getImage(idx);
    $("#imageContainer"+idx).append($img);
}

function getImage(idx) {

    var width = 343;
    var height = 300;

    var resizedCanvas = document.createElement("canvas");
    var resizedContext = resizedCanvas.getContext("2d");

    resizedCanvas.width = "" + width;
    resizedCanvas.height = "" + height;

    var canvas = document.getElementById("canvas"+idx);

    resizedContext.drawImage(canvas, 0, 0, width, height);
    var myResizedData = resizedCanvas.toDataURL();

    return $('<img>').attr("src", myResizedData);

}

function addExercise(exercise, idx) {
    var title = exercise.titulo;
    var description = exercise.descripcion;

    var $exerciseContainer = $('<div>',
        { id: "exerciseContainer"+idx,class: "row ejercicio m-1 rounded border border-secondary" });

    var $imageContainer = $('<div>',
        { id: "imageContainer"+idx, class: "col-7 p-1 border border-secondary" });

    var $bodyContainer = $('<div>',
        { id: "bodyContainer"+idx, class: "col border border-secondary" });

    $('<div>', { class: "row h4 p-1" }).text(title).appendTo($bodyContainer);
    $('<div>', { class: "row  p-1" }).text(resumirDescripcion(description)).appendTo($bodyContainer);

    var $buttonContainer = $('<div>',
        { id: "buttonContainer"+idx, class: "col-1  p-1 border border-secondary" });

    $('<button>', { class: "btn btn-success btn-block p-2" }).appendTo($buttonContainer);
    $('<button>', { class: "btn btn-primary btn-block p-2" }).appendTo($buttonContainer);
    $('<button>', { class: "btn btn-warning btn-block p-2" }).appendTo($buttonContainer);
    $('<button>', { class: "btn btn-info btn-block p-2" }).appendTo($buttonContainer);
    $('<button>', { class: "btn btn-danger btn-block p-2" }).appendTo($buttonContainer);

    $exerciseContainer.append($imageContainer);
    $exerciseContainer.append($bodyContainer);
    $exerciseContainer.append($buttonContainer);

    $("#contenedorEjercicios").append($exerciseContainer);
}

Не знаю почему, но вызываю эту функцию, когда янажмите кнопку, она работает как надо, но мне нужно, чтобы она работала при загрузке страницы.

это то, что я получаю при загрузке страницы

это то, что я хочу получить

После рефакторинга некоторого кода я получаю this , но это то же самое, что и раньше.

Ответы [ 2 ]

1 голос
/ 31 октября 2019
canvas.loadFromJSON(canvasJSON, function(){
  var url = canvas.toDataURL();
  var $img = getImage();
  $imageContainer.append($img);
});

canvas # loadFromJSON является асинхронным для некоторых объектов, поэтому лучше создать свое изображение при обратном вызове loadFromJSON.

canvas.loadFromJSON(exercise.figura, callbackFunction(idx)); В этой строке это будет callbackFunction(idx) excute callbackFunction,

Если вы хотите изменить анонимную функцию на именованную функцию и вам нужно передать параметр, вы можете сделать это следующим образом.


canvas.loadFromJSON(json, () => callbackFunction(exercise,idx))
function callbackFunction(exercise, idx){
  canvas.requestRenderAll();
  var url = canvas.toDataURL();
  var $img = getImage(idx);
  $imageContainer.append($img);
};
0 голосов
/ 02 ноября 2019

У меня есть полу-решение, я знаю, что это не лучшая практика, но это позволяет мне продолжить проект. Код тот же, что я написал в вопросе, но я изменил это:

function callbackFunction(idx) {
   canvas.renderAll.bind(canvas)();
   setTimeout(function () {
       var $img = getImage(idx);
       $("#imageContainer" + idx).append($img);
   }, 500);

}

Это так же просто, как заставить подождать полсекунды, когда визуализируется холст ...

...