How to get width and height of canvas after resizing the browser - javascript

I want to get width and height of canvas which is responsive. I have 5 canvas elements on a single page.
Using Javascript before drawing I want to know the height and width of canvas to be able to draw images at the right size.
HTML Code:
<div id='container'>
<div class='all'>
<canvas id='clock1' style="border:solid">
</div>
<div class='all'>
<canvas id='clock2' style="border:solid">
</div>
<div class='all'>
<canvas id='clock3' style="border:solid">
</div>
<div class='all'>
<canvas id='clock4' style="border:solid">
</div>
<div class='all'>
<canvas id='clock5' style="border:solid">
</div>
</div>
CSS:
#container
{
width:100%;
height:100%;
position:relative;
}
.all
{
width:30%;
height:45%;
float:left;
}
canvas
{
width:100%;
height:100%;
}

Usually you don't set size of canvas using CSS but calculating the w/h and use the width and height properties.
But if you use CSS you can get the calculated size of the canvas element set by CSS using getComputedStyle():
Online demo
var cs = getComputedStyle(canvas);
var width = parseInt( cs.getPropertyValue('width'), 10);
var height = parseInt( cs.getPropertyValue('height'), 10);
the size is here returned by getPropertyValue() as a string and in pixel size (ie. "400px"), so we use parseInt() to chop of the "px" part.
Then simply set the width and height on canvas and update its content.
Full example (adjust as needed):
window.onresize = updateCanvas;
updateCanvas();
function updateCanvas() {
var cs = getComputedStyle(canvas);
var width = parseInt(cs.getPropertyValue('width'), 10);
var height = parseInt(cs.getPropertyValue('height'), 10);
canvas.width = width;
canvas.height = height;
var ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(width, height);
ctx.moveTo(0, height);
ctx.lineTo(width, 0);
ctx.stroke();
}

Related

Dynamically load images into overlayed canvases and resize them

I have two canvases, which are overlaid. Now I want to load dynamically images into the canvases and adapt their size to the image size.
My problem now, is that after the canvases load the images and resize them self, they overlay all other html items below.
Here is the minimal example:
loadimage.onclick = function(e) {
//load image1
var img1 = new Image();
img1.onload = function() {
var canvas = document.getElementById("canvas1");
var ctx = canvas.getContext("2d");
//resize canvas1
canvas.width = this.naturalWidth;
canvas.height = this.naturalHeight;
ctx.drawImage(this, 0, 0);
};
img1.src = "https://via.placeholder.com/250/0000FF/808080/";
//load image2
var img2 = new Image();
img2.onload = function() {
var canvas = document.getElementById("canvas2");
var ctx = canvas.getContext("2d");
//resize canvas1
canvas.width = this.naturalWidth;
canvas.height = this.naturalHeight;
ctx.drawImage(this, 75, 75);
};
img2.src = "https://via.placeholder.com/50/00FF00/808080/";
}
<div id="container" style="position: relative; width: 200px; height: 100px;">
<canvas id="canvas1" width="200" height="100" style="position: absolute; left: 0; top: 0; z-index: 0; border: 1px solid #000;"></canvas>
<canvas id="canvas2" width="200" height="100" style="position: absolute; left: 0; top: 0; z-index: 1; border: 1px solid #000;"></canvas>
</div>
<button id="loadimage" type="button">Load Content</button>
After pressing the "Load Content"
button, the button doesn 't move down.
I tried to change also the width and height properties of the "container"
div, but the behaviour did not change.
What am I missing here ?
So, the code has many problems. If you are beginner, don't worry. That's normal. ☺
Firstly, <canvas> is pair tag. That means that you have to close it using </canvas>. The correct form is <canvas someattribute="somevalue"></canvas>. Inside the <canvas> tag is place for alternative content that will be used when the browser does not support the <canvas> tag (it is quite new).
Omitting the </canvas> broke the page.
HTML dictates what tags must be closed and what shouldn't and <canvas> is one of tags that must be closed. The Validator could help you identify mistakes in the code. Note that it is quite pedantic.
The second problem is that you were using absolute positioning and the canvases, when resized, overlaid the button. Simply disable the positioning or use some more precise way of positioning. The third option is to resize the container div appropriately in the JS.
The container div had also set fixed size. By default, when the content is larger, it overflows.
You were probably trying to solve it using z-index. Setting z-indexes is usually quite tricky and I try to use it as the last resort. Both your z-index properties were not valid. It is z-index: NUMBER, not z- index or z index.
And the last bug I have found was that you were using canvas1 (undefined variable) instead of canvas in the second function.
loadimage.onclick = function(e) {
//load image1
var img1 = new Image();
img1.onload = function() {
var canvas = document.getElementById("canvas1");
var ctx = canvas1.getContext("2d");
//resize canvas1
canvas.width = this.naturalWidth;
canvas.height = this.naturalHeight;
ctx.drawImage(this, 0, 0);
};
img1.src = "https://via.placeholder.com/250/0000FF/808080/";
//load image2
var img2 = new Image();
img2.onload = function() {
var canvas = document.getElementById("canvas2");
var ctx = canvas.getContext("2d");
//resize canvas1
canvas.width = this.naturalWidth;
canvas.height = this.naturalHeight;
ctx.drawImage(this, 0, 0);
};
img2.src = "https://via.placeholder.com/50/00FF00/808080/";
}
<div id="container">
<canvas id="canvas1" width="200" height="100" style="border: 1px solid #000;"></canvas>
<canvas id="canvas2" width="200" height="100" style="border: 1px solid #000;"></canvas>
</div>
<button id="loadimage" type="button">Load Content</button>

