how to call a javascript function from html? - javascript

Is there anything wrong in how i am calling the init2 function in my html file.
It's works fine when i run it in jsfiddle after removing the script reference in head.when i try to run it locally in my machine,there is no output in my browser.
i am not using any onclick methods,i want everything to be loaded when the page is loaded.
jsfiddle:https://jsfiddle.net/sukchguj/2/
This is the code i am trying to run locally.And also both the html and js files are in the same directory.
<!DOCTYPE html>
<html>
<head>
<title>js</title>
<script src="canvas.js"></script>
</head>
<body onload='init2()'>
<canvas id="canvas" width="1000" height="1000">
This text is displayed if your browser does not support HTML5 Canvas.
</canvas>
<!-- This image will be displayed on the canvas -->
<img id="myImage" src="https://image.slidesharecdn.com/bareconf-140329111624-phpapp02/95/draft-scientific-paper-1-638.jpg?cb=1396091812" style = "display: none">
</body>
</html>
canvas.js
// holds all our boxes
var boxes2 = [];
// New, holds the 8 tiny boxes that will be our selection handles
// the selection handles will be in this order:
// 0 1 2
// 3 4
// 5 6 7
var selectionHandles = [];
// Hold canvas information
var canvas;
var ctx;
var WIDTH;
var HEIGHT;
var INTERVAL = 20; // how often, in milliseconds, we check to see if a redraw is needed
var isDrag = false;
var isResizeDrag = false;
var expectResize = -1; // New, will save the # of the selection handle if the mouse is over one.
var mx, my; // mouse coordinates
// when set to true, the canvas will redraw everything
// invalidate() just sets this to false right now
// we want to call invalidate() whenever we make a change
var canvasValid = false;
// The node (if any) being selected.
// If in the future we want to select multiple objects, this will get turned into an array
var mySel = null;
// The selection color and width. Right now we have a red selection with a small width
var mySelColor = '#CC0000';
var mySelWidth = 2;
var mySelBoxColor = 'darkred'; // New for selection boxes
var mySelBoxSize = 6;
// we use a fake canvas to draw individual shapes for selection testing
var ghostcanvas;
var gctx; // fake canvas context
// since we can drag from anywhere in a node
// instead of just its x/y corner, we need to save
// the offset of the mouse when we start dragging.
var offsetx, offsety;
// Padding and border style widths for mouse offsets
var stylePaddingLeft, stylePaddingTop, styleBorderLeft, styleBorderTop;
// Box object to hold data
function Box2() {
this.x = 0;
this.y = 0;
this.w = 1; // default width and height?
this.h = 1;
this.fill = '#444444';
}
// New methods on the Box class
Box2.prototype = {
// we used to have a solo draw function
// but now each box is responsible for its own drawing
// mainDraw() will call this with the normal canvas
// myDown will call this with the ghost canvas with 'black'
draw: function(context, optionalColor) {
if (context === gctx) {
context.fillStyle = 'black'; // always want black for the ghost canvas
} else {
context.fillStyle = this.fill;
}
// We can skip the drawing of elements that have moved off the screen:
if (this.x > WIDTH || this.y > HEIGHT) return;
if (this.x + this.w < 0 || this.y + this.h < 0) return;
context.fillRect(this.x,this.y,this.w,this.h);
// draw selection
// this is a stroke along the box and also 8 new selection handles
if (mySel === this) {
context.strokeStyle = mySelColor;
context.lineWidth = mySelWidth;
context.strokeRect(this.x,this.y,this.w,this.h);
// draw the boxes
var half = mySelBoxSize / 2;
// 0 1 2
// 3 4
// 5 6 7
// top left, middle, right
selectionHandles[0].x = this.x-half;
selectionHandles[0].y = this.y-half;
selectionHandles[1].x = this.x+this.w/2-half;
selectionHandles[1].y = this.y-half;
selectionHandles[2].x = this.x+this.w-half;
selectionHandles[2].y = this.y-half;
//middle left
selectionHandles[3].x = this.x-half;
selectionHandles[3].y = this.y+this.h/2-half;
//middle right
selectionHandles[4].x = this.x+this.w-half;
selectionHandles[4].y = this.y+this.h/2-half;
//bottom left, middle, right
selectionHandles[6].x = this.x+this.w/2-half;
selectionHandles[6].y = this.y+this.h-half;
selectionHandles[5].x = this.x-half;
selectionHandles[5].y = this.y+this.h-half;
selectionHandles[7].x = this.x+this.w-half;
selectionHandles[7].y = this.y+this.h-half;
context.fillStyle = mySelBoxColor;
for (var i = 0; i < 8; i ++) {
var cur = selectionHandles[i];
context.fillRect(cur.x, cur.y, mySelBoxSize, mySelBoxSize);
}
}
} // end draw
}
//Initialize a new Box, add it, and invalidate the canvas
function addRect(x, y, w, h, fill) {
var rect = new Box2;
rect.x = x;
rect.y = y;
rect.w = w
rect.h = h;
rect.fill = fill;
boxes2.push(rect);
invalidate();
}
//***************************
// This will load the image into the variable "im"
var im = document.getElementById("myImage");
//***************************
// initialize our canvas, add a ghost canvas, set draw loop
// then add everything we want to intially exist on the canvas
function init2() {
canvas = document.getElementById('canvas');
HEIGHT = canvas.height;
WIDTH = canvas.width;
ctx = canvas.getContext('2d');
ghostcanvas = document.createElement('canvas');
ghostcanvas.height = HEIGHT;
ghostcanvas.width = WIDTH;
gctx = ghostcanvas.getContext('2d');
//fixes a problem where double clicking causes text to get selected on the canvas
canvas.onselectstart = function () { return false; }
// fixes mouse co-ordinate problems when there's a border or padding
// see getMouse for more detail
if (document.defaultView && document.defaultView.getComputedStyle) {
stylePaddingLeft = parseInt(document.defaultView.getComputedStyle(canvas, null)['paddingLeft'], 10) || 0;
stylePaddingTop = parseInt(document.defaultView.getComputedStyle(canvas, null)['paddingTop'], 10) || 0;
styleBorderLeft = parseInt(document.defaultView.getComputedStyle(canvas, null)['borderLeftWidth'], 10) || 0;
styleBorderTop = parseInt(document.defaultView.getComputedStyle(canvas, null)['borderTopWidth'], 10) || 0;
}
// make mainDraw() fire every INTERVAL milliseconds
setInterval(mainDraw, INTERVAL);
// set our events. Up and down are for dragging,
// double click is for making new boxes
canvas.onmousedown = myDown;
canvas.onmouseup = myUp;
canvas.ondblclick = myDblClick;
canvas.onmousemove = myMove;
// set up the selection handle boxes
for (var i = 0; i < 8; i ++) {
var rect = new Box2;
selectionHandles.push(rect);
}
// add custom initialization here:
// add a large green rectangle
addRect(260, 70, 60, 65, 'rgba(0,205,0,0.7)');
// add a green-blue rectangle
addRect(240, 120, 40, 40, 'rgba(2,165,165,0.7)');
// add a smaller purple rectangle
addRect(45, 60, 25, 25, 'rgba(150,150,250,0.7)');
}
//wipes the canvas context
function clear(c) {
c.clearRect(0, 0, WIDTH, HEIGHT);
}
// Main draw loop.
// While draw is called as often as the INTERVAL variable demands,
// It only ever does something if the canvas gets invalidated by our code
function mainDraw() {
if (canvasValid == false) {
clear(ctx);
// Add stuff you want drawn in the background all the time here
ctx.drawImage(im,0,0);
// draw all boxes
var l = boxes2.length;
for (var i = 0; i < l; i++) {
boxes2[i].draw(ctx); // we used to call drawshape, but now each box draws itself
}
// Add stuff you want drawn on top all the time here
canvasValid = true;
}
}
// Happens when the mouse is moving inside the canvas
function myMove(e){
if (isDrag) {
getMouse(e);
mySel.x = mx - offsetx;
mySel.y = my - offsety;
// something is changing position so we better invalidate the canvas!
invalidate();
} else if (isResizeDrag) {
// time ro resize!
var oldx = mySel.x;
var oldy = mySel.y;
// 0 1 2
// 3 4
// 5 6 7
switch (expectResize) {
case 0:
mySel.x = mx;
mySel.y = my;
mySel.w += oldx - mx;
mySel.h += oldy - my;
break;
case 1:
mySel.y = my;
mySel.h += oldy - my;
break;
case 2:
mySel.y = my;
mySel.w = mx - oldx;
mySel.h += oldy - my;
break;
case 3:
mySel.x = mx;
mySel.w += oldx - mx;
break;
case 4:
mySel.w = mx - oldx;
break;
case 5:
mySel.x = mx;
mySel.w += oldx - mx;
mySel.h = my - oldy;
break;
case 6:
mySel.h = my - oldy;
break;
case 7:
mySel.w = mx - oldx;
mySel.h = my - oldy;
break;
}
invalidate();
}
getMouse(e);
// if there's a selection see if we grabbed one of the selection handles
if (mySel !== null && !isResizeDrag) {
for (var i = 0; i < 8; i++) {
// 0 1 2
// 3 4
// 5 6 7
var cur = selectionHandles[i];
// we dont need to use the ghost context because
// selection handles will always be rectangles
if (mx >= cur.x && mx <= cur.x + mySelBoxSize &&
my >= cur.y && my <= cur.y + mySelBoxSize) {
// we found one!
expectResize = i;
invalidate();
switch (i) {
case 0:
this.style.cursor='nw-resize';
break;
case 1:
this.style.cursor='n-resize';
break;
case 2:
this.style.cursor='ne-resize';
break;
case 3:
this.style.cursor='w-resize';
break;
case 4:
this.style.cursor='e-resize';
break;
case 5:
this.style.cursor='sw-resize';
break;
case 6:
this.style.cursor='s-resize';
break;
case 7:
this.style.cursor='se-resize';
break;
}
return;
}
}
// not over a selection box, return to normal
isResizeDrag = false;
expectResize = -1;
this.style.cursor='auto';
}
}
// Happens when the mouse is clicked in the canvas
function myDown(e){
getMouse(e);
//we are over a selection box
if (expectResize !== -1) {
isResizeDrag = true;
return;
}
clear(gctx);
var l = boxes2.length;
for (var i = l-1; i >= 0; i--) {
// draw shape onto ghost context
boxes2[i].draw(gctx, 'black');
// get image data at the mouse x,y pixel
var imageData = gctx.getImageData(mx, my, 1, 1);
var index = (mx + my * imageData.width) * 4;
// if the mouse pixel exists, select and break
if (imageData.data[3] > 0) {
mySel = boxes2[i];
offsetx = mx - mySel.x;
offsety = my - mySel.y;
mySel.x = mx - offsetx;
mySel.y = my - offsety;
isDrag = true;
invalidate();
clear(gctx);
return;
}
}
// havent returned means we have selected nothing
mySel = null;
// clear the ghost canvas for next time
clear(gctx);
// invalidate because we might need the selection border to disappear
invalidate();
}
function myUp(){
isDrag = false;
isResizeDrag = false;
expectResize = -1;
}
// adds a new node
function myDblClick(e) {
getMouse(e);
// for this method width and height determine the starting X and Y, too.
// so I left them as vars in case someone wanted to make them args for something and copy this code
var width = 100;
var height = 150;
addRect(mx - (width / 2), my - (height / 2), width, height, 'rgba(220,205,65,0.7)');
}
function invalidate() {
canvasValid = false;
}
// Sets mx,my to the mouse position relative to the canvas
// unfortunately this can be tricky, we have to worry about padding and borders
function getMouse(e) {
var element = canvas, offsetX = 0, offsetY = 0;
if (element.offsetParent) {
do {
offsetX += element.offsetLeft;
offsetY += element.offsetTop;
} while ((element = element.offsetParent));
}
// Add padding and border style widths to offset
offsetX += stylePaddingLeft;
offsetY += stylePaddingTop;
offsetX += styleBorderLeft;
offsetY += styleBorderTop;
mx = e.pageX - offsetX;
my = e.pageY - offsetY
}
// If you dont want to use <body onLoad='init()'>
// You could uncomment this init() reference and place the script reference inside the body tag
//init();
The error is:

