does altair have a "play button" for sliders? - python-3.x

x = np.arange(100)
t = np.arange(100)
y = [p**2 for p in x]
source = pd.DataFrame({
't':t,
'x': x,
'f(x)': y
})
slider = alt.binding_range(min=int(min(t)), max=int(max(t)), step=1)
select_t = alt.selection_single(name="year", fields=['t'],
bind=slider, init={'year': 50})
alt.Chart(source).mark_line(point=True).encode(
alt.X('x',scale=alt.Scale(domain=(0,100))),
alt.Y('f(x)',scale=alt.Scale(domain=(0,10000)))
).add_selection(select_year).transform_filter(select_t)
so I'm putting together a simple animated point, and I've got the slider running ok. But I'd like it to run automatically. Is that possible?

No, there is not currently any direct way to automate the slider or produce an animation in Altair. Animations have been discussed within Vega (the renderer that underlies Altair), but have not yet been added to the implementation.

Here's how to add a Play button to play the slider.
HTML('''
<button onclick="play()">Play</button>
<script>
var timer;
function play(){
// restart if max
slider = document.querySelector("input[type=range]")
if (slider.value==slider.max) {
slider.value = slider.min
slider.dispatchEvent(new Event("input"))
}
timer = setInterval(step, 200) // change speed here
}
function step(){
slider = document.querySelector("input[type=range]")
slider.stepUp() // use defult step
slider.dispatchEvent(new Event("input"))
if (slider.value==slider.max){
clearInterval(timer)
}
}
</script>
''')

Related

Drag & Drop (swap) 3 texture buttons in a Margin Container->VBox

Following along a great tutorial, code is replicated yet does not function as shown. No new texture appears to be created when I try to drag the texture button. Only difference is the tutorial uses a TextureRect, while I'm using a TextureButton.
extends TextureButton
func get_drag_data(position: Vector2):
var vControl = Control.new()
var vData = {}
var vTexture = TextureRect.new()
vTexture.expand = true
vTexture.texture = texture_disabled
vTexture.rect_size = Vector2(320, 400)
vControl.add_child(vTexture)
vTexture.rect_position = -0.5 * vTexture.rect_size
set_drag_preview(vTexture)
return vData
Code above is attached to Party_1. texture_disabled does have a texture set.
It would work if you had the code in get_drag_data looking like this:
func get_drag_data(_position: Vector2):
var vTexture = TextureRect.new()
vTexture.expand = true
vTexture.texture = texture_disabled
vTexture.rect_size = Vector2(320, 400)
set_drag_preview(vTexture)
return {}
However, that would place the TextureRect top-left corner at the cursor position.
You want to offset the position of the TextureRect so it is centered at the cursor position. To do that, you create another Control, add the TextureRect as a child to it… And pass the TextureRect anyway? No, that does not work, you need to pass the new Control:
func get_drag_data(_position: Vector2):
var vTexture = TextureRect.new()
vTexture.expand = true
vTexture.texture = texture_disabled
vTexture.rect_size = Vector2(320, 400)
var vControl = Control.new()
vControl.add_child(vTexture)
vTexture.rect_position = -0.5 * vTexture.rect_size
set_drag_preview(vControl)
return {}
Please notice I'm giving vControl to set_drag_preview, not vTexture.
You cannot give to set_drag_preview a Control that has a parent. In fact, if you tried you would get an error in the Output console saying:
_gui_set_drag_preview: Condition "p_control->get_parent() != nullptr" is true.
Or
_gui_set_drag_preview: Condition "p_control->is_inside_tree()" is true.

Composition animation on a visual sub channel

I use the new Composition Animation API in UWP (Windows 10 1607) to animate a custom control. I want changes of the vertical offset of its children to be animated, but not changes to the horizontal offset.
I can animate the whole offset (X and Y) like this:
var offsetAnimation = compositor.CreateVector3KeyFrameAnimation();
offsetAnimation.Target = "Offset";
offsetAnimation.Duration = TimeSpan.FromSeconds(0.5);
offsetAnimation.InsertExpressionKeyFrame(1.0f, "This.FinalValue");
animationCollection["Offset"] = offsetAnimation;
var visual = ElementCompositionPreview.GetElementVisual(child);
visual.ImplicitAnimations = animationCollection;
I expected this code to only animate the Y offset of the child, but it doesn't display any animation at all:
var offsetAnimation = compositor.CreateScalarKeyFrameAnimation();
offsetAnimation.Target = "Offset.Y";
offsetAnimation.Duration = TimeSpan.FromSeconds(0.5);
offsetAnimation.InsertExpressionKeyFrame(1.0f, "This.FinalValue");
animationCollection["Offset"] = offsetAnimation;
var visual = ElementCompositionPreview.GetElementVisual(child);
visual.ImplicitAnimations = animationCollection;
Setting Target to "Offset.y" or the trigger to "Offset.Y" doesn't help.
I haven't found an example using visual sub channels in the documentation, so I would appreciate any help on how to only animate the y channel of the offset.
According to your code snippet, you set a Offset trigger for the animation. That means once the offset of child is changed, this animation will started. And you set 'This.FinalValue' for the ExpressionKeyFrame, so it will bind the value you set to the new offset and it will animate to that new value.
So we if we just set the new offset to only have y value changed (let x and z be same as the old one), the animation will only animate the y channel.
Code like follows:
<TextBlock x:Name="txtanimation" Text="animation test" Height="30" Width="100" Foreground="Red" ></TextBlock>
<Button x:Name="btnanimate" Click="btnanimate_Click" Content="Animate y" Margin="60"></Button>
Code behind:
Visual visual;
public MainPage()
{
this.InitializeComponent();
visual = ElementCompositionPreview.GetElementVisual(txtanimation);
Compositor compositor = ElementCompositionPreview.GetElementVisual(txtanimation).Compositor;
ImplicitAnimationCollection animationCollection = compositor.CreateImplicitAnimationCollection();
Vector3KeyFrameAnimation offsetAnimation = compositor.CreateVector3KeyFrameAnimation();
offsetAnimation.Target = "Offset";
offsetAnimation.Duration = TimeSpan.FromSeconds(2.5);
offsetAnimation.InsertExpressionKeyFrame(1.0f, "This.FinalValue");
animationCollection["Offset"] = offsetAnimation;
visual.ImplicitAnimations = animationCollection;
}
private void btnanimate_Click(object sender, RoutedEventArgs e)
{
visual.Offset=visual.Offset+ new System.Numerics.Vector3(0f, 400f, 0f);
}
And the result:
More samples please reference WindowsUIDevLabs. And more details you can reference videos like Implicit Animations.

