I'm trying to make this raindrop canvas script take up 100% width and height, but nothing I seem to do works. I tried changing the CSS, and height/width in the Canvas area, but it either doesn't change anything, or it makes it not work at all. The one time I tried something that actually made it full size, it seemed to have a weird effect on the raindrops, they became all blurry and much larger, so it must have actually stretched the canvas instead of making it larger. Here's the code for the default 800x800 pixel canvas.
Style
<style>
article, aside, figure, footer, header, hgroup,
menu, nav, section { display: block; }
</style>
Script for canvas
<script type="text/javascript">
var canvas = null;
var context = null;
var bufferCanvas = null;
var bufferCanvasCtx = null;
var flakeArray = [];
var flakeTimer = null;
var maxFlakes = 200; // Here you may set max flackes to be created
function init() {
canvas = document.getElementById('canvasRain');
context = canvas.getContext("2d");
bufferCanvas = document.createElement("canvas");
bufferCanvasCtx = bufferCanvas.getContext("2d");
bufferCanvasCtx.canvas.width = context.canvas.width;
bufferCanvasCtx.canvas.height = context.canvas.height;
flakeTimer = setInterval(addFlake, 200);
Draw();
setInterval(animate, 30);
}
function animate() {
Update();
Draw();
}
function addFlake() {
flakeArray[flakeArray.length] = new Flake();
if (flakeArray.length == maxFlakes)
clearInterval(flakeTimer);
}
function blank() {
bufferCanvasCtx.fillStyle = "rgba(0,0,0,0.8)";
bufferCanvasCtx.fillRect(0, 0, bufferCanvasCtx.canvas.width, bufferCanvasCtx.canvas.height);
}
function Update() {
for (var i = 0; i < flakeArray.length; i++) {
if (flakeArray[i].y < context.canvas.height) {
flakeArray[i].y += flakeArray[i].speed;
if (flakeArray[i].y > context.canvas.height)
flakeArray[i].y = -5;
flakeArray[i].x += flakeArray[i].drift;
if (flakeArray[i].x > context.canvas.width)
flakeArray[i].x = 0;
}
}
}
function Flake() {
this.x = Math.round(Math.random() * context.canvas.width);
this.y = -10;
this.drift = Math.random();
this.speed = Math.round(Math.random() * 5) + 1;
this.width = (Math.random() * 3) + 2;
this.height = this.width;
}
function Draw() {
context.save();
blank();
for (var i = 0; i < flakeArray.length; i++) {
bufferCanvasCtx.fillStyle = "white";
bufferCanvasCtx.fillRect(flakeArray[i].x, flakeArray[i].y, flakeArray[i].width, flakeArray[i].height);
}
context.drawImage(bufferCanvas, 0, 0, bufferCanvas.width, bufferCanvas.height);
context.restore();
}
</script>
And finally here's the body
<body onload="init()">
<canvas id="canvasRain" width="800px" height="800px">Canvas Not Supported</canvas>
</body>
body, #canvasRain {width:100%; height:100%; margin:0px;} will set your size properly but your problem is that your canvas height/width you're using to do your drawing doesn't pick up the proper px values when setting them with %'s. And that's where the scaling comes in with the fuzzy flakes. It takes some default canvas size and stretches to 100% of the view. Adding something like
bufferCanvas.width = canvas.width = window.innerWidth;
bufferCanvas.height = canvas.height = window.innerHeight;
seems to do the trick. And you might want/need to handle resize events to recalculate it. Here is a sample. I couldn't get jsFiddle to work for me, so it's just the whole thing.
I've set up a fiddle that shows how to resize the canvas using some simple CSS.
http://jsfiddle.net/C7LfU/1/
$('#canvasRain').css({
"height": window.innerHeight,
"width": window.innerWidth
});
I've also went ahead and updated your animation to use requestAnimationFrame. This probably what caused your Flakes to be fuzzy: The animation lagged since setTimeout doesn't scale to when the browser is actually ready to draw another frame.
window.requestAnimFrame = (function () {
return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function (callback) {
window.setTimeout(callback, 1000 / 60);
};
})();
function animate() {
requestAnimFrame(animate);
Update();
Draw();
}
Read a little more about why you should use requestAnimationFrame at: http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/
Related
Running into an interesting canvas bug: after translating a canvas, the pixels appear blurry on Safari but not Chrome.
I've tried just about every image-rendering and imageSmoothing trick to no avail.
Here's a codepen where I've been able to reproduce the issue: https://codepen.io/plillian/pen/RwQegyR
Is this a just Safari bug? Or is there a way to force nearest neighbor in Safari as well?
Yes this is a Safari bug, you may want to let them know about it. For what it's worth, it's still an issue in the latest Technology Preview (Safari 15.4, WebKit 17614.1.14.10.6) where it's not even able to render every frame on time and will just "blink".
As for a workaround, the only one I can think of would be to do this all on the canvas directly, you can easily make this resizing of an ImageData by first converting it to an ImageBitmap and use drawImage().
Though to implement the scrolling behavior we'll have a bit of work to do.
One way is to use a placeholder <div> and make it act as-if we did transform our <canvas>. This way we can still use the native scrolling behavior and simply update the arguments to drawImage().
We then can stick the canvas on the top left corner of the viewport, and set it to the size of the viewport, overcoming the issue of possibly having a too big canvas.
(async () => {
const SIZE = 1024;
const X = -208.97398878415459;
const Y = 47.03519866364394;
const scale = 80;
const viewport = document.getElementById('viewport');
const wrapper = document.getElementById('wrapper');
const placeholder = document.getElementById('placeholder');
const canvas = document.getElementById('cvs');
placeholder.style.width = SIZE + 'px';
placeholder.style.height = SIZE + 'px';
const c = canvas.getContext('2d');
const pixels = new Uint8ClampedArray(4 * SIZE * SIZE);
for (let xi = 0; xi < SIZE; xi++) {
for (let yi = 0; yi < SIZE; yi++) {
const idx = (xi + yi * SIZE) * 4;
pixels[idx] = (xi << 6) % 255;
pixels[idx + 1] = (yi << 6) % 255;
pixels[idx + 3] = 255;
}
}
const pixelData = new ImageData(pixels, SIZE, SIZE);
// Convert to an ImageBitmap for ease of resizing and cropping
const bmp = await createImageBitmap(pixelData);
// We resize the canvas bitmap based on the size of the viewport
// While respecting the actual dPR (gimme crisp pixels!)
// Thanks to gman for the reminder of how to suppport all early impl.
// https://stackoverflow.com/a/65435847/3702797
const observer = new ResizeObserver(([entry]) => {
let width;
let height;
const dPR = devicePixelRatio;
if (entry.devicePixelContentBoxSize) {
width = entry.devicePixelContentBoxSize[0].inlineSize;
height = entry.devicePixelContentBoxSize[0].blockSize;
} else if (entry.contentBoxSize) {
if ( entry.contentBoxSize[0]) {
width = entry.contentBoxSize[0].inlineSize * dPR;
height = entry.contentBoxSize[0].blockSize * dPR;
} else {
width = entry.contentBoxSize.inlineSize * dPR;
height = entry.contentBoxSize.blockSize * dPR;
}
} else {
width = entry.contentRect.width * dPR;
height = entry.contentRect.height * dPR;
}
canvas.width = width;
canvas.height = height;
canvas.style.width = (width / dPR) + 'px';
canvas.style.height = (height / dPR) + 'px';
c.scale(dPR, dPR);
c.imageSmoothingEnabled = false;
});
// observe the scrollbox size changes
try {
observer.observe(viewport, { box: 'device-pixel-content-box' });
}
catch(err) {
observer.observe(viewport, { box: 'content-box' });
}
function getDrawImageArgs(nodetranslate) {
const { width, height } = canvas;
const { scrollLeft, scrollTop } = viewport;
const mat = new DOMMatrix(nodetranslate).inverse();
const source = mat.transformPoint({ x: scrollLeft, y: scrollTop });
const sourceWidth = canvas.width;
const sourceHeight = canvas.height;
return [source.x, source.y, sourceWidth, sourceHeight, 0, 0, canvas.width * scale, canvas.height * scale];
}
function animate() {
const nodetranslate = `translate3D(${X}px, ${Y}px, 0px) scale(${scale})`;
wrapper.style.transform = nodetranslate;
c.clearRect(0, 0, canvas.width, canvas.height);
c.drawImage(bmp, ...getDrawImageArgs(nodetranslate));
requestAnimationFrame(animate);
}
animate();
})().catch(console.error)
body { margin: 0 }
#viewport {
position: absolute;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
overflow: auto;
}
.sticker {
position: sticky;
top: 0;
left: 0;
height: 0px;
width: 0px;
overflow: visible;
line-height: 0;
z-index: 1;
}
canvas {
position: absolute;
}
#wrapper {
transform-origin: 0 0;
position: absolute;
}
#placeholder {
display: inline-block;
}
<script>
// Because Safari wouldn't be Safari without all its little bugs...
// See https://stackoverflow.com/a/35503829/3702797
(()=>{if(function(){const e=document.createElement("canvas").getContext("2d");e.fillRect(0,0,40,40),e.drawImage(e.canvas,-40,-40,80,80,50,50,20,20);var a=e.getImageData(50,50,30,30),r=new Uint32Array(a.data.buffer),n=(e,t)=>r[t*a.width+e];return[[9,9],[20,9],[9,20],[20,20]].some(([e,t])=>0!==n(e,t))||[[10,10],[19,10],[10,19],[19,19]].some(([e,t])=>0===n(e,t))}()){const e=CanvasRenderingContext2D.prototype,i=e.drawImage;i?e.drawImage=function(e,t,a){if(!(9===arguments.length))return i.apply(this,[...arguments]);var r,n=function(e,t,a,r,n,i,o,h,m){var{width:s,height:d}=function(t){var e=e=>{e=globalThis[e];return e&&t instanceof e};{if(e("HTMLImageElement"))return{width:t.naturalWidth,height:t.naturalHeight};if(e("HTMLVideoElement"))return{width:t.videoWidth,height:t.videoHeight};if(e("SVGImageElement"))throw new TypeError("SVGImageElement isn't yet supported as source image.","UnsupportedError");return e("HTMLCanvasElement")||e("ImageBitmap")?t:void 0}}(e);r<0&&(t+=r,r=Math.abs(r));n<0&&(a+=n,n=Math.abs(n));h<0&&(i+=h,h=Math.abs(h));m<0&&(o+=m,m=Math.abs(m));var g=Math.max(t,0),u=Math.min(t+r,s),s=Math.max(a,0),d=Math.min(a+n,d),r=h/r,n=m/n;return[e,g,s,u-g,d-s,t<0?i-t*r:i,a<0?o-a*n:o,(u-g)*r,(d-s)*n]}(...arguments);return r=n,[3,4,7,8].some(e=>!r[e])?void 0:i.apply(this,n)}:console.error("This script requires a basic implementation of drawImage")}})();
</script>
<div id="viewport">
<div class="sticker">
<!-- <canvas> isn't a void element, it must have a closing tag -->
<!-- We place it in a "sticky" element, outside of the one that gets transformed -->
<canvas id="cvs"></canvas>
</div>
<div id="wrapper">
<div id="placeholder"><!--
We'll use it as an easy way to measure what part of the canvas we should draw
based on the current scroll position.
--></div>
<div>
</div>
You can inspect the <canvas> element and see it's actually only as big as the viewport and not some 81920x81920px.
Running into an interesting canvas bug: after translating a canvas, the pixels appear blurry on Safari but not Chrome.
I've tried just about every image-rendering and imageSmoothing trick to no avail.
Here's a codepen where I've been able to reproduce the issue: https://codepen.io/plillian/pen/RwQegyR
Is this a just Safari bug? Or is there a way to force nearest neighbor in Safari as well?
Yes this is a Safari bug, you may want to let them know about it. For what it's worth, it's still an issue in the latest Technology Preview (Safari 15.4, WebKit 17614.1.14.10.6) where it's not even able to render every frame on time and will just "blink".
As for a workaround, the only one I can think of would be to do this all on the canvas directly, you can easily make this resizing of an ImageData by first converting it to an ImageBitmap and use drawImage().
Though to implement the scrolling behavior we'll have a bit of work to do.
One way is to use a placeholder <div> and make it act as-if we did transform our <canvas>. This way we can still use the native scrolling behavior and simply update the arguments to drawImage().
We then can stick the canvas on the top left corner of the viewport, and set it to the size of the viewport, overcoming the issue of possibly having a too big canvas.
(async () => {
const SIZE = 1024;
const X = -208.97398878415459;
const Y = 47.03519866364394;
const scale = 80;
const viewport = document.getElementById('viewport');
const wrapper = document.getElementById('wrapper');
const placeholder = document.getElementById('placeholder');
const canvas = document.getElementById('cvs');
placeholder.style.width = SIZE + 'px';
placeholder.style.height = SIZE + 'px';
const c = canvas.getContext('2d');
const pixels = new Uint8ClampedArray(4 * SIZE * SIZE);
for (let xi = 0; xi < SIZE; xi++) {
for (let yi = 0; yi < SIZE; yi++) {
const idx = (xi + yi * SIZE) * 4;
pixels[idx] = (xi << 6) % 255;
pixels[idx + 1] = (yi << 6) % 255;
pixels[idx + 3] = 255;
}
}
const pixelData = new ImageData(pixels, SIZE, SIZE);
// Convert to an ImageBitmap for ease of resizing and cropping
const bmp = await createImageBitmap(pixelData);
// We resize the canvas bitmap based on the size of the viewport
// While respecting the actual dPR (gimme crisp pixels!)
// Thanks to gman for the reminder of how to suppport all early impl.
// https://stackoverflow.com/a/65435847/3702797
const observer = new ResizeObserver(([entry]) => {
let width;
let height;
const dPR = devicePixelRatio;
if (entry.devicePixelContentBoxSize) {
width = entry.devicePixelContentBoxSize[0].inlineSize;
height = entry.devicePixelContentBoxSize[0].blockSize;
} else if (entry.contentBoxSize) {
if ( entry.contentBoxSize[0]) {
width = entry.contentBoxSize[0].inlineSize * dPR;
height = entry.contentBoxSize[0].blockSize * dPR;
} else {
width = entry.contentBoxSize.inlineSize * dPR;
height = entry.contentBoxSize.blockSize * dPR;
}
} else {
width = entry.contentRect.width * dPR;
height = entry.contentRect.height * dPR;
}
canvas.width = width;
canvas.height = height;
canvas.style.width = (width / dPR) + 'px';
canvas.style.height = (height / dPR) + 'px';
c.scale(dPR, dPR);
c.imageSmoothingEnabled = false;
});
// observe the scrollbox size changes
try {
observer.observe(viewport, { box: 'device-pixel-content-box' });
}
catch(err) {
observer.observe(viewport, { box: 'content-box' });
}
function getDrawImageArgs(nodetranslate) {
const { width, height } = canvas;
const { scrollLeft, scrollTop } = viewport;
const mat = new DOMMatrix(nodetranslate).inverse();
const source = mat.transformPoint({ x: scrollLeft, y: scrollTop });
const sourceWidth = canvas.width;
const sourceHeight = canvas.height;
return [source.x, source.y, sourceWidth, sourceHeight, 0, 0, canvas.width * scale, canvas.height * scale];
}
function animate() {
const nodetranslate = `translate3D(${X}px, ${Y}px, 0px) scale(${scale})`;
wrapper.style.transform = nodetranslate;
c.clearRect(0, 0, canvas.width, canvas.height);
c.drawImage(bmp, ...getDrawImageArgs(nodetranslate));
requestAnimationFrame(animate);
}
animate();
})().catch(console.error)
body { margin: 0 }
#viewport {
position: absolute;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
overflow: auto;
}
.sticker {
position: sticky;
top: 0;
left: 0;
height: 0px;
width: 0px;
overflow: visible;
line-height: 0;
z-index: 1;
}
canvas {
position: absolute;
}
#wrapper {
transform-origin: 0 0;
position: absolute;
}
#placeholder {
display: inline-block;
}
<script>
// Because Safari wouldn't be Safari without all its little bugs...
// See https://stackoverflow.com/a/35503829/3702797
(()=>{if(function(){const e=document.createElement("canvas").getContext("2d");e.fillRect(0,0,40,40),e.drawImage(e.canvas,-40,-40,80,80,50,50,20,20);var a=e.getImageData(50,50,30,30),r=new Uint32Array(a.data.buffer),n=(e,t)=>r[t*a.width+e];return[[9,9],[20,9],[9,20],[20,20]].some(([e,t])=>0!==n(e,t))||[[10,10],[19,10],[10,19],[19,19]].some(([e,t])=>0===n(e,t))}()){const e=CanvasRenderingContext2D.prototype,i=e.drawImage;i?e.drawImage=function(e,t,a){if(!(9===arguments.length))return i.apply(this,[...arguments]);var r,n=function(e,t,a,r,n,i,o,h,m){var{width:s,height:d}=function(t){var e=e=>{e=globalThis[e];return e&&t instanceof e};{if(e("HTMLImageElement"))return{width:t.naturalWidth,height:t.naturalHeight};if(e("HTMLVideoElement"))return{width:t.videoWidth,height:t.videoHeight};if(e("SVGImageElement"))throw new TypeError("SVGImageElement isn't yet supported as source image.","UnsupportedError");return e("HTMLCanvasElement")||e("ImageBitmap")?t:void 0}}(e);r<0&&(t+=r,r=Math.abs(r));n<0&&(a+=n,n=Math.abs(n));h<0&&(i+=h,h=Math.abs(h));m<0&&(o+=m,m=Math.abs(m));var g=Math.max(t,0),u=Math.min(t+r,s),s=Math.max(a,0),d=Math.min(a+n,d),r=h/r,n=m/n;return[e,g,s,u-g,d-s,t<0?i-t*r:i,a<0?o-a*n:o,(u-g)*r,(d-s)*n]}(...arguments);return r=n,[3,4,7,8].some(e=>!r[e])?void 0:i.apply(this,n)}:console.error("This script requires a basic implementation of drawImage")}})();
</script>
<div id="viewport">
<div class="sticker">
<!-- <canvas> isn't a void element, it must have a closing tag -->
<!-- We place it in a "sticky" element, outside of the one that gets transformed -->
<canvas id="cvs"></canvas>
</div>
<div id="wrapper">
<div id="placeholder"><!--
We'll use it as an easy way to measure what part of the canvas we should draw
based on the current scroll position.
--></div>
<div>
</div>
You can inspect the <canvas> element and see it's actually only as big as the viewport and not some 81920x81920px.
Main Issue:
l essentially want to figure the issue with my event listener as it is aligning with the canvas object, which is the image '', in the middle of the canvas however, the Y areas below it are still clickable and the X areas on the right of it are still clickable.
l would like to eliminate this issue, which l believe is being caused by my IF statement and the DRAWIMAGE conditions, in relation to my canvas. There is a reproducible demo, fullscreen/expand it to see.
Another issue:
Another thing to note, which would be much appreciated, is the canvas object not truly sticking in one position on the canvas when you resize the browser window. It simply moves off into a different direction even though it should be stuck in one area of the canvas no matter what size my browser's window is - meaning that the canvas object somehow needs to dynamically resize along with how my browser resize + the event listener needs to see it. Again this would be highly appreciated as l really want to understand the error of my logic as l might using the wrong coordinate system,i don't really know :/
var canvas = document.getElementById("c");
var ctx = canvas.getContext("2d");
var the_button = document.getElementById("the_button");
var the_background = document.getElementById("the_background");
var button_imageX = 600;
var button_imageY = 390;
window.onload = function() {
ctx.drawImage(the_background, 0, 0, canvas.width, canvas.height);
drawButton();
}
initialize();
function initialize() {
window.addEventListener('resize', resizeCanvas, false);
resizeCanvas();
}
function drawButton() {
/* l belive this is partly responsible aswell for the issue */
ctx.drawImage(the_button, button_imageX, canvas.height - button_imageY, 170, 100);
}
function redraw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(the_background, 0, 0, canvas.width, canvas.height);
drawButton();
}
function resizeCanvas() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
redraw();
}
the_button_function = (paramater1) => {
/* Problem lies here in the IF statement aswell, that's my guess */
if ((paramater1.x > (canvas.width - button_imageX)) && (paramater1.x < canvas.width) && (paramater1.y > (canvas.height - button_imageY)) && (paramater1.y < canvas.height)) {
alert("<Button>")
}
}
canvas.addEventListener('click', (e) => the_button_function(e));
html,
body {
width: 100%;
height: 100%;
margin: 0px;
border: 0;
overflow: hidden;
display: block;
}
<html>
<canvas id="c"></canvas>
<img style="display: none;" id="the_button" src="https://i.imgur.com/wO7Wc2w.png" />
<img style="display: none;" id="the_background" src="https://img.freepik.com/free-photo/hand-painted-watercolor-background-with-sky-clouds-shape_24972-1095.jpg?size=626&ext=jpg" />
</html>
To stop clicks responding to the right of and below the button, take into account the width and height of the button!
Fixing this, and knowing where the image was previously drawn on the canvas should fix the second issue. To debug the problem the snippet code below replaces
button_imageX with button_imageLeft - how many pixels from canvas left to draw the image.
button_imageY with button_imageBottom - how many pixels from canvas bottom to draw the top of the image. (This seemed to be how the posted code was positioning the button in the y direction.)
[image_bottonLeft and image_buttonBottom values were modified for seeing results on Stack Overflow.]
And introduced
button_offsetX - x position of where the left hand side of the button was last drawn
button_offsetY - y position of where the top of the button was last drawn
button_imageWidth and button_imageHeight values for button height and width, replacing hard coded values function drawButton.
var canvas = document.getElementById("c");
var ctx = canvas.getContext("2d");
var the_button = document.getElementById("the_button");
var the_background = document.getElementById("the_background");
var button_imageLeft = 100;
var button_imageBottom = 150;
var button_imageWidth = 170;
var button_imageHeight = 100;
var button_offsetX, button_offsetY;
window.onload = function() {
ctx.drawImage(the_background, 0, 0, canvas.width, canvas.height);
drawButton();
}
initialize();
function initialize() {
window.addEventListener('resize', resizeCanvas, false);
resizeCanvas();
}
function drawButton() {
button_offsetX = button_imageLeft;
button_offsetY = canvas.height - button_imageBottom;
ctx.drawImage(the_button, button_offsetX, button_offsetY, button_imageWidth, button_imageHeight);
}
function redraw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(the_background, 0, 0, canvas.width, canvas.height);
drawButton();
}
function resizeCanvas() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
redraw();
}
the_button_function = (event) => {
const {x,y} = event;
if( (x >= button_offsetX && x < (button_offsetX+button_imageWidth))
&& (y >= button_offsetY && y < (button_offsetY+button_imageHeight))) {
alert("<Button>")
}
}
canvas.addEventListener('click', (e) => the_button_function(e));
html,
body {
width: 100%;
height: 100%;
margin: 0px;
border: 0;
overflow: hidden;
display: block;
}
<canvas id="c"></canvas>
<img style="display: none;" id="the_button" src="https://i.imgur.com/wO7Wc2w.png" />
<img style="display: none;" id="the_background" src="https://img.freepik.com/free-photo/hand-painted-watercolor-background-with-sky-clouds-shape_24972-1095.jpg?size=626&ext=jpg" />
In the following code I program a canvas and display a red block that grows in width as the game progresses. It all worked too! Until, I added a simple game loop to my originally (simpler) game loop. The original just updated, rendered, and restarted. The modern newer one Counts ticks and keeps it running at a consistent speed, no matter how fast the computer/browser. Can anyone explain why this is?
Here is the plain html to set up everything:
<html>
<head>
<meta charset="utf-8">
<title>Christmas Town</title>
<style>
canvas {
display: block;
position: fixed;
margin: auto;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
</style>
</head>
<body>
<script src="game.js"></script>
</body>
</html>
And here is the JavaScript which is supposed to create the canvas and Game Loop:
var canvas, context, keyState;
var width = 0;
function tick() {
"use strict";
console.log(5 + 6);
if (width < canvas.getWidth()) {
width += 1;
}
}
function render() {
"use strict";
context.fillStyle = "#FF0000";
context.fillRect(canvas.width, canvas.height, 0, 0);
context.save();
context.fillRect(width, 15, 0, 0);
context.restore();
}
function getTimeMillis() {
"use strict";
return window.performance && window.performance.now ? window.performance.now : new Date.getTime();
}
var FPS = 60, startTime, dt = 0, lastTime = getTimeMillis(), targetTime = 1 / FPS;
function frame() {
"use strict";
startTime = getTimeMillis();
dt = dt + Math.min(1, ((startTime - lastTime) / 1000));
while (dt < targetTime) {
dt -= targetTime;
tick();
}
render();
lastTime = startTime;
window.requestAnimationFrame(frame, canvas);
}
function main() {
"use strict";
canvas = document.createElement("canvas");
canvas.width = 500;
canvas.height = 500;
context = canvas.getContext("2d");
document.body.appendChild(canvas);
window.requestAnimationFrame(frame, canvas);
}
main();
The weird part is it's not even logging to the console, and there are no errors! But, I cant seem to figure out why tick is not being called without there being any errors. Please help!
Not sure if this is what you wanted but check it out. https://jsfiddle.net/jnsLfwde/
Couple things i changed.
context.fillRect( 0, 0, width, 15);
The parameters for fillRect are fillRect(x,y,width,height). You had it as (width,height,x,y);
I reversed the less than sign to greater than. Tick() wasn't being called until i did this.
(dt > targetTime)
You mentioned the animation restarting or something so i added this.
if (width < canvas.width)
width += 1;
else
width = 0;
I would like an image to move to the left if the mouse is to the left of the screen and to the right if the mouse to the right of the screen, using javascript, here is the code I have so far:
var dirx = 0;
var spdx = 35;
var imgLeftInt;
var imgTopInt;
var imgHeight;
var imgWidth;
var divWidth;
var divHeight;
var t;
var tempX;
var tempY;
So I'm pretty sure I'm not missing any variables...
function animBall(on) {
imgLeftInt = parseInt(document.images['logo'].style.left);
imgTopInt = parseInt(document.images['logo'].style.top);
imgHeight = parseInt(document.images['logo'].height);
imgWidth = parseInt(document.images['logo'].width);
divWidth = parseInt(document.images['container'].width);
if (tempX > 779){
dirx = 1;
}
else if(tempX < 767){
dirx = 2;
}
else {
spdx = 0;
}
So if tempX, which should be the x coordinate of the mouse location, is bigger than 779, which is the halfway point of the div tag, the image should go right. If it's less than that, it should go left, and otherwise, the speed should be zero, as in it should stay still.
if(dirx == 1){
goRight();
} else if(dirx == 2) {
goLeft();
}
}
function getMouseXY(e) {
tempX = e.clientX;
tempY = e.clientY;
}
I found hundreds of different ways to get the mouse location, but this was off W3C so I assume it works.
function goRight() {
document.images['logo'].style.left = imgLeftInt+spdx +"px";
if (imgLeftInt > (divWidth-imgWidth)){
dirx = 2;
spdx= 20;
}
}
function goLeft() {
document.images['logo'].style.left = (imgLeftInt-spdx) +"px";
if (imgLeftInt < 5){
dirx = 1;
spdx= 20;
}
}
</script>
So that's my whole script.
<div id="container" onmousemove="getMouseXY(event);" width="1546" height="423">
Start Animation Stop Animation <br />
<img src="http://qabila.tv/images/logo_old.png" style="position:absolute;left:10px;top:20px;" id="logo" />
</div>
I left the dependency on the mouse location to the very end so the animation script works fine (or at least worked, unless I broke something trying to get it to read the mouse location).
Any ideas what I'm doing wrong??
If it's any help, I've hosted the code here.
I went to your link and tried debugging your code. I get an error on line 21 because your document has no "container" image ("container" is a div).
At the start of your question, you said you wanted to know mouse position relative to center of "screen". For that, you'd probably want to use window.innerWidth instead of the width attribute that you set on your div.
Well that needed a whole load of work, anyway, I have done some of it for you and you can now see things partially working, but you will need to play with it on jsfiddle. Perhaps you can now open some specific questions regarding getting this to work.
<div id="container" width="1546" height="423"> <a id="start" href="#">Start Animation</a> <a id="stop" href="#">Stop Animation</a>
<br />
<img src="http://qabila.tv/images/logo_old.png" style="position:absolute;left:10px;top:20px;" id="logo" />
</div>
/*jslint sub: true, maxerr: 50, indent: 4, browser: true */
/*global */
(function () {
"use strict";
var start = document.getElementById("start"),
stop = document.getElementById("stop"),
container = document.getElementById("container"),
logo = document.getElementById("logo"),
dirx = 0,
spdx = 35,
imgLeftInt,
imgTopInt,
imgHeight,
imgWidth,
divWidth,
divHeight,
t,
tempX,
tempY;
function getMouseXY(e) {
tempX = e.clientX;
tempY = e.clientY;
}
function goRight() {
logo.style.left = imgLeftInt + spdx + "px";
if (imgLeftInt > (divWidth - imgWidth)) {
dirx = 2;
spdx = 20;
}
}
function goLeft() {
logo.style.left = (imgLeftInt - spdx) + "px";
if (imgLeftInt < 5) {
dirx = 1;
spdx = 20;
}
}
// attribute on unused
function animBall(on) {
imgLeftInt = parseInt(logo.style.left, 10);
imgTopInt = parseInt(logo.style.top, 10);
imgHeight = parseInt(logo.height, 10);
imgWidth = parseInt(logo.width, 10);
divWidth = parseInt(container.width, 10);
if (tempX > 779) {
dirx = 1;
} else if (tempX < 767) {
dirx = 2;
} else {
spdx = 0;
}
if (dirx === 1) {
goRight();
} else if (dirx === 2) {
goLeft();
}
}
function startAnim() {
t = setInterval(animBall, 80);
}
start.addEventListener("click", startAnim, false);
function stopAnim() {
clearInterval(t);
}
stop.addEventListener("click", stopAnim, false);
container.addEventListener("mousemove", getMouseXY, false);
}());
Why don't you usee the html5 canvas and gee.js
Here's the js fiddle result (it may take a while to load, but that's fault of jsfiddle, the script will load much faster once on your website): http://jsfiddle.net/wLCeE/7/embedded/result/
and here's the much simpler code to make it work:
var g = new GEE({
width: 500,
height: 423,
container: document.getElementById('canvas')
});
var img = new Image(); // Create new img element
img.onload = function () {
demo(g)
};
img.src = 'http://qabila.tv/images/logo_old.png'; // Set source path
function demo(g) {
var style = "left"
g.draw = function () {
if (g.mouseX > g.width / 2 && style == "left") styleRight()
else if (g.mouseX < g.width / 2 && style == "right") styleLeft()
}
function styleLeft() {
style = "left"
g.ctx.clearRect(0, 0, g.width, g.height)
g.ctx.drawImage(img, 0, 0)
}
function styleRight() {
style = "right"
g.ctx.clearRect(0, 0, g.width, g.height)
g.ctx.drawImage(img, g.width - img.width, 0)
}
}