Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 10 years ago.
Improve this question
I am trying to make the following codes less ugly and not sure what to do. Are there any suggestions from you guys? Thanks
a lot.
if($element.is('builder') || $element.is('#options') ){
tooltipYPos=yPos + 35;
}
if($element.is('#button')){
tooltipXPos=xPos - 240;
}
if($element.is('#addn')){
tooltipXPos=xPos - 295;
tooltipYPos=yPos - 80;
}
if($element.is('#count')){
tooltipXPos=xPos + 180;
tooltipYPos=yPos - 90;
}
if($element.is('label')){
tooltipXPos=xPos + 80;
tooltipYPos=yPos - 90;
}
The general cure is to move the problem from code to data. One solution (demonstrated below) is to set up a JavaScript associative array keyed on the various ID tags and the values are value pairs X and Y offsets (in some cases one or the other is 0). At usage time, loop through the keys of the associative array, looking for matches. If so, add the X and Y offsets from the associative array onto toolTipXPos and toolTipYPos.
This will keep your offsets in one place, out of the way, and the code to manipulate them short and simple.
(untested, naturally)
// This can be stashed away anywhere.
var a = {
'#te_classbuilder': { X: 0, Y: 35 },
'#te_options': { X: 0, Y: 35 },
'#lesson-details-extend-button': { X: -240, Y: 0 },
'#asset-list-asset-add-button': { X: 295, Y: -80 },
'#asmnt_option_label_q_count': { X: 180, Y: -90 },
"label": { X: 80, Y: -90 }
}
// Put this where you need the actual evaluation to happen
jQuery.each(data, function(key, value) {
if ( $element.is(key) ) {
tooltipXPos = xPos + value.X;
tooltipYPos = yPos + value.Y;
}
});
Edit: changed to loop, so that label could be tested for, and not #label.
Another option would be to make use of jQuery's .data function to store the appropriate X and Y values on the elements themselves, like so:
$('label').data({ x: 80, y: -90 });
$('#te_classbuilder, #te_options').data({ x: 0, y: 35 });
$('#lesson-details-extend-button').data({ x: -240, y: 0 });
$('#asset-list-asset-add-button').data({ x: -295, y: -80 });
$('#asmnt_option_label_q_count').data({ x: 180, y: -90 });
Then, when it comes time to modify your tooltip position values, no conditional statements are required. Simply retrieve the x and y data attributes from $element.
tooltipXPos = xPos + $element.data('x');
tooltipYPos = yPos + $element.data('y');
This, of course, assumes that any element that may be assigned to $element will have previously had .data called on it with appropriate x and y values.
Can you work out the height/width of $element and then alter tooltipXPos/tooltipYPos accordingly, instead of hard-coding the deltas?
In first if you can combine conditions:
if ($element.is('#te_classbuilder, #te_options')) {
tooltipYPos = yPos + 35;
}
If we could not make some big changes then I would write it this way:
if ($element.is('#te_classbuilder, #te_options')) tooltip = { x: 0, y: yPos + 35 };
if ($element.is('#lesson-details-extend-button')) tooltip = { x: xPos - 240, y: 0 };
if ($element.is('#asset-list-asset-add-button')) tooltip = { x: xPos - 295, y: yPos - 80 };
if ($element.is('#asmnt_option_label_q_count')) tooltip = { x: xPos + 180, y: yPos - 90 };
if ($element.is('label')) tooltip = { x: xPos + 80; y: yPos - 90 };
Related
This question already has answers here:
How to find the coordinate that is closest to the point of origin?
(2 answers)
Closed 4 years ago.
I am wondering how can I calculate my coordinates to an array of coordinates and find out which one is closest?
Lets say:
var player = {
x: 10,
y: 20
}
var box = [
{x: 17, y: 30},
{x: 41, y: 14},
{x: 20, y: 30}
];
So my player stays on 10, 20. And i have 3 different boxed, and i need to find out which one is closest. Is there any easy way to caluculate that?
You could calculate the distance and reduce the array by checking each distance and return the object with the shortest.
function getDistance(p1, p2) {
return Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2))
}
var player = { x: 10, y: 20 },
box = [{ x: 17, y: 30 }, { x: 41, y: 14 }, { x: 20, y: 30 }];
console.log(box.reduce((a, b) => getDistance(a, player) < getDistance(b, player) ? a : b));
To find the least distance (the closest point) just find the least difference in the sum of the squares of their x and y offsets. You don't need to take the square root to find the actual distance as per Pythagorous's theorom. If you have trouble writing the code don't forget to include what you have tried.
You can use 2 points canvas formla and sort it based on distance
let positions = [
{x: 17, y: 30},
{x: 41, y: 14},
{x: 20, y: 30}
];
let x=10;
let y= 20;
let positions_close=positions.sort(p=>Math.hypot(p.x-x, p.y-y));
console.log(positions_close[0]);
//check the distance
let distances=positions.map(p=>Math.hypot(p.x-x, p.y-y));
console.log(distances);
I have some javascript code that tries to place some objects above each other relative from a center point in this case 0,0
The thing is that the amount of objects, size of the objects, and spacing between the objects are all variable.
See this image below that explains my situation the best (hopefully ;)):
So in this case the center point is the green dot and the mesh center positions are the yellow dots.
The Mh stands for Mesh Height (variable)
The Sh stands for Spacing height (variable)
I tried to show the logic behind the calculation of the yellow dots. But when i try to implement this in javascript it works for 3 lines but it breaks on other amount of lines.
This is what i have tried so far:
var data = {
text : ["THE NEXT","POINT","OF VIEW"],
size : 5,
height : 2,
curveSegments : 12,
line_height : 2
};
function generateTextGeometry(mesh) {
var scaled_lineheight = map_r(data.size, 2, 75, 0.5, 20);
var y_start = (0 - data.text.length * data.size / 2 - data.size / 2 - (data.text.length - 1) * scaled_lineheight)/2;
var loader = new THREE.FontLoader();
loader.load( 'data/suisse_2.json', function ( font ) {
for (var i = data.text.length - 1; i >= 0; i--) {
var geometry = new THREE.TextGeometry( data.text[i], {
font: font,
size: data.size,
height: data.height,
curveSegments: data.curveSegments
});
geometry.center();
mesh.children[i].geometry = geometry;
mesh.children[i].position.y = y_start;
console.log(mesh.children[i].position);
if (i < data.text.length) {
y_start += (data.size + scaled_lineheight);
}else{
y_start += data.size;
}
}
console.log('-----------------------');
});
}
and When i console.log the position for 3 lines it is ok:
p {x: 0, y: -6.301369863013699, z: 0}
p {x: 0, y: 0, z: 0}
p {x: 0, y: 6.301369863013699, z: 0}
but for any other amount of lines it is wrong:
p {x: 0, y: -4.4006849315068495, z: 0}
p {x: 0, y: 1.9006849315068495, z: 0}
So my final question is how do i always get the yellow positions on the right location relative from the green center? What is wrong in my current logic?
If anything is unclear please let me know! So i can clarify.
So after reading my own question about 20 times. The light shined upon my brains haha.
So i just made a mistake when calculating the initial start Here is the updated line:
var y_start = 0 - (((data.text.length - 1) * data.size) + ((data.text.length - 1) * scaled_lineheight))/ 2;
I'd like to be able to passively tween a property on my object, so that during the tween I can update this object and TweenLite will carry on.
For example, the following code will tween coordinates in an object from 0 to 15 over 15 seconds. Whilst this is happening, I also want to update the x and y variables of target.position, and I cannot do this as TweenLite seems to "hog" the object until it's done (as in, until 15 seconds have passed).
// target.position starts at { x:0, y: 0 }
TweenLite.to(target.position, 15, {
x: 15,
y: 15,
ease: Power4.easeOut
})
// for examples sake i'd like to do the following, yet it does not have an effect
setTimeout(function(){ target.position.x += 10 }, 1000)
setTimeout(function(){ target.position.y += 15 }, 2500)
setTimeout(function(){ target.position.x -= 17 }, 7500)
I solved my question by using the ModifiersPlugin that Tahir Ahmed recommended.
The ModifiersPlugin gives you two values in the callback, it's current value and the running total of the tween, I have named this cX and rT. What is returned in the callback will used by TweenLite in the next call, and given again as rT. This is handy so I can let ModifiersPlugin look after it's own running total, tween to x and y yet not actually update the target.position.. pretty useful.
All I do is work out the change needed, so the delta, which I call dX and add that to my target position, and passively tweening a variable is possible!
My code now looks something like this:
// just some dummy example data
target.position.x = 200
target.position.y = 300
x = 300
y = 400
TweenLite.to({ x: target.position.x, y: target.position.y }, 0.3, {
x: x,
y: y,
ease: Power4.easeOut,
modifiers: {
x: function(cX, rT) {
// get delta (current change in) value from running total - current
const dX = cX - rT.x
target.position.x += dX
// update running total with current delta
rT.x += dX
return rT.x
},
y: function(cY, rT) {
const dY = cY - rT.y
target.position.y += dY
rT.y += dY
return rT.y
}
}
})
I saving polygon value inside angular $localStorage .
Once fabric js draw the object . my $localStorage changed.
var arr = [{
x: 81,
y: 58
}, {
x: 221,
y: 23
}, {
x: 247,
y: 158
}, {
x: 100,
y: 219
}, {
x: 81,
y: 58
}];
if(!$localStorage.mask)
$localStorage.mask = arr;
Is it a bug ?
Here the plunker
Indeed, FabricJS seems to modify the given points array for its internal purposes (i.e. offset), specifically in this piece of code (from https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.5.0/fabric.js):
...
//misko321: only for reference of what minX, minY, width and height are
_calcDimensions: function() {
var points = this.points,
minX = min(points, 'x'),
minY = min(points, 'y'),
maxX = max(points, 'x'),
maxY = max(points, 'y');
this.width = (maxX - minX) || 0;
this.height = (maxY - minY) || 0;
this.minX = minX || 0,
this.minY = minY || 0;
},
_applyPointOffset: function() {
// change points to offset polygon into a bounding box
// executed one time
this.points.forEach(function(p) {
p.x -= (this.minX + this.width / 2);
p.y -= (this.minY + this.height / 2);
}, this);
},
...
Together with the fact that ngStorage observes for any changes to the added objects, it updates those modified (internally by Fabric.js) coordinates.
The cleanest solution that comes to my mind at the moment is to copy the arr object (ref. Most elegant way to clone a JavaScript object) and send one of the objects to ngStorage and the other one to FabricJS.
Nevertheless, it would be nice, if ngStorage supported some sort of freeze() method, that would disable the AngularJS watch on this object, thus preventing it from further modifications.
I know there are many many questions about sorting javascript arrays by multiple values, but none of the answers solved my problem.
I have an array of coordinates like:
x | y
--------
10 20
12 18
20 30
5 40
100 2
How can I get the coordinate that is closest to the point of origin?
Calculate the distance of each point using
Math.sqrt( Math.pow(x, 2) + Math.pow(y, 2) );
Take the result that's the lowest
var points = [
{x: 10, y: 20},
{x: 12, y: 18},
{x: 20, y: 30},
{x: 5, y: 40},
{x: 100, y: 2}
];
function d(point) {
return Math.pow(point.x, 2) + Math.pow(point.y, 2);
}
var closest = points.slice(1).reduce(function(min, p) {
if (d(p) < min.d) min.point = p;
return min;
}, {point: points[0], d:d(points[0])}).point;
closest;
// {x: 12, y:18}
You'll notice that we're skipping the Math.sqrt step here. As Mark Setchell points out, calculating the square root is a sort of "lowest common denominator" operation; We can still determine the closest point by getting the smallest x^2 + y^2 value.
For each x,y pair, square x, square y and add together. Smallest number is nearest to the origin.