raphael question - using animateAlong - javascript

I am using raphael to do some SVG animation and cannot seem to get the function animateAlong to work. I continue to get the error "attrs[0] is undefined" referencing line 3450 of the un-compressed raphael code.
Basically, I create a circle with a given center and then want to animate an image around that path. Here is that simple code:
var circle = paper.circle(circleCenterX, circleCenterY, circleRadius);
I then clone an image (since I plan to have a number of these on this path) and place at the edge of the circle:
var wheelClone = wheel.clone();
var wheelRadius = parseInt(wheel8ImageWidth/2);
wheelClone
.translate((circleCenterX + circleRadius)-3, circleCenterY-wheelRadius);
where I init circleCenterX earlier with circleCenterX = circle.attr(cx);
This all works fine with image placed correctly - but it errors on animateAlong.
I have studied as many examples as i can find and have dissected the documentation but cannot get the hang here.
So, I simply try to call the function but have no earthly idea what the documentation is referring to. The documentation animates a dot around a path but refers to two variables - rx and ry which I cannot suss out - both in an init function and then with the callback.
Here is what I have - - where the rx and ry and just made up as I have no idea what they refer to.
var wheelAttr = {
rx: 5,
ry: 3
};
wheelClone.attr(wheelAttr).animateAlong(circle, 2000, true, function() {
wheel.attr({rx: 4, ry: 4});
});
My current jsFiddle is a bit of a mess at the moment and I can clean it up, but I suspect that there is some obvious thing here?
Thanks to all
S

I don't think a circle is actually a valid path (i.e, something you can pass to animateAlong()). I think you need to create a path that is circular. See the following:
svg-animation-along-path-with-raphael
Hopefully, it will help.

Related

Connect 2 svg elements

There has been a lot of questions regarding the coördinate system of svg elements but no one has got me solving my problem.
Look at this fiddle:
https://jsfiddle.net/archemedia/4f54jnm8/
In the startup function, I added connect("A", "B") which connects element A and B with the line.
When I try to connect("A", "D") the line doesn't position correctly, due to the transform attribute of element D.
Could someone provide me with a clear solution?
I don't want to use a svg library, I just want plain javascript code which solves the problem, preferably by adding it to the fiddle.
Many thanks
Your getMid function needs to account for the transform matrix of the rectangles.
function getMid (rect, svg) {
let point = svg.createSVGPoint();
point.x = rect.x.baseVal.value + rect.width.baseVal.value / 2;
point.y = rect.y.baseVal.value + rect.height.baseVal.value / 2;
return point.matrixTransform(svg.getScreenCTM().inverse().multiply(rect.getScreenCTM()));
}
Note the new svg parameter. This is your SVGSVGElement. In the fiddle, you can grab it with document.getElementById('Laag_1').
Normally, I'd cite the relevant pages on MDN, but their SVG documentation is lacking. I had to piece this together from a couple of SO questions. The key was searching "svg get transform matrix" and following the rabbit hole from there.
This is by far the most correct and useful answer and it might server the community. I've searched a lot and got multiple workarounds with regex and custom functions, all of which didn't work. My problem is finally solved.
I updated the fiddle with the answer from AuxTaco and the getCTM() tweak suggested by jcaron. Thanks everyone!
function getMid(rect, svg){
var point = svg.createSVGPoint();
point.x = rect.x.baseVal.value + rect.width.baseVal.value / 2;
point.y = rect.y.baseVal.value + rect.height.baseVal.value / 2;
return point.matrixTransform(svg.getCTM().inverse().multiply(rect.getCTM()));
}
https://jsfiddle.net/archemedia/4f54jnm8/2/

Find 'view' co-ordinates in vis.js

I'm working on a modification to vis.js's Graph3d to do a filled line graph, like this:
The hard part - unsurprisingly - is working out the rendering order for the polygons. I think I can do this by checking whether a ray from the viewer to a given line B crosses line A:
In this example, since line A is "in the way" of line B, we should draw line A first. I'll use a snippet of code from How do you detect where two line segments intersect? to check whether the lines cross.
However, I haven't figured how to find the position of the user's view. I kind of assumed this would be the camera object, so wrote a little bit of debug code to draw the camera on the graph:
var camera = this._convert3Dto2D(this.camera.getCameraLocation());
ctx.strokeStyle = Math.random()>0.5 ? 'ff0000' : '00ff00';
ctx.beginPath();
ctx.moveTo(camera.x, camera.y);
ctx.lineTo(camera.x, camera.y+5);
ctx.stroke();
In fact, the camera co-ordinates as measured by this are always at 0,0,0 on the graph (which would be the far top right on the above screengrab). What I need, I think, is effectively the bottom of the screen.
How can I find this? Or is there a better way to achieve what I'm trying to do?
I don't know if this is still an active issue, but FWIW, Graph3D has internal handling of the sort ordering.
All graph points are sorted with respect to the viewpoint, using a representative coordinate called point.bottom. The rendering is then done using this ordering, with the most distant elements drawn first. This works fine as long as none of the elements intersect; in that case, you can expect artefacts.
Basically, all you need to do, is define point.bottom per graph polygon, and Graph3D will then pick it up from there.
If you are still interested in working on this:
This happens in Graph3d.js, method Graph3d.prototype._calcTranslations(). For an example, have a look at how the Grid and Surface graph elements are initialized in Graph3d.prototype._getDataPoints(). The relevant code is:
obj = {};
obj.point = point3d;
obj.trans = undefined;
obj.screen = undefined;
obj.bottom = new Point3d(x, y, this.zRange.min);

