scaling images to fit on canvas without streching - javascript

according to the post HTML Canvas: Scaling image to fit without stretching?, when I open an image to fit on canvas it Works if I am using the descktop view, but when I i am using a responsive view It doesn't work well.
My application is published in https://www.galeonweb.es/web, and the code I am using to open an image is:
var img=new Image();
img.onload=function(){
var wrh=img.width/img.height;
var newWidth=canvas.width;
var newHeight=newWidth/wrh;
if (newHeight>canvas.height){
newHeight=canvas.height;
newWidth=newHeight*wrh;
}
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(img, 0, 0, newWidth, newHeight);
//ctx.drawImage(img,0,0, img.width, img.height, 0,0, canvas.width, canvas.height); //Coloco la imagen en el canvas
imgData=ctx.getImageData(0,0,canvas.width,canvas.height); //Extraigo su array forma.guardarEnHistorico(imgData);
};
img.src=url;
//Cerramos el cuadro de dialogo abrir
ocultarVentana($('#abrir'));
On the other hand, I use a responsive CSS with the following code:
canvas {
width:100%;
height:420px;
background:white;
box-shadow: 0 0 10px black;
}
and the HTML code is:
<div id="lienzo">
<video id="video" class="oculto" preload="none" autoplay>
<source src="video.webM" type="video/webM">
</video>
<button id="snap" class="oculto">Tomar Foto</button>
<canvas id="poo"></canvas>
</div>
I appreciate any help, thanks

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>

The canvas has been tainted by cross-origin data in videojs

I'm try to play my video in canvas but I got this error:
Uncaught DOMException: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The canvas has been tainted by cross-origin data.
I can't change the source (the server to support cors), so what can I do to solve this?
document.addEventListener('DOMContentLoaded', function(){
var v = document.getElementById('my-video');
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');
var back = document.createElement('canvas');
var backcontext = back.getContext('2d');
var cw,ch;
console.log({ v });
v.addEventListener('play', function(){
cw = v.clientWidth;
ch = v.clientHeight;
canvas.width = cw;
canvas.height = ch;
back.width = cw;
back.height = ch;
draw(v,context,backcontext,cw,ch);
},false);
},false);
function draw(v,c,bc,w,h) {
if(v.paused || v.ended) return false;
// First, draw it into the backing canvas
bc.drawImage(v,0,0,w,h);
// Grab the pixel data from the backing canvas
var idata = bc.getImageData(0,0,w,h);
var data = idata.data;
idata.data = data;
// Draw the pixels onto the visible canvas
c.putImageData(idata,0,0);
// Start over!
setTimeout(draw,20,v,c,bc,w,h);
}
#c {
position: absolute;
top: 50%;
left: 50%;
margin: -180px 0 0 20px;
}
<head>
<link href="https://vjs.zencdn.net/7.6.6/video-js.css" rel="stylesheet" />
<!-- If you'd like to support IE8 (for Video.js versions prior to v7) -->
<script src="https://vjs.zencdn.net/ie8/1.1.2/videojs-ie8.min.js"></script>
</head>
<body>
<video
id="my-video"
class="video-js"
controls
preload="auto"
width="640"
height="264"
poster="MY_VIDEO_POSTER.jpg"
data-setup="{}"
>
<source src="http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4" type="video/mp4" />
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a
web browser that
<a href="https://videojs.com/html5-video-support/" target="_blank"
>supports HTML5 video</a
>
</p>
</video>
<canvas id="c" ></canvas>
<script src="https://vjs.zencdn.net/7.6.6/video.js"></script>
</body>

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>

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/

How do I get a video to be play on the canvas under my canvas animation?

How do I get a video to be play on the canvas under my canvas animation?
For instance this clip.
So this animation moves along the bottom of the video.
Code:
<html>
<head>
<script type='text/javascript' src='http://code.jquery.com/jquery-1.8.3.js'></script>
<script type="text/javascript">
var context;
var text = "";
var textDirection ="";
$(function()
{
context = document.getElementById("cvs").getContext("2d");
setInterval("animate()", 360);
textDirection ="right";
textXpos = 5;
text = "This is my video..";
});
function animate() {
// Clear screen
context.clearRect(0, 0, 500, 500);
context.globalAlpha = 1;
context.fillStyle = '#fff';
context.fillRect(0, 0, 500, 500);
var metrics = context.measureText(text);
var textWidth = metrics.width;
if (textDirection == "right") {
textXpos += 10;
if (textXpos > 500 - textWidth) {
textDirection = "left";
}
}
else {
textXpos -= 10;
if (textXpos < 10) {
textDirection = "right";
}
}
context.font = '20px _sans';
context.fillStyle = 'black';
context.textBaseline = 'top';
context.fillText ( text, textXpos, 180);
}
</script>
</head>
<body>
<div id="page">
<canvas id="cvs" width="500" height="500">
Your browser does not support the HTML 5 Canvas.
</canvas>
</div>
</body>
</html>
I don't think you need to play the video in the canvas. Just create a video element in your HTML and use CSS to place your canvas element over it.
HTML:
<div id="page">
<video id="video" autoplay loop>
<source id='mp4'
src="http://media.w3.org/2010/05/sintel/trailer.mp4"
type='video/mp4'>
<source id='webm'
src="http://media.w3.org/2010/05/sintel/trailer.webm"
type='video/webm'>
<source id='ogv'
src="http://media.w3.org/2010/05/sintel/trailer.ogv"
type='video/ogg'>
<p>Your user agent does not support the HTML5 Video element.</p>
</video>
<canvas id="cvs" width="500" height="500">
Your browser does not support the HTML 5 Canvas.
</canvas>
</div>
CSS:
#cvs {
position: absolute;
top: 0px;
left: 0px;
}
Fiddle.

Categories