Fabric.js background appears only after click - javascript

With the following code I create a Fabric canvas
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();
The canvas is created, but the background image doesn't appear unless I click inside the canvas, as I click inside the canvas the background appears.
I'm working on my local machine and the application will not be published online.
Why do you think that I'm having this problem? Am I doing anything wrong? How could I fix this behaviour?

fabric.image.fromURL is asyncronous.
You have to call the renderAll() inside the callback if you want to show the backgroundimage asap.
Otherwise your mouse click will trigger a renderAll some fraction of second after the load is finished and the background will be rendered.
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();
});

In my case, Safari iOS would not render the background ~20-60% of the time (version "fabric": "^4.3.1"). Waiting did not resolve. Tapping the canvas would activate/render the background. Adding renderAll() in various places did not resolve it for me. Did not happen on Chrome, only Safari iOS (ver. 14.1 at the time)
B64 workaround:
Dropping the fabric.Image.fromURL and instead providing a b64 image to setBackgroundImage worked for me consistently with all browsers.
let myImg = `data:image/jpeg;charset=utf-8;base64,<- base64 data->`
this.canvasObj.setBackgroundImage(
myImg, //b64
this.canvasObj.renderAll.bind(this.canvasObj)
);

Related

How can I make a image appear in javascript (and scroll whilst zoomed in)