jQuery to get background image height and change parent based on ratio

I have a background image for each item; in this case the image size is 580x374.
This is being set inline on the li a item for each as a background image but I need to set the elements height so it shows correctly. The image height returned I need to half as it's two images in one that I need to move position on hover but I can do that.
What I am having a problem with is getting the elements width, getting the background size, working out the ratio of the background image size and setting the height of the container to display it.
I need it to be responsive as well, so it sets right on page load whichever viewport size it is and resize.
Here is where I have got to so far, but I'm new to JS.
HTML EXAMPLE:
<ul>
<li class="collection-list-item grid-item first collection-hover">
<a href="/collections/butterfly-sofa" data-image="//cdn.shopify.com/s/files/1/1839/7697/collections/category-panel-butterfly.jpg?v=1490985733" style="background-image: url("//cdn.shopify.com/s/files/1/1839/7697/collections/category-panel-butterfly.jpg?v=1490985733");">
<div class="collection-list-hover-desc right">
<p>Dein eigener Ruhepol in einer hektischen Welt. Der durch eine Struktur im Inneren formstabile Sitzsack vereint Komfort und Ästhetik.</p>
</div>
<div class="collection-list-hover-button left">
<span class="button">Entdecken</span>
</div>
</a>
</li>
<li class="collection-list-item grid-item first collection-hover">
<a href="/collections/butterfly-sofa" data-image="//cdn.shopify.com/s/files/1/1839/7697/collections/category-panel-butterfly.jpg?v=1490985733" style="background-image: url("//cdn.shopify.com/s/files/1/1839/7697/collections/category-panel-butterfly.jpg?v=1490985733");">
<div class="collection-list-hover-desc right">
<p>Dein eigener Ruhepol in einer hektischen Welt. Der durch eine Struktur im Inneren formstabile Sitzsack vereint Komfort und Ästhetik.</p>
</div>
<div class="collection-list-hover-button left">
<span class="button">Entdecken</span>
</div>
</a>
</li>
<li class="collection-list-item grid-item first collection-hover">
<a href="/collections/butterfly-sofa" data-image="//cdn.shopify.com/s/files/1/1839/7697/collections/category-panel-butterfly.jpg?v=1490985733" style="background-image: url("//cdn.shopify.com/s/files/1/1839/7697/collections/category-panel-butterfly.jpg?v=1490985733");">
<div class="collection-list-hover-desc right">
<p>Dein eigener Ruhepol in einer hektischen Welt. Der durch eine Struktur im Inneren formstabile Sitzsack vereint Komfort und Ästhetik.</p>
</div>
<div class="collection-list-hover-button left">
<span class="button">Entdecken</span>
</div>
</a>
</li>
</ul>
JS:
$('.collection-hover a').each(function (index, value){
var collection_bg_img = new Image;
collection_bg_img.src = $(this).data('image');
var bgImgWidth = collection_bg_img.width;
var bgImgHeight = collection_bg_img.height;
var divWidth = $(this).width();
var realImgHeight = ( bgImgHeight / bgImgWidth) * divWidth;
var halfImage = (realImgHeight / 2);
$(this).height(halfImage);
//console.log(halfImage);
});
I guess could set a max width and height and change it width whatever width is set by viewport and adjust height based on ratio?
UPDATE
I tried something like this, not got it working yet though... but maybe a good approach as would be a max width:
$('.collection-hover a').each(function() {
var maxWidth = 580; // Max width for the image
var maxHeight = 374; // Max height for the image
var ratio = 0; // Used for aspect ratio
var width = $(this).width(); // Current image width
var height = $(this).height(); // Current image height
// Check if the current width is larger than the max
if(width > maxWidth){
ratio = maxWidth / width; // get ratio for scaling image
$(this).css("width", maxWidth); // Set new width
$(this).css("height", height * ratio); // Scale height based on ratio
height = height * ratio; // Reset height to match scaled image
}
var width = $(this).width(); // Current image width
var height = $(this).height(); // Current image height
// Check if current height is larger than max
if(height > maxHeight){
ratio = maxHeight / height; // get ratio for scaling image
$(this).css("height", maxHeight); // Set new height
$(this).css("width", width * ratio); // Scale width based on ratio
width = width * ratio; // Reset width to match scaled image
}
});
You can only :
address DOM elements after the document is ready
measure an image's width after it has successfully loaded.
Therefore :
jQuery(function($) {
function resizeBgImgContainers() {
$('.collection-hover a').each(function() {
var $a = $(this);
var img = new Image();
img.onload = function() {
$a.height(img.height * $a.width() / img.width / 2);
};
img.src = $a.data('image');
});
}
$(window).on('resize', resizeBgImgContainers).trigger('resize');
});
If I understand this question correctly, you're trying to:
Add a div to a webpage, the width of which is unknowable.
Add a background to that div and have the background stretch to the width of the div
Resize the div to 1/2 the height of the stretched background
This can actually be accomplished with a combination of img tags and pure CSS.
Here's a JsFiddle demonstating that: https://jsfiddle.net/x11n48yz/1/
<div id='my-page'>
<div class='image-holder'>
<img src='http://cflrs.in/wp-content/uploads/2017/01/example.jpg'/>
</div>
</div>
#my-page {
background-color: green;
width: 200px;
height: 800px;
}
.image-holder {
position:relative;
width: 100%;
height: 0;
padding-bottom: 50%;
margin-bottom: -10%;
overflow: hidden;
}
.image-holder img {
width: 100%;
height: 200%;
position: absolute;
left: 0;
}
.image-holder img:hover {
bottom: 0;
}

