I have similar issue with layers as described here html5 - canvas element - Multiple layers
But, accepted answer doesn't work for me, as for layer1 I have rendered image (drawImage)
And second layer - layer2 (gradient) always under layer1.
Sample code:
canvas = document.getElementById("layer1");
ctx = canvas.getContext("2d");
var img = new Image();
img.src = "/img/img.png";
img.onload = function() {
ctx.drawImage(img, 0, 0);
};
canvas2 = document.getElementById("layer2");
ctx2 = canvas.getContext("2d");
var my_gradient = ctx2.createLinearGradient(0, 0, 0, 400);
my_gradient.addColorStop(0, "black");
my_gradient.addColorStop(1, "white");
ctx2.fillStyle = my_gradient;
ctx2.fillRect(0, 0, 500, 555);
HTML:
<canvas id="layer1" width="1000" height="1000" style="position: absolute; left: 0; top: 0; z-index: 0;"></canvas>
<canvas id="layer2" width="1000" height="1000" style="position: absolute; left: 0; top: 0; z-index: 1;"></canvas>
You are setting ctx2 to layer1's context:
ctx2 = canvas.getContext("2d");
Of course, since the image loads asynchronously, the onload event fires after you've already drawn the gradient, and it gets drawn on the same canvas.
Related
I have two layers. One layer is big and another one is small. So to align the small layer with the big layer I am scaling the small layer to size of the big layer.
Scaling works on top/left but on bottom/right it's not working as I had hoped: it looks like it's not scaling equally in all directions.
I'm doing it like:
var canvas=document.getElementById("canvas");
var context=canvas.getContext("2d");
var imageObject1=new Image();
imageObject1.onload=function(){
context1.clearRect(0,0,imageObject1.width,imageObject1.width);
context1.scale(1.0927,1.0956);
context1.drawImage(imageObject1,0,0);
}
imageObject1.src=canvas.toDataURL();
JsFiddle of problem: https://jsfiddle.net/7cufxf6d/
Any idea how to solve this problem?
Your offsets and ratio's seem wrong. In your code they are hardcoded and then shifted again using hardcoded values. You might want to re-investigate the values and how you obtain them.
Scaling (using canvas's transformation matrix) when using floating point values can introduce more rounding errors as opposed to using more fixed boundaries as provided by drawImage. As you are already hardcoding these values you might save some work (and memory) and both shift and scale the image when drawing it (see: https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/drawImage):
ctx.drawImage(image, dx, dy, dWidth, dHeight)
I slightly modified your fiddle:
// Silver Layer
var canvas0 = document.getElementById("layer1");
var context0 = canvas0.getContext("2d");
var imageObject0 = new Image();
imageObject0.crossOrigin = "anonymous";
imageObject0.onload = function() {
document.getElementById('layer1').width = imageObject0.width;
document.getElementById('layer1').height = imageObject0.height;
context0.clearRect(0, 0, imageObject0.width, imageObject0.width);
// context.scale(1.5,1.5);
context0.drawImage(imageObject0, 0, 0);
};
imageObject0.src = 'https://i.imgur.com/tIaNJku.png';
// Black Layer
var canvas1 = document.getElementById("layer2");
var context1 = canvas1.getContext("2d");
var imageObject1 = new Image();
imageObject1.crossOrigin = "anonymous";
imageObject1.onload = function() {
document.getElementById('layer2').width = imageObject1.width;
document.getElementById('layer2').height = imageObject1.height;
context1.clearRect(0, 0, imageObject1.width, imageObject1.width);
//context1.scale(1.0927,1.0956);
context1.drawImage(imageObject1, -65, -10, 3020, 2680); // MODIFIED LINE
//REMOVED SHIFT
};
imageObject1.src = 'https://i.imgur.com/29aRnzv.png'; //black
<div style="position: relative;">
<canvas id="layer1" width="100" height="100" style="position: absolute; left: 0; top: 0; z-index: 0;"></canvas>
<canvas id="layer2" width="100" height="100" style="position: absolute; left: 0; top: 0; z-index: 1;"></canvas>
</div>
I am trying to add images to canvas using fabric.js. I want to add a image every time the button is clicked. The image is stored in my computer. When the image is added to the canvas, I would like to be able to drag it over the canvas.
Here is my javascript code:
function addimage1() {
var canvas = new fabric.Canvas('c');
var img = document.createElement("img");
img.src = url_1;
img.height = 50;
img.width = 100;
//optionally set a css class on the image
// var class_name = "foo";
// img.setAttribute("class", class_name);
var imgInstance = new fabric.Image(img, {
left: 100,
top: 100,
angle: 30,
opacity: 0.85
});
canvas.add(imgInstance);
//document.getElementById("resizable").appendChild(img);
//document.body.appendChild(img);
}
and here is the html code for button and canvas:
<div class="description">
<canvas id="c" width="710" height="600" style="background-color: #ffffff" ></canvas>
</div>
What am I doing wrong so the image wont be displayed?
I have canvas with svg path on it. I want to do something like this:
http://jsfiddle.net/tbqrn/
var canvas = new fabric.Canvas('c');
var ctx = canvas.getContext("2d");
ctx.beginPath();
ctx.rect(10,10,150,150);
ctx.rect(180,10,200,200);
ctx.closePath();
ctx.stroke();
ctx.clip();
fabric.Image.fromURL(img01URL, function(oImg) {
oImg.scale(.25);
oImg.left = 50;
oImg.top = 100;
canvas.add(oImg);
canvas.renderAll();
});
fabric.Image.fromURL(img02URL, function(oImg) {
oImg.scale(.25);
oImg.left = 300;
oImg.top = 100;
canvas.add(oImg);
canvas.renderAll();
});
but with one difference: the image after leaving one area should immediately appear in another one.
How can I do it?
This is not doable with a single canvas. The only way I can think of that works is this:
Have two canvases with two different images and "synchronize" the position of the image between them. You actually have to use two images.
HTML:
<canvas id="c1" width="200" height="400"></canvas>
<canvas id="c2" width="200" height="400"></canvas>
CSS:
#c1, #c2 {
border: 1px solid #ccc;
}
#c2 {
margin-left: 20px;
}
.canvas-container {
float: left;
}
JS:
var offsetLeft = 220; // #c1 width + #c2 margin-left
var canvas1 = new fabric.Canvas('c1');
var canvas2 = new fabric.Canvas('c2');
var c1Img, c2Img;
fabric.Image.fromURL(img01URL, function(oImg) {
c1Img = oImg;
c1Img.scale(.25);
c1Img.left = 0;
c1Img.top = 0;
c1Img.hasControls = false;
c1Img.hasRotatingPoint = false;
canvas1.add(c1Img);
canvas1.renderAll();
});
fabric.Image.fromURL(img01URL, function(oImg) {
c2Img = oImg;
c2Img.scale(.25);
c2Img.left = -offsetLeft;
c2Img.top = 0;
c2Img.hasControls = false;
c2Img.hasRotatingPoint = false;
canvas2.add(c2Img);
canvas2.renderAll();
});
canvas1.on('object:moving', function(e) {
c2Img.set({left: e.target.left -offsetLeft, top: e.target.top});
c2Img.setCoords();
canvas2.renderAll();
});
canvas2.on('object:moving', function(e) {
c1Img.set({left: e.target.left + offsetLeft, top: e.target.top});
c1Img.setCoords();
canvas1.renderAll();
});
Test it here: http://jsfiddle.net/se9sw1d8/2/
I want to display the mouse's x position on canvas as mouse moves. Can someone please tell why the text is so big and blurry and also is there any way to achieve the transparency between these two canvases
<body style="margin: 0; padding: 0; height: 100%; width: 100%; overflow: hidden;">
<canvas id="myCanvas" style="display: block; height: 100%; width: 100%;">
Your browser does not support the HTML5 canvas tag.</canvas> <canvas id="temp">
Your browser does not support the HTML5 canvas tag.</canvas>
<script type="text/javascript">
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var hgap = 0;
var vgap = 0;
var rows, cols;
var annotation_x = 1;
var row = 0; var col = 0;
//ctx.font = "14px Arial";
var t = document.getElementById("temp");
tctx = t.getContext("2d");
// tctx.lineWidth = 10;
tctx.lineJoin = 'round';
tctx.lineCap = 'round';
tctx.strokStyle = 'red';
var mouse = { x: 0, y: 0 };
c.addEventListener('mousemove', function (evt) {
// tctx.clearRect(0, 0, c.width, c.height);
ctx.clearRect(0, 0, c.width, c.height);
mouse.x = evt.pageX;
mouse.y = evt.pageY;
ctx.fillText(mouse.x, 10, 10);
}, false);
</script>
</body>
The problem isn't due to having two canvas.
The problem is that you scale your canvas using CSS, but you don't modify its number of pixels (height and width attributes). Then, the result is blurry.
If you don't scale it with CSS, the result is fine: Demo
Alternatively, you can try using image-rendering CSS property (e.g. crisp-edges, demo)
You can also modify height and width attributes when the browser is resized (resize event), and redraw the canvas.
<canvas id="myCanvas" style="display: block; height: 100%; width: 100%;">
^ You shouldn't scale a canvas element with CSS unless you want it's contents to be interpolated. Consider a 300x125px image, which you've scaled to the width and height of the browser window - the image will become blurry.
If you wish to have a full-screen canvas you need to scale it with JS:
var c = document.getElementById("myCanvas");
c.width = window.innerWidth;
c.height = window.innerHeight;
..or with HTML:
<canvas width="1920" height="1080"></canvas>
I have an image background in my HTML5 canvas.
var canvas = new fabric.Canvas('#canvas1');
canvas.setBackgroundImage(
'http://fabricjs.com/assets/jail_cell_bars.png',
canvas.renderAll.bind(canvas)
);
How to set dimensions of my canvas (width, height) to the dimensions of the background image?
Thanks.
I think the above answer does not use fabric.js, it uses normal canvas.
When you use fabric.js and its Fabric.Canvas class, the code should be:
image.onLoad = function() {
var fabric_canvas = new fabric.Canvas('canvas1');
fabric_canvas.setDimensions({width:image.width, height:image.height});
};
In my case,
var canvas = new fabric.Canvas("test_fabric");
canvas.setDimensions({width:800, height:200});
The result is:
<canvas id="test_fabric" width="800" height="200" class="lower-canvas" style="position: absolute; width: 800px; height: 200px; left: 0px; top: 0px; -webkit-user-select: none;"></canvas>
Both canvas.width and canvas.style.width are set.
These work as well!
canvas.setWidth(500);
canvas.setHeight(400);
You can use CSS or dom properties to set the dimensions of your canvas. If you know the dimensions of your image, you can do it in a stylesheet:
#canvas1 { width: XXXpx; height: YYYpx; }
Or in the dom:
<canvas id="canvas1" width="XXX" height="YYY"></canvas>
If the image is dynamic and want to set the dimensions in JS, you do something like this:
var image = new Image()
image.src = 'http://fabricjs.com/assets/jail_cell_bars.png';
image.onLoad = function () {
var canvas = document.getElementById('canvas1');
canvas.width = image.width;
canvas.height = image.height;
};