Normalize x values and log y values in d3.js

I am using Scatter plot to visualize data http://bl.ocks.org/mbostock/3887118. I have more than 2 graphs on a page. I want to keep two options where an user can select
1. Normalize button: Values at x-axes will get normalized and new graphs are plotted.
2. log y button: Values at y axes are changed to log y and new graphs are built on the same page accordingly.
How to do this d3.js?
Also I am plotting this using Nodejs, Express and d3.js.
Till now I have built the graphs. These are the options to increase interactivity.
I think the best is to define two different scales:
var yNormal = d3.scale.linear() ...
and
var yLog = d3.scale.log() ....
and on button click redraw the circles using the other scale:
//in button event handler
if( /* log */) {
svg.selectAll(".dot").attr('cy', function() { return yLog(d.yourDataField); }
}
else {
svg.selectAll(".dot").attr('cy', function() { return yNorm(d.yourDataField); }
}
You can also use transition to animate the redraw like this:
svg.selectAll(".dot").transition().duration(500).attr('cy', function() { return yLog(d.yourDataField); }
You can also animate the rescaling of the axis using this method.
You can apply the same to X axis as well.

Dragging a circle

I am beginning to use snap.svg, and stuck in a probably simple question. I draw a circle, and want to let the user drag it around, and when the user stops dragging, I want to know the alert the final position of the circle.
I started with this:
var s = Snap("#svg");
var d = s.circle(20,20,5);
Then I created the following functions as drag event-handlers; I only need the drag-end event so I made the two other event-handlers null:
var endFnc = function(e) {
alert("end: "+e.layerX+","+e.layerY);
}
var startFnc = null;
var moveFnc = null;
Then I installed the drag event handlers:
d.drag(moveFnc,startFnc,endFnc);
Whenever I tried to drag a circle, the end event fired, but, the circle did not move.
So I figured maybe I have to also create the drag move event (although I don't need it):
var moveFnc = function(dx, dy, x, y) {
this.transform('t' + x + ',' + y);
}
Now the circle did move, but, not exactly at the mouse, but approximately 20 pixels at its bottom right.
I read the documentation here: http://snapsvg.io/docs and there seems to be no explanation about how to create working drag events.
How does anyone get this knowledge?!
After struggling for some hours to do this with snap.js, I finally discovered svg.js and its draggable plugin, with which it is so much easier:
var draw = SVG('svg');
var circle = draw.circle(10).attr({cx:30,cy:30,fill:'#f06'});
circle.dragend = function(delta, event) {
alert(this.attr('cx'))
}
circle.draggable();
So, I switched to svg.js ...

How to clear all the previously drawn graphics in vc++ paint?

I have drawn rectangles in picture box using paint event. When i click clear button. i want the graphics to vanish. i call paint event everytime the mouse moves. What should i do?
Code in paint event:
Graphics^ g = e->Graphics;
float PenWidth = 2;
if(msdwnflag!=-1 && count%2==1)
{
if(selecflag==0)
{
g->DrawRectangle( gcnew Pen( Color::Blue,PenWidth ), RcDraw);
}
else
{
RcDraw.Width = finalMousePos.X- RcDraw.X;
RcDraw.Height = finalMousePos.Y- RcDraw.Y;
g->DrawRectangle( gcnew Pen( Color::Red,PenWidth ), RcDraw);
}
}
If pb is your PictureBox then clear its image to clear all the graphics. Also, You can use a variable (buttonpressed) to check whether it is true (button clear pressed) or false (otherwise)
buttonpressed=1;
pb->Image = nullptr;
pb->Refresh();
In your paint method include all the graphics if Not buttonpressed:
if (buttonpressed != 1){
// all your graphics code
}
When you want the graphics to appear back when you press a button change the buttonpressed value:
buttonpressed=0;
pb->Refresh();
Draw a graphics of the transparent colour. thats wat i finally did. not a gud design but works :)

Resources