Hide / show images inside canvas

I'm making a page where I want people to be able to overlapp images and then upload them to my server.
I've built the uploading page and I've put two test images in a canvas. The only issue noe is to be able to hide / show these two images through a button or checkbox.
I've uploaded a test page here: http://kaosmos.no/bokbodentest2/upload.html
This is my code for the canvas:
<input type="checkbox"/>Check to hide img1
<input type="checkbox"/>Check to hide img2
<img class="bilder" id="img1" src="test1.png">
<img class="bilder" id="img2" src="test2.png">
<canvas id="canvas"></canvas>
<script type="text/javascript">
var img1 = document.getElementById('img1');
var img2 = document.getElementById('img2');
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
canvas.width = img1.width;
canvas.height = img1.height;
context.globalAlpha = 1.0;
context.drawImage(img1, 0, 0);
context.globalAlpha = 0.5; //Remove if pngs have alpha
context.drawImage(img2, 0, 0);
</script>
And CSS:
canvas {
border: solid;
overflow: hidden;
}
canvas img {
width: 600px;
position: absolute;
mix-blend-mode: multiply;
}
.bilder {
display: none;
}
The display: none; in the "bilder" class is so that the images won't be visable outside the canvas. How do I make a function to hide / show these images?
Any help is much appreciated!
Since when an image is drawn to the canvas, it is no longer linked to the original element in the DOM, you want to hide it on the canvas, so you'll need to redraw the canvas each time an input is changed, not calling the relevant context.drawImage function. Something along these lines:
<input type="checkbox" onchange="draw()"/>Check to hide img1
<input type="checkbox" onchange="draw()"/>Check to hide img2
<img class="bilder" id="img1" src="test1.png">
<img class="bilder" id="img2" src="test2.png">
<canvas id="canvas"></canvas>
<script type="text/javascript">
var img1 = document.getElementById('img1');
var img2 = document.getElementById('img2');
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
var inputs = document.querySelectorAll('input[type="checkbox"]');
canvas.width = img1.width;
canvas.height = img1.height;
function draw(){
context.clearRect(0, 0, canvas.width, canvas.height);
context.globalAlpha = 1.0;
if(inputs[0].checked){
context.drawImage(img1, 0, 0);
}
context.globalAlpha = 0.5; //Remove if pngs have alpha
if(inputs[1].checked){
context.drawImage(img2, 0, 0);
}
}
</script>

