I'm hoping someone can help me out with this, I'm using a jquery plugin (jquery rotate) to rotate some elements inside a container, however a new crazy requirement came up and now I also need to rotate the container div, the problem is the children elements can be dragged and dropped inside this container and when it is rotated dragging stops working and it starts acting weird (I guess it makes sense as the coordinates system is being altered by the rotation on the container so the dragging behavior just goes crazy) so the only way that I can see to keep dragging and dropping working is to "simulate" the parent rotation by somehow calculate what the position of the children elements would be if the parent is rotated (without actually rotating the parent container) and position each child element on its corresponding final position, this way the coordinates system does not get "broken" and the drag and drop of the children remains working as expected.
To clarify what I'm trying to achieve lets suppose the container is 400x400px and that it has a children at top=0 and left=0, I would like to perform a "fake" 180 degrees rotation on the container that would send the child element to top=400px and left=400px (which is where the child element would visually end up being if the parent is rotated), I'm hoping there is a library I can use to perform this math (math is not my thing though) on each children and somehow "calculate" or "determine" the position they should have within the container if it is rotated 180 degrees and then position each children where they should be (the container rotation will always be a 180 degrees rotation which means it will be either at a "normal" angle of 0 degrees or a "flipped" angle of 180 degrees).
Any help would be greatly appreciated.
Related
Alright, so I have a good deal of experience with HTML and CSS, and some experience with Javascript (I can write basic functions and have coded in similar languages).
I'm looking to start some visual projects and am specifically interested in getting into particle systems. I have an idea for something similar to Codecademy's name generator here (https://www.codecademy.com/courses/animate-your-name/0/1) where particles are mapped to a word and move if hovered over. It seems as though alphabet.js is what's really behind Codecademy's demo however I can't understand exactly how they mapped the particles to a word, etc.
I've done some basic tutorials just creating rudimentary particles in a canvas but I'm not sure a canvas is the best way to go - demos that utilize one of the many libraries available (such as http://soulwire.github.io/sketch.js/examples/particles.html) don't use a canvas.
So my question is - what is the best way for a beginner/intermediate in Javascript to start with particle systems? Specifically to accomplish the Codecademy name effect or similar? Should I try to use canvas or which library would be best to start with and how would you recommend starting?
The code for this project is achievable for your intermediate JS programmer status.
How the CodeAcademy project works ...
Start by building each letter out of circles and saving each circle's centerpoint in an array. The alphabet.js script holds that array of circle centerpoints.
On mousemove events, test which circles are within a specified radius of the mouse position. Then animate each of those discovered circles radially outward from the mouse position using simple trigonometry.
When the mouse moves again, test which circles are no longer within the specified radius of the current mouse position. Then animate each of those "outside" circles back towards their original positions.
You can also use native html5 canvas without any libraries...
Another approach allowing any text to be "dissolved" and reassembled
Start by drawing the text on the canvas. BTW, this approach will "dissolve" any drawing, not just text.
Use context.getImageData to fetch the opacity value of every pixel on the canvas. Determine which pixels on the canvas contain parts of the text. You can tell if a pixel is part of the text because it will be opaque rather than transparent.
Now do the same procedure that CodeAcademy did with their circles -- but use your pixels:
On mousemove events, test which pixels are within a specified radius of the mouse position. Then animate each of those discovered pixels radially outward from the mouse position using simple trigonometry.
When the mouse moves again, test which pixels are no longer within the specified radius of the current mouse position. Then animate each of those "outside" pixels back towards their original positions.
[Addition: mousemove event to test if circles are within mouse distance]
Note: You probably want to keep an animation frame running that moves circles closer or further from their original positions based on a flag (isInside) for each circle.
function handleMouseMove(e){
// tell the browser we're handling this event
e.preventDefault();
e.stopPropagation();
// calc the current mouse position
mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
// test each circle to see if it's inside or outside
// radius of 40px to current mouse position
// circles[] is an array of circle objects shaped like this
// {x:,y:,r:,originalX:,originalY:,isInside:}
var radius=40;
for(var i=0;i<circles.length;i++){
var c=circles[i];
var dx=c.x-mouseX;
var dy=c.y-mouseY;
if(dx*dx+dy*dy<radius*radius){
c.isInside=true;
// move c.x & c.y away from its originalX & originalY
}else{
c.isInside=false;
// if the circle is not already back at it's originalX, originalY
// then move c.x & c.y back towards its originalX, originalY
}
}
}
Aim:
I have a website with some content and svg scheme in the middle of it. When one points to the elements of the scheme, tooltips should appear next to the mouse cursor.
Problems: Based on examples like this (which was shown by Julian Berger in How to get the position of SVG element), I made working SVG. Unfortunately it is working only as long as the SVG scheme is not included into the website. Content other then SVG make evt.clientX and Y coordinates system to fail --> the tooltip starts to appear in some distance from the cursor (it seems that the more of other then SVG content I have, the further tooltip is moved away from cursor). The simple example is shown here, simply by adding couple of <br/> before the actual SVG begins.
And my question:
Do you have some ideas how to fix the position of the tooltip, so that it would appear always next to the moving cursor?
All the best,
Wojtek
All you have to do is alter mousemove handler a little. It should position the tooltip relative to the top left of the SVG, rather than the page. You do that by subtracting the position of the SVG, which we get by surrounding the SVG with a <div> element and accessing its offsetLeft and offsetTop properties.
<div id="mysvg">
<svg>...</svg>
</div>
function ShowTooltip(evt, mouseovertext) {
svg = document.getElementById("mysvg");
tooltip.setAttributeNS(null,"x",evt.clientX+11 - svg.offsetLeft);
tooltip.setAttributeNS(null,"y",evt.clientY+27 - svg.offsetTop);
...
}
Full demo here
I am working on a page where I can view images. I want to create a rotation tool. I've done that, but, it's not working consistently. When I set up the centre point to rotate by, the image jumps slightly, and it gets worse each time. I was experimenting, and, I have code to add a wedge to the top left corner of my top level group ( so, at 0,0 ). If I rotate the image by 45 degrees and drag it so that half of it is off the left edge of my canvas, then I call getAbsolutePosition on the wedge and on the group, I get these values:
layer.getAbsolutePosition()
Object {x: 104.66479545850302, y: 279.2748571151325}
wedge.getAbsolutePosition()
Object {x: 180.2684127179338, y: -73.48773356791764}
I think this means my y position is actually the bottom of the image, which is off screen.
What I want to do, is calculate the absolute position of the middle of my image, when the mouse moves over it, regardless of it's rotation. I have some code that works out points with rotation, which seems like it works at first, almost, but it just gets more and more broken the more I use the tool. I feel like there's something about how Kinetic is tracking these things and what it's reporting, that I am missing. Any hints would be most appreciated. Tutorials I can read are even better ( yes, I've read everything linked from the KineticJS site and searched the web ).
In a nutshell, the question is, if I have an image inside a group, and it's rotated, how do I work out the centre point of the image, taking the rotation in to account, and how do I set the offset so it will rotate from that point, and stay in the same place ?
Thanks
As you've discovered about KinetiJS:
rotation is easy
dragging is easy
dragging+rotation is difficult
After you drag your image you must reset its rotation point (offsetX/offsetY).
KineticJS makes dragging+rotation more difficult than it has to be.
Resetting the offset points of your image will cause KineticJS to automatically move your image (Noooo!!).
That's what's causing your jumping.
The solution to the "jumping" problem:
When you reset the image's rotation point (offsetX/OffsetY) you must also reset the image's X/Y position.
This code resets both XY and Offsets for an image after dragging:
A Demo: http://jsfiddle.net/m1erickson/m9Nw7/
// calc new position and offset
var pos=rect.getPosition();
var size=rect.getSize();
var offset=rect.getOffset();
var newX=pos.x-offset.x+size.width/2;
var newY=pos.y-offset.y+size.height/2;
// reset both position and offset
rect.setPosition([newX,newY]);
rect.setOffset(size.width/2,size.height/2);
I have a parent div and child div. Child is position absolute with respect to parent div. Child div is rotated by 90 degrees. Since the origin is the center (meeting point of 2 diagonals) of the child, the child div is shifted pixels outside of the container.
To elaborate this problem I have added 2 parents-child output in the fiddle below.
http://jsfiddle.net/Xja29/
In the fiddle I have added an event which resets the child position to the top-left corner of their respective parents. Here is the reset code. Note top & left values are different for the 2 child divs
JQuery Code:
$("#link").click(function(){
//Child 1 needs top=45 and left=-45
$("#c1").css({"top":"45px", "left":"-45px"});
//Whereas Child 2 needs top=30 and left=-30
$("#c2").css({"top":"25px", "left":"-25px"});
//As one can see there are different values for top and left for childs of different dimension. Is there any relation or formula to find out this values?
});
Exactly, I want to find out the relation between rotation angle, width, height and co-ordinate system of the child div. Please let me know if anything such exists. Thank you.
You can use as style:
transform: rotate(90deg) translate(0,-100%)
transform-origin: top left
to get the requested alignment without using Javascript
You can always use the following calculation:
top = (child_div.width - child_div.height)/2
left = (child_div.height - child_div.width)/2 = -top
Let's examine the formula for top. The center of the child div is (child_div.height/2) units below the top of the parent's div. After rotating the child div, its top is (child_div.width/2) units above its own center. This implies that its top is (child_div.width/2) - (child_div.width/2) units above its parent's top. Simplifying it, we get the aforesaid formula. The formula for left can be derived analogously.
If you are going to move them using Javascript, you can calculate these values at the run time and use them.
Well, the child div resides in its own coordinate system relative to the parent container which position' is not static (the body otherwise). If you want to rotate a div around a certain point, which is not the origin of its coordinate system the steps to be taken are as follows:
subtract the vetor of the rotation point from the position vector of the div. (so the rotation center will lie in the origin).
rotate the div.
undo step one by adding the "rotation-center-vector" to the position of the div.
These steps are a quite general approach and a common concept, just have a look at tranformation matrices. In other words, rotating arround a certain point always involves these three steps (the same holds true for scaling objects).
Good luck...
I am using force layout. New d3 nodes are created by clicking inside a div element. The node is created at the point of click. The nodes are rectangles of size 50 pixels x 50 pixels. Immediately after creating a node, I set its fixed property to true so that it does not move on its own. I am not calling force.drag. The nodes can be moved by holding down ctrl key and dragging the node. An edge can be created by dragging mouse (without holding ctrl key) from one node to the other.
Now, I want to add the following feature.
The closest distance between any two nodes should be more than a certain minimum. You can assume any positive value for the minimum distance. Let us assume 100 pixels. When any new node is created too close to an existing node, then the nodes should move so that the distance between any two nodes becomes more than 100 pixels. Similarly, when one node is moved and brought too close to another, then also the nodes should move to maintain minimum 100 pixels distance.
There is no condition on which nodes to move and in which direction. One way is to check coordinates and distances and then calculate which nodes to move, how much, in what direction and execute code accordingly. But, is there a simpler way in d3?
Consider just using force.linkDistance() and force.linkStrength() to achieve this. linkDistance represents your minimum distance constraint, and linkStrength (in the range of [0, 1]) determines how 'rigid' the link distance is, or how much linkDistance can be overridden by the simulation.
force.linkDistance
force.linkStrength