I realise the title might be misleading, but did not know how to phrase it any other way.
The problem im facing is that I draw up a SVG panel from a JSON object, and in that object there is moving parts that is being controlled by a server that is sending values to us. I get the moving part to be in the right position, but after awhile it keeps adding X position to itself so much that it goes out of the border, which its not meant to do. Basically what it does is add X+X+X repeatedly from the initialposition, but I want it to consider the initialposition first when calculating a new position to be at.
Here is the function behind that, I tried having an if statement that checked for a variable standardX and standardY, while they were set as undefined it would set obj.transform.baseVal.getItem(length).matrix.e as the value to it, but that did not work.
Any tips on any workaround?
Thanks in advance.
var moveX = function(elem, i) {
return function () {
var stepvalue = 6.25;
var step = "0";
var x1 = "0";
var y1 = "0";
var obj = elem.dyn[i].obj;
var standardX = obj.transform.baseVal.getItem(length).matrix.e;
var standardY = obj.transform.baseVal.getItem(length).matrix.f;
console.log(elem.value);
if (elem.value <= elem.dyn[i].rlow) {
step = 0;
x1 = standardY;
y1 = standardX;
obj.setAttribute("transform", "translate("+ x1 + "," + y1 +")");
} else if (elem.value > elem.dyn[i].rlow && elem.value <= elem.dyn[i].rhigh) {
step = stepvalue * elem.value;
x1 = step -25;
y1 = standardY;
x1 += standardX;
obj.setAttribute("transform", "translate("+ x1 + "," + y1 +")");
} else {
step = stepvalue * elem.dyn[i].rhigh;
x1 = step -25;
y1 = standardY;
x1 += standardX;
obj.setAttribute("transform", "translate("+ x1 + "," + y1 +")");
}
}};
Not really sure as we don't have access to the whole code.
From what I gather the problem you're having is that you are initializing standardX and standardY at every call of the function.
You might want to initialize them when you declare the function, like so :
var moveX = function(elem, i) {
return function () {
var stepvalue = 6.25;
var step = "0";
var x1 = "0";
var y1 = "0";
var obj = elem.dyn[i].obj;
console.log(elem.value);
if (elem.value <= elem.dyn[i].rlow) {
step = 0;
x1 = moveX.standardY;
y1 = moveX.standardX;
obj.setAttribute("transform", "translate("+ x1 + "," + y1 +")");
} else if (elem.value > elem.dyn[i].rlow && elem.value <= elem.dyn[i].rhigh) {
step = stepvalue * elem.value;
x1 = step -25;
y1 = moveX.standardY;
x1 += moveX.standardX;
obj.setAttribute("transform", "translate("+ x1 + "," + y1 +")");
} else {
step = stepvalue * elem.dyn[i].rhigh;
x1 = step -25;
y1 = moveX.standardY;
x1 += moveX.standardX;
obj.setAttribute("transform", "translate("+ x1 + "," + y1 +")");
}
};
};
moveX.standardX = obj.transform.baseVal.getItem(length).matrix.e;
moveX.standardY = obj.transform.baseVal.getItem(length).matrix.f;
Another option might be the following, if it needs some kind of dynamic initialization.
var moveX = function(elem, i) {
var standardX = obj.transform.baseVal.getItem(length).matrix.e;
var standardY = obj.transform.baseVal.getItem(length).matrix.f;
return function () {
var stepvalue = 6.25;
var step = "0";
var x1 = "0";
var y1 = "0";
var obj = elem.dyn[i].obj;
console.log(elem.value);
if (elem.value <= elem.dyn[i].rlow) {
step = 0;
x1 = standardY;
y1 = standardX;
obj.setAttribute("transform", "translate("+ x1 + "," + y1 +")");
} else if (elem.value > elem.dyn[i].rlow && elem.value <= elem.dyn[i].rhigh) {
step = stepvalue * elem.value;
x1 = step -25;
y1 = standardY;
x1 += standardX;
obj.setAttribute("transform", "translate("+ x1 + "," + y1 +")");
} else {
step = stepvalue * elem.dyn[i].rhigh;
x1 = step -25;
y1 = standardY;
x1 += standardX;
obj.setAttribute("transform", "translate("+ x1 + "," + y1 +")");
}
};
};
To be noted that all of this is possible because you can access variables declared outside the current function.
You can find more on function scope and context switch in this article.
Related
The Bug I encountered is when I was making the collision detection system for detecting collision between the player and squares drawn using a for statement, It picks up the collisions perfectly fine I know this because I have it logging to the console whenever it detects a collision along with the side that the collision was one. But after that console log, it should stop the player movement by setting a variable I am using for movement from 10 to 0 but it isn't, Sorry for adding all the code I just have no clue as to why the problem exists in the first place
var frame = setInterval(draw,10);
var canvas = document.getElementById('Canvas');
var ctx = canvas.getContext('2d');
var pos = [[300,250],[500,250],[700,250]]
var height = 150;
var width = 150;
var plyr = {pos:[0,0],width: 50,height: 50};
var a = {up: 10, down:10, left:10, right:10};
function draw(){
canvas.width = canvas.width
for(var i=0;i < pos.length;i++){
ctx.rect(pos[i][0],pos[i][1],height,width);
ctx.stroke();
}
ctx.rect(plyr.pos[0],plyr.pos[1],plyr.width,plyr.height);
ctx.stroke();
}
document.onkeydown = checkKey;
function checkKey(e) {
e = e || window.event;
if (e.keyCode == '38') {/*up*/plyr.pos[1] -= a.up;}
else if (e.keyCode == '40') {/*down*/plyr.pos[1] += a.down;}
else if (e.keyCode == '37') {/*left*/plyr.pos[0] -= a.left;d=1;}
else if (e.keyCode == '39') {/*right*/plyr.pos[0] +=
a.right;d=0;}
for(var c=0;c < pos.length;c++){
touch(plyr.pos[0],plyr.pos[1],plyr.width,plyr.height,pos[c]
[0],pos[c][1],height,width);
}
}
function touch(x1,y1,width1,height1,x2,y2,width2,height2){
if( x1 + width1 > x2 && x2 + width2 > x1 && y1 + height1 > y2 &&
y2 + height2 > y1){
if( y1 + height1 > y2 && y2 + 20 > y1 + height1 )
{console.log('touch down');a.down = 0;}
else if( y2 + height2 > y1 && y1 + 20 > y2 + height2)
{console.log('touch up');a.up = 0;}
else if( x1 + width1 > x2 && x2 + 20 > x1 + width1)
{console.log('touch right');a.right = 0;}
else if( x2 + width2 > x1 && x1 + 20 > x2 + width2)
{console.log('touch left');a.left = 0;}
}
else{
a.up = 10;
a.down = 10;
a.left = 10;
a.right = 10;
}
}
<!doctype html>
<html>
<head>
<title>Testing</title>
</head>
<body>
<canvas id="Canvas" width="1000" height="500"></canvas>
</body>
</html>
Perhaps a better way to solve this, is to set the players position to the edge of the object on collision.
function touch(x1,y1,width1,height1,x2,y2,width2,height2){
if( x1 + width1 > x2 && x2 + width2 > x1 && y1 + height1 > y2 &&
y2 + height2 > y1){
if( y1 + height1 > y2 && y2 + 20 > y1 + height1 )
{console.log('touch down');plyr.pos[1] = y2-plyr.height;}
else if( y2 + height2 > y1 && y1 + 20 > y2 + height2)
{console.log('touch up');plyr.pos[1] = y2+height2;}
else if( x1 + width1 > x2 && x2 + 20 > x1 + width1)
{console.log('touch right');plyr.pos[0] = x2-plyr.width;}
else if( x2 + width2 > x1 && x1 + 20 > x2 + width2)
{console.log('touch left');plyr.pos[0] = x2+plyr.width;}
}
}
I have a div with id, lines. It contains a sketched(programmatically) map. I keep track of the mouse click coordinates so that I can display tooltips at clicked position. I need to include the content of signo[i] and status[i] in the tooltip. Could you tell me how to do that in javascript?
Code :
<div id="lines" onclick="showCoords(event)">
<script>
b = xmlDoc.getElementsByTagName("TRACK");
jQuery.ajax({
type: "POST",
url: "WebForm1.aspx/GetStations", //It calls our web method
contentType: "application/json; charset=utf-8",
data: JSON.stringify({ myArray1: dl_id_track, myArray2: dl_id_gate, myArray3: dl_id_point}),
dataType: "json",
async: true,
success: function (data) {
if (data != null) {
var len = data.d.length;
for (var i = 0; i < len; i++) {
signo[i] = data.d[i].signo;
status[i] = data.d[i].status;
}
function showCoords(event) {
var xcoord = event.clientX;
var ycoord = event.clientY;
var coords = "X coords: " + xcoord + ", Y coords: " + ycoord;
document.getElementById("demo1").innerHTML = coords;
for (var i = 0; i < b.length; i++) {
var x1 = parseInt(left_track[i]) + parseInt(x1_track[i]);
var y1 = parseInt(top_track[i]) + parseInt(y1_track[i]);
var x2 = parseInt(left_track[i]) + parseInt(x2_track[i]);
var y2 = parseInt(top_track[i]) + parseInt(y2_track[i]);
var slope = (y2 - y1) / (x2 - x1);
var line = (slope * xcoord) - ycoord - x1 + y1;
if (line == 0) {
asset = "track";
}
}
}
</script>
use title Attribute
Below content here will show as tool tip
function showCoords(event) {
var xcoord = event.clientX;
var ycoord = event.clientY;
var coords = "X coords: " + xcoord + ", Y coords: " + ycoord;
document.getElementById("demo1").innerHTML = coords;
for (var i = 0; i < b.length; i++) {
var x1 = parseInt(left_track[i]) + parseInt(x1_track[i]);
var y1 = parseInt(top_track[i]) + parseInt(y1_track[i]);
var x2 = parseInt(left_track[i]) + parseInt(x2_track[i]);
var y2 = parseInt(top_track[i]) + parseInt(y2_track[i]);
var slope = (y2 - y1) / (x2 - x1);
var line = (slope * xcoord) - ycoord - x1 + y1;
if (line == 0) {
asset = "track";
}
}
document.getElementById("lines").title =coords;
}
use this to position you tooltip
HTML-Tooltip position relative to mouse pointer
I am new to javascript and unfortunately (or fortunately?) have tackle with the issue of asynchronous events in js. I know we should use callbacks and I did try using them with no good results.
There are 3 functions that each fills a bar, how could I use callbacks to make the bars fill one after the other?
var x1 = 0;
var x2 = 0;
var x3 = 0;
var lifeRemaining = 100 - (getPercentage(age, lifeExpectancy) + getPercentage(
effLifeRemaining, lifeExpectancy));
function ShowBar1() {
if (x1 < getPercentage(age, lifeExpectancy)) {
x1 += 1;
var y1 = "width: " + x1.toString() + "%";
progressBar1.setAttribute("style", y1);
progressBar1.textContent = x1.toString() + "%";
}
}
function ShowBar2() {
if (x2 < getPercentage(effLifeRemaining, lifeExpectancy)) {
x2 += 1;
var y2 = "width: " + x2.toString() + "%";
progressBar2.setAttribute("style", y2);
progressBar2.textContent = x2.toString() + "%"
}
}
function ShowBar3() {
if (x3 < lifeRemaining) {
x3 += 1;
var y3 = "width: " + x3.toString() + "%";
progressBar3.setAttribute("style", y3);
progressBar3.textContent = x3.toString() + "%";
}
}
setInterval(ShowBar1, 50);
setInterval(ShowBar2, 50);
setInterval(ShowBar3, 50);
You do not need to use interval if you have callback. You can refer below for sample callback:
var x1 = 0;
var x2 = 0;
var x3 = 0;
var lifeRemaining = 100 - (getPercentage(age, lifeExpectancy) + getPercentage(
effLifeRemaining, lifeExpectancy));
function ShowBar1(callback) {
if (x1 < getPercentage(age, lifeExpectancy)) {
x1 += 1;
var y1 = "width: " + x1.toString() + "%";
progressBar1.setAttribute("style", y1);
progressBar1.textContent = x1.toString() + "%";
}
return callback;
}
function ShowBar2(callback) {
if (x2 < getPercentage(effLifeRemaining, lifeExpectancy)) {
x2 += 1;
var y2 = "width: " + x2.toString() + "%";
progressBar2.setAttribute("style", y2);
progressBar2.textContent = x2.toString() + "%"
}
return callback;
}
function ShowBar3() {
if (x3 < lifeRemaining) {
x3 += 1;
var y3 = "width: " + x3.toString() + "%";
progressBar3.setAttribute("style", y3);
progressBar3.textContent = x3.toString() + "%";
}
}
var bar2 = ShowBar1(ShowBar2);
var bar3 = bar2(ShowBar3);
bar3();
You can refer below for callback that executes the 3 function with a 50 ms delay. I just remove extra code for simplification.
function ShowBar1(callback, callback2) {
console.log('ShowBar1');
callback(callback2);
}
function ShowBar2(callback) {
console.log('ShowBar2');
callback();
}
function ShowBar3() {
console.log('ShowBar3');
setTimeout(ShowBar1, 50, ShowBar2, ShowBar3);
}
ShowBar1(ShowBar2, ShowBar3);
All your three Intervals running together forever in parallel
You have to do something like this:
var x1 = 0;
var x2 = 0;
var x3 = 0;
var lifeRemaining = 100 - (getPercentage(age, lifeExpectancy) + getPercentage(
effLifeRemaining, lifeExpectancy));
var curInterval;
curInterval = setInterval(ShowBar1, 50)
function ShowBar1() {
if (x1 < getPercentage(age, lifeExpectancy)) {
x1 += 1;
var y1 = "width: " + x1 + "%";
progressBar1.setAttribute("style", y1);
progressBar1.textContent = x1 + "%";
} else {
clearInterval(curInterval);
curInterval = setInterval(ShowBar2, 50)
}
}
function ShowBar2() {
if (x2 < getPercentage(effLifeRemaining, lifeExpectancy)) {
x2 += 1;
var y2 = "width: " + x2 + "%";
progressBar2.setAttribute("style", y2);
progressBar2.textContent = x2 + "%"
} else {
clearInterval(curInterval);
curInterval = setInterval(ShowBar3, 50)
}
}
function ShowBar3() {
if (x3 < lifeRemaining) {
x3 += 1;
var y3 = "width: " + x3 + "%";
progressBar3.setAttribute("style", y3);
progressBar3.textContent = x3 + "%";
} else {
clearInterval(curInterval);
}
}
Here, finally solved it, using call backs, all three bars start filling one after the other, see
function ShowBar1(callback) {
var x1 = 0;
var y1;
progressBar2.setAttribute("style", "width: 0%");
progressBar3.setAttribute("style", "width: 0%");
var test = setInterval(function() {
x1 += 1;
y1 = "width: " + x1.toString() + "%";
progressBar1.setAttribute("style", y1);
progressBar1.textContent = x1.toString() + "%";
if (x1 === getPercentage(age, lifeExpectancy)) {
clearInterval(test);
callback(); //bar 2 starts filling using callback
}
}, 50);
}
function ShowBar2() {
var x2 = 0;
var y2;
var test2 = setInterval(function() {
x2 += 1;
y2 = "width: " + x2.toString() + "%";
progressBar2.setAttribute("style", y2);
progressBar2.textContent = x2.toString() + "%"
if (x2 === getPercentage(effLifeRemaining,
lifeExpectancy)) {
clearInterval(test2); //bar 3 starts filling from this point
var x3 = 0;
var y3;
var test3 = setInterval(function() {
x3 += 1;
y3 = "width: " + x3.toString() + "%";
progressBar3.setAttribute("style", y3);
progressBar3.textContent = x3.toString() +
"%";
if (x3 == lifeRemaining) {
clearInterval(test3);
}
}, 50);
}
}, 50);
}
ShowBar1(ShowBar2);
I've got some code for part of a game where an absolutely positioned div (id = 'cursor') follows your mouse's cursor around. When the cursor div runs into another div (class = 'thing') (these are the white boxes in the jsfiddles), the cursor speed changes.
In this JSfiddle you'll see that it works perfectly fine. When cursor hits thing, cursor speeds up. This is the conditional used to change the speed (newSpeed is what determines the speed for cursor):
if (b1 < y2 || y1 > b2 || r1 < x2 || x1 > r2){
newSpeed = 200;
changeCursorSpeed();
} else {
newSpeed = 12;
changeCursorSpeed();
console.log('hit');
}
The problem I'm having is when I switch around the values for newSpeed in the conditional:
if (b1 < y2 || y1 > b2 || r1 < x2 || x1 > r2){
newSpeed = 12;
changeCursorSpeed();
} else {
newSpeed = 200;
changeCursorSpeed();
console.log('hit');
}
Here's the JSFiddle for this. This causes the collision to not change newSpeed in the else part of the condition. However, using console.log('hit'), you can clearly see that the collision is detected.
Logically, this doesn't seem to make sense. I'd like to hear input from others about this as well as possible solutions. Thanks for any help.
Here's the entire code for the collision detection. The JSfiddles have a more complete code for the program.
var newSpeed;
var newInt = setInterval(function() {
function collision($cursor, $thing) {
var x1 = $cursor.offset().left;
var y1 = $cursor.offset().top;
var h1 = $cursor.outerHeight(true);
var w1 = $cursor.outerWidth(true);
var b1 = y1 + h1;
var r1 = x1 + w1;
$thing.each(function(i){
var x2 = $(this).offset().left;
var y2 = $(this).offset().top;
var h2 = $(this).outerHeight(true);
var w2 = $(this).outerWidth(true);
var b2 = y2 + h2;
var r2 = x2 + w2;
if (b1 < y2 || y1 > b2 || r1 < x2 || x1 > r2){
newSpeed = 12;
changeCursorSpeed();
} else {
newSpeed = 200;
changeCursorSpeed();
console.log('hit');
}
});
function changeCursorSpeed(){
$xp += (($mouseX - $xp)/newSpeed);
$yp += (($mouseY - $yp)/newSpeed);
$("#cursor").css({left:$xp +'px', top:$yp +'px'});
}
}
$(collision($('#cursor'), $('.thing')));
}, 20);
I have the following javascript code that runs fine if called outside the jQuery function on the bottom. I don't know what I am doing wrong.
Bresenham Algorithm:
function bresenham(x0,y0,x1,y1){
var bresenham = [];
var x = 0;
var dx = x1-x0;
var dy = y1-y0;
var D = 2 * dy - dx;
bresenham.push(x0 + "," + y0);
var y = y0;
for (x = x0+1;x<=x1;x++){
if (D>0){
y = y+1;
bresenham.push(x + "," + y);
D = D + (2*dy - 2*dx);
} else {
bresenham.push(x + "," + y);
D = D + (2*dy);
}
}
return bresenham;
};
JQuery:
$(document).ready(function(){
$(".button").click(function(){
$("div#output p").remove();
var x0 = $('input[name=x0]').val();
var y0 = $('input[name=y0]').val();
var x1 = $('input[name=x1]').val();
var y1 = $('input[name=y1]').val();
var bres = bresenham(x0,y0,x1,y1);
console.log(bres);
});
});
If I input: x0 = 1, y = 0 and x1 = 15, y2 = 9
it outputs: ["1,0", "11,01", "12,01", "13,011", "14,0111", "15,0111"]
I would change
$(document).ready(function(){
$(".button").click(function(){
$("div#output p").remove();
var x0 = $('input[name=x0]').val();
var y0 = $('input[name=y0]').val();
var x1 = $('input[name=x1]').val();
var y1 = $('input[name=y1]').val();
var bres = bresenham(x0,y0,x1,y1);
console.log(bres);
});
});
to
$(document).ready(function(){
$(".button").click(function(){
$("div#output p").remove();
var x0 = parseInt($('input[name=x0]').val());
var y0 = parseInt($('input[name=y0]').val());
var x1 = parseInt($('input[name=x1]').val());
var y1 = parseInt($('input[name=y1]').val());
var bres = bresenham(x0,y0,x1,y1);
console.log(bres);
});
});