I am very new to JavaScript. I'm trying to create a basic infinite runner game, but I'm stuck on one little issue. I need a image to print out on my HTML canvas, but when I try to nothing happens. I am creating this game with basic JavaScript. No AJAX/jQuery. Here's my code, and what I have tried.
//this is my code as of right now for printing images.
function make_base () {
base_image = new Image();
base_image.src = 'picture.png'
}
//draw the image to the canvas 2d context
cc.drawImage(base_image, 0, 0);
What this is doing, is nothing. It is not showing any sign of a image. Here's some other code I've gotten, as from w3schools (they're awesome :) )
//image source by html hidden element
var img = document.getElementById("picture");
cc.drawImage(img, 10, 10);
</script>
<image src="picture.png" id="picture" hidden></image>
This is doing the same thing that the new code is doing. Showing absolutely nothing. I'm not sure why, I've tried with Google Chrome, Firefox, and Internet Explorer. All of them with the file uploaded to my website, and with file:///c:/users/name/desktop/js/one.html. Nothing is showing up on the canvas for some strange reason. I've also told Chrome to always use JavaScript. Not only this, but how can I make it zoom in, and scroll from left to right (I can add the blocks/variables that "kill"/make the player restart)?
You probably need to wait for the image to load before trying to draw it.
const c = document.querySelector('canvas')
const cc = c.getContext('2d');
drawImage();
function drawImage() {
const image = new Image();
image.onload = function() {
cc.drawImage(image, 0, 0)
}
image.src = "//placecage.com/200/300"
}
<canvas width="500" height="500"></canvas>
Also, it's <img> not <image>. I haven't checked this, but some browsers don't allow loading things if you're on file://, you'll have to spin up a small server and serve from localhost.

How to fix?: Image disappears in Safari, when I'm using fabric js image filters

I'm programming an application where people can upload images. The images appear in a canvas and then the user can click buttons with image filters, so the image in the canvas changes brightness, contrast, saturation and so on. I'm using Fabric Js. You can see the javascript of a noise filter below. This code works fine in IE and Chrome, but it doesn't work in Safari 11.0.3. There, when I click on the buttons, the image turns transparent / disappears. What am I doing wrong? Do I miss something?
$("#noise").click(function () {
var filter = new fabric.Image.filters.Noise({
noise: 700
});
var obj = canvas.getActiveObject();
obj.filters.push(filter);
obj.applyFilters();
canvas.renderAll();
});
EDIT: Seems like the images were too big! With smaller images the code is running fine in Safari.

Image on HTML5 canvas only appearing for one frame

Long time lurker but never made an account. Just wanted to preface that I'm by no means a dev and just tinkering and experimenting for fun, so I apologise in advance if I seem really dumb.
I'm working on a dynamic overlay for Twitch streaming and was previously using AS3 but I've switched over to HTML5 now. I'm trying to load an image onto the canvas (which will eventually be a profile picture fetched using Twitch API... but one step at a time). I'm using Adobe Animate and I have the following so far applied in Actions on the first frame of the layer:
var canvas = document.getElementById('canvas'),
context = canvas.getContext('2d');
show_image();
function show_image() {
source_image = new Image();
source_image.src = 'https://cdn.sstatic.net/stackexchange/img/logos/so/so-icon.png';
source_image.onload = function () {
context.drawImage(source_image, 100, 100);
}
}
When I hit Ctrl+Enter and see it in Chrome, the image appears for the first frame then disappears. I'm not sure how I'm supposed to get it to stay indefinitely. I need to be able to animate it later, and it'll change depending on the latest follow/donation/sub, etc.
I tried extending the frame itself in the timeline, however, this just changed long how it took to loop and didn't make the image itself stay longer. I'm probably missing something really simple!
Any help would be appreciated. Thanks!
Your code is okay if your approach is using a canvas with HTML and JS, without any libraries involved. However, this is not the case, as you are using Animate, and the way to draw graphics with it is different than using default canvas methods like drawImage().
Animate includes the CreateJS suite, which includes the EaselJS library ,and this allows you to use another tools to draw to your canvas. Two or them are the Stage object, the visual container of your animate project, and the Bitmap object, who represents an image, canvas or video. For effects of this question, only both objects are required.
Note that the code below is only for the first frame:
/* It is not necessary to declare the canvas or stage element,
as both are already declared. At this point the stage is ready to be drawn */
show_image();
function show_image() {
var source_image = new Image();
source_image.src = 'https://cdn.sstatic.net/stackexchange/img/logos/so/so-icon.png';
source_image.onload = function(event) {
/* A new Bitmap object is created using your image element */
var bmp = new createjs.Bitmap(event.currentTarget);
/* The Bitmap is added to the stage */
stage.addChild(bmp);
}
}

Fabric.js: Image controls behind an overlay image

I'm building a canvas user interface with jquery and fabric.js library and I set an overlay png image with a transparent section using the following code
var bgImgSrc = bgImg.attr('src');
canvas.setOverlayImage(bgImgSrc, function(img){
canvas.renderAll();
});
I also added an image behind the overlay and resized to fit the container using the following code
var photoImg = $('#img-photo');
var photoImgSrc = photoImg.attr('src');
fabric.Image.fromURL(photoImgSrc, function(img) {
var photoImgWidth = photoImg.width();
var photoImgHeight = photoImg.height();
var hRatio = 380/photoImgWidth;
var vRatio = 300/photoImgHeight;
var ratio = Math.min(hRatio, vRatio);
pImg = img.set({left: 380/2, top: 300/2, angle: 0})
img.scale(ratio).setCoords();
canvas.add(pImg);
canvas.sendToBack(pImg);
canvas.renderAll();
});
And it works as expected, however, when I click on the image to scale/resize it, I don't see the controls, except through the transparent space of the overlay image. Controls are behind the overlay image, is there a way to force show the image controls without having to put the entire image in front of the overlay?
Just set the boolean controlsAboveOverlay:
canvas.controlsAboveOverlay = true;
The problem here is that overlay image is rendered on top of objects' controls. This is expected behavior. Take a look at this wiki article, which shows the z-index of various things on fabric canvas and in which order they're rendered.
There are plans to add support for object controls that are always on top, as you can see from this ticket, but I can't tell you when that's going to happen.
You can also try using "after:render" callback and draw image manually onto canvas.
canvas.controlsAboveOverlay = true; //did the job... but:
I don't want to render controls above the overlay image (as overlay means overlay to me). I just want to render the stack exactly as described in Wiki (by default).
I just wonder...as described in the Wiki rendering-stack, the controls should be rendered on top of all objects (always visible by default), but they do not (look at kitchensink demo).
IMHO this behaviour should be set by a flag like canvas.controlsInStack = true.
By the way ... that thing is really beautiful!

Image readystate in canvas

Is it possible to use imagename.readyState in canvas?
If not does anyone know a way of detecting when an image being drawn to the canvas using "drawImage" has loaded and is ready to display?
I am creating an image showcase using the canvas - when an image is selected I want to have a loading animation (which I have already created) display until the loaded condition is met.
I am still learning to use javascript and have been trying all day to no avail - so apologies for the lack of example code to display and illustrate what I'm asking!
You might try loading the image by using new Image() and setting the .onload event to draw the image on the canvas after the image has been loaded.
var img = new Image();
img.onload = function() {
// code to draw image on the canvas...
}
img.src = "/path/to/img.jpg";
See also: https://developer.mozilla.org/samples/canvas-tutorial/3_1_canvas_drawimage.html

Categories