I'm playing with the following application using the HTML Canvas: http://driz.co.uk/particles/
At the moment it is set to 640x480 pixels, but I would like to make it full screen as it will be shown a projector. However as far as I can tell I cannot set the canvas size to be 100% as the variables only except numbers and not the %. Using CSS just stretches it rather than making it actual full screen.
Any ideas?
EDIT: Tried finding the height and width using jQuery but it breaks the canvas any ideas why?
var $j = jQuery.noConflict();
var canvas;
var ctx;
var canvasDiv;
var outerDiv;
var canvasW = $j('body').width();
var canvasH = $j('body').height();
//var canvasW = 640;
//var canvasH = 480;
var numMovers = 550;
var movers = [];
var friction = .96;
var radCirc = Math.PI * 2;
var mouseX, mouseY, mouseVX, mouseVY, prevMouseX = 0, prevMouseY = 0;
var isMouseDown = true;
function init()
{
canvas = document.getElementById("mainCanvas");
if( canvas.getContext )
{
setup();
setInterval( run , 33 );
}
}
function setup()
{
outerDiv = document.getElementById("outer");
canvasDiv = document.getElementById("canvasContainer");
ctx = canvas.getContext("2d");
var i = numMovers;
while( i-- )
{
var m = new Mover();
m.x = canvasW * .5;
m.y = canvasH * .5;
m.vX = Math.cos(i) * Math.random() * 25;
m.vY = Math.sin(i) * Math.random() * 25;
m.size = 2;
movers[i] = m;
}
document.onmousedown = onDocMouseDown;
document.onmouseup = onDocMouseUp;
document.onmousemove = onDocMouseMove;
}
function run()
{
ctx.globalCompositeOperation = "source-over";
ctx.fillStyle = "rgba(8,8,12,.65)";
ctx.fillRect( 0 , 0 , canvasW , canvasH );
ctx.globalCompositeOperation = "lighter";
mouseVX = mouseX - prevMouseX;
mouseVY = mouseY - prevMouseY;
prevMouseX = mouseX;
prevMouseY = mouseY;
var toDist = canvasW / 1.15;
var stirDist = canvasW / 8;
var blowDist = canvasW / 2;
var Mrnd = Math.random;
var Mabs = Math.abs;
var Msqrt = Math.sqrt;
var Mcos = Math.cos;
var Msin = Math.sin;
var Matan2 = Math.atan2;
var Mmax = Math.max;
var Mmin = Math.min;
var i = numMovers;
while( i-- )
{
var m = movers[i];
var x = m.x;
var y = m.y;
var vX = m.vX;
var vY = m.vY;
var dX = x - mouseX;
var dY = y - mouseY;
var d = Msqrt( dX * dX + dY * dY );
var a = Matan2( dY , dX );
var cosA = Mcos( a );
var sinA = Msin( a );
if( isMouseDown )
{
if( d < blowDist )
{
var blowAcc = ( 1 - ( d / blowDist ) ) * 2;
vX += cosA * blowAcc + .5 - Mrnd();
vY += sinA * blowAcc + .5 - Mrnd();
}
}
if( d < toDist )
{
var toAcc = ( 1 - ( d / toDist ) ) * canvasW * .0014;
vX -= cosA * toAcc;
vY -= sinA * toAcc;
}
if( d < stirDist )
{
var mAcc = ( 1 - ( d / stirDist ) ) * canvasW * .00022;
vX += mouseVX * mAcc;
vY += mouseVY * mAcc;
}
vX *= friction;
vY *= friction;
var avgVX = Mabs( vX );
var avgVY = Mabs( vY );
var avgV = ( avgVX + avgVY ) * .5;
if( avgVX < .1 ) vX *= Mrnd() * 3;
if( avgVY < .1 ) vY *= Mrnd() * 3;
var sc = avgV * .45;
sc = Mmax( Mmin( sc , 3.5 ) , .4 );
var nextX = x + vX;
var nextY = y + vY;
if( nextX > canvasW )
{
nextX = canvasW;
vX *= -1;
}
else if( nextX < 0 )
{
nextX = 0;
vX *= -1;
}
if( nextY > canvasH )
{
nextY = canvasH;
vY *= -1;
}
else if( nextY < 0 )
{
nextY = 0;
vY *= -1;
}
m.vX = vX;
m.vY = vY;
m.x = nextX;
m.y = nextY;
ctx.fillStyle = m.color;
ctx.beginPath();
ctx.arc( nextX , nextY , sc , 0 , radCirc , true );
ctx.closePath();
ctx.fill();
}
//rect( ctx , mouseX - 3 , mouseY - 3 , 6 , 6 );
}
function onDocMouseMove( e )
{
var ev = e ? e : window.event;
mouseX = ev.clientX - outerDiv.offsetLeft - canvasDiv.offsetLeft;
mouseY = ev.clientY - outerDiv.offsetTop - canvasDiv.offsetTop;
}
function onDocMouseDown( e )
{
isMouseDown = true;
return false;
}
function onDocMouseUp( e )
{
isMouseDown = true;
return false;
}
// ==========================================================================================
function Mover()
{
this.color = "rgb(" + Math.floor( Math.random()*255 ) + "," + Math.floor( Math.random()*255 ) + "," + Math.floor( Math.random()*255 ) + ")";
this.y = 0;
this.x = 0;
this.vX = 0;
this.vY = 0;
this.size = 0;
}
// ==========================================================================================
function rect( context , x , y , w , h )
{
context.beginPath();
context.rect( x , y , w , h );
context.closePath();
context.fill();
}
// ==========================================================================================
The javascript has
var canvasW = 640;
var canvasH = 480;
in it. Try changing those as well as the css for the canvas.
Or better yet, have the initialize function determine the size of the canvas from the css!
in response to your edits, change your init function:
function init()
{
canvas = document.getElementById("mainCanvas");
canvas.width = document.body.clientWidth; //document.width is obsolete
canvas.height = document.body.clientHeight; //document.height is obsolete
canvasW = canvas.width;
canvasH = canvas.height;
if( canvas.getContext )
{
setup();
setInterval( run , 33 );
}
}
Also remove all the css from the wrappers, that just junks stuff up. You have to edit the js to get rid of them completely though... I was able to get it full screen though.
html, body {
overflow: hidden;
}
Edit: document.width and document.height are obsolete. Replace with document.body.clientWidth and document.body.clientHeight
You can just insert the following in to your main html page, or a function:
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
Then to remove the margins on the page
html, body {
margin: 0 !important;
padding: 0 !important;
}
That should do the job
The newest Chrome and Firefox support a fullscreen API, but setting to fullscreen is like a window resize. Listen to the onresize-Event of the window-object:
$(window).bind("resize", function(){
var w = $(window).width();
var h = $(window).height();
$("#mycanvas").css("width", w + "px");
$("#mycanvas").css("height", h + "px");
});
//using HTML5 for fullscreen (only newest Chrome + FF)
$("#mycanvas")[0].webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT); //Chrome
$("#mycanvas")[0].mozRequestFullScreen(); //Firefox
//...
//now i want to cancel fullscreen
document.webkitCancelFullScreen(); //Chrome
document.mozCancelFullScreen(); //Firefox
This doesn't work in every browser. You should check if the functions exist or it will throw an js-error.
for more info on html5-fullscreen check this:
http://updates.html5rocks.com/2011/10/Let-Your-Content-Do-the-Talking-Fullscreen-API
Because it was not posted yet and is a simple css fix:
#canvas {
position:fixed;
left:0;
top:0;
width:100%;
height:100%;
}
Works great if you want to apply a fullscreen canvas background (for example with Granim.js).
All you need to do is set the width and height attributes to be the size of the canvas, dynamically. So you use CSS to make it stretch over the entire browser window, then you have a little function in javascript which measures the width and height, and assigns them. I'm not terribly familliar with jQuery, so consider this psuedocode:
window.onload = window.onresize = function() {
theCanvas.width = theCanvas.offsetWidth;
theCanvas.height = theCanvas.offsetHeight;
}
The width and height attributes of the element determine how many pixels it uses in it's internal rendering buffer. Changing those to new numbers causes the canvas to reinitialise with a differently sized, blank buffer. Browser will only stretch the graphics if the width and height attributes disagree with the actual real world pixel width and height.
If you want to show it in a presentation then consider using requestFullscreen() method
let canvas = document.getElementById("canvas_id");
canvas.requestFullscreen();
that should make it fullscreen whatever the current circumstances are.
also check the support table https://caniuse.com/?search=requestFullscreen
On document load set the
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
A - How To Calculate Full Screen Width & Height
Here is the functions;
canvas.width = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
canvas.height = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
Check this out
B - How To Make Full Screen Stable With Resize
Here is the resize method for the resize event;
function resizeCanvas() {
canvas.width = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
canvas.height = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
WIDTH = canvas.width;
HEIGHT = canvas.height;
clearScreen();
}
C - How To Get Rid Of Scroll Bars
Simply;
<style>
html, body {
overflow: hidden;
}
</style>
D - Demo Code
<html>
<head>
<title>Full Screen Canvas Example</title>
<style>
html, body {
overflow: hidden;
}
</style>
</head>
<body onresize="resizeCanvas()">
<canvas id="mainCanvas">
</canvas>
<script>
(function () {
canvas = document.getElementById('mainCanvas');
ctx = canvas.getContext("2d");
canvas.width = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
canvas.height = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
WIDTH = canvas.width;
HEIGHT = canvas.height;
clearScreen();
})();
function resizeCanvas() {
canvas.width = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
canvas.height = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
WIDTH = canvas.width;
HEIGHT = canvas.height;
clearScreen();
}
function clearScreen() {
var grd = ctx.createLinearGradient(0,0,0,180);
grd.addColorStop(0,"#6666ff");
grd.addColorStop(1,"#aaaacc");
ctx.fillStyle = grd;
ctx.fillRect( 0, 0, WIDTH, HEIGHT );
}
</script>
</body>
</html>
I hope it will be useful.
// Get the canvas element
var canvas = document.getElementById('canvas');
var isInFullScreen = (document.fullscreenElement && document.fullscreenElement !== null) ||
(document.webkitFullscreenElement && document.webkitFullscreenElement !== null) ||
(document.mozFullScreenElement && document.mozFullScreenElement !== null) ||
(document.msFullscreenElement && document.msFullscreenElement !== null);
// Enter fullscreen
function fullscreen(){
if(canvas.RequestFullScreen){
canvas.RequestFullScreen();
}else if(canvas.webkitRequestFullScreen){
canvas.webkitRequestFullScreen();
}else if(canvas.mozRequestFullScreen){
canvas.mozRequestFullScreen();
}else if(canvas.msRequestFullscreen){
canvas.msRequestFullscreen();
}else{
alert("This browser doesn't supporter fullscreen");
}
}
// Exit fullscreen
function exitfullscreen(){
if (document.exitFullscreen) {
document.exitFullscreen();
} else if (document.webkitExitFullscreen) {
document.webkitExitFullscreen();
} else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen();
} else if (document.msExitFullscreen) {
document.msExitFullscreen();
}else{
alert("Exit fullscreen doesn't work");
}
}
function resize() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
render();
}
window.addEventListener('resize', resize, false); resize();
function render() { // draw to screen here
}
https://jsfiddle.net/jy8k6hfd/2/
it's simple, set canvas width and height to screen.width and screen.height. then press F11! think F11 should make full screen in most browsers does in FFox and IE.
Well, I was looking to make my canvas fullscreen too, This is how i did it. I'll post the entire index.html since I am not a CSS expert yet : (basically just using position:fixed and width and height as 100% and top and left as 0% and i nested this CSS code for every tag. I also have min-height and min-width as 100%. When I tried it with a 1px border the border size was changing as I zoomed in and out but the canvas remained fullscreen.)
<!DOCTYPE html>
<html style="position:fixed;min-height:100%;min-width:100%;height:100%;width:100%;top:0%;left:0%;resize:none;">
<head>
<title>MOUSEOVER</title>
<script "text/javascript" src="main.js"></script>
</head>
<body id="BODY_CONTAINER" style="position:fixed;min-height:100%;min-width:100%;height:100%;width:100%;top:0%;left:0%;resize:none;">
<div id="DIV_GUI_CONTAINER" style="position:fixed;min-height:100%;min-width:100%;height:100%;width:100%;top:0%;left:0%;resize:none;">
<canvas id="myCanvas" style="position:fixed;min-height:100%;min-width:100%;height:100%;width:100%;top:0%;left:0%;resize:none;">
</canvas>
</div>
</body>
</html>
EDIT:
add this to the canvas element:
<canvas id="myCanvas" width="" height="" style="position:fixed;min-height:100%;min-width:100%;height:100%;width:100%;top:0%;left:0%;resize:none;">
</canvas>
add this to the javascript
canvas.width = window.screen.width;
canvas.height = window.screen.height;
I found this made the drawing a lot smoother than my original comment.
Thanks.
AFAIK, HTML5 does not provide an API which supports full screen.
This question has some view points on making html5 video full screen for example using webkitEnterFullscreen in webkit.
Is there a way to make html5 video fullscreen
You could just capture window resize events and set the size of your canvas to be the browser's viewport.
Get the full width and height of the screen and create a new window set to the appropriate width and height, and with everything disabled. Create a canvas inside of that new window, setting the width and height of the canvas to the width - 10px and the height - 20px (to allow for the bar and the edges of the window). Then work your magic on that canvas.
Related
I'm trying to limit boundaries and I'm running into issues. I'm upscaling an image from another canvas and then implementing zoom and pan. My issue (code below) is with limiting/capping the offsetx/y so that you never see the whitespace; only parts of the image.
Pardon the mess! Any help is appreciated! :P
var zoomIntensity = 0.2;
var canvas = document.getElementById("canvas");
var canvas2 = document.getElementById("canvas2");
var context = canvas.getContext("2d");
var context2 = canvas2.getContext("2d");
var width = 200;
var height = 200;
var scale = 1;
var originx = 0;
var originy = 0;
var offset = {x:0, y:0};
//fill smaller canvas with random pixels
for(var x = 0; x < 100; x++)
for(var y = 0; y < 100; y++)
{
var rando = function(){return Math.floor(Math.random() * 9)};
var val = rando();
context2.fillStyle = "#" + val + val + val;
context2.fillRect(x,y,1,1);
}
//draw the larger canvas
function draw()
{
context.imageSmoothingEnabled = false;
// Clear screen to white.
context.fillStyle = "white";
context.fillRect(originx - offset.x, originy - offset.y, width/scale, height/scale);
context.drawImage(canvas2, 0,0, width, height);
}
// Draw loop at 60FPS.
setInterval(draw, 1000/60);
canvas.onmousewheel = function (event){
event.preventDefault();
// Get mouse offset.
var mousex = event.clientX - canvas.offsetLeft;
var mousey = event.clientY - canvas.offsetTop;
// Normalize wheel to +1 or -1.
var wheel = event.wheelDelta/120;
// Compute zoom factor.
var zoom = Math.exp(wheel*zoomIntensity);
// Translate so the visible origin is at the context's origin.
context.translate(originx - offset.x, originy - offset.y); //offset is panning
//make sure we don't zoom out further than normal scale
var resultingScale = scale * zoom;
if(resultingScale < 1)
zoom = 1/scale;
// Compute the new visible origin. Originally the mouse is at a
// distance mouse/scale from the corner, we want the point under
// the mouse to remain in the same place after the zoom, but this
// is at mouse/new_scale away from the corner. Therefore we need to
// shift the origin (coordinates of the corner) to account for this.
originx -= mousex/(scale*zoom) - mousex/scale;
originy -= mousey/(scale*zoom) - mousey/scale;
// Scale it (centered around the origin due to the trasnslate above).
context.scale(zoom, zoom);
// Offset the visible origin to it's proper position.
context.translate(-originx + offset.x, -originy + offset.y); //offset is panning
// Update scale and others.
scale *= zoom;
}
document.onkeydown = function (evt)
{
var offsetx = 0;
var offsety = 0;
switch(evt.which)
{
case 37: //left
offsetx = 1;
break;
case 38: //up
offsety = 1;
break;
case 39: //right
offsetx = -1
break;
case 40: //down
offsety = -1;
break;
}
offsetx /= scale;
offsety /= scale;
offset.x += offsetx;
offset.y += offsety;
context.translate(offsetx,offsety);
}
<canvas id="canvas" width="200" height="200"></canvas>
<canvas id="canvas2" width="100" height="100"></canvas>
Using transformation matrix to constrain a view
To constrain the position you need to transform the corner coordinates of the image to screen coordinates. As getting the transform is still not standard across browsers the demo below holds a copy of the transform.
The object view holds the canvas view. When you use the function view.setBounds(top,left,right,bottom); the view will be locked to that area (the image you are viewing 0,0,100,100)
The scale and position (origin) will be constrained to keep the bounds outside or one the edge of the canvas context set by view.setContext(context).
The function scaleAt(pos,amount); will scale at a specified pos (eg mouse position)
To set the transform use view.apply() this will update the view transform and set the context transform.
The are a few other functions that may prove handy see code.
Demo uses mouse click drag to pan and wheel to zoom.
Demo is a copy of the OP's example width modifications to answer question.
// use requestAnimationFrame when doing any form of animation via javascript
requestAnimationFrame(draw);
var zoomIntensity = 0.2;
var canvas = document.getElementById("canvas");
var canvas2 = document.getElementById("canvas2");
var context = canvas.getContext("2d");
var context2 = canvas2.getContext("2d");
var width = 200;
var height = 200;
context.font = "24px arial";
context.textAlign = "center";
context.lineJoin = "round"; // to prevent miter spurs on strokeText
//fill smaller canvas with random pixels
for(var x = 0; x < 100; x++){
for(var y = 0; y < 100; y++) {
var rando = function(){return Math.floor(Math.random() * 9)};
var val = rando();
if(x === 0 || y === 0 || x === 99 || y === 99){
context2.fillStyle = "#FF0000";
}else{
context2.fillStyle = "#" + val + val + val;
}
context2.fillRect(x,y,1,1);
}
}
// mouse holds mouse position button state, and if mouse over canvas with overid
var mouse = {
pos : {x : 0, y : 0},
worldPos : {x : 0, y : 0},
posLast : {x : 0, y : 0},
button : false,
overId : "", // id of element mouse is over
dragging : false,
whichWheel : -1, // first wheel event will get the wheel
wheel : 0,
}
// View handles zoom and pan (can also handle rotate but have taken that out as rotate can not be contrained without losing some of the image or seeing some of the background.
const view = (()=>{
const matrix = [1,0,0,1,0,0]; // current view transform
const invMatrix = [1,0,0,1,0,0]; // current inverse view transform
var m = matrix; // alias
var im = invMatrix; // alias
var scale = 1; // current scale
const bounds = {
topLeft : 0,
left : 0,
right : 200,
bottom : 200,
}
var useConstraint = true; // if true then limit pan and zoom to
// keep bounds within the current context
var maxScale = 1;
const workPoint1 = {x :0, y : 0};
const workPoint2 = {x :0, y : 0};
const wp1 = workPoint1; // alias
const wp2 = workPoint2; // alias
var ctx;
const pos = { // current position of origin
x : 0,
y : 0,
}
var dirty = true;
const API = {
canvasDefault () { ctx.setTransform(1,0,0,1,0,0) },
apply(){
if(dirty){ this.update() }
ctx.setTransform(m[0],m[1],m[2],m[3],m[4],m[5]);
},
getScale () { return scale },
getMaxScale () { return maxScale },
matrix, // expose the matrix
invMatrix, // expose the inverse matrix
update(){ // call to update transforms
dirty = false;
m[3] = m[0] = scale;
m[1] = m[2] = 0;
m[4] = pos.x;
m[5] = pos.y;
if(useConstraint){
this.constrain();
}
this.invScale = 1 / scale;
// calculate the inverse transformation
var cross = m[0] * m[3] - m[1] * m[2];
im[0] = m[3] / cross;
im[1] = -m[1] / cross;
im[2] = -m[2] / cross;
im[3] = m[0] / cross;
},
constrain(){
maxScale = Math.min(
ctx.canvas.width / (bounds.right - bounds.left) ,
ctx.canvas.height / (bounds.bottom - bounds.top)
);
if (scale < maxScale) { m[0] = m[3] = scale = maxScale }
wp1.x = bounds.left;
wp1.y = bounds.top;
this.toScreen(wp1,wp2);
if (wp2.x > 0) { m[4] = pos.x -= wp2.x }
if (wp2.y > 0) { m[5] = pos.y -= wp2.y }
wp1.x = bounds.right;
wp1.y = bounds.bottom;
this.toScreen(wp1,wp2);
if (wp2.x < ctx.canvas.width) { m[4] = (pos.x -= wp2.x - ctx.canvas.width) }
if (wp2.y < ctx.canvas.height) { m[5] = (pos.y -= wp2.y - ctx.canvas.height) }
},
toWorld(from,point = {}){ // convert screen to world coords
var xx, yy;
if(dirty){ this.update() }
xx = from.x - m[4];
yy = from.y - m[5];
point.x = xx * im[0] + yy * im[2];
point.y = xx * im[1] + yy * im[3];
return point;
},
toScreen(from,point = {}){ // convert world coords to screen coords
if(dirty){ this.update() }
point.x = from.x * m[0] + from.y * m[2] + m[4];
point.y = from.x * m[1] + from.y * m[3] + m[5];
return point;
},
scaleAt(at, amount){ // at in screen coords
if(dirty){ this.update() }
scale *= amount;
pos.x = at.x - (at.x - pos.x) * amount;
pos.y = at.y - (at.y - pos.y) * amount;
dirty = true;
},
move(x,y){ // move is in screen coords
pos.x += x;
pos.y += y;
dirty = true;
},
setContext(context){
ctx = context;
dirty = true;
},
setBounds(top,left,right,bottom){
bounds.top = top;
bounds.left = left;
bounds.right = right;
bounds.bottom = bottom;
useConstraint = true;
dirty = true;
}
};
return API;
})();
view.setBounds(0,0,canvas2.width,canvas2.height);
view.setContext(context);
//draw the larger canvas
function draw(){
view.canvasDefault(); // se default transform to clear screen
context.imageSmoothingEnabled = false;
context.fillStyle = "white";
context.fillRect(0, 0, width, height);
view.apply(); // set the current view
context.drawImage(canvas2, 0,0);
view.canvasDefault();
if(view.getScale() === view.getMaxScale()){
context.fillStyle = "black";
context.strokeStyle = "white";
context.lineWidth = 2.5;
context.strokeText("Max scale.",context.canvas.width / 2,24);
context.fillText("Max scale.",context.canvas.width / 2,24);
}
requestAnimationFrame(draw);
if(mouse.overId === "canvas"){
canvas.style.cursor = mouse.button ? "none" : "move";
}else{
canvas.style.cursor = "default";
}
}
// add events to document so that mouse is captured when down on canvas
// This allows the mouseup event to be heard no matter where the mouse has
// moved to.
"mousemove,mousedown,mouseup,mousewheel,wheel,DOMMouseScroll".split(",")
.forEach(eventName=>document.addEventListener(eventName,mouseEvent));
function mouseEvent (event){
mouse.overId = event.target.id;
if(event.target.id === "canvas" || mouse.dragging){ // only interested in canvas mouse events including drag event started on the canvas.
mouse.posLast.x = mouse.pos.x;
mouse.posLast.y = mouse.pos.y;
mouse.pos.x = event.clientX - canvas.offsetLeft;
mouse.pos.y = event.clientY - canvas.offsetTop;
view.toWorld(mouse.pos, mouse.worldPos); // gets the world coords (where on canvas 2 the mouse is)
if (event.type === "mousemove"){
if(mouse.button){
view.move(
mouse.pos.x - mouse.posLast.x,
mouse.pos.y - mouse.posLast.y
)
}
} else if (event.type === "mousedown") { mouse.button = true; mouse.dragging = true }
else if (event.type === "mouseup") { mouse.button = false; mouse.dragging = false }
else if(event.type === "mousewheel" && (mouse.whichWheel === 1 || mouse.whichWheel === -1)){
mouse.whichWheel = 1;
mouse.wheel = event.wheelDelta;
}else if(event.type === "wheel" && (mouse.whichWheel === 2 || mouse.whichWheel === -1)){
mouse.whichWheel = 2;
mouse.wheel = -event.deltaY;
}else if(event.type === "DOMMouseScroll" && (mouse.whichWheel === 3 || mouse.whichWheel === -1)){
mouse.whichWheel = 3;
mouse.wheel = -event.detail;
}
if(mouse.wheel !== 0){
event.preventDefault();
view.scaleAt(mouse.pos, Math.exp((mouse.wheel / 120) *zoomIntensity));
mouse.wheel = 0;
}
}
}
div { user-select: none;} /* mouse prevent drag selecting content */
canvas { border:2px solid black;}
<div>
<canvas id="canvas" width="200" height="200"></canvas>
<canvas id="canvas2" width="100" height="100"></canvas>
<p>Mouse wheel to zoom. Mouse click drag to pan.</p>
<p>Zoomed image constrained to canvas</p>
</div>
I am super stuck on this, what i have done so far is I created function that creates random sized rectanges, which appears in a random place of the canvas. What i need to do is using JS draw Rectangle whenever I create new one, it can't collide with existing ones.
<!DOCTYPE html>
<html>
<head>
<title>rectangles sucks</title>
</head>
<body>
<button id="buttonxD">press me!</button>
<script>
var body = document.getElementsByTagName("body")[0];
var canvas = document.createElement("canvas");
canvas.height = 500;
canvas.width = 500;
var context = canvas.getContext("2d");
body.appendChild(canvas);
function create() {
// Opacity
context.globalAlpha=0.7;
var color = '#'+ Math.round(0xffffff * Math.random()).toString(16);
context.fillStyle = color;
//Each rectangle's size is (20 ~ 100, 20 ~ 100)
context.fillRect(Math.random()*canvas.width, Math.random()*canvas.width, Math.random()*80+20, Math.random()*80+20);
}
document.getElementById('buttonxD').addEventListener('click', create);
</script>
</body>
</html>
I seen that this function is used to check collision detection
function isCollide(a, b) {
return !(
((a.y + a.height) < (b.y)) ||
(a.y > (b.y + b.height)) ||
((a.x + a.width) < b.x) ||
(a.x > (b.x + b.width))
);
}
But I failing to integrate it to my code...
Any ideas what I should do differently with my existing code, anything will help, thanks!
You need a way to keep the coords from the existing rectangles. So you can check against that list if your new rectangle does not collide with one of them.
<!DOCTYPE html>
<html>
<head>
<title>rectangles sucks</title>
</head>
<body>
<button id="buttonxD">press me!</button>
<script>
var body = document.getElementsByTagName("body")[0];
var canvas = document.createElement("canvas");
canvas.height = 500;
canvas.width = 500;
var context = canvas.getContext("2d");
body.appendChild(canvas);
var rects = [];
function create() {
// Opacity
context.globalAlpha = 0.7;
var color = '#' + Math.round(0xffffff * Math.random()).toString(16);
context.fillStyle = color;
//Each rectangle's size is (20 ~ 100, 20 ~ 100)
var coordx = Math.random() * canvas.width;
var coordy = Math.random() * canvas.width;
var width = Math.random() * 80 + 20;
var height = Math.random() * 80 + 20;
var rect = {
x: coordx,
y: coordy,
w: width,
h: height
}
var ok = true;
rects.forEach(function (item) {
if (isCollide(rect, item)) {
console.log("collide");
ok = false;
} else {
console.log("no collision");
}
})
if (ok) {
context.fillRect(coordx, coordy, width, height);
rects.push(rect);
} else {
console.log('rect dropped');
}
console.log(rects);
}
function isCollide(a, b) {
return !(
((a.y + a.h) < (b.y)) ||
(a.y > (b.y + b.h)) ||
((a.x + a.w) < b.x) ||
(a.x > (b.x + b.w))
);
}
document.getElementById('buttonxD').addEventListener('click', create);
</script>
</body>
</html>
This only creates a rectangle if it does not collide.
Reproduction: focus your mouse on canvas , then spin your mouse in circles for ~15 sec. At first you'll notice how things are smooth. After some time it starts to lose its smoothness and becomes really laggy.
Part of the js function came from the following answer
Make moving Rect more smooth
var canvas = document.getElementById('canvas');
var ctx = document.getElementById('canvas').getContext('2d');
var x;
var y;
var tx = tx || 0;
var ty = ty || 0;
var xDir;
var yDir;
function followMouse(e) {
x = e.offsetX;
y = e.offsetY;
moveObject();
}
function moveObject() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
var scale = 0.2 * Math.max(canvas.width, canvas.height);
xDir = 0;
yDir = 0;
xDir = (x - tx) / scale;
yDir = (y - ty) / scale;
tx = tx != x ? tx + xDir : tx;
ty = ty != y ? ty + yDir : ty;
ctx.fillRect(tx - 25, ty + 25, 50, 10);
if (tx != x || ty != y) {
window.requestAnimationFrame(moveObject);
}
}
function resizeCanvas() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
};
canvas.addEventListener('mousemove', _.throttle(function(e) {
followMouse(e);
}, 30));
window.addEventListener('resize', resizeCanvas, false);
resizeCanvas();
html,
body {
margin: 0;
height: 100%;
}
canvas {
display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<canvas id="canvas"></canvas>
This happens as for each mousemove a new loop is started. These loops will accumulate and eventually slow things down.
To solve you can implement cancelAnimationFrame() by doing:
...
var timer;
function followMouse(e) {
x = e.offsetX;
y = e.offsetY;
cancelAnimationFrame(timer);
moveObject();
}
Then store timer reference in the main loop:
...
timer = requestAnimationFrame(moveObject);
This will abort the current request for frame update and allow you to start a new loop without accumulating calls.
For this reason you would also have to initialize x and y since they are not initialized otherwise until the mouse has been moved (which is of course no guarantee).
var x = 0;
var y = 0;
Note: A side-effect of this correction is that now the movement is only calculated once per frame. When accumulated the movement got calculated many times per frame. To compensate adjust the scale to a lower value (shown below).
Modified example
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var x = 0;
var y = 0;
var tx = tx || 0;
var ty = ty || 0;
var xDir;
var yDir;
var timer;
function followMouse(e) {
x = e.clientX;
y = e.clientY;
cancelAnimationFrame(timer);
moveObject();
}
function moveObject() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
var scale = 0.02 * Math.max(canvas.width, canvas.height);
xDir = 0;
yDir = 0;
xDir = (x - tx) / scale;
yDir = (y - ty) / scale;
tx = tx != x ? tx + xDir : tx;
ty = ty != y ? ty + yDir : ty;
ctx.fillRect(tx - 25, ty + 25, 50, 10);
if (tx != x || ty != y) {
timer = requestAnimationFrame(moveObject);
}
}
function resizeCanvas() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
};
canvas.addEventListener('mousemove', _.throttle(function(e) {
followMouse(e);
}, 30));
window.addEventListener('resize', resizeCanvas, false);
resizeCanvas();
html,
body {
margin: 0;
height: 100%;
}
canvas {
display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<canvas id="canvas"></canvas>
I've a nice bit of JS that creates falling confetti using the HTML canvas -- but it only starts drawing if you resize the browser:
http://jsfiddle.net/JohnnyWalkerDesign/pmfgexfL/
Before resize:
After resize:
Why is this?
Your canvas width is only set inside the resizeWindow(); function.
Try adding resizeWindow(); directly after the function definition:
resizeWindow = function() {
window.w = canvas.width = window.innerWidth;
return window.h = canvas.height = window.innerHeight;
};
resizeWindow();
otherwise it doesn't get called until the page is resized.
http://jsfiddle.net/pmfgexfL/3/
Your window.onload won't get called because it is inside confetti().
EDIT: As fuyushimoya pointed out, also remove the window.w = 0; and window.h = 0; lines since they're not required. I think that it is actually cleaner to set the size in a function on resize (as you do) in case you want to do something more custom, but you need to call it to initialize too.
http://jsfiddle.net/pmfgexfL/5/
At initialization, you have:
canvas = document.getElementById("world");
context = canvas.getContext("2d");
window.w = 0;
window.h = 0;
which makes w and h for cofettis becomes (0, 0). It cause your Confetti.prototype.replace to have useless xmax and ymax:
Confetti.prototype.replace = function() {
this.opacity = 0;
this.dop = 0.03 * range(1, 4);
this.x = range(-this.r2, w - this.r2);
this.y = range(-20, h - this.r2);
this.xmax = w - this.r; // -2 ~ -6
this.ymax = h - this.r; // -2 ~ -6
this.vx = range(0, 2) + 8 * xpos - 5;
return this.vy = 0.7 * this.r + range(-1, 1);
};
These makes its draw function unable to draw something properly, as x and y would be invalid when x or y is greater that 0.
Change it to
canvas = document.getElementById("world");
context = canvas.getContext("2d");
// Init the width and height of the canvas, and the global w and h.
window.w = canvas.width = window.innerWidth;
window.h = canvas.height = window.innerHeight;
See Altered Jsfiddle.
So Im trying to activate videos when they scroll into the viewport and just calling their different IDs but its not working, admittedly I am very new to this (js/jquery) and am not 100% about whats going on so any help would be great.
Just to be clear Im trying to get each video to play separately whenever they are scrolled into view, I have the 1st video working but none of the other subsequent videos play when scrolled over.
I created this to help with seeing what Im trying to accomplish http://jsfiddle.net/8TpN5/
Update: Ok so this is how I want it to work http://jsfiddle.net/8TpN5/1/ but how could I get it to work and not repeat the code?
var videoId = document.getElementById("video","videoTwo");
var playVideo = videoId,
fraction = 0.9;
function checkScroll() {
var x = playVideo.offsetLeft,
y = playVideo.offsetTop,
w = playVideo.offsetWidth,
h = playVideo.offsetHeight,
r = x + w, //right
b = y + h, //bottom
visibleX,
visibleY,
visible;
if (window.pageXOffset >= r || window.pageYOffset >= b || window.pageXOffset + window.innerWidth < x || window.pageYOffset + window.innerHeight < y) {
return;
}
visibleX = Math.max(0, Math.min(w, window.pageXOffset + window.innerWidth - x, r - window.pageXOffset));
visibleY = Math.max(0, Math.min(h, window.pageYOffset + window.innerHeight - y, b - window.pageYOffset));
visible = visibleX * visibleY / (w * h);
if (visible > fraction) {
playVideo.play();
} else {
playVideo.pause();
}
}
checkScroll();
window.addEventListener('scroll', checkScroll, false);
window.addEventListener('resize', checkScroll, false);
This line:
var videoId = document.getElementById("video","videoTwo");
Should be:
var videoOne = document.getElementById("video"),
videoTwo = document.getElementById("videoTwo");
getElementById only takes one id as parameter and returns one object.
just change the getElementById to getElementsByTagName.
Hope this helps:
http://jsfiddle.net/jAsDJ/
var videos = document.getElementsByTagName("video"),
fraction = 0.8;
function checkScroll() {
for(var i = 0; i < videos.length; i++) {
var video = videos[i];
var x = video.offsetLeft, y = video.offsetTop, w = video.offsetWidth, h = video.offsetHeight, r = x + w, //right
b = y + h, //bottom
visibleX, visibleY, visible;
visibleX = Math.max(0, Math.min(w, window.pageXOffset + window.innerWidth - x, r - window.pageXOffset));
visibleY = Math.max(0, Math.min(h, window.pageYOffset + window.innerHeight - y, b - window.pageYOffset));
visible = visibleX * visibleY / (w * h);
if (visible > fraction) {
video.play();
} else {
video.pause();
}
}
}
window.addEventListener('scroll', checkScroll, false);
window.addEventListener('resize', checkScroll, false);