Inverse of camera.lookAt()

I googled far and wide but I haven't found the solution to what I think to actually be a pretty common situation. Say I have a THREE.PerspectiveCamera initialized to look at a certain point in space:
var camera = new THREE.PerspectiveCamera(45, 2, 0.1, 100);
var target = new THREE.Vector3(1, 2, 3);
camera.lookAt(target);
Now, later on in the code I'd like to be able to find out the coordinates of target by simply querying camera.
I tried what suggested in this question, adapting it to my own scenario:
var vector = new THREE.Vector3();
vector.applyQuaternion(camera.quaternion);
console.log(vector);
But it logs a vector of coordinates (0, 0, 0) instead of the correct coordinates (which, in my example, should be (1, 2, 3)).
Any insights? Cheers.
EDIT:
Ok so I'm going to try to contextualize here, so as to justify why MrTrustworthy's solution is unfortunately not applicable in my scenario. I'm trying to tweak the THREE.OrbitControls library for my purposes, since I noticed that when using it, it overrides whichever position the camera was looking at originally. This has also been reported here. Basically, on line 36 of OrbitControls.js (I'm using the version which can be found here) this.target is initialized to a new THREE.Vector3(); I found out that if I manually set it to equal the same vector I use as argument of camera.lookAt() everything works just fine: I can start panning, orbiting and zooming the scene from the same POV I would see the scene from if I didn't apply the controls. Of course, I cannot hard-code this information into OrbitControls.js because it would require me to change it every time I want to change the initial "lookAt" of my camera; and if I were to follow MrTrustworthy's suggestion I would have to change line 36 of OrbitControls.js to read like this: this.target = object.targetRef (or this.target = object.targetRef || new THREE.Vecotr3()), which is also too "opinionated" (it would always require object to have a targetRef property, whereas I'm trying to stick to using only three.js's existing object properties and methods). Hope this helps get a better understanding of my case. Cheers.
If your only usecase is "I want to be able to access the camera-targets position via the camera object", you could just put a reference into the camera object.
var camera = new THREE.PerspectiveCamera(45, 2, 0.1, 100);
var target = new THREE.Vector3(1, 2, 3);
camera.lookAt(target);
camera.targetRef = target;
//access it
var iNeedThisNow = camera.targetRef;
I figured it out and wrote my solution here. Since the issue affects both THREE.TrackballControls and THREE.OrbitControls, the solution involves applying a slight change to both those files. I wonder if it can be considered a valid change and make its way to rev. 70; I will issue a PR on github just for the sake of it :)
Thanks to all those who pitched in.
well you could put the object in parent, have parent lookat, and have the child object rotated 180 degrees. That's the quick noob solution

Detecting irregular Shape

