In my smithchart project i am trying to animate an arc. I calculated start and stop angles via f which returns an double but could not find a way to use that angles. The point is angles which has double type can not be used in KeyValue which accepts WriteableValue.
double angle;
angle = f();
KeyValue keyAngle = new KayValue(angle, 360.0);
Also casting angle to WritableValue has no effect.
Is there any way to make this work?
Animation API works with properties (which implement WritableValue). Thus if you want to change startAngle of your arc using animation you should provide Arc#startAngleProperty() to KeyValue:
KeyValue kv = new KeyValue(arc.startAngleProperty(), my_double_angle_value);
An example of the animated arc:
Arc arc = ArcBuilder.create()
.centerX(150)
.centerY(150)
.radiusX(100)
.radiusY(50)
.startAngle(0)
.length(30)
.type(ArcType.ROUND)
.fill(Color.RED)
.build();
Pane root = new Pane();
root.getChildren().add(arc);
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Hello Arc!");
primaryStage.setScene(scene);
primaryStage.show();
KeyValue kv = new KeyValue(arc.startAngleProperty(), 360);
KeyFrame kf = new KeyFrame(Duration.seconds(3), kv);
Timeline timeline = new Timeline();
timeline.setAutoReverse(false);
timeline.setCycleCount(Timeline.INDEFINITE);
timeline.getKeyFrames().add(kf);
timeline.play();
Related
In three.js, I want to add a mesh to a position in the scene
I've tried:
// mesh is an instance of THREE.Mesh
// scene is an instance of THREE.Scene
scene.add(mesh)
scene.updateMatrixWorld(true)
mesh.matrixWorld.setPosition(new THREE.Vector3(100, 100, 100))
scene.updateMatrix()
BUT it didn't affect anything.
What should I do ?
I would recommend you to check the documentation over here:
http://threejs.org/docs/#Reference/Objects/Mesh
As you can see on the top of the docu-page, Mesh inherits from "Object3D". That means that you can use all methods or properties that are provided by Object3D. So click on the "Object3D" link on the docu-page and check the properties list. You will find the property ".position". Click on ".position" to see what data-type it is. Paha..its Vector3.
So try to do the following:
// scene is an instance of THREE.Scene
scene.add(mesh);
mesh.position.set(100, 100, 100);
i saw it on a github earlier. (three.js r71 )
mesh.position.set(100, 100, 100);
and can be done for individuals
mesh.position.setX(200);
mesh.position.setZ(200);
reference: https://threejs.org/docs/#api/math/Vector3
detailed explanation is below:
since mesh.position is "Vector3". Vector3() has setX() setY() and setZ() methods. we can use it like this.
mesh.position = new THREE.Vector3() ; //see position is Vector3()
vector1 = new THREE.Vector3();
mesh.position.setX(100); //or this
vector1.setX(100) // because all of them is Vector3()
camera1.position.setZ(100); // or this
light1.position.setY(100) // applicable to any object.position
I prefer to use Vector3 to set position.
let group = new THREE.Group();
// position of box
let vector = new THREE.Vector3(10, 10, 10);
// add wooden Box
let woodenBox = new THREE.Mesh(boxGeometry, woodMaterial);
//update postion
woodenBox.position.copy(vector);
// add to scene
group.add(woodenBox)
this.scene.add(group);
If some one looking for way to update position from Vector3
const V3 = new THREE.Vector3(0,0,0) // Create variable in zero position
const box = new THREE.Mesh(geometry, material) // Create an object
Object.assign(box.position, V3) // Put the object in zero position
OR
const V3 = new THREE.Vector3(0,0,0) // Create variable in zero position
const box = new THREE.Mesh(geometry, material) // Create an object
box.position.copy(V3)
I am not able to solve this. I looked other related three.js solutions at stack overflow but still not achieving the result. With the code below the 3D object appears some diagonal distant away from the mouse cursor when in mousedown click.
this.mouse = new THREE.Vector2();
this.scene = this.el.sceneEl;
this.camera = this.scene.camera;
this.obj = this.el.object3D;
this.scene.addEventListener('mousedown', e => {
let rc = new THREE.Raycaster();
rc.setFromCamera(this.mouse, this.camera);
let dist = this.obj.position.distanceTo(this.camera.position);
let point = rc.ray.direction.multiplyScalar(dist);
document.querySelector('#red').setAttribute('position',point.x+'
'+point.y+' '+ point.z); //red is a 3D box
}
Is there any ready component for this?
Using
let point = rc.ray.at(dist);
instead of
let point = rc.ray.direction.multiplyScalar(dist);
worked
I'm trying to use the three.js lookAt() method on a meshes (from CylinderBufferGeometry) so that it is oriented toward a point, but when I use the .lookAt() method, it causes the mesh to disappear from view.
The cylinder shows up fine if I comment out the .lookAt() method. I'm using a THREE.PerspectiveCamera and the THREE.WebGLRenderer incase that could have anything to do with the issue.
// Build cylinder
var cylinderRadius = 0.15
var cylinderHeight = 20
var geometry = new THREE.CylinderBufferGeometry(cylinderRadius, cylinderRadius, cylinderHeight);
var material = new THREE.MeshBasicMaterial({color: 0xffffff});
var cylinder = new THREE.Mesh(geometry, material);
// Point the cylinder up
cylinder.geometry.rotateX( Math.PI / 2);
cylinder.geometry.translate(0,0, cylinderHeight/2 );
// Move cylinder to position
cylinder.position.x = 10;
cylinder.position.y = 10;
// Look at point
cylinder.lookAt(0,0,15); // <-- ISSUE OCCURS HERE
scene.add(cylinder);
render();
Use cylinder.lookAt(new THREE.Vector3(0,0,15)); instead of cylinder.lookAt(0,0,15);
I am trying to create a continuous animation, eventually the goal would be a bouncing ball that bounces off the edges of the screen, however, one step at a time.
I started with the sample code from Oracle that has an animation of circles that move for 40 seconds.
public void start(Stage primaryStage)
{
Group root = new Group();
Scene scene = new Scene(root, 800, 600);
primaryStage.setScene(scene);
Group circles = new Group();
for (int i = 0; i < 1; i++)
{
MovingCircle circle = new MovingCircle(150, Color.web("white", 0.05));
circle.setStrokeType(StrokeType.OUTSIDE);
circle.setStroke(Color.web("black", 0.16));
circle.setStrokeWidth(4);
circles.getChildren().add(circle);
}
root.getChildren().add(circles);
Timeline timeline = new Timeline();
timeline.setCycleCount(Timeline.INDEFINITE);
for (Node circle: circles.getChildren())
{
if(circle instanceof MovingCircle)
{
MovingCircle c = (MovingCircle)circle;
timeline.getKeyFrames().addAll(
/* new KeyFrame(Duration.ZERO, // set start position at 0
new KeyValue(circle.translateXProperty(), random() * 800),
new KeyValue(circle.translateYProperty(), random() * 600)
),*/
new KeyFrame(new Duration(10), // set end position at 40s
c.getXMovement(), c.getYMovement())
);
c.updateCenter();
}
}
// play 40s of animation
timeline.play();
primaryStage.show();
}
I created a new MovingCircle that extends Circle to try and add other stuff to it later. The two new class methods return exactly what was commented out from the default code given.
I changed the cycle to indefinite so that it would go forever. All the circle does though is bounce between its original starting point and the translated point. I have tried updating its center location in hopes that the next bounce would move it to a different location, however, that doesn't work.
I am at quite a loss as to what to try next to get this working more the way I was hoping.
sample code
//node
Rectangle rect = new Rectangle (0, 0, 20, 20);
//path
Text text = TextBuilder.create()
.text("J a v a F X R o c k s")
.font(new Font(50))
.x(65)
.y(100)
.build();
// path transition
pathTransition = PathTransitionBuilder.create()
.duration(Duration.seconds(15))
.path(text)
.node(rect)
.orientation(OrientationType.ORTHOGONAL_TO_TANGENT)
.cycleCount(Timeline.INDEFINITE)
.autoReverse(true)
.build();
I want to display part of the the text(path) that traveled by rect node. Meaning in the above figure as rect node traveled until java, i want to be display that part only at that point of time ..
You can try to assign a clipping area to the Text and update it during animation:
public void start(Stage primaryStage) {
final Rectangle pen = new Rectangle(0, 0, 20, 20);
// this pane this contain clipping
final Pane clip = new Pane();
// listener to update clipping area
ChangeListener changeListener = new ChangeListener() {
#Override
public void changed(ObservableValue ov, Object t, Object t1) {
Rectangle newrect = new Rectangle(pen.getTranslateX(), pen.getTranslateY(), pen.getWidth(), pen.getHeight());
newrect.setRotate(pen.getRotate());
clip.getChildren().add(newrect);
}
};
// rect coordinates will be changed during animation, so we will listen to them
pen.translateXProperty().addListener(changeListener);
pen.translateYProperty().addListener(changeListener);
pen.rotateProperty().addListener(changeListener);
final Text text = TextBuilder.create()
.text("J a v a F X R o c k s")
.font(new Font(50))
.clip(clip)
.x(65)
.y(100)
.build();
PathTransition pathTransition = PathTransitionBuilder.create()
.duration(Duration.seconds(15))
.path(text)
.node(pen)
.orientation(OrientationType.ORTHOGONAL_TO_TANGENT)
.build();
// once we done we don't want to store thousands of rectangles used to clip
pathTransition.setOnFinished(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent t) {
text.setClip(null);
clip.getChildren().clear();
}
});
Pane root = new Pane();
root.getChildren().addAll(text, pen);
primaryStage.setScene(new Scene(root, 600, 200));
primaryStage.show();
pathTransition.play();
}
A bit more efficient way to store clipping area can be Canvas object, but it will require a bit of math to draw rectangles with rotation on canvas, so it's your call.