HTML:
<div class="canvas-wrapper">
<canvas id="myCanvas"></canvas>
</div>
CSS
.canvas-wrapper {
width: 900px;
min-height: 600px;
}
#myCanvas{
border:1px solid red;
position: absolute;
top:22px;
left:0px;
height: 100%;
width: 99%;
}
JS
var myCanvas = new fabric.Canvas('myCanvas');
My canvas get resized to 300x150 after it's been initialized, why?
in the latest version, you will have to do something like:
var canvas = new fabric.Canvas('myCanvas');
canvas.setHeight(500);
canvas.setWidth(800);
.... Your code ....
canvas.renderAll();
Works fine for me..
For dynamically changing size, this works too
When initializing canvas, Fabric reads width/height attributes on canvas element or takes width/height passed in options.
var myCanvas = new fabric.Canvas('myCanvas', { width: 900, height: 600 });
or:
<canvas width="900" height="600"></canvas>
...
var myCanvas = new fabric.Canvas('myCanvas');
A real answer to this question—not involving a new static size but actually permitting CSS to be effective—is one of the following options:
In CSS, you can override individual properties and following them with !important; the downside to this is that any further definitions must also use !important or they will be ignored:
[width], [height], [style]
{
width: 100vw!important;
min-height: 100vh!important;
}
Using JQuery you can set the inline property values to an empty string. You can presumably achieve this without JQuery, but I will leave that as an exercise to you.
Javascript (JQuery):
$('[style]').attr( 'style', function(index, style){ return ''; });
$('[height]').attr( 'height', function(index, height){ return ''; });
$('[width]').attr( 'width', function(index, height){ return ''; });
CSS:
*, *:before, *:after
{
box-sizing: border-box;
}
body
{
width: 100vw;
min-height: 100vh;
padding: 0;
margin: 0;
}
.canvas-container,
canvas
{
width: inherit;
min-height: inherit;
}
canvas.lower-canvas
{
position: absolute;
top: 0;
}
After that, CSS will be applied as expected.
It is apparently also necessary to tell Fabric about the change:
function sizeCanvas()
{
var width = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
var height = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
canvas.setHeight( height )
canvas.setWidth( width )
}
window.addEventListener('resize', draw, false);
function initDraw()
{
// setup
}
function draw()
{
canvas.renderAll();
}
sizeCanvas();
initDraw();
This will configure Fabric to the viewport size and keep it sized accordingly if it resizes.
It's worth noting that this problem arises for two reasons:
Someone thought it was a good idea to use inline styles and should be severely castigated, as there is no situation where this is ever an appropriate practice.
Fabric changes the DOM arrangement and nests the original canvas in a new div with a second nested canvas, which may result in surprises.
Related
I use images created on the fly to maintain the aspect ratio of boxes with a fixed height. Image sources are set as data-urls provided from a canvas with a given width and height, the images are then attached to divs which can contain any content, have any height, and still maintain a fixed aspect ratio.
This works well, however, on slower phones with less memory the large number of data-urls on the page can start to be a little bit of a drag. Some of the ratios can't be reduced below a certain point resulting in relatively large canvases.
Is there any way to set the ratio of an img element without setting its source? Is there any way to set the source to a format that is an truly empty image with only a width and height?
EDIT: The snippet below throws an error - iframe restrictions, probably having to do with making images. You can see an error free version over at this CodePen.
const wrapper = document.querySelector(".wrapper");
function addRatioBox(width, height = 1) {
const cvs = document.createElement("canvas");
const img = new Image(width, height);
const box = document.createElement("div");
cvs.width = width;
cvs.height = height;
img.src = cvs.toDataURL("image/png");
box.appendChild(img);
box.className = "ratioBox";
wrapper.appendChild(box);
}
addRatioBox(1);
addRatioBox(4, 3);
addRatioBox(16, 9);
addRatioBox(2, 1);
.ratioBox {
background: orange;
display: inline-block;
height: 100%;
margin-right: 10px;
}
.ratioBox img {
height: 100%;
width: auto;
display: block;
}
/* just a whole bunch of stuff to make things prettier from here on down */
.wrapper {
background: #556;
padding: 10px;
position: absolute;
height: 20%;
top: 50%;
left: 50%;
white-space: nowrap;
transform: translate(-50%, -50%);
}
body {
background: #334;
}
.ratioBox:last-of-type {
margin-right: 0;
}
<div class="wrapper"></div>
I'm trying to make the canvas with p5.js resize together with a div in which it is in when clicking on a button that extends this div giving it additional height. I don't need the canvas to reload, instead I just need it to add some additional height. Is there a way to do it? I tried making the canvas width 100% and height: auto, but it doesn't work. Please, see the code below:
<div class="canvas-wrapper">
<div id="canvas"></div>
</div>
<button type="button" class="button" id="extend-canvas">Extend</button>
Scripts:
function setup() {
var myCanvas = createCanvas(498, 598);
myCanvas.parent('canvas');
}
$( "#extend-canvas" ).click(function() {
var canvasHeight = $(".canvas-wrapper").height();
$(".canvas-wrapper").height(canvasHeight + 300);
});
CSS:
.canvas-wrapper {
margin: 0 auto;
background: #fff;
width: 500px;
height: 600px;
position: relative;
}
#canvas canvas {
width: 100% !important;
height: auto !important;
}
You can use the resizeCanvas() function for this. More info can be found in the reference.
Here's an example that resizes the canvas to match the screen width and height:
function setup() {
createCanvas(windowWidth, windowHeight);
}
function draw() {
background(0, 100, 200);
}
function windowResized() {
resizeCanvas(windowWidth, windowHeight);
}
But you could also get the width and height of the div and set the canvas size to that.
I am trying to set the width/height of a canvas element to fill the container it is in. Currently it works, but when it fills the body, scrollbars are added.
let masterCanvas = document.querySelector('canvas');
let parent = masterCanvas.parentElement;
masterCanvas.width = parent.offsetWidth;
masterCanvas.height = parent.offsetHeight;
I have the following styles:
<style>
body, html { padding: 0; margin: 0; width: 100vw; height: 100vh; }
* { box-sizing: border-box; }
</style>
And the following body:
<body>
<canvas></canvas>
</body>
Here is a fiddle that demonstrates this: https://jsfiddle.net/ynkcfsud/
The canvas element behaves like an image, so it is an inline element. You'll need to apply display: block to the canvas.
I am trying to get the dimensions of images on a page for further use with a custom 'lightbox' or sorts. However, when trying both a pure js method, and a jquery method, I get the output undefined on my variables. Why is this? Is it because of jquery load event? I tried both onload and ready.
Basically I need the full dimensions of the image to justify whether it should be loaded in a lightbox with a click event or not.
Update I am now able to get console feedback from the function now, however it's not providing me a dimension of the image.
$('.postbody').find('img').each(function() {
var img = new Image(), width, height;
$(img).load(function() {
width = $(this).width();
height = $(this).height();
console.log('Width: '+width+' Height: '+height);
});
console.log($(this).attr('src'));
img.src = $(this).attr('src');
});
#theater-box {
display: none;
position: fixed;
width: auto;
height: auto;
min-width: 1005px;
max-width: 1428px;
padding: 10px;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: rgba(0,0,0,0.90);
border: 2px solid rgba(255,255,255,0.4);
}
.postbody {
width: 90%;
height: 90%;
background: rgba(100,50,50,0.5);
}
.postbody * img {
width: 100%;
max-width: 1168px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="theater-box"></div>
<div class="postbody">
<div id="someclass"><img src="https://e8zzxa.bl3301.livefilestore.com/storageservice/passport/auth.aspx?sru=https:%2f%2fe8zzxa.bl3301.livefilestore.com%2fy2pDapooeiISgUV7-ugpyADuRULJ_stpkiALbypYJHjNxrhUqcvRsZ6eRk4PiJlClABLOfByjulDSDLOMCEpHhggVkgvM4z5Gdq0Jo-C0e1pCU%2fMajipoorHighlands2.jpg&wa=wsignin1.0" /></div>
</div>
You are setting the variables asynchronously and getting it directly.
In pseudocode it is a bit like this:
Set the function to retrieve the width and height when the images loads
Display the width and height variables (not set yet)
The functions set in step 1 runs and sets the varaibles.
So your code that uses the width and height should be inside the image.load function.
I hope it helps, if you have any further questions dont hesitate to comment :-)
Perhaps you can just put the console.log line as the last line in the $(img).load function.
Try this...
$(img).load = function() {
var $this = $(this);
width = $this.width();
height = $this.height();
}
I'm not exactly sure why the original method (which works in a lot of examples) was not working here. So I found some awesome code by GregL from right here at Stackoverflow.
Essentially, the method loads a new, and hidden image into the body, and then captures the width and height before removing it.
$('.postbody').find('img').each(function() {
var img = $(this), width, height,
hiddenImg = img.clone().css('visibility', 'hidden').removeAttr('height').removeAttr('width').appendTo('body');
width = hiddenImg.height();
height = hiddenImg.width();
hiddenImg.remove();
console.log('Width: '+width+' Height: '+height);
});
Check out the Fiddle
I have a problem to get my window size, I try this code:
Javascript
var game;
function game() {
this.canvas = document.getElementById('canvas');
this.canvasWidth = window.innerWidth;
this.canvasHeight = window.innerHeight;
this.initCanvas = function() {
this.canvas.style.width = this.canvasWidth + "px";
this.canvas.style.height = this.canvasHeight + "px";
}
this.run = function() {
this.initCanvas();
}
}
game = new game();
game.run();
I also have
CSS
html, body {
padding: 0;
margin: 0;
}
I only have a canvas in my body.
Problem is, that I have a vertical and horizontal scroll bar. This means the size of canvas is too large. How to make it of the window size without the scroll bars appearing?
It looks like you're just trying to make your canvas have a width and height of 100%. You can do this with just css:
HTML
<body>
<canvas id="canvas"></canvas>
</body>
CSS
body, html {
height: 100%;
width: 100%;
margin: 0px;
}
canvas {
background: #ffcccc;
height: 100%;
width: 100%;
display: block;
}
Demo
Or if you want to use your code but get rid of the scroll bars on the window, you need to specify block on the canvas tag.
CSS
canvas {
display: block;
}
Demo
When you use CSS to style your <canvas> element it will get scaled instead of sized. Be sure to set the .width and .height properties on the canvas element instead (ie canvas.width not canvas.style.width).
jsfiddle example
In the example the first canvas element is scaled correctly, the second (using CSS) is not scaled properly. This has to do with a default canvas element size (300x150) that CSS scales.
To prevent getting scrollbars when setting the <canvas> to the full window width/height set the body to overflow:hidden; as used in the jsfiddle above.