Leading up from this question Detecting mouse coordinates with precision, I have learnt quite a bit in the past few days. Here are what I picked as best learning resources on this topic:
http://gamedev.tutsplus.com/tutorials/implementation/quick-tip-use-quadtrees-to-detect-likely-collisions-in-2d-space/
http://www.gamedev.net/page/resources/_/technical/graphics-programming-and-theory/quadtrees-r1303
http://jsfiddle.net/2dchA/2/
The code in (3) works in JSFiddle but breaks at this section in my testing environment (VS2012):
var myTree = new Quadtree({
x: 0,
y: 0,
width: 400,
height: 300
});
with the message Quadtree is undefined in IE. FF & Chrome just gloss over it and display an empty page. I couldn't sort it out. Question 1: Can someone help out with that?
My main question:
I have a region (parcels of land like a map) with about 1500 parcels drawn in html5, not jpg or png images. It is a lot of lines of code to complete that but the rendering is great, so I am keeping it that way. I intend to have a mouseover event tell me which parcel I am standing on when the mouse stops. As you will see in the previous question referred my previous attempts were not impressive. Based on the learning I have been doing, and thanks to Ken J's answer/comments, I would like to go with this new approach of slicing up my canvas into say 15 quads of 100 objects each. However, I would like some guidance before I take another wild dive the wrong way.
Question 2: Should I slice it up at creation or should the slicing happen when the mouse is over a region, ie, trail the mouse? The latter sounds better to me but I think I can do with some advice and, if possible, some start out code. The quadtree concept is completely new to me. Thanks.
Can't help with question 1.
You should definitely build the tree as early as possible, given that the objective is to get the page to respond as quick as possible once the user clicks somewhere.
Keep the tree for as long as the user interacts with the 2d area. Updating a quad tree shouldn't be too hard, so even if the area changes contents, you should be able to reuse the existing tree (just update it).
Given the fact that your draw area is well know i see no advantage in a QuadTree over a spacial hash function. This function will give you an integer out of an (x,y) point.
var blocWidth = 20;
var blocHeight = 20;
var blocsPerLine = ( 0 | ( worldWidth / blocWidth) ) + 1 ;
function hashPoint(x,y) {
return ( 0 | (x/blocWidth)) + blocsPerLine*(0|(y/blocHeight));
}
once you built that, hash all your parcels within an array :
parcelHash = [];
function addHash(i,p) {
if (!parcelHash[i]) { parcelHash[i]=[ p ]; return; }
if (parcelHash[i].indexOf(p) != -1 ) return;
parcelHash[i].push(p);
}
function hashParcel (p) {
var thisHash = hashPoint(p.x,p.y); // upper left
addHash( thisHash, p);
thisHash = hashPoint(p.x+width, p.y); // upper right
addHash(thisHash, p);
thisHash = hashPoint(p.x, p.y+p.height); // lower left
addHash(thisHash, p);
thisHash = hashPoint(p.x+width, p.y+p.height); // lower right
addHash(thisHash, p);
};
for (var i=0; i<allParcels.length; i++) { hashParcel(allParcels[i]) };
now if you have a mouse position, you can retrieve all the parcels in the
same block with :
function getParcels(x,y) {
var thisHash = hashPoint(x,y);
return parcelHash[thisHash];
}
I'll just give you few tips in addition to what others have said.
... have a mouseover event tell me which parcel I am standing on ...
From your other messages I conclude that parcels will have irregular shapes. Quadtrees in general work with rectangles, so you'd have to calculate the bounding rectangle around the shape of the parcel and insert that rectangle in the quadtree. Then are when you want to determine whether mouse is over a parcel, you'll query the quadtree which will give you a set of parcels that might be under the mouse, but you'll have to then do a more precise check on your own to see if it indeed is.
... when the mouse stops.
From your other questions I saw that you try to detect when the mouse has "stopped". Maybe you should look at it this way: mouse cursor is never moving, it's teleporting around the screen from previous point to next. It's always stopped, never moving. This might seem a bit philosophical, but it'll keep your code simpler. You should definitely be able to achieve what you intended without any setTimeout checks.
... slicing up my canvas into say 15 quads of 100 objects each.
... Should I slice it up at creation or should the slicing happen when the mouse is over a region
You won't (and can't) do slicing, quadtree implementation does that automatically (that's its purpose) when you insert or remove items from it (note that moving the item is actually removing then re-inserting it).
I didn't look into the implementation of quadtree that you're using, but here are two MX-CIF quadtree implementations in case that one doesn't work out for you:
https://github.com/pdehn/jsQuad
https://github.com/bjornharrtell/jsts/tree/master/src/jsts/index/quadtree
The problem in question 1 probably happens because jsfiddle (http) page is trying access quadtree.js which is on https

jQuery animate not moving to the correct location

I've run into a mysterious problem. I'm using jQuery's animate function and the object I'm animating is not moving to the 'left' coordinate I provide; rather the left coordinate is always 0. However, the 'top' coordinate does move as expected. I had this working fine at one point and I rearranged some things around and it has stopped.
var new_x,
new_y,
player_tranistion_holder;
new_x = bg_app.boardModel[id_num].x+'px';
new_y = (bg_app.boardModel[id_num].chips.length) * bg_app.game_utils.parse_css_dimension(selected_chip.chip.css('height'));
console.log(new_x) //outputs 300px for example - the expected value;
selected_chip.chip.animate({'left': new_x, 'top': new_y }, 500, 'easeInOutQuad', function () {
console.log(selected_chip.chip.css('left'); //output is 0
});
Any idea what could cause this to screw up? The stuff I changed around it was merely in how the function came to be called, nothing in the function itself. Do I have some syntax error that I'm missing?
I've put the broken site here:
http://www.warunicorn.com/bg_show_busted/
here is an example with it working:
http://www.warunicorn.com/bg_show/
Any advice would be appreciated.
I found the problem. When using the animate function if the new value passed in is the same as the current value of the object jQuery gets confused and sets the value to 0. I haven't done extensive testing on this and so there may be exceptions where it does work, but in this case, that was the problem.

Categories

Resources