How can I get the position of an object in Raphael? I can get the size using getBBox(), but there appears to be no way to get the position?
getBBox() should give you position as well as x and y properties.
var bbox = el.getBBox();
alert([bbox.x, bbox.y]);
getBBox() returns an object with 5 properties. they are:
x
y
width
height
toString()
if you set getBBox( false ) it will return coordinate data for the object's position AFTER a transformation. set it to getBBox( true ) to return coordinates for the object prior to transformation
use like this ...
paper.Raphael(10,10,300,300);
circle.paper( 30, 55, 15 );
var circleBBox = circle.getBBox( false );
edit: just downloaded R 2.1 and i believe it has added x2 and y2 to the properties returned by getBBox()
Depending on what kind of shape it is, the documentation seems to say it can be accessed using the .attr() function. So, if it's a circle...
var x = myCircle.attr('cx'); //cx is the center-x-coordinate of the circle
var y = myCircle.attr('cy'); //same, for y
var r = myCircle.attr('r'); //Radius of circle.
A square would have attrs of x, y, width, height. Check the documentation for more info.
you may also access the x and y values this way:
var x = myCircle.attrs.x;
var y = myCircle.attrs.y
attributes x, y are those within the set. The issue here is that if the set gets translated somewhere else, the x and y given in by .getBBOx() do not account for the translation.
Raphael.transformPath(path, transform) can help by applying the same transforms that the set has...
to translate that point you can:
tp = Raphael.transformPath("M"+x+","+y, set.attr('transform'))
x = tp[0][1]
y = tp[0][2]
Related
Using fabric.js (1.7.11) , I am trying to have one object follow the rotation of another without grouping them, and while maintaining the relative position of the child object to the parent. So I believe I need to (1) set the rotation center of the "child" object to that of the "parent", then (2) as the parent object is rotating, apply that rotation delta to the child ( which may already start in a rotated state ). The end result is such that the child appears "stuck" to the parent ( like a sticky-note on a game-board, and you then rotate the game-board )
Here is the pseudo-code
canvas.on('object:rotating', canvasEvent_ObjectRotating);
function canvasEvent_ObjectRotating(e)
{
// set r2'2 center of rotation = r1's center of rotation
// r2.angle += ( delta of rotation of r1 angle )
}
Here is a fiddle:
https://jsfiddle.net/emaybert/bkb5awj6/
Any help with 1 or 2 would be appreciated. Either how to get the angle delta in the object:rotating callback, and/or how to pivot a object around an arbitrary point. I've seen the reference to fabric.util.rotatePoint and an example of how to rotate a Line using it, but not an object, and couldn't make that mental transformation.
Is this something that you're trying to do?
https://jsfiddle.net/logie17/ofr8e6qd/1/
function canvasEvent_ObjectRotating(e)
{
origX = r2.getCenterPoint().x;
origY = r2.getCenterPoint().y;
let topLeftPoint = new fabric.Point(origX, origY);
if (!previousAngle) {
previousAngle = r1.getAngle();
}
let angle = fabric.util.degreesToRadians(r1.getAngle() - previousAngle);
previousAngle = r1.getAngle();
let center = r1.getCenterPoint();
let origin = new fabric.Point(r1.left, r1.top);
let newCoords = fabric.util.rotatePoint(topLeftPoint,origin,angle);
r2.set({ left: newCoords.x, top: newCoords.y }).setCoords();
}
Im trying to apply a force to an object. To get it to move in the angle that my mouseposition is generating relative to the object.
I have the angle
targetAngle = Matter.Vector.angle(myBody.pos, mouse.position);
Now I need to apply a force, to get the body to move along that angle.
What do I put in the values below for the applyForce method?
// applyForce(body, position, force)
Body.applyForce(myBody, {
x : ??, y : ??
},{
x:??, y: ?? // how do I derive this force??
});
What do I put in the x and y values here to get the body to move along the angle between the mouse and the body.
To apply a force to move your object in that direction you need to take the sine and cosine of the angle in radians. You'll want to just pass the object's position as the first vector to not apply torque (rotation).
var targetAngle = Matter.Vector.angle(myBody.pos, mouse.position);
var force = 10;
Body.applyForce(myBody, myBody.position, {
x: cos(targetAngle) * force,
y: sin(targetAngle) * force
});
Also if you need it, the docs on applyForce() are here.
(I understand this question is old, I'm more or less doing this for anyone who stumbles across it)
You can rely on the Matter.Vector module and use it to substract, normalize and multiply positions vectors:
var force = 10;
var deltaVector = Matter.Vector.sub(mouse.position, myBody.position);
var normalizedDelta = Matter.Vector.normalise(deltaVector);
var forceVector = Matter.Vector.mult(normalizedDelta, force);
Body.applyForce(myBody, myBody.position, forceVector);
I am attempting to distort an image displayed within a canvas, so it looks like a "planet". However I am struggling to find away to deal with a distortion issue. The only solution coming to mind is to find a way to reduce the radiusDistance variable, the bigger it is. That said, I am unsure how to achieve this. Any suggestions?
Below is the math and objects I am currently using to achieve this:
polarArray = [];
var polar = function(a,r,c){ //polar object, similar to pixel object.
this.a = a; //angle
this.r = r; //radius (distance)
this.color = c; //color, stored using an object containg r,g,b,a variables
};
loopAllPixels(function(loop){//loop through every pixel, stored in a pixel array
var pixel = loop.pixel;
/*each pixel object is structured like this:
pixel {
x,
y,
color {
r,
g,
b,
a
}
}
*/
var angle = pixel.x/360*Math.PI;
var radiusDistance = pixel.y/Math.PI;
polarArray.push(new polar(angle,radiusDistance,pixel.color));//store polar coordinate pixel + colour.
pixel.color = new colorRGBA(255,255,255,255);//set background as white.
});
for (var i=0;i<polarArray.length;i++){//loop through polarArray (polar coordinate pixels + colour)
var p = polarArray[i]; //polar pixel
var x = (p.r*Math.cos(p.a))+(canvas.width/2); //x coordinate
var y = (p.r*Math.sin(p.a))+(canvas.height/2); //y coordinate
if (setpixel(x,y,p.color)==true){ //set pixel at location.
continue;
}
break;
}
updatePixelsToContext();//draw to canvas
And here is the effect it currently produces (note that I flip the image horizontally before applying it to the canvas, and in this example, I set the background with a magenta kind of colour, for better clarity of the issue):
Note:
I am intending for the warping effect, just not the "ripping" of the pixels, caused by not obtaining all the neccessary pixel data required.
Also bear in mind that speed and effeciency isn't my priority here as of yet.
When rotating a group in fabric.js, the .left and .top values of the group "jump". Is that a fabric.js bug or somehow explainable/intended?
group.on "moving", ->
#Yields values of about 100 px, also after the group was rotated
group.on "rotating", ->
#Yields values of about 130 px
JSFiddle -> http://jsfiddle.net/thomasf1/X76X9/2/
The difference is due to the originX and originY values changing upon rotation. originX and originY will become 'center' in place of their typical values of 'left' and 'top'. I encountered a similar issue where the positioning would change and found that I needed to be aware of the origin values.
I faced similar problem, but not with group, but single object.
Solution for me was not taking the top and left positions of rotated object, but top left Oocord x and y position.
For example:
fabricPlace.on('object:modified', function(event){
var object = event.target;
var save = {};
save.position = {};
save.id = object.id;
save.position.y = object.oCoords.tl.y;
save.position.x = object.oCoords.tl.x;
save.position.angle = object.angle;
console.log(object);
changeObject(save);
});
I'm trying to convert a lat/lon pair to a pixel coordinate. I have found this mercator projection but I don't understand the code. What is the factor,x_adj, y_adj variable?
When I run the code without those constants my lat/lon pair is not on my map and the x and y pixel coordinate is not what I want.
function get_xy(lat, lng)
{
var mapWidth=2058;
var mapHeight=1746;
var factor=.404;
var x_adj=-391;
var y_adj=37;
var x = (mapWidth*(180+lng)/360)%mapWidth+(mapWidth/2);
var latRad = lat*Math.PI/180;
var mercN = Math.log(Math.tan((Math.PI/4)+(latRad/2)));
var y = (mapHeight/2)-(mapWidth*mercN/(2*Math.PI));
return { x: x*factor+x_adj,y: y*factor+y_adj}
}
Source: http://webdesignerwall.com/tutorials/interactive-world-javascript-map/comment-page-1?replytocom=103225
[2] Covert latitude/longitude point to a pixels (x,y) on mercator projection
Where did those variables come from
These variables are chosen to match the computed coordinates to the background image of the map. If the projection parameters of the map were known, they could be computed. But I believe it is far more likely that they were obtained through trial and error.
How to compute a Mercator projection
If you want a more general method to describe the section of the world a given (not transverse) Mercator map shows, you can use this code:
// This map would show Germany:
$south = deg2rad(47.2);
$north = deg2rad(55.2);
$west = deg2rad(5.8);
$east = deg2rad(15.2);
// This also controls the aspect ratio of the projection
$width = 1000;
$height = 1500;
// Formula for mercator projection y coordinate:
function mercY($lat) { return log(tan($lat/2 + M_PI/4)); }
// Some constants to relate chosen area to screen coordinates
$ymin = mercY($south);
$ymax = mercY($north);
$xFactor = $width/($east - $west);
$yFactor = $height/($ymax - $ymin);
function mapProject($lat, $lon) { // both in radians, use deg2rad if neccessary
global $xFactor, $yFactor, $west, $ymax;
$x = $lon;
$y = mercY($lat);
$x = ($x - $west)*$xFactor;
$y = ($ymax - $y)*$yFactor; // y points south
return array($x, $y);
}
A demo run of this code is available at http://ideone.com/05OhG6.
Regarding aspect ratio
A setup with $xFactor != $yFactor produces a kind of stretched Mercator projection. This is not conformal (angle-preserving) any more. If one wants a true Mercator projection, one can omit any of the first six variable assignments, i.e. those defining the bounding box or those describing the size of the resulting map, and then use some computation too choose it satisfying $xFactor == $yFactor. But since the choice which to omit is kind of arbitrary, I feel that the above code is the most symmetric way to describe things.
Here's how to get the returned variables X and Y from the function you've found...
var xy=get_xy(56,34);
var X=xy.x;
var Y=xy.y;
Now X and Y contain the coordinates.