I have a function called turnWheel:
turnWheel : function() {
var el = this.getContainerElement().getDomElement();
qx.bom.element.Animation.animate(el, {
duration: 300,
timing: "linear",
keep: 100,
origin: "50% 50%",
keyFrames : {
0: {rotate: "0deg"},
50: {rotate: "45deg"},
100 : {rotate : "90deg"}
}
});
}
But when I execute turnWheel, it turns an image for 90 degrees. But if I execute again, the image goes back to original place and rotates the same 90 degrees. What I want to achieve is, the image turns 90 degrees on each click, and moves on to the next 90 degrees on 2nd click, and so on.
What did I miss?
You can calculate the rotation on every call of the method either reading the former value of the rotation or simply by storing a external counter. Check out the playground sample if created to show you a working solution:
http://tinyurl.com/ox653l5
Related
TL;DR: I am using the Panresponder code from the React Native docs, and need help understanding why the 'offset' value is used, as opposed to just using the animated value.
Full Question:
The Scenario:
I am using a Panresponder in React Native to drag and drop objects around the screen. I am using standard code from the RN docs.
Basically, the draggable object has an animated position value. When you click the object, the offset on that animated value is set to the animated value, and the animated value is set to zero. As you drag, the animated value is incrementally set to the magnitude of how far it has been dragged in that gesture. When you release the object, the offset is added to the animated value, and the offset is then set to zero.
Example:
For example, if the object starts from position 0, then initially both the animated value and the offset are set to 0. If you drag the object by 100px, the animated value gradually increases from 0 to 100 as you drag. When you release, the zero offset is added to the animated value (so nothing happens). If you click the object again, the offset is set to 100, and the animated value is re-set to 0. If you drag the object another 50px, the animated value increases from 0 to 50. When you release the object, the 100 offset is added to the animated value, which becomes 150, and the offset is re-set to zero.
In this way, the animated value always holds the distance dragged in the current gesture, with the offset saving the position that the object was at before the current drag gesture started, and when you release the object, that saved offset value is tacked onto the animated value, so that when the object is at rest, the animated value contains the total distance that the object has been dragged by all gestures combined.
Code:
Here's the code I'm using to do this:
this.animatedValue.addListener((value) => this._value = value); // Make this._value hold the value of this.animatedValue (essentially extract the x and y values from the more complex animatedValue)
this.panResponder = PanResponder.create({
onPanResponderGrant: () => { // When user clicks to initiate drag
this.animatedValue.setOffset({ // Save 'distance dragged so far' in offset
x: this._value.x,
y: this._value.y,
})
this.animatedValue.setValue({ x: 0, y: 0}) // Set this.animatedValue to (0, 0) so that it will hold only 'distance so far in current gesture'
},
onPanResponderMove: Animated.event([ // As object is dragged, continually update animatedValue
null, { dx: this.animatedValue.x, dy: this.animatedValue.y}
]),
onPanResponderRelease: (e, gestureState) => { // On release, add offset to animatedValue and re-set offset to zero.
this.animatedValue.flattenOffset();
}
}
My Question:
This code works perfectly well. When I don't understand though, is why do we need the offset? Why do we need to re-set the animated value to zero on every new gesture, save its value in offset, and re-add that to the animated value after it's finished being dragged? When the object is released, it ends up just holding the total distance dragged, so why not just use the animated value and not use the offset? With my example above, why not just increment animated value to 100 when you drag it 100px, then when you click and drag it again, keep updating the animated value?
Possible Solution:
The only advantage I can think of to using the offset is that animatedValue will now allow you to keep track of the 'distance so far in current gesture', as opposed to just 'total distance so far over all gestures combined'. There might be a scenario in which you need the 'distance so far in current gesture' value, so I'm wondering if this is the only reason to ever use the offset, or is there a more fundamental reason I'm missing why we should use it all the time?
Any insight would be great.
Thanks!
Actually the logic isn't right in the example you used because it's just a partial example using flattenOffset that isn't meant to be used for standard drag/drop behaviour (see the bottom paragraph: https://animationbook.codedaily.io/flatten-offset/):
Because we reset our offset and our animated value in the onPanResponderGrant, the call to flattenOffset is unnecessary, here. However, in the case where we want to trigger an animation from the released location to another location, flattenOffset is required.
The whole point of the offset is that you don't need to keep track of the absolute position value in a separate variable. So you were right to doubt the need for the offset given that you where storing the absolute position in this._value.
At the beginning of a drag, the x/y values of the Animated.Value start from [0, 0], so the drag is relative to the starting position:
offset + [0, 0] = absolute position at the beginning of a drag
offset + [x, y] = absolute position at the end of the drag
For the next drag to start at the right position, you just need to add [x, y] to the offset, which is done by extractOffset():
this.panResponder = PanResponder.create({
// Allow dragging
onStartShouldSetPanResponder: (e, gesture) => true,
// Update position on move
onPanResponderMove: (e, gestureState)=> {
Animated.event([
null,
{dx: this.animatedValue.x, dy: this.animatedValue.y},
])(e, gestureState)
},
// Update offset once we're done moving
onPanResponderRelease: (e, gestureState)=> {
this.animatedValue.extractOffset();
}
});
Thanks to the offset, you don't need this._value anymore to get the proper drag behaviour.
Because it's better to have the entire animated value's state be self-contained, so you can pass its value to a transform. Of course maybe you don't want the "total distance travelled" in which case, well, don't use offsets, but if you do, using AnimatedValue's offset is the best solution.
Let me show you why by coding up an example of tracking the total distance travelled between touches without using the built-in offset:
this.offsetValue = {x: 0, y:0};
this.panResponder = PanResponder.create({
onPanResponderGrant: () => { // When user clicks to initiate drag
this.animatedValue.setValue({ x: 0, y: 0}) // Set this.animatedValue to (0, 0) so that it will hold only 'distance so far in current gesture'
},
onPanResponderMove: Animated.event([ // As object is dragged, continually update animatedValue
null, { dx: this.animatedValue.x, dy: this.animatedValue.y}
]),
onPanResponderRelease: (e, gestureState) => {
// Set the offset to the current position
this.offsetValue = {x: gestureState.dx, y: gestureState.dy}
// Reset our animatedvalue since the offset is now all good
this.animatedValue.setValue({ x: 0, y: 0})
}
}
This works, and it's less code you now have the raw value for the current touch in Animated.Value and if you want the total distance moved you can use this.offsetValue. Except... how do you apply it to get the total distance exactly? You might think you can do this:
<Animated.View
style={{
transform: [
{ translateX: this.offset.x + this.animatedValue.x },
{ translateY: this.offset.y + this.animatedValue.y },
],
}}
{...this.panResponder.panHandlers}
/>
But this will be an error because animatedValue.x isn't a number obviously. You could use ._value directly but then what's the point of using Animated? The entire idea is that you can pass a single Animated object to a transform property. So that's why you simply use the object's internal offset.
i am working on d3 charts with react and new on both react and d3. The issue i am trying to solve is;
I have a line chart and i have useInteractiveGuideline enabled, so when i hover over the graph, i can see what my value is on that point(with a circle on the line). The problem is; for the y axis values that are close to min or max grid lines, the data point is cropped just from the edge domain values and becomes an half circle.
line chart with cropped data points
I need some sort of padding to see the whole point on edges.
Is there any way to do that other than changing the domain values? I don't wanna change the domain values since my data is dynamic and can reach to very big numbers, so it may not be stable.
nv.addGraph(() => {
let chart = nv.models.lineChart()
.padData(true)
.noData('')
.margin({ "top": 20, "right": 20, "bottom": 20, "left": 20 })
.yDomain([0, max])
.useInteractiveGuideline(true);
chart.xAxis
.showMaxMin(false)
.ticks(5)
.tickFormat((d) => {
return ticks[d]
})
chart.yAxis.tickFormat((d) => {
return d;
})
d3.select('#chart')
.datum(chartData)
.transition().duration(700)
.call(chart);
return chart;
});
I've added below line and issue is solved
chart.lines.clipEdge(false);
I am using Microsoft.DirectX.Direct3D and Microsoft.DirectX to render some data in 3D.
Now, I would like to draw text to indicate the height value inside the space. As shown the picture below:
Now I am facing two main problems:
Problem 1: As you can see, the draw text is set upside down. What can I do to make it to be show correctly?
Problem 2: I am getting Direct3DXException error when I tried to rotate the screen. The error message as per below:
Below is my code for DrawText() using Sprite class
Microsoft.DirectX.Direct3D Device = new Device(0, DeviceType.Hardware, this.panel1,
CreateFlags.HardwareVertexProcessing, presentationParameters);
private void Render()
{
device.BeginScene();
if(checkBox1.checked)
{
DrawText();
}
device.EndScene();
device.SetTexture(0, null);
device.Present();
}
private void DrawText()
{
Sprite fontsprite = new Sprite(device);
fontsprite.Begin(SpriteFlags.AlphaBlend | SpriteFlags.ObjectSpace);
_font = new Microsoft.DirectX.Direct3D.Font(device, 10, 10, FontWeight.Bold, 1, false, CharacterSet.Ansi, Precision.Default, FontQuality.ClearType, PitchAndFamily.DefaultPitch, "face1");
_font.DrawText(fontsprite, "1.5 Km", 120, 15, Color.Black);
_font.DrawText(fontsprite, "2.5 Km", 120, 25, Color.Black);
_font.DrawText(fontsprite, "3.5 Km", 120, 35, Color.Black);
fontsprite.Transform.Translate(120, 100, 100);
fontsprite.End();
}
Need some help on resolving problem 1 and problem 2. Thank you.
Update: Problem 1 has been solved by myself. Now left problem 2 only.
Code to solve problem 1:
fontsprite.Transform = Matrix.RotationZ((float)Math.PI);
fontsprite.Transform *= Matrix.Translation(heightBoxSize, heightValue, heightBoxSize);
fontsprite.Transform.Translate(100, 100, 100);
I think it is because high memory consumption because you are creating new Sprite in every frame. (and 60 frames for each second?)
This problem happened where, rotating the screen using the mouse event, it will constantly update the result of device in frontsprite.
Therefore I suggest you to move part of the codes out.
Move the declaration part to global and then move initialization to Initialization() part.
Also move the fontsprite.End() to the Final() part.
I hopes that help.
With the help of a fellow stackoverflow user, I am able to change the position of a two lines and a circle on the stage using the following:
var circle2 = new Kinetic.Circle({
drawFunc: function(canvas) {
var context2 = canvas.getContext();
var centerX2 = blueLine2.getPosition().x;
centerY2 = greenLine2.getPosition().y;
context2.drawImage(gArrow2, -156, -23 + centerY2, 11, 23);
context2.drawImage(gArrow2, 156, -23 + centerY2, 11, 23);
context2.drawImage(bArrow2, centerX2, 156, 23, 11);
context2.drawImage(bArrow2, centerX2, -156, 23, 11);
context2.beginPath();
context2.arc(centerX2, centerY2, this.getRadius(), 0, 2 * Math.PI, false);
context2.lineWidth = this.getStrokeWidth();
context2.strokeStyle = this.getStroke();
context2.stroke();
},
x: cx + gx,
y: cy + gy,
radius: 70,
stroke: '#00ffff',
strokeWidth: 3,
opacity: 0.5
});
layer2.add(circle2);
It works great, now my challenge is if I move a line on a second stage for example the horizontal line, I can also move the horizonal line on the first stage using:
greenLine2.on('dragend', function (event) {
var y1 = greenLine2.getPosition().y;
greenLine3.setPoints([0, 256 + y1, 512, 256 + y1]);
centerY3 = 256 + y1;
layer3.draw();
layer2.draw();
});
However I can't update the layer to move also the vertical line and the circle. I would appreciate your suggestions, thanks in advance.
Lets say that greenLine2 is the one you're moving, and you want greenLine3 to move to the same position on the other stage. I'm going to assume the stages are the same size, but you can change up the code to account for these changes.
greenLine2.on('dragmove', function (event) {
var userPos = stage.getUserPosition(); //if this doesnt work the way you need, try a different approach, such as below:
//var userPos = greenLine.getPosition(); //other possibility
greenLine3.setPosition(userPos);
layer3.draw();
layer2.draw();
});
and if you want other things to move as well, you can do the same kind of code using .setPosition() with some offset so that the drawing is relative.
Another approach would be to create a group in each stage, and make the group draggable, that way, you can drag all the items in a group at the same time, and synchronously across stages.
Program crashes when set location coordinates using MKMapView.
Log:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Invalid Region <center:+112.57075000, +37.87049600 span:+0.05165163, +0.43945312>'
span in my program is
MKCoordinateSpan span;
span.latitudeDelta = .05;
span.longitudeDelta = .02;
after coding:
self.mMKMapview.region = [self.mMKMapview regionThatFits:region];
as the log shows, span changes to :+0.05165163, +0.43945312
anyone help please, I have been standstill here for two days.
Thanks!
The problem is the center coordinate:
+112.57075000, +37.87049600
The latitude must be from -90 to +90 so +112.57075 is out of range.
Check how the center coordinate is being set or maybe the data is backwards.
Also, you don't need to explicitly call regionThatFits because the map view does it automatically when you set the region normally (ie. just call setRegion). It's normal, by the way, for the map view to adjust the span as needed to fit the map view dimensions or zoom level.
I use the following code to set the region:
if( centerLat > -89 && centerLat < 89 && centerLng > -179 && centerLng < 179 ){
[self.mapView setRegion:region animated:YES];
}
I would rather suggest to use CLLocationCoordinate2DIsValid
so something like
guard CLLocationCoordinate2DIsValid(centerLat) else {
return
}