Фон Fabric.js появляется только после нажатия

С помощью следующего кода я создаю холст Fabric

canvas = new fabric.Canvas('canvas');
canvas.setWidth(660);
canvas.setHeight(590);

fabric.Image.fromURL('assets/img/materials/marble.bmp', function(image) {
    image.set({
        // I need this because the image size and the canvas size could be different
        // in this way the image always covers the canvas
        width:660,
        height:590
    });

    canvas.setBackgroundImage(image);
});

canvas.renderAll();

Холст создан, но фоновое изображение не отображается, пока я не щелкну внутри холста, когда я щелкну внутри холста, появится фон.

Я работаю на своем локальном компьютере, и приложение не будет опубликовано в Интернете.

Как вы думаете, почему у меня такая проблема? Я что-то не так делаю? Как я мог исправить такое поведение?


person Luigi Caradonna    schedule 06.02.2016    source источник
comment
Попробуйте вызвать canvas.renderAll() в обратном вызове function(image) - fabric.Image.fromURL, вероятно, загружает изображение асинхронно, поэтому нижняя строка вашего кода выполняется до загрузки изображения.   -  person Kenney    schedule 06.02.2016
comment
Спасибо, это работает. В качестве комментария я не могу назвать ваш ответ правильным.   -  person Luigi Caradonna    schedule 06.02.2016
comment
Пожалуйста! Ничего страшного - таких вопросов огромное множество; он, вероятно, будет отмечен как дубликат кем-то, кто сможет найти лучший ответ для ссылки ;-)   -  person Kenney    schedule 06.02.2016


Ответы (2)


fabric.image.fromURL является асинхронным. Вы должны вызвать renderAll () внутри обратного вызова, если хотите показать фоновое изображение как можно скорее.

В противном случае щелчок мышью вызовет renderAll через несколько долей секунды после завершения загрузки и отрисовки фона.

canvas = new fabric.Canvas('canvas');
canvas.setWidth(660);
canvas.setHeight(590);

    fabric.Image.fromURL('assets/img/materials/marble.bmp', function(image) {
        image.set({
            // I need this because the image size and the canvas size could be different
            // in this way the image always covers the canvas
            width:660,
            height:590
        });

        canvas.setBackgroundImage(image);
        canvas.renderAll();
    });
person AndreaBogazzi    schedule 11.02.2016
comment
Поскольку setBackgroundImage() также является асинхронным, не будет ли безопаснее вызывать canvas.renderAll () внутри необязательного параметра обратного вызова setBackgroundImage? (Я бы хотел, чтобы эта библиотека была дружественной к обещаниям.) - person faintsignal; 20.06.2019
comment
Поскольку setBackgroundImage получает объект изображения в качестве аргумента, не должно быть асинхронным. это? - person AndreaBogazzi; 21.06.2019
comment
setBackgroundImage асинхронный. У него есть необязательный второй аргумент для обратного вызова. Возможно, в более ранних версиях этого не было - я новичок в ткани. Я просто упомянул об этом на случай, если я смогу избавить кого-то от неприятностей, которые у меня возникли, от того, что я не разобрался с этим нюансом. - person faintsignal; 21.06.2019
comment
Теоретически вам не нужно использовать обратный вызов в этом случае, вы также можете просто сделать canvas.backgroundImage=image и использовать renderAll или requestRenderall - person AndreaBogazzi; 21.06.2019

В моем случае Safari iOS не отображал фон примерно в 20–60% случаев (версия "fabric": "^4.3.1"). Ожидание не разрешилось. Нажатие на холст активирует / визуализирует фон. Добавление renderAll() в разные места не решило для меня этого. Не было в Chrome, только Safari iOS (версия 14.1 в то время)

Обходной путь B64:

Удаление fabric.Image.fromURL и предоставление вместо setBackgroundImage изображения b64 сработало для меня во всех браузерах.

let myImg = `data:image/jpeg;charset=utf-8;base64,<- base64 data->`

this.canvasObj.setBackgroundImage(
  myImg, //b64
  this.canvasObj.renderAll.bind(this.canvasObj)
);
person PotatoFarmer    schedule 07.05.2021