<!DOCTYPE html>
<html>
<head>
<title>js</title>
</head>
<body onload='init2()'>
<canvas id="canvas" width="1000" height="1000">
This text is displayed if your browser does not support HTML5 Canvas.
</canvas>
<!-- This image will be displayed on the canvas -->
<img id="myImage" src="https://image.slidesharecdn.com/bareconf-140329111624-phpapp02/95/draft-scientific-paper-1-638.jpg?cb=1396091812" style = "display: none">
<script src="canvas.js"></script>
</body>
</html>
Move you script tag to the end in the body.
Why you should move script to the end can be found here: https://stackoverflow.com/a/17106486/4713768

Move the assignment of the im variable
im = document.getElementById("myImage");
into the init2() function. Otherwise, it's executing when the script is loaded, before the rest of the DOM has been loaded.
See Why does jQuery or a DOM method such as getElementById not find the element?

Related

Game Multiplayer converstion websockets

I've found a cool bit of code online that I'm looking to adapt into a game, but firstly I want to get multiplayer working on it using sockets like socket.io, express or eureca.io, but I'm not sure how to adapt the code I have to multiplayer, could anyone lend me a hand and show me how to do it?
Regards
A confused individual
<!DOCTYPE html>
<html>
<head>
<title></title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script type="text/javascript" src="script.js"></script>
</head>
<body>
<center><canvas id="gameCanvas" width="600" height="600"></canvas></center>
$(document).ready(function() {
var socket = io.connect();
window.Game = {};
(function(){
function Rectangle(left, top, width, height){
this.left = left || 0;
this.top = top || 0;
this.width = width || 0;
this.height = height || 0;
this.right = this.left + this.width;
this.bottom = this.top + this.height;
}
Rectangle.prototype.set = function(left, top, /*optional*/width, /*optional*/height){
this.left = left;
this.top = top;
this.width = width || this.width;
this.height = height || this.height
this.right = (this.left + this.width);
this.bottom = (this.top + this.height);
}
Rectangle.prototype.within = function(r) {
return (r.left <= this.left &&
r.right >= this.right &&
r.top <= this.top &&
r.bottom >= this.bottom);
}
Rectangle.prototype.overlaps = function(r) {
return (this.left < r.right &&
r.left < this.right &&
this.top < r.bottom &&
r.top < this.bottom);
}
// add "class" Rectangle to our Game object
Game.Rectangle = Rectangle;
})();
// wrapper for "class" Camera (avoid global objects)
(function(){
// possibles axis to move the camera
var AXIS = {
NONE: "none",
HORIZONTAL: "horizontal",
VERTICAL: "vertical",
BOTH: "both"
};
// Camera constructor
function Camera(xView, yView, canvasWidth, canvasHeight, worldWidth, worldHeight)
{
// position of camera (left-top coordinate)
this.xView = xView || 0;
this.yView = yView || 0;
// distance from followed object to border before camera starts move
this.xDeadZone = 0; // min distance to horizontal borders
this.yDeadZone = 0; // min distance to vertical borders
// viewport dimensions
this.wView = canvasWidth;
this.hView = canvasHeight;
// allow camera to move in vertical and horizontal axis
this.axis = AXIS.BOTH;
// object that should be followed
this.followed = null;
// rectangle that represents the viewport
this.viewportRect = new Game.Rectangle(this.xView, this.yView, this.wView, this.hView);
// rectangle that represents the world's boundary (room's boundary)
this.worldRect = new Game.Rectangle(0, 0, worldWidth, worldHeight);
}
// gameObject needs to have "x" and "y" properties (as world(or room) position)
Camera.prototype.follow = function(gameObject, xDeadZone, yDeadZone)
{
this.followed = gameObject;
this.xDeadZone = xDeadZone;
this.yDeadZone = yDeadZone;
}
Camera.prototype.update = function()
{
// keep following the player (or other desired object)
if(this.followed != null)
{
if(this.axis == AXIS.HORIZONTAL || this.axis == AXIS.BOTH)
{
// moves camera on horizontal axis based on followed object position
if(this.followed.x - this.xView + this.xDeadZone > this.wView)
this.xView = this.followed.x - (this.wView - this.xDeadZone);
else if(this.followed.x - this.xDeadZone < this.xView)
this.xView = this.followed.x - this.xDeadZone;
}
if(this.axis == AXIS.VERTICAL || this.axis == AXIS.BOTH)
{
// moves camera on vertical axis based on followed object position
if(this.followed.y - this.yView + this.yDeadZone > this.hView)
this.yView = this.followed.y - (this.hView - this.yDeadZone);
else if(this.followed.y - this.yDeadZone < this.yView)
this.yView = this.followed.y - this.yDeadZone;
}
}
// update viewportRect
this.viewportRect.set(this.xView, this.yView);
// don't let camera leaves the world's boundary
if(!this.viewportRect.within(this.worldRect))
{
if(this.viewportRect.left < this.worldRect.left)
this.xView = this.worldRect.left;
if(this.viewportRect.top < this.worldRect.top)
this.yView = this.worldRect.top;
if(this.viewportRect.right > this.worldRect.right)
this.xView = this.worldRect.right - this.wView;
if(this.viewportRect.bottom > this.worldRect.bottom)
this.yView = this.worldRect.bottom - this.hView;
}
}
// add "class" Camera to our Game object
Game.Camera = Camera;
})();
// wrapper for "class" Player
(function(){
function Player(x, y){
// (x, y) = center of object
// ATTENTION:
// it represents the player position on the world(room), not the canvas position
this.x = x;
this.y = y;
// move speed in pixels per second
this.speed = 200;
// render properties
this.width = 50;
this.height = 50;
}
Player.prototype.update = function(step, worldWidth, worldHeight){
// parameter step is the time between frames ( in seconds )
// check controls and move the player accordingly
if(Game.controls.left)
this.x -= this.speed * step;
if(Game.controls.up)
this.y -= this.speed * step;
if(Game.controls.right)
this.x += this.speed * step;
if(Game.controls.down)
this.y += this.speed * step;
// don't let player leaves the world's boundary
if(this.x - this.width/2 < 0){
this.x = this.width/2;
}
if(this.y - this.height/2 < 0){
this.y = this.height/2;
}
if(this.x + this.width/2 > worldWidth){
this.x = worldWidth - this.width/2;
}
if(this.y + this.height/2 > worldHeight){
this.y = worldHeight - this.height/2;
}
}
Player.prototype.draw = function(context, xView, yView){
// draw a simple rectangle shape as our player model
context.save();
context.fillStyle = "black";
// before draw we need to convert player world's position to canvas position
context.fillRect((this.x-this.width/2) - xView, (this.y-this.height/2) - yView, this.width, this.height);
context.restore();
}
// add "class" Player to our Game object
Game.Player = Player;
})();
// wrapper for "class" Map
(function(){
function Map(width, height){
// map dimensions
this.width = width;
this.height = height;
// map texture
this.image = null;
}
// generate an example of a large map
Map.prototype.generate = function(){
var ctx = document.createElement("canvas").getContext("2d");
ctx.canvas.width = this.width;
ctx.canvas.height = this.height;
var rows = ~~(this.width/44) + 1;
var columns = ~~(this.height/44) + 1;
ctx.restore();
// store the generate map as this image texture
this.image = new Image();
this.image.src = ctx.canvas.toDataURL("image/png");
// clear context
ctx = null;
}
// draw the map adjusted to camera
Map.prototype.draw = function(context, xView, yView){
// easiest way: draw the entire map changing only the destination coordinate in canvas
// canvas will cull the image by itself (no performance gaps -> in hardware accelerated environments, at least)
//context.drawImage(this.image, 0, 0, this.image.width, this.image.height, -xView, -yView, this.image.width, this.image.height);
// didactic way:
var sx, sy, dx, dy;
var sWidth, sHeight, dWidth, dHeight;
// offset point to crop the image
sx = xView;
sy = yView;
// dimensions of cropped image
sWidth = context.canvas.width;
sHeight = context.canvas.height;
// if cropped image is smaller than canvas we need to change the source dimensions
if(this.image.width - sx < sWidth){
sWidth = this.image.width - sx;
}
if(this.image.height - sy < sHeight){
sHeight = this.image.height - sy;
}
// location on canvas to draw the croped image
dx = 0;
dy = 0;
// match destination with source to not scale the image
dWidth = sWidth;
dHeight = sHeight;
context.drawImage(this.image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
}
// add "class" Map to our Game object
Game.Map = Map;
})();
// Game Script
(function(){
// prepaire our game canvas
var canvas = document.getElementById("gameCanvas");
var context = canvas.getContext("2d");
// game settings:
var FPS = 30;
var INTERVAL = 1000/FPS; // milliseconds
var STEP = INTERVAL/1000 // seconds
// setup an object that represents the room
var room = {
width: 600,
height: 600,
map: new Game.Map(600, 600)
};
// generate a large image texture for the room
room.map.generate();
// setup player
var player = new Game.Player(50, 50);
// setup the magic camera !!!
var camera = new Game.Camera(0, 0, canvas.width, canvas.height, room.width, room.height);
camera.follow(player, canvas.width/2, canvas.height/2);
// Game update function
var update = function(){
player.update(STEP, room.width, room.height);
camera.update();
}
// Game draw function
var draw = function(){
// clear the entire canvas
context.clearRect(0, 0, canvas.width, canvas.height);
// redraw all objects
room.map.draw(context, camera.xView, camera.yView);
player.draw(context, camera.xView, camera.yView);
}
// Game Loop
var gameLoop = function(){
update();
draw();
}
// <-- configure play/pause capabilities:
// I'll use setInterval instead of requestAnimationFrame for compatibility reason,
// but it's easy to change that.
var runningId = -1;
Game.play = function(){
if(runningId == -1){
runningId = setInterval(function(){
gameLoop();
}, INTERVAL);
console.log("play");
}
}
Game.togglePause = function(){
if(runningId == -1){
Game.play();
}
else
{
clearInterval(runningId);
runningId = -1;
console.log("paused");
}
}
// -->
})();
// <-- configure Game controls:
Game.controls = {
left: false,
up: false,
right: false,
down: false,
};
window.addEventListener("keydown", function(e){
switch(e.keyCode)
{
case 37: // left arrow
Game.controls.left = true;
break;
case 38: // up arrow
Game.controls.up = true;
break;
case 39: // right arrow
Game.controls.right = true;
break;
case 40: // down arrow
Game.controls.down = true;
break;
}
}, false);
window.addEventListener("keyup", function(e){
switch(e.keyCode)
{
case 37: // left arrow
Game.controls.left = false;
break;
case 38: // up arrow
Game.controls.up = false;
break;
case 39: // right arrow
Game.controls.right = false;
break;
case 40: // down arrow
Game.controls.down = false;
break;
case 80: // key P pauses the game
Game.togglePause();
break;
}
}, false);
// -->
// start the game when page is loaded
window.onload = function(){
Game.play();
}
});
You create a canvas in Map.prototype.generate, and you select your existing canava in html at the end in Game Script (prepaire our game canvas)
It's normaly not worked ....

Javascript - get actual rendered font height

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

Changing my Jquery project to plain javascript

I created a breakout game for a school project using jquery and a helpful online tutorial.
The working fiddle is here: http://jsfiddle.net/Kinetic915/kURvf/
EDIT revised fiddle: http://jsfiddle.net/Kinetic915/nVctR/
I have changed most to javascript but am having problems changing the jquery code that renders the ball to javascript.
I have Marked and left spaces in the areas where there are problems.
Thank you very much for any help given!!
//***********************************************************************************
// START CODE
//***********************************************************************************
// VARIABLES and other initializing functions are here
function start() {
//******************************************************************************
//JQUERY
// HERE IS THE MAIN PROBLEM!!!!!!
// HERE IS THE MAIN PROBLEM!!!!!!
Cir = $('#canvas')[0].getContext("2d");
//JQUERY
//changing to Cir = canvas.getContext("2d"); causes the code to FAIL.
return setInterval(drawCIRCLE, 10);
}
function windowsize() {
//success with javascript
WIDTH.width = window.innerWidth;
HEIGHT.height = window.innerHeight;
WIDTH = window.innerWidth;
HEIGHT = window.innerHeight;
//Previous JQUERY:
// WIDTH = $("#canvas")[0].width = $(window).width();
// HEIGHT = $("#canvas")[0].height = $(window).height();
}
windowsize();
var x = WIDTH / 2 - 30; //divide by 2 start in middle of window
var y = HEIGHT / 2;
//THIS DRAWS THE CIRCLE
function circle() {
//Cir.clearRect(0, 0, WIDTH, HEIGHT);
Cir.beginPath();
Cir.arc(x, y, 10, 0, Math.PI * 2, true);
Cir.closePath();
Cir.fill();
}
// Initialization of the Block array, rendering of the gutter area and coordinate box
were here
//*********************************************************
// HERE IS THE CODE THAT RENDERS THE BALL MOVEMENT ETC.
//draw a circle
function drawCIRCLE() {
clear();
circle();
drawPADDLE(); //calls draw paddle function
drawGUTTER(); // calls draw gutter function
drawCOORBOX(); // calls draw coordinate box function
drawBRICKS(); //calls the function to draw the boxes
//have we hit a brick?
rowheight = brickheight + padding;
colwidth = brickwidth + padding;
row = Math.floor(y / rowheight);
col = Math.floor(x / colwidth);
//if so, reverse the ball and mark the brick as broken
if (y < numrows * rowheight && row >= 0 && col >= 0 && bricks[row][col] == 1) {
dy = -dy;
bricks[row][col] = 0;
}
if (x + dx > WIDTH || x + dx < 0) dx = -dx;
if (y + dy < 0) dy = -dy;
else if (y + dy > ((HEIGHT - paddleh) - ppoffset) || y + dy > HEIGHT) {
if (x > paddlex && x < paddlex + paddlew)
//switch! once first is true, then second goes
dy = -dy;
else if (y + dy > ((HEIGHT - paddleh) - ppoffset) && y + dy > HEIGHT) {
clearInterval(intervalId);
}
}
x += dx;
y += dy;
if (rightpress) paddlex += 5;
else if (leftpress) paddlex -= 5;
}
function clear() {
Cir.clearRect(0, 0, WIDTH, HEIGHT);
//Is this jquery? I suspect this part of the code making the circle rendering fail.
}
start();
init_paddle();
initbricks();
Ages ago I wrote a similar code in pure JavaScript here
this code uses pure javascript and no library.The code is well commented(I think :))
I generally attached events like this
document.onkeydown = function(e)
{
e = e || window.event;
switch (e.keyCode) { // which key was pressed?
case 32: // release ball.
if(!game.ball.isFree)
{
game.ball.isFree = true;
game.ball.directionX = game.ball.directionY = 1;
game.ball.x = game.ball.offsetLeft;
game.ball.y = game.screen.offsetHeight - game.ball.offsetTop;
}
break;
case 37: // left, rotate player left
game.bar.direction = -1;
break;
case 39: // right, rotate player right
game.bar.direction = 1;
break;
}
}
document.onkeyup = function(e)
{
e = e || window.event;
switch (e.keyCode)
{
case 37:
case 39:
game.bar.direction = 0;
break;
}
}
},
Ofcourse you have many other places which might need porting so a helpful break down of questions would be easier to answer :)
Hope this helps

