I am trying to do a simple animation example in JavaScript. However, I have an image and I have tried everything that I have found on the internet and seen on previous posts and all that but I can't figure out why this image won't resize. Can someone tell me what the problem is?
var x = 50;
var y = 20;
var xDirection = 1;
var yDirection = 1;
var image = new Image();
image.src = "http://2.bp.blogspot.com/-iS6eK4lSfi4/UJJRqbKA-VI/AAAAAAAABLA/HLxLJpCpau4/s320/Smiley-Face-2.jpg";
image.style.width = "50px";
image.style.height = "50px";
var canvas = null;
var context = null;
window.onload = init;
function init() {
canvas = document.getElementById("gameSurface");
context =canvas.getContext("2d");
setInterval(draw, 1000/30);
}
function draw() {
context.clearRect(0,0,500,500);
context.drawImage(image, x, y);
x += xDirection;
y += yDirection;
if ((x + 50) >= 500) {
x = 450;
xDirection = -1;
}else if (x <= 0) {
x = 0;
xDirection = 1;
}
if ((y + 50) >= 500) {
y = 450;
yDirection = -1;
}else if (y <= 0) {
y = 0;
yDirection = 1;
}
}
As you can see all I want is a smiley face bouncing around the screen. I seem to always have issues with JS... and I do not know anything about JQuery, sorry.
You're resizing the img element by setting its style, but the canvas .drawImage() method doesn't use the element style. However .drawImage() does let you specify the size if you provide additional arguments:
context.drawImage(image, x, y, 50, 50);
Demo: http://jsfiddle.net/vz28W/
See MDN for more details.
Related
Can't figure out how to get this in place. I have the right function firing but am lost when it comes to why the logic isn't working my script. I have a console.log to show the variables are updating but the animation width doesn't update with it.
Javascript
$( document ).ready(function() {
var imgTag = new Image();
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
var x = canvas.width;
var y = 0;
imgTag.onload = animate;
imgTag.src = "http://foodhall.hellogriptest.com/hh/assets/medallion-bounce.png";
var h = window.innerHeight;
var w = window.innerWidth;
canvas.height = h;
canvas.width = w;
//moving image
var mover = {
x: 0,
y: 0,
width: 100,
height: 100,
color: '#000',
down: true,
right: true
}
function animate() {
clear();
render();
rID = requestAnimationFrame(animate);
}
function clear() {
context.clearRect(0, 0, canvas.width, canvas.height);
}
function render() {
//set direction
if (mover.down && mover.y >= h - mover.height)
mover.down = false;
if (!mover.down && mover.y <= 0)
mover.down = true;
if (mover.right && mover.x >= w - mover.width)
mover.right = false;
if (!mover.right && mover.x <= 0)
mover.right = true;
//make move
if (mover.right)
mover.x += 6;
else
mover.x -= 6;
if (mover.down)
mover.y += 6;
else
mover.y -= 6;
//drawRectangle(mover);
drawImage(mover);
}
function drawImage(mover) {
context.drawImage(imgTag, mover.x, mover.y); // draw image at current position
}
window.onresize = function() {
W = window.innerWidth;
H = window.innerHeight;
canvas.width = W;
canvas.height = H;
x = W;
console.log(x);
clear();
render();
drawImage(mover);
}
});//ready
Codepen
—
https://codepen.io/alcoven/pen/KROPrK
This is a simple fix. In the beginning of your script, you are setting lowercase w and lowercase h to the width and height of the window, but in you resize function, you set W = window.innerWidth. The capital W variable is then created and assigned the innerWidth. The lowercase w variable still exists as the original width, and that is what your render is using.
i"m working in angular projet and i want to add two javascript file in my project ; so i just include those js file in my assets and call them in my angular cli script part . i can see that those file are called correcty .
but i have this problems :
my html code is :
<div class=" demo-1">
<div class="content">
<div id="large-header" class="large-header">
<canvas id="demo-canvas"></canvas>
<h1 class="main-title">ALTEN <span class="thin">GAV²</span></h1>
</div>
</div>
</div><!-- /container -->
and my js code is :
(function() {
var width, height, largeHeader, canvas, ctx, points, target, animateHeader = true;
// Main
initHeader();
initAnimation();
addListeners();
function initHeader() {
width = window.innerWidth;
height = window.innerHeight;
target = {x: width/2, y: height/2};
largeHeader = document.getElementById('large-header');
largeHeader.style.height = height+'px';
canvas = document.getElementById('demo-canvas');
canvas.width = width;
canvas.height = height;
ctx = canvas.getContext('2d');
// create points
points = [];
for(var x = 0; x < width; x = x + width/20) {
for(var y = 0; y < height; y = y + height/20) {
var px = x + Math.random()*width/20;
var py = y + Math.random()*height/20;
var p = {x: px, originX: px, y: py, originY: py };
points.push(p);
}
}
// for each point find the 5 closest points
for(var i = 0; i < points.length; i++) {
var closest = [];
var p1 = points[i];
for(var j = 0; j < points.length; j++) {
var p2 = points[j]
if(!(p1 == p2)) {
var placed = false;
for(var k = 0; k < 5; k++) {
if(!placed) {
if(closest[k] == undefined) {
closest[k] = p2;
placed = true;
}
}
}
for(var k = 0; k < 5; k++) {
if(!placed) {
if(getDistance(p1, p2) < getDistance(p1, closest[k])) {
closest[k] = p2;
placed = true;
}
}
}
}
}
p1.closest = closest;
}
// assign a circle to each point
for(var i in points) {
var c = new Circle(points[i], 2+Math.random()*2, 'rgba(255,255,255,0.3)');
points[i].circle = c;
}
}
// Event handling
function addListeners() {
if(!('ontouchstart' in window)) {
window.addEventListener('mousemove', mouseMove);
}
window.addEventListener('scroll', scrollCheck);
window.addEventListener('resize', resize);
}
function mouseMove(e) {
var posx = posy = 0;
if (e.pageX || e.pageY) {
posx = e.pageX;
posy = e.pageY;
}
else if (e.clientX || e.clientY) {
posx = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
posy = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
}
target.x = posx;
target.y = posy;
}
function scrollCheck() {
if(document.body.scrollTop > height) animateHeader = false;
else animateHeader = true;
}
function resize() {
width = window.innerWidth;
height = window.innerHeight;
largeHeader.style.height = height+'px';
canvas.width = width;
canvas.height = height;
}
// animation
function initAnimation() {
animate();
for(var i in points) {
shiftPoint(points[i]);
}
}
function animate() {
if(animateHeader) {
ctx.clearRect(0,0,width,height);
for(var i in points) {
// detect points in range
if(Math.abs(getDistance(target, points[i])) < 4000) {
points[i].active = 0.3;
points[i].circle.active = 0.6;
} else if(Math.abs(getDistance(target, points[i])) < 20000) {
points[i].active = 0.1;
points[i].circle.active = 0.3;
} else if(Math.abs(getDistance(target, points[i])) < 40000) {
points[i].active = 0.02;
points[i].circle.active = 0.1;
} else {
points[i].active = 0;
points[i].circle.active = 0;
}
drawLines(points[i]);
points[i].circle.draw();
}
}
requestAnimationFrame(animate);
}
function shiftPoint(p) {
TweenLite.to(p, 1+1*Math.random(), {x:p.originX-50+Math.random()*100,
y: p.originY-50+Math.random()*100, ease:Circ.easeInOut,
onComplete: function() {
shiftPoint(p);
}});
}
// Canvas manipulation
function drawLines(p) {
if(!p.active) return;
for(var i in p.closest) {
ctx.beginPath();
ctx.moveTo(p.x, p.y);
ctx.lineTo(p.closest[i].x, p.closest[i].y);
ctx.strokeStyle = 'rgba(156,217,249,'+ p.active+')';
ctx.stroke();
}
}
function Circle(pos,rad,color) {
var _this = this;
// constructor
(function() {
_this.pos = pos || null;
_this.radius = rad || null;
_this.color = color || null;
})();
this.draw = function() {
if(!_this.active) return;
ctx.beginPath();
ctx.arc(_this.pos.x, _this.pos.y, _this.radius, 0, 2 * Math.PI, false);
ctx.fillStyle = 'rgba(156,217,249,'+ _this.active+')';
ctx.fill();
};
}
// Util
function getDistance(p1, p2) {
return Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2);
}
})();
when i try to log the largeHeader viariable in my js it return null .
this code work correctly . but including it in angular cli make problems .
is that a problem of webpack ?
thank you in advance
It's important to say what build tool you are using. If it's Webpack based (ie. Angular CLI) then you can reference a JavaScript file (or any other type) with one of the following:
import * as test from './test.js';
// or
require('./test.js');
However, your error message indicates that your JavaScript is running, but it's failing on these lines:
largeHeader = document.getElementById('large-header');
largeHeader.style.height = height+'px';
It's not finding an element on your page with ID large-header, so the call to .style fails. I suspect that, because you are importing the file from the top level HTML page, the JavaScript code is running before the template has a chance to render, so the large-header element is not created at that point.
To diagnose further, you could use the Sources tab of the Chrome Dev Tools to set a breakpoint on the line in question, then inspect the Elements tab to see if the expected div is actually present at this point.
I'm not sure exactly what you're trying to achieve here, but throwing in arbitrary bits of JavaScript that are not part of the "Angular world" might not be the best way to approach an Angular app. In the long term, perhaps it would be better to refactor this code into a Component or a Directive.
In my on-the-fly editor tool I would really appreciate to get actual rendered height of the text / font - (I do not mean just getting CSS font-size, neither computed nor preset).
Is this achieveable in javascript?
If not directly, is possible something as rendering font in canvas the same way as it is rendered as regular text - and then finding out?
EDIT - my "dev" solution: Based on suggested links I've built a little pure-javascript code, that goes through pixels in canvas and analyses whether the pixel is white or not and acts accordingly, it is hardly a developer version of a code - just outputs few useful info and shows how to access computed data - http://jsfiddle.net/DV9Bw/1325/
HTML:
<canvas id="exampleSomePrettyRandomness" width="200" height="60"></canvas>
<div id="statusSomePrettyRandomness"></div>
JS:
function findPos(obj) {
var curleft = 0, curtop = 0;
if (obj.offsetParent) {
do {
curleft += obj.offsetLeft;
curtop += obj.offsetTop;
} while (obj = obj.offsetParent);
return { x: curleft, y: curtop };
}
return undefined;
}
var status = document.getElementById('statusSomePrettyRandomness');
var example = document.getElementById('exampleSomePrettyRandomness');
var context = example.getContext('2d');
context.fillStyle = "rgb(255,255,255)";
context.fillRect(0, 0, 200, 200);
context.fillStyle = "rgb(0,0,0)";
context.font = "30px Arial";
context.fillText("Hello World",0,30);
var pos = findPos(example);
var x = example.pageX - pos.x;
var y = example.pageY - pos.y;
var foundTop = false;
xPos = 0;
yPos = 0;
topY = -1;
bottomY = -1;
var fuse = 1000;
while( fuse-- > 0 ){
//status.innerHTML += yPos+"<br>";
if( yPos == (example.offsetHeight - 2) ){
xPos++;
yPos = 0;
continue;
}
var data = context.getImageData(xPos, yPos, 1, 1).data;
if( ! foundTop ){
if( (data[0] != 255) && (data[1] != 255) && (data[2] != 255) ){
topY = yPos;
status.innerHTML += "<br>Found top: "+topY+" X:"+xPos+" Color: rgba("+data[0]+","+data[1]+","+data[2]+")"+"<br>";
foundTop = true;
}
} else {
if( (data[0] == 255) && (data[1] == 255) && (data[2] == 255) ){
bottomY = yPos;
status.innerHTML += "<br>Found bottom: "+bottomY+" X:"+xPos+"<br>";
break;
}
}
yPos++;
if( yPos > example.offsetHeight ){
status.innerHTML += ""
+"Y overflow ("+yPos+">"+example.offsetHeight+")"
+" - moving X to "+xPos
+" - reseting Y to "+yPos
+"<br>"
;
xPos++;
yPos = 0;
}
}
status.innerHTML += "Fuse:"+fuse+", Top:"+topY+", Bottom: "+bottomY+"<br>";
status.innerHTML += "Font height should be: "+(bottomY-topY)+"<br>";
EDIT 2: Why this is not a duplicate: My question is about really just real rendered height of a font or a letter, "possible duplicate" is about how much space do you need to print a text, answers provided there don't answer my exact problem anyways.
I am not aware of any method that would return the height of a text such as measureText (which does currently return the width).
However, in theory you can simply draw your text in the canvas then trim the surrounding transparent pixels then measure the canvas height..
Here is an example (the height will be logged in the console):
// Create a blank canvas (by not filling a background color).
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
// Fill it with some coloured text.. (black is default)
ctx.font = "48px serif";
ctx.textBaseline = "hanging";
ctx.fillText("Hello world", 0, 0);
// Remove the surrounding transparent pixels
// result is an actual canvas element
var result = trim(canvas);
// you could query it's width, draw it, etc..
document.body.appendChild(result);
// get the height of the trimmed area
console.log(result.height);
// Trim Canvas Pixels Method
// https://gist.github.com/remy/784508
function trim(c) {
var ctx = c.getContext('2d'),
// create a temporary canvas in which we will draw back the trimmed text
copy = document.createElement('canvas').getContext('2d'),
// Use the Canvas Image Data API, in order to get all the
// underlying pixels data of that canvas. This will basically
// return an array (Uint8ClampedArray) containing the data in the
// RGBA order. Every 4 items represent one pixel.
pixels = ctx.getImageData(0, 0, c.width, c.height),
// total pixels
l = pixels.data.length,
// main loop counter and pixels coordinates
i, x, y,
// an object that will store the area that isn't transparent
bound = { top: null, left: null, right: null, bottom: null };
// for every pixel in there
for (i = 0; i < l; i += 4) {
// if the alpha value isn't ZERO (transparent pixel)
if (pixels.data[i+3] !== 0) {
// find it's coordinates
x = (i / 4) % c.width;
y = ~~((i / 4) / c.width);
// store/update those coordinates
// inside our bounding box Object
if (bound.top === null) {
bound.top = y;
}
if (bound.left === null) {
bound.left = x;
} else if (x < bound.left) {
bound.left = x;
}
if (bound.right === null) {
bound.right = x;
} else if (bound.right < x) {
bound.right = x;
}
if (bound.bottom === null) {
bound.bottom = y;
} else if (bound.bottom < y) {
bound.bottom = y;
}
}
}
// actual height and width of the text
// (the zone that is actually filled with pixels)
var trimHeight = bound.bottom - bound.top,
trimWidth = bound.right - bound.left,
// get the zone (trimWidth x trimHeight) as an ImageData
// (Uint8ClampedArray of pixels) from our canvas
trimmed = ctx.getImageData(bound.left, bound.top, trimWidth, trimHeight);
// Draw back the ImageData into the canvas
copy.canvas.width = trimWidth;
copy.canvas.height = trimHeight;
copy.putImageData(trimmed, 0, 0);
// return the canvas element
return copy.canvas;
}
<canvas id="canvas"></canvas>
Image Data API: https://developer.mozilla.org/en-US/docs/Web/API/ImageData
I'm having trouble trying to make an animation with JavaScript and the HTML5 canvas element.
I need to have an animation that starts in the bottom right corner of my canvas, which moves up diagonally to the top right hand corner and then reverses back the other direction to create a back and forth movement.
I can get my animation to move diagonally, but then I can't get it to change the direction.
I'm also having trouble getting the animation to start from the bottom no matter what I do.
The code below currently moves my animation top to bottom diagonally.
var context;
var x = 0;
var y = 0;
var stepx = 1.55;
var stepy = 1.55;
function setupAnimCanvas() {
var canvas = document.getElementById('assignmenttwoCanvas');
if (canvas.getContext) {
ctx = canvas.getContext('2d');
setInterval('draw();', 20);
img = new Image();
img.src = '../images/dragon.png';
//animation();
}
}
startPos = (500, 500);
endPos = (0, 0);
function draw() {
ctx.clearRect(0,0, 500,500);
drawBackground();
ctx.drawImage(img, y, x);
x += 3;
if(x < endPos){
x -= stepx;
y += stepy;
}
else if (y > endPos) {
x += stepx;
y -= stepy;
}
else {
endPos = startPos;startPos = y;
}
moveit();
setTimeout('mover()',25);
}
You can use a delta value for x and y. When the x or y position is at start or end you just reverse the delta by setting delta = -delta;
var dx = -3, dy = -3;
Then simply check for any criteria that would reverse the direction:
if (x < endPos[0] || x > startPos[0] || y < endPos[1] || y > startPos[1] ) {
dx = -dx;
dy = -dy;
}
See demo here:
http://jsfiddle.net/AbdiasSoftware/5dSSZ/
The essence of this (see comments and original source lines at fiddler-link)
var startPos = [500, 500];
var endPos = [0, 0];
var dx = -3, dy = -3;
var x = startPos[0], y = startPos[1];
function draw() {
ctx.clearRect(0, 0, 500, 500);
ctx.fillRect(x, y, 20, 20); //for demo as no image
x += dx;
y += dy;
if (x < endPos[0] || x > startPos[0] ||
y < endPos[1] || y > startPos[1] ) {
dx = -dx;
dy = -dy;
}
setTimeout(draw, 16); //requestAnimationFrame is a better choice
}
I'm fairly new to Javascript and HTML5, and I'm trying to figure out how to zoom on a canvas. Let's say my Javascript code looks like this:
window.addEventListener('load', function() {
var theCanvas = document.getElementById('myCanvas');
theCanvas.style.border = "black 1px solid";
if(theCanvas && theCanvas.getContext) {
var context = theCanvas.getContext('2d');
if(context) {
var x = 10;
var y = 10;
var z = 255;
var color = "rgb(0," + z + ",0)";
context.fillStyle = "rgb(100,0,0)";
for(var y = 0; y <= 290; y += 10) {
for(var x = 0; x <= 290; x += 10) {
if(z >= 1) {
z -= 1;
}
color = "rgb(0," + z + ",0)";
if(x % 20 === 0) {
context.fillStyle = color;
} else {
context.fillStyle = color;
}
context.fillRect(x, y, 10, 10);
}
}
}
}
}, false);
In summary, this code just fills the canvas with tiled rectangles of changing color. But how would one go about zooming in and out on something like this?
You'll want the scale method of context.
And note that, once you've drawn something on the canvas, it can't really be zoomed or scaled — you've got to re-draw the entire canvas at the new "zoom level".