I am new to three.js, I have created a simple particle app with three.js, but the flow of particles is moving from centre. I want move particles something like displayed in the attached screenshot (top right corner to bottom left corner).
working code is at https://jseditor.io/?key=ee98d51a9b4111eab74e00224d6bfcd5.
any reference will be very helpful. Thank you.
Your updateParticles function is only changing the particles' z position:
particle.position.z += mouseY * 0.1;
if(particle.position.z>1000) particle.position.z-=2000;
If you want to move them vertically and horizontally, you're going to have to update the x and y positions as well.
particle.position.x -= mouseY * 0.1;
particle.position.y -= mouseY * 0.1;
if(particle.position.x<-500) particle.position.x+=1000;
if(particle.position.y<-500) particle.position.y+=1000;
I don't know the size of your scene, so you might need to adjust the numbers accordingly.
Related
I am new to css and learning different type of css styles. I want to learn how the effect used in official MongoDb website. The effect which tracks the mouse position and transforms the boxes. I know how to do the transform in css. But, how can it be done with the mouse position. Thanks for the help.
General overview of how to do it:
Register a mousemove-handler and track your mouse-screen location (see link)
translate mouse screenlocation, to mouse location relative to rectangle:
e.target in mousemove event gives you the rectangle (or some descendent which allows you to get to the rectangle.
given the target element get it's position (top + left using getBoundingClientRect) as well as width and height. These should be easy to lookup
Notice that the mouse at the center of the rectangle doesn't rotate the rectangle. Only when moving to the edges, the rotation starts to get going. This rotational rate-of-change seems to be linear. So:
determine the max rotation that seems nice to have in degrees. Simply test with different numbers in the chrome dev tools or similar: transform: rotateY(0.01deg) rotateX(0.01deg); Say you want to have a max rotation of 25 degrees.
say the rectangle is 100px in width. It's clear to see that each pixel movement from the center to the edge (50 px in total) adds 0.5 degree to the rotation due to the linear rate of change: 25 deg / 50px. So for example moving 20px to the left of the center translates to rotateY(10deg);. Moving 20px to the right results in the mirror rotation (rotateY(-10deg);). NOTE: the positive and negative may need to be flipped.
similarly, moving along the Y-axis changes the rotateX-property.
Once calculated, set the css-property and you're done
I believe this must be done with Javascript. The general idea is when the mouse enter/move on the element, you compare it's coordinate with the position and width/height of the element to decide the rotation values. When the mouse leave the element, you reset the values of the rotation back to normal.
You can get the coordinate of the mouse from event by using:
const mouseX = event.clientX; // Get the horizontal coordinate
const mouseY = event.clientY; // Get the vertical coordinate
And the position of the element:
const eleLoc = event.target.getBoundingClientRect();
From there you calculate the center and the width/height of the element:
const centerX = (eleLoc.right + eleLoc.left) / 2
const centerY = (eleLoc.bottom + eleLoc.top) / 2
const halfWidth = (eleLoc.right - eleLoc.left) / 2
const halfHeight = (eleLoc.bottom- eleLoc.top) / 2
Then you calculate the distance between the mouse and the center in percent. In the center, the distance is 0, at the border, it's 1 (or -1).
const percentX = (mouseX - centerX) / halfWidth
const percentY = (mouseY - centerY) / halfHeight
Now you only need to rotate X/Y based on the distance percent:
const degX = percentX * maxDegX
const defY = percentY * maxDegY
event.target.style.transform = `perspective(${yourPerspective}px) rotateX(${degX}deg) rotateY(${degY}deg)`
Remember to reset the transform when your mouse move out.
There are some libraries for this, ie: tilt.js
I'm creating a webpage that draws a trail along a path as the page is scrolled, using canvas to draw the trail and SVGs to determine the path coordinates. (Similar to this demo - https://tympanus.net/Development/StorytellingMap/)
I have a hidden canvas set up as a 'room' which contains the full map background, then draws from this to the main canvas (using a 'camera' to get the position). I've managed to get the background to zoom using drawImage to scale the selected area as follows:
ctx.drawImage(
image,
camera.position.x + ((canvas.width - (canvas.width / zoom)) / 2),
camera.position.y + ((canvas.height - (canvas.height / zoom)) / 2),
canvas.width / zoom,
canvas.height / zoom,
0,
0,
canvas.width,
canvas.height
);
The line is drawn by looping through an array of points like this:
ctx.beginPath();
for (var i = 0; i < points.length; i++) {
ctx.lineTo(
points[i].x - camera.position.x,
points[i].y - camera.position.y
);
}
ctx.stroke();
However I can't adapt the line to account for zoom - I can multiply all the coordinates by the zoom factor and the size appears correct, but I lose the position set by the camera, so it's not aligned to the background. Can anyone tell me how I can account for this?
I hope I've explained this well enough, I can try to upload the whole thing if anyone needs to see it in context!
Please let me know any questions, I'd really appreciate any advice or guidance.
Edit:
Link: http://staging.clicky.co.uk/map-scroll/ (Scroll to see the map update!)
I have a fiddle here.
What i am asking is that the space ship must be facing the direction of movement because it would not make sense not to. Anyway i think the problem i am having is to find a angle and have the ship rotate by that angle when the ship moves somewhere differently.
function draw () { //Create and animates
var angle = Math.atan2(clickedChords.y - player.y, clickedChords.x - player.x);
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.fillStyle= 'white';
ctx.beginPath();
//Creates crossHair/nav marker
ctx.arc(clickedChords.x,clickedChords.y,3,0,360);
ctx.rect(clickedChords.x - 8,clickedChords.y - 1,16,2);
ctx.fill();
ctx.drawImage(ships.blueBeginers,player.x-15,player.y-15);
player.x += Math.cos(angle);
player.y += Math.sin(angle);
requestAnimationFrame(draw); //God
}
draw();
I am having a problem also translating the image and then rotating from the middle of the image. It could be something simple but i am stuck.
Thank you for helping me.
You need to translate the canvas to the center point at which you will do the rotation
Rotate based on the angle you have
Draw image
Reset transformation
In code it would be these lines:
ctx.translate(player.x, player.y); // translate to center of rotation
ctx.rotate(angle + 0.5*Math.PI); // rotate, here +90deg to comp image dir.
ctx.translate(-player.x, -player.y); // translate back
ctx.drawImage(ships.blueBeginers,player.x-15,player.y-15); // draw image
ctx.setTransform(1,0,0,1,0,0); // reset transforms (identity matrix)
FIDDLE
The flickering is because you calculate the atan2 angle each frame. When position equals click position you will have atan of a very small value toggling due to the adding of cos/sin later.
You can fix this by caching the angle on your click object as in this version:
FIDDLE fixing flicker
However, you need a conditional check to stop animating as now you just add the values from cos/sin and nothing is stopping it (here is one way of doing it).
Tip 1: Create the image of the ship facing right. This would correspond to 0° and save you from adding 90° each time.
Tip 2: Cache the angle value and calculation once then you don't have to calculate atan2/cos/sin each time as they are relative expensive operation.
I need to rotate objects in a smooth way like Elbert F's freeTransform does.
Please anyone review my code and help me to solve this problem.
I don't need any other code or any other plugin but some editing in my own code
I think some correct formula of angle in move function of code is responsible for smooth rotation of object.
Thanks in advance
I have done this and its a bit tricky formula of Math which helped me.
Here is updated code
var centreX = "center of rectanlge, x-coordinate", centreY = "center of rectangle, y-coordinate";
var theta = Math.atan2(centreX - dx, centreY - dy); // dx and dy are movement of mouse from the rotating element
angle = 1 * (theta * 180)/3.1415;;
element.rotate(angle, centreX, centreY);
For example it may be used in the application of manually adjusting the hands of the clock. I guess it probably involves translating the needle (to make the end point of the needle the centre of rotation) then rotating it, then translating the needle again.
But since the needle listens to the mouse event all the time, the 1st mouse event will be captured. The result is that the needle ends up being translated and not rotated at all. Mouse event is impossible to debug too...
Any idea or code snippets that I can refer to? Using Javascript or CSS to rotate both fine.
In your example, you will want to calculate the angle between the centre of the clock face (black dot), and the current mouse position (red dot), relative to the Y axis (cardinal north if you imagine a compass).
If I remember my trig correctly, you can calculate this by using the following:
var angle = Math.atan2(y2 - y1, x2 - x1) * 180 / Math.PI;
// alter the angle to be relative to Y axis instead of X
angle += 90;
if(angle < 0) { angle = 360 + angle; }
In the formula, x and y are the coordinates of the two points, one of which you will know (it is the centre of the clock face), and the other you can get from the mouse move event.
Once you have the angle, you can simply translate to the the centre of the circle, rotate the canvas by the calculated amount, and draw the hand.
Update: I created a jsfiddle to illustrate the angle calculation:
http://jsfiddle.net/DAEpy/1/