Canvas drawing off center, Erase doesn't work correctly

I wrote a JavaScript that allows a user to draw with their mouse on an HTML5 canvas (similar to MS Paint).
Right now, I have 2 problems:
The drawing feature only works if the HTML5 canvas element is positioned at the top left corner (0, 0) of the web page, otherwise it doesn't work at all OR the drawing is off center.
I'm unable to erase the drawing. When I erase the drawing it erases BUT as soon as I start drawing again, it comes back.
My code is below:
HTML Canvas
<canvas id="can1" width="500" height="500"></canvas>1
JavaScript for Canvas Drawing
// Variables
var x1;
var y1;
var isPressed = false;
var myCanvas;
var myContext;
function startCanvas() {
// Canvas stuff
myCanvas = document.getElementById("can1");
myContext = myCanvas.getContext("2d");
// Specify a black background, and white lines that are 3 pixels thick.
myContext.fillStyle = '#fff';
myContext.strokeStyle = '#fff';
myContext.fillRect(0, 0, 500, 500);
myContext.lineWidth = 3;
myContext.fill();
}
function functionMouseDown(e) {
// Get coordinates
x1 = e.clientX
y1 = e.clientY;
isPressed = true;
}
function functionMouseMove(e) {
// If mouse is down and moved start drawing line
if (isPressed == true) {
drawLine(e);
}
}
function functionMouseUp() {
// Stop drawing line
isPressed = false;
//myContext.closePath();
//myContext.stroke();
}
function drawLine(e) {
// Draw line
var x = e.clientX;
var y = e.clientY;
myContext.strokeStyle = '#cc0000';
myContext.lineWidth = 1;
myContext.moveTo(x1, y1);
myContext.lineTo(x, y);
myContext.stroke();
// Set start coordinates to current coordinates
x1 = x;
y1 = y;
}
JavaScript that I use to erase canvas:
myContext.clearRect(0, 0, 500, 500);
I use the following function to accomplish this
function relMouseCoords(event){/*needs fixing for general case*/
var totalOffsetX = 0
var totalOffsetY = 0
var canvasX = 0
var canvasY = 0
var currentElement = this
do{
totalOffsetX += currentElement.offsetLeft
totalOffsetY += currentElement.offsetTop
}
while(currentElement = currentElement.offsetParent)
canvasX = event.pageX - totalOffsetX
canvasY = event.pageY - totalOffsetY
return {x:canvasX, y:canvasY}
}
HTMLCanvasElement.prototype.relMouseCoords = relMouseCoords;
then
var cord = e.target.relMouseCoords(e);
x1 = cord.x;
y1 = cord.y;
...
var cord = e.target.relMouseCoords(e);
var x = cord.x;
var y =cord.y;
http://jsfiddle.net/mowglisanu/u3rvT/1/
The simplest solution is to set the off set of the canvas using myCanvas.offsetLeft and myCanvas.offsetTop.