Draw More Arc Canvas

Hello People I'd Like to Know How to Draw More Arc Inside My Canvas, What I Need to Draw This circles:
So I Write This Responsive Code to Make my Canvas is Responsive:
var myCanvas = document.getElementById('myCanvas');
var ctx = myCanvas.getContext('2d');
var centerX = myCanvas.width / 2;
var centerY = myCanvas.height / 2;
var borderWidth = 20;
var borderColor = '#2DC36A';
var radius = (myCanvas.width / 2) - (borderWidth / 2);
// days arc canvas background
ctx.beginPath();
ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
ctx.lineWidth = borderWidth;
ctx.strokeStyle = borderColor;
ctx.stroke();
ctx.closePath();
// Make Canvas Responsive
function makeResponsive() {
var containerWidth = $('.progress-nested').width();
$('.progress-nested').height(containerWidth);
var canvasElements = ['#myCanvas'];
$('#myCanvas').width(containerWidth).height(containerWidth);
}
makeResponsive(); // Make Canvas Responsive in Document ready
$(window).resize(function () {
makeResponsive(); // Make Canvas Responsive in Window Resize
});
#progress {
width: 100%;
padding: 5px;
}
.progress-nested{
position:relative;
border-radius:50%;
}
canvas {
display:block;
position:absolute;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<div id="progress">
<div class="container">
<div class="row">
<div class="col-xs-3 col-md-2 col-md-offset-2">
<div class="progress-nested">
<canvas id="myCanvas" width="250" height="250"></canvas>
</div>
</div>
</div>
</div>
</div>
Note: Please Run Code Snippet In Full Page

How to append HTML5 video snapshots to a scrolling DIV without Jquery

How can I take multiple snapshots (via onclick buttons) from an HTML5 video playing locally, and add the snapshot images with timestamp to a scrollable div without jQuery or external libraries?
I'm able to make a snapshot via canvas but how can I convert the canvas image to a small file size format and append the image (with a href="" scrpt) to a scrolling div?
codepine example http://codepen.io/anon/pen/OVGZEg
HTML
<span> Working example</span>
<br>
<video controls id="sourceVid">
<source src="http://html5multimedia.com/code/ch9/media/elephants-dream-medium.mp4" type="video/mp4">
<source src="../media/elephants-dream-medium.webm" type="video/webm">
</video>
<canvas></canvas>
<br>
<button id="snap" onclick="snap()">Take Snapshot</button>
<br>
<br>
<br>
<!----------------------------------------
Desired Result
---------------------------------------->
<div id="DesiredResult" style="background-color:grey;width: 100%;">
<br>
Desired Result
<br>
How can I take a snapshot & add it to scrolling DIV on the left?
<br>
<video controls id="Result" style="float: left;" >
<source src="http://html5multimedia.com/code/ch9/media/elephants-dream-medium.mp4" type="video/mp4">
<source src="../media/elephants-dream-medium.webm" type="video/webm">
</video>
<div id="snapshotscroll" >
<div id="snapshot#1" class="snapshots" style="background-color:#FE2E2E;" >
snapshot image
<br>#1
</div>
<div id="snapshot#1" class="snapshots" style="background-color:#FA5858;" >
snapshot image
<br>#2
</div>
<div id="snapshot#1" class="snapshots" style="background-color:#F78181;" >
snapshot image
<br>#3
</div>
<div id="snapshot#1" class="snapshots" style="background-color:#F5A9A9;" >
snapshot image
<br>#4
</div>
<div id="snapshot#1" class="snapshots" style="background-color:#F6CECE;" >
snapshot image
<br>#5
</div>
</div>
</div>
<button id="snap" onclick="alert('How can I take a snapshot & add it to scrolling DIV on the left?')">Take Snapshot</button>
CSS
video, canvas {
border:1px solid #000;
}
#snapshotscroll {
overflow-y: scroll;
height:258px;
width:220px;
}
.snapshots {
width: 200px;
height: 100px;
border: 1px solid #000;
}
JAVASCRIPT
// Get handles on the video and canvas elements
var video = document.getElementById('sourceVid');
var canvas = document.querySelector('canvas');
// Get a handle on the 2d context of the canvas element
var context = canvas.getContext('2d');
// Define some vars required later
var w, h, ratio;
// Add a listener to wait for the 'loadedmetadata' state so the video's dimensions can be read
video.addEventListener('loadedmetadata', function() {
// Calculate the ratio of the video's width to height
ratio = video.videoWidth / video.videoHeight;
// Define the required width as 100 pixels smaller than the actual video's width
w = 200;
// Calculate the height based on the video's width and the ratio
h = 100;
// Set the canvas width and height to the values just calculated
canvas.width = w;
canvas.height = h;
}, false);
// Takes a snapshot of the video
function snap() {
// Define the size of the rectangle that will be filled (basically the entire element)
context.fillRect(0, 0, w, h);
// Grab the image from the video
context.drawImage(video, 0, 0, w, h);
}
I ended up getting your example working with a few tweaks. This example uses a counter to keep track of which div to append the snapshot to.
Live Working Example (full screen it):
var w = 200, h = 100, snapnum = 1;
// Takes a snapshot of the video
function snap() {
var cv = document.createElement("canvas");
cv.width = w;
cv.height = h;
console.log(document.getElementById("snapshot#" + snapnum));
document.getElementById("snapshot#" + snapnum).textContent = "";
document.getElementById("snapshot#" + snapnum).appendChild(cv);
var cx = cv.getContext('2d');
cx.fillRect(0, 0, w, h);
// Grab the image from the video
cx.drawImage(document.getElementById('Result'), 0, 0, w, h);
snapnum++;
}
video, canvas {
border:1px solid #000;
}
#snapshotscroll {
overflow-y: scroll;
height:258px;
width:220px;
}
.snapshots {
width: 200px;
height: 100px;
border: 1px solid #000;
}
<!---------------------------------------- Desired Result ---------------------------------------->
<div id="DesiredResult" style="background-color:grey;width: 100%;">
<br>Desired Result
<br>
<video controls id="Result" style="float: left;">
<source src="http://html5multimedia.com/code/ch9/media/elephants-dream-medium.mp4" type="video/mp4">
<source src="../media/elephants-dream-medium.webm" type="video/webm">
</video>
<div id="snapshotscroll">
<div id="snapshot#1" class="snapshots" style="background-color:#FE2E2E;">snapshot image
<br>#1</div>
<div id="snapshot#2" class="snapshots" style="background-color:#FA5858;">snapshot image
<br>#2</div>
<div id="snapshot#3" class="snapshots" style="background-color:#F78181;">snapshot image
<br>#3</div>
<div id="snapshot#4" class="snapshots" style="background-color:#F5A9A9;">snapshot image
<br>#4</div>
<div id="snapshot#5" class="snapshots" style="background-color:#F6CECE;">snapshot image
<br>#5</div>
</div>
</div>
<button id="snap" onclick="snap()">Take Snapshot</button>
JSFiddle Version: https://jsfiddle.net/y80m3z33/

Categories