What I'm doing
I'm using anime.js to animate some circles along paths in an svg. I create paths using Vue as I'd like the circle on the top to end up on the bottom, so it can't just be a static SVG.
What I expect
I expect the circles to start at one end of the svg path, and finish at the other end.
What's actually happening
I have a demo here:
https://codepen.io/EightArmsHQ/pen/paVxpd
When I click animate, the circles are jumping to a different position, then animating almost correctly, before finishing in the wrong place.
This is the code I am using for anime.js:
for(var c = 0; c < this.coins.length; c++){
var path = anime.path('#path-'+ c);
anime({
targets: document.getElementById(this.coins[c].ref),
translateX: path('x'),
translateY: path('y'),
rotate: path('angle'),
duration: 1000,
delay : this.coins.length * 100 - (100 * c),
easing: 'easeInOutQuad',
rotation: 0,
});
}
I know its almost definitely to do with transform-origin and the rotation transform that is applied to the circles, but I can't get my head around it.
I found after some experimenting the issue was that I was altering the transformX and transformY properties, which, while it sort of worked and would work better for DOM elements, I should have been using cx and cy attributes. I also removed the rotation as well.
for(var c = 0; c < this.coins.length; c++){
var path = anime.path('#path-'+ c);
anime({
targets: document.getElementById(this.coins[c].ref),
cx: path('x'),
cy: path('y'),
duration: 1000,
delay : this.coins.length * 100 - (100 * c),
easing: 'easeInOutQuad',
rotation: 0,
});
}
Here is a demo:
https://codepen.io/EightArmsHQ/pen/aqKXrQ?editors=1010
Related
I imported a svg in PaperJS and let it move along a path.
As it moves along the path, I calculate the rotation to let it follow the path with the right rotation.
Now I need a point that is offset from the svg.
Please have a look at this image for a better understanding of what I need:
https://imgur.com/Lyua7oW
I already found it out. If anyone is interested here is the answer:
Add the two points together (offset points of normal and tangent) then add the point of the svg.
var normal = this.strecke.getNormalAt(offset)
var normalOffset = normal.multiply(Math.random() * (this.bubbleOffsetX - (-1)*this.bubbleOffsetX + 1) + (-1)*this.bubbleOffsetX)
var tanOffset = tangent.multiply(this.bubbleOffsetY)
var bubblePosition = normalOffset.add(tanOffset).add(point)
var bubble = new Path.Circle({
center: bubblePosition,
radius: Math.floor(Math.random() * (this.bubbleMaxSize - this.bubbleMinSize + 1) + this.bubbleMinSize),
fillColor: '#A4F2FB',
opacity: Math.random > 50 ? .5 : .3,
})
setTimeout(() => {
bubble.remove()
}, this.bubbleLifespan);
I was trying to use tick function as described in the below link https://github.com/aframevr/aframe/blob/master/docs/introduction/best-practices.md but it didnt worked out
AFRAME.registerComponent('foo', {
tick: function () {
var el = this.el;
var rotationTmp = this.rotationTmp = this.rotationTmp || {x: 0, y: 0, z: 0};
var rotation = el.getAttribute('rotation');
rotationTmp.x = rotation.x + 0.1;
rotationTmp.y = rotation.y;
rotationTmp.z = rotation.z;
el.setAttribute('rotation', rotationTmp);
}
});
Expected output the object should rotate around x actual result nothing happens..
I hope it's okay if i clarify a bit Kevin's answer.
But first of all, the code is working. Both in aframe 0.9.2 and 0.8.2.
The issue may be related to
the script being placed after the scene is loaded
the component not being attached to the entity:
js:
AFRAME.registerComponent('foo', {
// component body
})
html:
<a-entity foo></a-entity>
As for Kevins answer - it may be a good idea to make changes in the tick function with referring to the underlying THREE.js object.
If you want to rotate a box, there's no need to throw in all that logic you have:
1) create a tmp variable
2) get the object rotation
3) set the tmp variable
4) set the object rotation
When you have a function which executes on each render loop (tick) then you want to minimize what's happening there. So Kevin directly accesses the THREE.js object, and changes the rotation:
tick: function() {
el.object3D.rotation.x += 0.1 * Math.PI / 180 // three uses radians
}
Check it out in this fiddle.
You can just do el.object3D.rotation.x += 0.1
When I use QGraphicsItemAnimation::setRotationAt() function to rotate a QGraphicsItem for an animation, the original point is always left top point of the item.
So I tried QGraphicsItem::setTransformOriginPoint() to make the rotation point to be at right top. But it still doesn't work. Is there any way to rotate the item itself at the right top?
for (int i = 0; i < 1000; ++i){
mAnimation->setTranslationAt(i / 1000.0, size.w, 0);
mAnimation->setRotationAt(i / 1000.0, qreal(i / 1000.0 * angle));
mAnimation->setTranslationAt(i / 1000.0, -size.w, 0);
}
Here is the answer i found, when set frames of the item, need to translate the original point before rotation, and translate it back.
Is it possible to translate a QML Rectangle on the Z axis similar to how we can do in HTML with CSS transform:translateZ() and transform:translate3d()?
Applying transform: Translate {x: 0; y: 0; z: 100} on a Rectangle throws an error that the z property isn't defined.
I am able to apply transform: Rotation{} to a Rectangle with a z-axis rotation and it looks 3D. I was hoping I could translate things in 3D as well.
Is there a way to do it?
EDIT: I tried setting a Matrix4x4 like this:
transform: Matrix4x4 {
matrix: Qt.matrix4x4(
1,0,0,0,
0,1,0,0,
0,0,1,10,
0,0,0,1
)
}
I set the number 10 where I believe the Z translation is, but the Rectangle just disappears instead of getting a little closer to the camera.
Applying transform: Translate {x: 0; y: 0; z: 100} on a Rectangle throws an error as expected as Translate only has only x and y properties (See http://doc.qt.io/qt-5/qml-qtquick-translate.html).
The Transform does not correspond with how you are trying to use it as z is not the position along the z-axis. z is the "stacking order" which is used to control which items are drawn on top or below other items (http://doc.qt.io/qt-5/qml-qtquick-item.html#z-prop).
If you wanted to let your Rectangle appear "a little closer to the camera", Scale seems like a possible Transform to use (http://doc.qt.io/qt-5/qml-qtquick-scale.html) or just use the item's scale property (http://doc.qt.io/qt-5/qml-qtquick-item.html#scale-prop).
This answer might also be helpful to you as someone else had a similar question. It illustrates how you can rotate along different axis. For example, You could do something like: transform: Rotation { origin.x: 50; origin.y: 55; axis { x: 0; y: 1; z: 0 } angle: 60}.
Note though that it is not possible to actually translate a QML Rectangle along the "z-axis". So if your goal is to create a 3D scene in QML, two possible options are Qt Canvas3D or the Qt3D module. If you want to use three.js check out this post
Looking to animate the below SVG, which I have got working initially. However, I want it to 'draw' the second SVG in the opposite direction, WITH the dots i've defined.
Is there any way I can do this? Effectively drawing my shape from left to right with the dots.
Codepen: http://codepen.io/anon/pen/gFcAz
The normal dash offset animation trick really only works with solid lines.
This is the closest I managed to get using CSS animations.
http://jsfiddle.net/L4zCY/
Unfortunately the dashes crawl because you have no control over the step rate of the stroke-dashoffset. If you could make it step by 10 at a time, the dashes wouldn't move.
So I think the only way around it is to use Javascript.
var path = document.querySelectorAll("svg path").item(0);
animateDashedPath(path);
/*
* Animates the given path element.
* Assumes the path has a "5 5" dash array.
*/
function animateDashedPath(path)
{
var pathLength = path.getTotalLength();
var animationDuration = 2000;
var numSteps = Math.round(pathLength / (5+5) + 1);
var stepDuration = animationDuration / numSteps;
// Build the dash array so we don't have to do it manually
var dasharray = [];
while (numSteps-- > 0) {
dasharray.push(5);
dasharray.push(5);
}
dasharray.push(pathLength);
// Animation start conditions
path.setAttribute("stroke-dasharray", dasharray.join(" "));
path.setAttribute("stroke-dashoffset", -pathLength);
// We use an interval timer to do each step of the animation
var interval = setInterval(dashanim, stepDuration);
function dashanim() {
pathLength -= (5+5);
path.setAttribute("stroke-dashoffset", -pathLength);
if (pathLength <= 0) {
clearInterval(interval);
}
}
}
Demo here
Update
It looks like there is an issue with in FF. If you create the "right" number of dashes for the path length, it doesn't quite reach the end of the path. You need to add extra.
A version of the demo that works properly on FF is here