Detect mouse click location within canvas

I'm having a real issue trying to define a function for where I click on empty space. So far I have managed to define where I click on an object - of which there are 10 - but now I need a separate function for when I am not clicking on any of the objects. The general idea can be found at http://deciballs.co.uk/experience.html. The objects are the rings. My code is below... Any ideas?
var shapeObj = function (context, canvas, settingsBox, radius) {
this.ctx = context;
this.canvas = canvas;
this.sBox = settingsBox;
this.frequencies = new Array(220, 440, 1024, 2048);
this.cols = new Array(255, 225, 200, 175, 150);
this.strokes = new Array(1, 1.5, 2);
this.waves = new Array('sine', 'sawtooth', 'triangle', 'square');
this.properties = {
dur: Math.random()*0.5,
freq: this.frequencies[Math.floor(Math.random() * this.frequencies.length)],
radius: radius,
stroke: this.strokes[Math.floor(Math.random() * this.strokes.length)],
speed: Math.random()*6-3,
vol: Math.random()*10,
col1: this.cols[Math.floor(Math.random() * this.cols.length)],
col2: this.cols[Math.floor(Math.random() * this.cols.length)],
col3: this.cols[Math.floor(Math.random() * this.cols.length)],
alpha: 0,
wave: this.waves[Math.floor(Math.random() * this.waves.length)],
delay: 0
}
this.x = Math.random()*this.ctx.canvas.width;
this.y = Math.random()*this.ctx.canvas.height;
this.vx = 0.5;
this.vy = 1;
this.draw = function () {
this.ctx.beginPath();
this.ctx.arc(this.x, this.y, this.properties.radius, 0, Math.PI*2, false);
this.ctx.closePath();
this.ctx.stroke();
this.ctx.fill();
}
this.clickTest = function (e) {
var canvasOffset = this.canvas.offset();
var canvasX = Math.floor(e.pageX-canvasOffset.left);
var canvasY = Math.floor(e.pageY-canvasOffset.top);
var dX = this.x-canvasX;
var dY = this.y-canvasY;
var distance = Math.sqrt((dX*dX)+(dY*dY));
if (distance < this.properties.radius) {
this.manageClick();
} else {
this.properties.alpha = 0;
}
};
this.manageClick = function () {
this.sBox.populate(this.properties, this);
var divs = document.getElementsByTagName('section');
for(var i = 0, e = divs[0], n = divs.length; i < n; e = divs[++i]){
e.className='class2';
}
this.properties.alpha = 0.5;
}
}
Getting perfect mouse clicks is slightly tricky, I'll share the most bulletproof mouse code that I have created thus far. It works on all browsers will all manner of padding, margin, border, and add-ons (like the stumbleupon top bar).
// Creates an object with x and y defined,
// set to the mouse position relative to the state's canvas
// If you wanna be super-correct this can be tricky,
// we have to worry about padding and borders
// takes an event and a reference to the canvas
function getMouse(e, canvas) {
var element = canvas, offsetX = 0, offsetY = 0, mx, my;
// Compute the total offset. It's possible to cache this if you want
if (element.offsetParent !== undefined) {
do {
offsetX += element.offsetLeft;
offsetY += element.offsetTop;
} while ((element = element.offsetParent));
}
// Add padding and border style widths to offset
// Also add the <html> offsets in case there's a position:fixed bar (like the stumbleupon bar)
// This part is not strictly necessary, it depends on your styling
offsetX += stylePaddingLeft + styleBorderLeft + htmlLeft;
offsetY += stylePaddingTop + styleBorderTop + htmlTop;
mx = e.pageX - offsetX;
my = e.pageY - offsetY;
// We return a simple javascript object with x and y defined
return {x: mx, y: my};
}
You'll notice that I use some (optional) variables that are undefined in the function. They are:
stylePaddingLeft = parseInt(document.defaultView.getComputedStyle(canvas, null)['paddingLeft'], 10) || 0;
stylePaddingTop = parseInt(document.defaultView.getComputedStyle(canvas, null)['paddingTop'], 10) || 0;
styleBorderLeft = parseInt(document.defaultView.getComputedStyle(canvas, null)['borderLeftWidth'], 10) || 0;
styleBorderTop = parseInt(document.defaultView.getComputedStyle(canvas, null)['borderTopWidth'], 10) || 0;
// Some pages have fixed-position bars (like the stumbleupon bar) at the top or left of the page
// They will mess up mouse coordinates and this fixes that
var html = document.body.parentNode;
htmlTop = html.offsetTop;
htmlLeft = html.offsetLeft;
I'd recommend only computing those once, which is why they are not in the getMouse function.
You should really have a single function hat handles mouse clicks, calls getMouse once, and then goes though a list of objects, checking against each one with the x and y. Pseudocode:
function onMouseDown(e) {
var mouse = getMouse(e, canvas)
var l = myObjects.length;
var found = false;
// Maybe "deselect" them all right here
for (var i = 0; i < l; i++) {
if (distance sqrt to myObjects[i]) {
found = true;
myObjects[i].ManageClickOrWhateverYouWantHere()
}
break;
}
// And now we can know if we clicked on empty space or not!
if (!found) {
// No objects found at the click, so nothing has been clicked on
// do some relevant things here because of that
// I presume from your question this may be part of what you want
}
}

Categories