<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Animation &#8211; Xojo Programming Blog</title>
	<atom:link href="https://blog.xojo.com/tag/animation/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.xojo.com</link>
	<description>Blog about the Xojo programming language and IDE</description>
	<lastBuildDate>Thu, 22 Jan 2026 20:51:02 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>
	<item>
		<title>Xojo + XAML + Goto = &#x1f525;</title>
		<link>https://blog.xojo.com/2026/01/22/xojo-xaml-goto/</link>
		
		<dc:creator><![CDATA[William Yu]]></dc:creator>
		<pubDate>Thu, 22 Jan 2026 20:50:59 +0000</pubDate>
				<category><![CDATA[Desktop]]></category>
		<category><![CDATA[Fun]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[Animation]]></category>
		<category><![CDATA[DesktopXAMLContainer]]></category>
		<category><![CDATA[XAML]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15790</guid>

					<description><![CDATA[For decades, Goto has been treated as a programming faux pas—something to avoid at all costs. Like most rules though, there are exceptions. The Goto&#8230;]]></description>
										<content:encoded><![CDATA[
<p>For decades, Goto has been treated as a programming faux pas—something to avoid at all costs. Like most rules though, there are exceptions. The Goto I’m talking about here is one of them… and it can quite literally light your app on fire—programmatically speaking.</p>



<p>One of the hidden gems in <a href="https://xojo.com/download/" target="_blank" rel="noreferrer noopener">Xojo 2025r3</a> is support for XAML transitions, which makes it possible to add lightweight animations to your UI without writing any custom animation code in Xojo. Instead, you define visual states in XAML and let the XAML engine handle the animation for you.</p>



<p>At a high level, the workflow looks like this:</p>



<ol class="wp-block-list">
<li>Define one or more&nbsp;<strong>VisualStates</strong>&nbsp;in XAML.</li>



<li>Attach transitions to those states (for example, moving or fading an element).</li>



<li>From Xojo code, switch between states using&nbsp;<code>Invoke("GotoState", ...)</code>.</li>
</ol>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4a1.png" alt="💡" class="wp-smiley" style="height: 1em; max-height: 1em;" />&nbsp;<strong>Pro Tip</strong><br><code>DesktopXAMLContainer</code>&nbsp;subscribes to&nbsp;<code>Operator_Lookup</code>, so you don’t have to call&nbsp;<code>Invoke</code>&nbsp;directly. Instead of writing<code> XAMLContainer1.Invoke("GotoState", "WhichState")</code>, you can simply call <code>XAMLContainer1.GotoState("WhichState")</code>.</p>



<h3 class="wp-block-heading">Visual States in XAML</h3>



<p>A&nbsp;<em>VisualState</em>&nbsp;represents a named configuration of UI properties. When you transition from one state to another, XAML can automatically animate the change.</p>



<p>Below is a simple example that animates a fire emoji <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f525.png" alt="🔥" class="wp-smiley" style="height: 1em; max-height: 1em;" /> moving upward, similar to a candle flame flickering or burning upward.</p>



<h3 class="wp-block-heading">Example XAML</h3>



<p>This example uses a&nbsp;<code>TextBlock</code>&nbsp;to display the fire emoji and animates its vertical position with a&nbsp;<code>TranslateTransform</code>. Note that visual states must be defined on a control, so we attach them to a&nbsp;<code>UserControl</code>, allowing it to participate in&nbsp;<code>GotoState</code>&nbsp;transitions.</p>



<pre class="wp-block-preformatted">&lt;UserControl&gt;<br>  &lt;Grid&gt;<br>    &lt;VisualStateManager.VisualStateGroups&gt;<br>      &lt;VisualStateGroup Name="FlameStates"&gt;<br><br>        &lt;VisualState Name="Bottom"&gt;<br>          &lt;Storyboard&gt;<br>            &lt;DoubleAnimation<br>              Storyboard.TargetName="FlameTransform"<br>              Storyboard.TargetProperty="Y"<br>              To="40"<br>              Duration="0:0:1" /&gt;<br>          &lt;/Storyboard&gt;<br>        &lt;/VisualState&gt;<br><br>        &lt;VisualState Name="Top"&gt;<br>          &lt;Storyboard&gt;<br>            &lt;DoubleAnimation<br>              Storyboard.TargetName="FlameTransform"<br>              Storyboard.TargetProperty="Y"<br>              To="-100"<br>              Duration="0:0:1" /&gt;<br>          &lt;/Storyboard&gt;<br>        &lt;/VisualState&gt;<br><br>      &lt;/VisualStateGroup&gt;<br>    &lt;/VisualStateManager.VisualStateGroups&gt;<br><br>    &lt;TextBlock<br>      Text="<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f525.png" alt="🔥" class="wp-smiley" style="height: 1em; max-height: 1em;" />"<br>      FontSize="32"<br>      HorizontalAlignment="Center"<br>      VerticalAlignment="Bottom"&gt;<br><br>      &lt;TextBlock.RenderTransform&gt;<br>        &lt;TranslateTransform Name="FlameTransform" /&gt;<br>      &lt;/TextBlock.RenderTransform&gt;<br><br>    &lt;/TextBlock&gt;<br>  &lt;/Grid&gt;<br>&lt;/UserControl&gt;</pre>



<p>In this XAML:</p>



<ul class="wp-block-list">
<li>The&nbsp;<code>VisualStateGroup</code>&nbsp;named&nbsp;<strong>FlameStates</strong>&nbsp;contains two states:
<ul class="wp-block-list">
<li><strong>Bottom</strong>&nbsp;– moves the emoji downward.</li>



<li><strong>Top</strong>&nbsp;– moves the emoji upward.</li>
</ul>
</li>



<li>The&nbsp;<code>DoubleAnimation</code>&nbsp;targets the&nbsp;<code>Y</code>&nbsp;property of a&nbsp;<code>TranslateTransform</code>.</li>



<li>The transition duration is handled entirely by XAML.</li>
</ul>



<h3 class="wp-block-heading">Triggering the Transition from Xojo</h3>



<p>Once the visual states are defined, switching between them from Xojo is straightforward. Assuming this XAML is hosted in a&nbsp;<code>XAMLContainer</code>&nbsp;named&nbsp;<code>XAMLContainer1</code>, you can trigger the animation like this:</p>



<pre class="wp-block-code"><code>XAMLContainer1.GotoState("Top")</code></pre>



<p>And to move it back down:</p>



<pre class="wp-block-code"><code>XAMLContainer1.GotoState("Bottom")</code></pre>



<h3 class="wp-block-heading">Why This Is Powerful</h3>



<p>What makes this feature especially useful is that:</p>



<ul class="wp-block-list">
<li>The animation logic stays in XAML, where it naturally belongs.</li>



<li>Xojo code remains clean and declarative—just tell the UI&nbsp;<em>which state</em>&nbsp;to go to.</li>



<li>More complex effects (opacity, scaling, rotation, easing functions) can be added without changing any Xojo code.</li>
</ul>



<p>Here&#8217;s a more interesting variation, where the flames drift upward rather than moving in a straight line:</p>



<pre class="wp-block-code"><code>&lt;UserControl&gt;
  &lt;Grid Width="160" Height="240"&gt;

    &lt;!-- Fire emoji 1 --&gt;
    &lt;TextBlock Name="Fire1"
           Text="&#x1f525;"
           FontSize="32"
           VerticalAlignment="Bottom"
           HorizontalAlignment="Center"&gt;
      &lt;TextBlock.RenderTransform&gt;
        &lt;TranslateTransform Name="Move1"/&gt;
      &lt;/TextBlock.RenderTransform&gt;
    &lt;/TextBlock&gt;

    &lt;!-- Fire emoji 2 --&gt;
    &lt;TextBlock Name="Fire2"
           Text="&#x1f525;"
           FontSize="26"
           VerticalAlignment="Bottom"
           HorizontalAlignment="Center"
           Margin="20,0,0,0"
           Opacity="0.8"&gt;
      &lt;TextBlock.RenderTransform&gt;
        &lt;TranslateTransform Name="Move2"/&gt;
      &lt;/TextBlock.RenderTransform&gt;
    &lt;/TextBlock&gt;

    &lt;!-- Fire emoji 3 --&gt;
    &lt;TextBlock Name="Fire3"
           Text="&#x1f525;"
           FontSize="22"
           VerticalAlignment="Bottom"
           HorizontalAlignment="Center"
           Margin="-20,0,0,0"
           Opacity="0.7"&gt;
      &lt;TextBlock.RenderTransform&gt;
        &lt;TranslateTransform Name="Move3"/&gt;
      &lt;/TextBlock.RenderTransform&gt;
    &lt;/TextBlock&gt;

    &lt;VisualStateManager.VisualStateGroups&gt;
      &lt;VisualStateGroup Name="FireStates"&gt;

        &lt;VisualState Name="Off"/&gt;

        &lt;VisualState Name="On"&gt;
          &lt;Storyboard RepeatBehavior="Forever"&gt;

            &lt;!-- Fire 1 --&gt;
            &lt;DoubleAnimation Storyboard.TargetName="Move1"
                     Storyboard.TargetProperty="Y"
                     From="0"
                     To="-180"
                     Duration="0:0:1.2"/&gt;

            &lt;DoubleAnimation Storyboard.TargetName="Move1"
                     Storyboard.TargetProperty="X"
                     From="0"
                     To="10"
                     Duration="0:0:0.6"
                     AutoReverse="True"/&gt;

            &lt;!-- Fire 2 --&gt;
            &lt;DoubleAnimation Storyboard.TargetName="Move2"
                     Storyboard.TargetProperty="Y"
                     From="0"
                     To="-160"
                     Duration="0:0:1.0"
                     BeginTime="0:0:0.3"/&gt;

            &lt;DoubleAnimation Storyboard.TargetName="Move2"
                     Storyboard.TargetProperty="X"
                     From="0"
                     To="-12"
                     Duration="0:0:0.5"
                     AutoReverse="True"/&gt;

            &lt;!-- Fire 3 --&gt;
            &lt;DoubleAnimation Storyboard.TargetName="Move3"
                     Storyboard.TargetProperty="Y"
                     From="0"
                     To="-140"
                     Duration="0:0:1.4"
                     BeginTime="0:0:0.15"/&gt;

            &lt;DoubleAnimation Storyboard.TargetName="Move3"
                     Storyboard.TargetProperty="X"
                     From="0"
                     To="8"
                     Duration="0:0:0.7"
                     AutoReverse="True"/&gt;

          &lt;/Storyboard&gt;
        &lt;/VisualState&gt;

      &lt;/VisualStateGroup&gt;
    &lt;/VisualStateManager.VisualStateGroups&gt;

  &lt;/Grid&gt;
&lt;/UserControl&gt;</code></pre>



<p>To light up the flames we&#8217;ll simply invoke the &#8220;On&#8221; state:</p>



<pre class="wp-block-code"><code>XAMLContainer1.GotoState("On")</code></pre>



<figure class="wp-block-video"><video height="720" style="aspect-ratio: 1280 / 720;" width="1280" controls loop src="https://blog.xojo.com/wp-content/uploads/2026/01/XAMLFire.mp4" playsinline></video></figure>



<p>For subtle UI polish—like animated indicators, highlights, or playful effects such as this candle flame—XAML transitions provide a surprisingly powerful new tool in Xojo.</p>



<p><em><em><em>William Yu grew up in Canada learning to program BASIC on a Vic-20. He is Xojo’s resident Windows and Linux engineer, among his many other skills. Some may say he has joined the dark side here in the USA, but he will always be a Canadian at heart.</em></em></em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>
]]></content:encoded>
					
		
		<enclosure url="https://blog.xojo.com/wp-content/uploads/2026/01/XAMLFire.mp4" length="177770" type="video/mp4" />

			</item>
		<item>
		<title>Beyond Static UI: Create Dynamic Loading Animations with Xojo Graphics</title>
		<link>https://blog.xojo.com/2024/11/05/beyond-static-ui-create-dynamic-loading-animations-with-xojo-graphics/</link>
		
		<dc:creator><![CDATA[Gabriel Ludosanu]]></dc:creator>
		<pubDate>Tue, 05 Nov 2024 15:10:24 +0000</pubDate>
				<category><![CDATA[Desktop]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Animation]]></category>
		<category><![CDATA[Custom Controls]]></category>
		<category><![CDATA[DesktopCanvas]]></category>
		<category><![CDATA[Graphics]]></category>
		<category><![CDATA[Phase-Animation]]></category>
		<category><![CDATA[UI-Design]]></category>
		<category><![CDATA[Visual Feedback]]></category>
		<category><![CDATA[Xojo-Graphics]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=13975</guid>

					<description><![CDATA[Ever wondered how to create those sleek, professional-looking loading animations you see in modern apps? In this blog post, we&#8217;re going to unlock the power&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Ever wondered how to create those sleek, professional-looking loading animations you see in modern apps?</p>



<p>In this blog post, we&#8217;re going to unlock the power of Xojo&#8217;s DesktopCanvas and its Graphics capabilities to recreate one of the popular <a href="https://tobiasahlin.com/spinkit/">SpinKit loading animations originally created by Tobias Ahlin</a>. We&#8217;ll be implementing the &#8220;Three Bounce&#8221; animation, transforming this beloved CSS animation into native Xojo code!</p>



<p>Not only will you learn how to create this specific animation, but you&#8217;ll also gain valuable insights into animation principles in Xojo that you can use to create your own custom animations. By the end of this tutorial, you&#8217;ll understand how to:</p>



<ul class="wp-block-list">
<li>Harness the power of DesktopCanvas for custom graphics</li>



<li>Create smooth animations using Timers</li>



<li>Implement phase-based animations</li>



<li>Use Graphics methods to draw dynamic shapes</li>



<li>Manage animation lifecycles properly</li>
</ul>



<h3 class="wp-block-heading">Why This Matters</h3>



<p>Loading animations are more than just eye candy – they&#8217;re essential UI elements that keep users engaged while your app processes data. Instead of using static images or third-party libraries, creating your own animations gives you complete control over the look and feel of your application while keeping your dependencies minimal.</p>



<h3 class="wp-block-heading">What We&#8217;re Building</h3>



<p>We&#8217;ll create a smooth, professional-looking three-dot loading animation where dots gracefully scale up and down in sequence. The result is a lightweight, customizable loading indicator that you can drop into any Xojo project. Here&#8217;s what makes this implementation special:</p>



<ul class="wp-block-list">
<li>Pure Xojo code &#8211; no external dependencies</li>



<li>Smooth, fluid animation</li>



<li>Easily customizable colors and timing</li>



<li>Efficient resource usage</li>



<li>Clean, object-oriented design</li>
</ul>



<figure class="wp-block-video"><video height="184" style="aspect-ratio: 360 / 184;" width="360" controls loop preload="auto" src="https://blog.xojo.com/wp-content/uploads/2024/10/spinkit_animation.mp4" playsinline></video></figure>



<p>Ok, let&#8217;s start building our awesome animation class.</p>



<h2 class="wp-block-heading">Step 1: Setting Up the Base Class</h2>



<p>First, create a new class (Insert &gt; Class) that inherits from DesktopCanvas:</p>


<div class="wp-block-image">
<figure class="aligncenter"><img decoding="async" src="https://storage.googleapis.com/co-writer/images/HRIwK4xjWLXvNRyAbzXbq5t8wJF3/-1730379923862.webp" alt="IMAGE"/></figure>
</div>


<pre class="wp-block-code"><code>Protected Class SpinKitClass Inherits DesktopCanvas</code></pre>



<h2 class="wp-block-heading">Step 2: Defining Core Properties</h2>



<p>Add these essential properties to control the animation:</p>


<div class="wp-block-image">
<figure class="aligncenter"><img decoding="async" src="https://storage.googleapis.com/co-writer/images/HRIwK4xjWLXvNRyAbzXbq5t8wJF3/-1730380034310.webp" alt="IMAGE"/></figure>
</div>


<pre class="wp-block-code"><code>Private animationPhases() As Double      // Stores phase offsets for each dot
Private animationSpeed As Integer = 60   // Animation refresh rate in milliseconds
Private animationTimer As Timer         // Timer to drive the animation
Private currentPhase As Double = 0.0    // Current animation phase
Private dotSize As Integer = 20         // Size of each dot
Private dotSpacing As Integer = 20      // Space between dots</code></pre>



<h2 class="wp-block-heading">Step 3: Setting Up Constants</h2>



<p>Define the constants that control the animation behavior:</p>


<div class="wp-block-image">
<figure class="aligncenter"><img decoding="async" src="https://storage.googleapis.com/co-writer/images/HRIwK4xjWLXvNRyAbzXbq5t8wJF3/-1730380079168.webp" alt="IMAGE"/></figure>
</div>


<pre class="wp-block-code"><code>Private Const kDefaultColor As Color = &amp;c333333    // Dot color
Private Const kPhaseIncrement As Double = 0.05    // Animation speed</code></pre>



<h2 class="wp-block-heading">Step 4: Implementing Animation Control Methods</h2>



<p>Add methods to start and stop the animation:</p>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<pre class="wp-block-code"><code>Public Sub StartAnimation()
  /// Initializes and starts the animation
  /// Sets up initial phase offsets for the dots
  /// Creates and configures the animation timer
  
  If animationTimer = Nil Then
    animationPhases = Array(0.0, 0.16, 0.32)
    
    animationTimer = New Timer
    AddHandler animationTimer.Action, AddressOf UpdateAnimation
    animationTimer.Period = animationSpeed
    animationTimer.RunMode = Timer.RunModes.Multiple
  End If
End Sub</code></pre>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<pre class="wp-block-code"><code>Public Sub StopAnimation()
  /// Stops the running animation
  /// Removes the timer handler and cleans up
  /// Refreshes the canvas to clear the animation
  
  If animationTimer &lt;&gt; Nil Then
    RemoveHandler animationTimer.Action, AddressOf UpdateAnimation
    animationTimer = Nil
    Refresh
  End If
End Sub</code></pre>
</div>
</div>



<h2 class="wp-block-heading">Step 5: Creating the Animation Update Logic</h2>



<p>Implement the timer callback that drives the animation:</p>



<pre class="wp-block-code"><code>Private Sub updateAnimation(sender As Timer)
  /// Timer callback that updates the animation state
  /// Increments the phase and triggers a redraw
  /// @param sender The Timer that triggered this callback
  
  #Pragma Unused sender
  
  // Increment the current phase (spin08)
  currentPhase = currentPhase + kPhaseIncrement
  // Reset currentPhase if it exceeds 1.0
  If currentPhase &gt; 1.0 Then currentPhase = 0
  
  // Invalidate the canvas to trigger a repaint
  Refresh()
End Sub</code></pre>



<h2 class="wp-block-heading">Step 6: Implementing the Drawing Logic</h2>



<p>Add the core animation rendering code:</p>



<pre class="wp-block-code"><code>Private Sub animation08(g As Graphics)
  /// Renders a single frame of the three-dot loading animation
  /// Draws 3 dots that scale up and down in sequence
  /// @param g The graphics context to draw into
  
  Var centerX As Integer = Me.Width / 2
  Var centerY As Integer = Me.Height / 2
  
  For i As Integer = 0 To 2
    Var phase As Double = currentPhase + animationPhases(i)
    
    // Ensure phase is within 0 to 1
    If phase &gt; 1.0 Then phase = phase - 1.0
    
    Var scale As Double
    If phase &lt; 0.4 Then
      scale = phase / 0.4
    Else
      scale = (1.0 - phase) / 0.6
    End If
    
    Var size As Integer = dotSize * scale
    Var x As Integer = centerX + (i - 1) * dotSpacing - size / 2
    Var y As Integer = centerY - size / 2
    
    g.DrawingColor = kDefaultColor
    g.FillOval(x, y, size, size)
  Next
End Sub</code></pre>



<h2 class="wp-block-heading">Step 7: Handling the Paint Event</h2>



<p>Implement the Paint event to trigger the animation rendering:</p>



<pre class="wp-block-code"><code>Sub Paint(g As Graphics, areas() As Rect) Handles Paint
  /// Paint event handler that renders the animation
  /// Called automatically when the canvas needs to be redrawn
  /// If animation is running, calls animation08, otherwise clears the canvas
  
  If animationTimer &lt;&gt; Nil Then
    animation08(g)
  Else
    g.ClearRectangle(0, 0, Width, Height)
  End If
End Sub
</code></pre>



<h2 class="wp-block-heading">How It Works</h2>



<ol class="wp-block-list">
<li>The animation uses a phase-based system where each dot is offset in its animation cycle.</li>



<li>The dots scale up and down based on their current phase.</li>



<li>A timer drives the animation by incrementing the phase and triggering redraws.</li>



<li>The dots are positioned horizontally with equal spacing around the center.</li>



<li>Each dot&#8217;s size is calculated based on its current phase in the animation.</li>
</ol>



<h2 class="wp-block-heading">Using the Animation</h2>



<p>To use this animation in your project, all you have to do is simply drag and drop the class on a DesktopWindow and then start or stop the animation when needed.</p>



<pre class="wp-block-code"><code>// Start the animation
SpinKit1.StartAnimation()

// Stop the animation when done
SpinKit1.StopAnimation()</code></pre>



<h2 class="wp-block-heading">Customization</h2>



<p>You can customize the animation by adjusting:</p>



<ul class="wp-block-list">
<li><code>dotSize</code> for larger or smaller dots</li>



<li><code>dotSpacing</code> to change the spread of the dots</li>



<li><code>animationSpeed</code> to make it faster or slower</li>



<li><code>kDefaultColor</code> to change the dot color</li>



<li><code>kPhaseIncrement</code> to adjust the animation speed</li>
</ul>



<h2 class="wp-block-heading">Taking It Further</h2>



<p>The &#8220;Three Bounce&#8221; animation we&#8217;ve created is just one of many amazing animations in the <a href="https://tobiasahlin.com/spinkit/">SpinKit collection</a>. Now that you understand the fundamentals, why not try recreating other SpinKit animations? Here are some exciting challenges to tackle:</p>



<ul class="wp-block-list">
<li>Modify the current animation to use different shapes (squares, rectangles).</li>



<li>Experiment with different timing functions for varied animation effects.</li>



<li>Try implementing the &#8220;Rotating Plane&#8221; or &#8220;Chasing Dots&#8221; animations from SpinKit.</li>



<li>Create your own unique variations by combining what you&#8217;ve learned.</li>



<li>Optimize the class further.</li>
</ul>



<h2 class="wp-block-heading">Share Your Creations!</h2>



<p>Have you created an awesome variation or implemented another SpinKit animation in Xojo? Share it with the community! The <a target="_blank" rel="noreferrer noopener" href="https://forum.xojo.com/">Xojo Forums</a> and social media are great places to showcase your work and inspire others.</p>



<h2 class="wp-block-heading">Resources for Further Exploration</h2>



<ul class="wp-block-list">
<li>Original SpinKit animations by Tobias Ahlin: <a href="https://tobiasahlin.com/spinkit/" target="_blank" rel="noreferrer noopener">https://tobiasahlin.com/spinkit/</a></li>



<li>Xojo Graphics documentation: <a href="https://documentation.xojo.com/api/graphics/graphics.html" target="_blank" rel="noreferrer noopener">https://documentation.xojo.com/api/graphics/graphics.html</a></li>



<li>Xojo DesktopCanvas documentation: <a href="https://documentation.xojo.com/api/user_interface/desktop/desktopcanvas.html" target="_blank" rel="noreferrer noopener">https://documentation.xojo.com/api/user_interface/desktop/desktopcanvas.html</a></li>
</ul>



<p><strong>Remember</strong>: Every great application deserves great animations and now you have the tools to create them! Keep experimenting, keep creating, and most importantly, keep animating!</p>



<p><em>Gabriel is a digital marketing enthusiast who loves coding with Xojo to create cool software tools for any platform. He is always eager to learn and share new ideas!</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>
]]></content:encoded>
					
		
		<enclosure url="https://blog.xojo.com/wp-content/uploads/2024/10/spinkit_animation.mp4" length="308355" type="video/mp4" />

			</item>
		<item>
		<title>Building a Vertical Navigation for your Web Application</title>
		<link>https://blog.xojo.com/2023/03/29/building-a-vertical-navigation-for-your-web-application/</link>
		
		<dc:creator><![CDATA[Ricardo Cruz]]></dc:creator>
		<pubDate>Wed, 29 Mar 2023 12:41:00 +0000</pubDate>
				<category><![CDATA[Learning]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Animation]]></category>
		<category><![CDATA[Atomic Design Methodology]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Web 2.0]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[webdev]]></category>
		<category><![CDATA[Xojo Code]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=11472</guid>

					<description><![CDATA[Composing new controls using primitives is something you definitely want to explore. Let’s build a reusable vertical navigation, with animations, for your Xojo Web projects using the Atomic Design Methodology.]]></description>
										<content:encoded><![CDATA[
<p>Composing new controls using primitives is something you definitely want to explore. Let’s build a reusable vertical navigation, with animations, for your Xojo Web projects.</p>



<h2 class="wp-block-heading">Brief introduction to the Atomic Design Methodology</h2>



<p>If you haven&#8217;t heard about Atomic Design before, I really recommend that you dig a bit into this topic. With this way of methodology in mind, we will start building the smallest controls we can. Then, we will compose more complex controls reusing the smallest.</p>



<p>Keep in mind you don&#8217;t really need to blindly follow the Atoms, Molecules and Organisms proposed categories, and don&#8217;t overthink where to categorize them. As long as you can compose controls with other controls, that&#8217;s perfect. Adapt it to your own personal way of building software.</p>



<p>The idea resonates perfectly with Xojo and, while we will create a few web controls in this example, you can apply it to other targets like Desktop or Mobile.</p>



<p>Here is a <a href="https://www.youtube.com/watch?v=W-h1FtNYim4">video</a> from Brad Frost, the person behind Atomic Design Methodology.</p>



<h2 class="wp-block-heading">Containers to the rescue! </h2>



<p>In this case, we won&#8217;t need to use any Web SDK control, CSS or JavaScript. We will be using just plain Xojo Web Containers for creating our Atoms and Molecules.</p>



<p>This is how Twitter&#8217;s navigation sidebar looks like:</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img fetchpriority="high" decoding="async" width="280" height="481" src="https://blog.xojo.com/wp-content/uploads/2023/03/Explore.png" alt="" class="wp-image-11473" srcset="https://blog.xojo.com/wp-content/uploads/2023/03/Explore.png 280w, https://blog.xojo.com/wp-content/uploads/2023/03/Explore-175x300.png 175w" sizes="(max-width: 280px) 100vw, 280px" /><figcaption class="wp-element-caption">Twitter Vertical Navigation</figcaption></figure>
</div>


<p>We will create something similar. Using Atomic Design, let&#8217;s break it down it into a few new reusable controls:</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img decoding="async" width="700" height="525" src="https://blog.xojo.com/wp-content/uploads/2023/03/components-atomic-design.png" alt="" class="wp-image-11474" srcset="https://blog.xojo.com/wp-content/uploads/2023/03/components-atomic-design.png 700w, https://blog.xojo.com/wp-content/uploads/2023/03/components-atomic-design-300x225.png 300w" sizes="(max-width: 700px) 100vw, 700px" /><figcaption class="wp-element-caption">Individual Controls</figcaption></figure>
</div>


<p>Each Atom, Molecule and Organism will be a Container. In the above image, we have identified each of them.</p>



<ul class="wp-block-list">
<li>There is a &#8220;Navigation Link Icon&#8221;, an Atom, which will show one of the available <a rel="noreferrer noopener" href="https://icons.getbootstrap.com" data-type="URL" data-id="https://icons.getbootstrap.com" target="_blank">Bootstrap Icons</a>. As you notice in the Twitter example, if the link is active, the icon will be filled.</li>



<li>For the label Atom, we can just use the WebLabel built-in control. There is no need to wrap it in a Container, in this case.</li>



<li>The navigation link will be a Molecule, combining the icon and the label.</li>



<li>The Active Link Indicator will move to the active link, using an animation.</li>



<li>Finally, the Vertical Navigation Control will be the Organism, combining everything into one.</li>
</ul>



<h2 class="wp-block-heading">Navigation Link Icon</h2>



<p>This Control is basically a Container, with an ImageViewer inside. Technically, this could be just an ImageViewer subclass, but using a WebContainer we can also specify its default width and height.</p>



<p>It will have two computed properties:</p>



<ul class="wp-block-list">
<li>Active As Boolean</li>



<li>IconName As String</li>
</ul>



<p>There will also be a private ShowIcon method. Whenever you change either the Active property or IconName, the computed property will call ShowIcon.</p>



<p>The magic is inside ShowIcon:</p>



<pre class="wp-block-code Xojo"><code><code>Var iconColor As Color = If(mActive, Color.Black, Color.LightGray)
Var icon As String = If(mActive, mIconName + "-fill", mIconName)
IconImageViewer.Picture = WebPicture.BootstrapIcon(icon, iconColor)</code></code></pre>


<div class="wp-block-image">
<figure class="aligncenter size-large"><img decoding="async" width="1024" height="716" src="https://blog.xojo.com/wp-content/uploads/2023/03/Captura-de-Pantalla-2023-03-27-a-las-13.55.04-1024x716.png" alt="" class="wp-image-11475" srcset="https://blog.xojo.com/wp-content/uploads/2023/03/Captura-de-Pantalla-2023-03-27-a-las-13.55.04-1024x716.png 1024w, https://blog.xojo.com/wp-content/uploads/2023/03/Captura-de-Pantalla-2023-03-27-a-las-13.55.04-300x210.png 300w, https://blog.xojo.com/wp-content/uploads/2023/03/Captura-de-Pantalla-2023-03-27-a-las-13.55.04-768x537.png 768w, https://blog.xojo.com/wp-content/uploads/2023/03/Captura-de-Pantalla-2023-03-27-a-las-13.55.04.png 1381w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">NavigationLinkIcon in the IDE</figcaption></figure>
</div>


<p>The icon color will be either LightGray or Black, depending if it&#8217;s active or not. There are also a lot of Bootstrap Icons with the &#8220;-fill&#8221; suffix so we&#8217;ll use them. This will force us to only use icons which have that suffix, but we will have to live with that.</p>



<p>The final trick is to use the Inspector Behavior and expose our Active and IconName computed properties. Right click on NavigationLinkIcon, then click on Inspector Behavior:</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="400" height="508" src="https://blog.xojo.com/wp-content/uploads/2023/03/Open-in-New-Tab.png" alt="" class="wp-image-11476" srcset="https://blog.xojo.com/wp-content/uploads/2023/03/Open-in-New-Tab.png 400w, https://blog.xojo.com/wp-content/uploads/2023/03/Open-in-New-Tab-236x300.png 236w" sizes="auto, (max-width: 400px) 100vw, 400px" /><figcaption class="wp-element-caption">How to open the Inspector Behavior</figcaption></figure>
</div>


<p>From there you can enable the checkboxes and define their default value:</p>


<div class="wp-block-image">
<figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="1024" height="716" src="https://blog.xojo.com/wp-content/uploads/2023/03/Captura-de-Pantalla-2023-03-27-a-las-14.00.49-1024x716.png" alt="" class="wp-image-11477" srcset="https://blog.xojo.com/wp-content/uploads/2023/03/Captura-de-Pantalla-2023-03-27-a-las-14.00.49-1024x716.png 1024w, https://blog.xojo.com/wp-content/uploads/2023/03/Captura-de-Pantalla-2023-03-27-a-las-14.00.49-300x210.png 300w, https://blog.xojo.com/wp-content/uploads/2023/03/Captura-de-Pantalla-2023-03-27-a-las-14.00.49-768x537.png 768w, https://blog.xojo.com/wp-content/uploads/2023/03/Captura-de-Pantalla-2023-03-27-a-las-14.00.49.png 1381w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">Enabling properties in the Inspector Behavior</figcaption></figure>
</div>


<p>Now that we have the Control ready, let&#8217;s see how it works on its own:</p>


<div class="wp-block-image">
<figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="1024" height="716" src="https://blog.xojo.com/wp-content/uploads/2023/03/Captura-de-Pantalla-2023-03-27-a-las-13.51.02-1024x716.png" alt="" class="wp-image-11478" srcset="https://blog.xojo.com/wp-content/uploads/2023/03/Captura-de-Pantalla-2023-03-27-a-las-13.51.02-1024x716.png 1024w, https://blog.xojo.com/wp-content/uploads/2023/03/Captura-de-Pantalla-2023-03-27-a-las-13.51.02-300x210.png 300w, https://blog.xojo.com/wp-content/uploads/2023/03/Captura-de-Pantalla-2023-03-27-a-las-13.51.02-768x537.png 768w, https://blog.xojo.com/wp-content/uploads/2023/03/Captura-de-Pantalla-2023-03-27-a-las-13.51.02.png 1381w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">NavigationLinkIcon demo</figcaption></figure>
</div>


<figure class="wp-block-video aligncenter"><video height="488" style="aspect-ratio: 660 / 488;" width="660" controls src="https://blog.xojo.com/wp-content/uploads/2023/03/NavigationLinkIcon-demo.mp4"></video><figcaption class="wp-element-caption">NavigationLinkIcon demo</figcaption></figure>



<p>Neat! You can reuse this Atom everywhere, including other projects.</p>



<h2 class="wp-block-heading">Navigation Link Control</h2>



<p>Combining our fresh NavigationLinkIcon, a built-in WebLabel and exposing an API, we&#8217;ll create our NavigationLink Molecule.</p>



<p>Create a new Container and place the items inside. Then add some computed properties:</p>



<ul class="wp-block-list">
<li>Active</li>



<li>Caption</li>



<li>IconName</li>
</ul>



<p>Whenever the property changes, just update the underlying control.</p>



<p>One trick, to make the control clickable, is to add a WebCanvas on top of the other controls. Implement its Pressed event and forward it as a new &#8220;Pressed&#8221; Event Definition.</p>



<p>If you want to show a pointer cursor when the user moves the mouse over your control, add this line of code into the container&#8217;s Opening event:</p>



<pre class="wp-block-code xojo"><code><code>Me.Style.Cursor = WebStyle.Cursors.Pointer</code></code></pre>



<p>This is how it looks like in the IDE:</p>


<div class="wp-block-image">
<figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="1024" height="716" src="https://blog.xojo.com/wp-content/uploads/2023/03/Captura-de-Pantalla-2023-03-27-a-las-14.28.18-1024x716.png" alt="" class="wp-image-11480" srcset="https://blog.xojo.com/wp-content/uploads/2023/03/Captura-de-Pantalla-2023-03-27-a-las-14.28.18-1024x716.png 1024w, https://blog.xojo.com/wp-content/uploads/2023/03/Captura-de-Pantalla-2023-03-27-a-las-14.28.18-300x210.png 300w, https://blog.xojo.com/wp-content/uploads/2023/03/Captura-de-Pantalla-2023-03-27-a-las-14.28.18-768x537.png 768w, https://blog.xojo.com/wp-content/uploads/2023/03/Captura-de-Pantalla-2023-03-27-a-las-14.28.18.png 1381w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">NavigationLink in the IDE</figcaption></figure>
</div>


<p>Let&#8217;s quickly test it:</p>



<figure class="wp-block-video aligncenter"><video height="488" style="aspect-ratio: 660 / 488;" width="660" controls src="https://blog.xojo.com/wp-content/uploads/2023/03/NavigationLink-demo.mp4"></video><figcaption class="wp-element-caption">NavigationLink demo</figcaption></figure>



<p>We are getting there.</p>



<h2 class="wp-block-heading">Active Link Indicator</h2>



<p>We have most of the Atoms and Molecules created already. The Navigation Link Indicator is so simple and so tied to the Sidebar, that I don&#8217;t think creating an individual Atom for it is worth the effort.</p>



<p>Using a WebRectangle, with a line of two of code in its Opening event, will be enough. This is completely up to you!</p>



<h2 class="wp-block-heading">Vertical Navigation Control</h2>



<p>Now it&#8217;s time to glue the Atoms and Molecules together to make our first Organism. Create a new Container called VerticalNavigation.</p>



<p>Drop a WebRectangle on it. Set its Left and Top to 0, and implement its Opening event with these lines of code:</p>



<pre class="wp-block-code Xojo"><code><code>Me.Style.BorderThickness = 0
Me.Style.AddTransition("top", 0.2)</code></code></pre>



<p>That will remove the border that comes by default with this control. It will also tell the browser to animate the rectangle whenever we change the Top position.</p>



<p>The rectangle background color will be a light gray, but this is again up to you.</p>



<p>For the API we want to expose, add these Methods:</p>



<ul class="wp-block-list">
<li>AddLink(caption As String, icon As String, active As Boolean = False)</li>



<li>HandleLinkPressed(sender As NavigationLink)</li>



<li>SetActiveLink(index As Integer)</li>
</ul>



<p>AddLink and SetActiveLink can be left Public, HandleLinkPressed will be a Private Method.</p>



<p>AddLink code:</p>



<pre class="wp-block-code Xojo"><code><code>// We will create a new NavigationLink instance
// and set the properties we're receiving.
Var link As New NavigationLink
link.Caption = caption
link.IconName = icon

// For its pressed event, we will handle it
// internally in the HandleLinkPressed method.
AddHandler link.Pressed, WeakAddressOf HandleLinkPressed

// We will place it programatically in  the container.
Const padding = 10
Var linkTop As Integer = mLinks.Count * (link.Height + padding)
link.EmbedWithin(Self, padding, linkTop, Self.Width - padding, link.Height)

// A reference for this NavigationLink will be
// needed later, so we will store it internally.
mLinks.Add(link)

// Finally, if the item is active, we will
// handle it just like if it's been pressed
// by the user.
If active Then
  SetActiveLink(mLinks.LastIndex)
End If</code></code></pre>



<p>HandleLinkPressed code:</p>



<pre class="wp-block-code xojo"><code><code>SetActiveLink(mLinks.IndexOf(sender))
RaiseEvent Pressed(sender)</code></code></pre>



<p>And, finally, SetActiveLink:</p>



<pre class="wp-block-code xojo"><code><code>// Here we will loop through the NavigationLink
// references we have and enable or disable the
// Active property, depending on the index
// comparison.
For i As Integer = 0 To mLinks.LastIndex
  mLinks(i).Active = i = index
Next

// Move the visual active indicator to the
// NavigationLink position.
ActiveLinkIndicator.Top = mLinks(index).Top</code></code></pre>


<div class="wp-block-image">
<figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="1024" height="714" src="https://blog.xojo.com/wp-content/uploads/2023/03/Captura-de-Pantalla-2023-03-27-a-las-17.48.51-1024x714.png" alt="" class="wp-image-11482" srcset="https://blog.xojo.com/wp-content/uploads/2023/03/Captura-de-Pantalla-2023-03-27-a-las-17.48.51-1024x714.png 1024w, https://blog.xojo.com/wp-content/uploads/2023/03/Captura-de-Pantalla-2023-03-27-a-las-17.48.51-300x209.png 300w, https://blog.xojo.com/wp-content/uploads/2023/03/Captura-de-Pantalla-2023-03-27-a-las-17.48.51-768x535.png 768w, https://blog.xojo.com/wp-content/uploads/2023/03/Captura-de-Pantalla-2023-03-27-a-las-17.48.51.png 1485w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">VerticalNavigation in the IDE</figcaption></figure>
</div>


<h2 class="wp-block-heading">Final Result</h2>



<p>Everything is ready, drop your VerticalNavigation somewhere in your WebPage and add a few links inside its Opening event:</p>



<pre class="wp-block-code xojo"><code><code>// Setting the third parameter to "True" will set that link as Active.
Me.AddLink("Home", "house")
Me.AddLink("Explore", "binoculars", True)
Me.AddLink("Notifications", "bell")</code></code></pre>



<p>You should see something similar to this:</p>



<figure class="wp-block-video aligncenter"><video height="488" style="aspect-ratio: 660 / 488;" width="660" controls src="https://blog.xojo.com/wp-content/uploads/2023/03/result-demo.mp4"></video><figcaption class="wp-element-caption">Final result!</figcaption></figure>



<p>Congratulations! You&#8217;ve built a vertical navigation, with nice transitions, using some Atomic Design principles.</p>



<p>Code repository: <a rel="noreferrer noopener" href="https://github.com/piradoiv/vertical-navigation-example" target="_blank">https://github.com/piradoiv/vertical-navigation-example</a><br>Download the project: <a rel="noreferrer noopener" href="https://github.com/piradoiv/vertical-navigation-example/archive/refs/heads/main.zip" target="_blank">vertical-navigation-example</a></p>



<p><em>Ricardo has always been curious about how things work. Growing up surrounded by computers</em> he became interested in <em>web technologies in the dial-up connections era. Xojo has been his secret weapon and language of preference since 2018. When he’s not online, chances are he will be scuba diving … or crocheting amigurumis. Find Ricardo on Twitter <a href="https://web.archive.org/web/20220805000833/https://www.twitter.com/piradoiv" target="_blank" rel="noreferrer noopener">@piradoiv</a>.</em></p>
]]></content:encoded>
					
		
		<enclosure url="https://blog.xojo.com/wp-content/uploads/2023/03/NavigationLinkIcon-demo.mp4" length="55146" type="video/mp4" />
<enclosure url="https://blog.xojo.com/wp-content/uploads/2023/03/NavigationLink-demo.mp4" length="210022" type="video/mp4" />
<enclosure url="https://blog.xojo.com/wp-content/uploads/2023/03/result-demo.mp4" length="90366" type="video/mp4" />

			</item>
		<item>
		<title>Cross-Platform Mobile Bounce Animation</title>
		<link>https://blog.xojo.com/2021/03/17/cross-platform-mobile-bounce-animation/</link>
		
		<dc:creator><![CDATA[Paul Lefebvre]]></dc:creator>
		<pubDate>Wed, 17 Mar 2021 18:04:06 +0000</pubDate>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[Fun]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Animation]]></category>
		<category><![CDATA[Canvas]]></category>
		<category><![CDATA[iOSCanvas]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Timers]]></category>
		<category><![CDATA[Xojo API 2.0]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=8175</guid>

					<description><![CDATA[Here's a fun little project you can try to get a feel for some simple animation in your iOS and future Android apps.]]></description>
										<content:encoded><![CDATA[
<p>Here&#8217;s a fun little project you can try to get a feel for simple animation in your iOS apps. As you can see, this project moves a small &#8220;ball&#8221; around the screen and it bounces off the edges.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="448" height="799" src="https://blog.xojo.com/wp-content/uploads/2021/03/CleanShot-2021-03-11-at-17.25.02.gif" alt="" class="wp-image-8177"/></figure>



<p>Create a new iOS project and on Screen1 add a couple Buttons and a Canvas, the buttons at the top and the Canvas using up the rest of the space. Also add a Timer.</p>



<p>Add some properties to track the ball&#8217;s position and direction:</p>



<ul class="wp-block-list"><li>Public Property XDirection as Integer = 10</li><li>Public Property XPosition as Integer = 10</li><li>Public Property YDirection as Integer = 10</li><li>Public Property YPosition as Integer = 10</li></ul>



<p>In the Opening event for Screen1, initialize the Timer (which I&#8217;ve named MoveTimer):</p>



<pre class="wp-block-preformatted">MoveTimer.Period = 50
MoveTimer.RunMode = Timer.RunModes.Multiple
MoveTimer.Enabled = False</pre>



<p>Speaking of the Timer, in its Run event put this code to move the ball:</p>



<pre class="wp-block-preformatted">XPosition = XPosition + XDirection
YPosition = YPosition + YDirection
BounceCanvas.Refresh</pre>



<p>Add the Paint and PointerDown events to the Canvas. In the Paint event draw the ball with this code:</p>



<pre class="wp-block-preformatted">Var size As Integer = 25
g.DrawingColor = Color.RGB(255, 0, 0)
g.DrawRectangle(0, 0, g.Width, g.Height)
g.FillOval(XPosition, YPosition, size, size)
If (XPosition + size) &gt; g.Width Then
  XDirection = -XDirection
End If
If ( YPosition + size) &gt; g.Height Then
  YDirection = -YDirection
End If
If XPosition &lt; 0 Then
  XDirection = -XDirection
End If
If YPosition &lt; 0 Then
  YDirection = -YDirection
End If</pre>



<p>And in the PointerDown event, reset the ball&#8217;s position to the touch:</p>



<pre class="wp-block-preformatted">XPosition = position.X
YPosition = position.Y
XDirection = -XDirection
YDirection = -YDirection</pre>



<p>Lastly you can add the Pressed event to the Start button and tell it to start the Timer:</p>



<pre class="wp-block-preformatted">MoveTimer.Enabled = True</pre>



<p>Similarly add the Pressed event to the Stop button and tell it to stop the Timer:</p>



<pre class="wp-block-preformatted">MoveTimer.Enabled = False</pre>



<p>That&#8217;s it. Run the project, click start to watch the ball bounce. Tap on the screen to change its position and direction. You could probably use this as the start of a Pong game!</p>



<p>Oh, and I forgot to mention that the code above was actually copied from the Android project where I first created this. The exact code copied over to iOS and worked as is with no changes. For a little teaser, here&#8217;s Bounce running on Android:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="377" height="799" src="https://blog.xojo.com/wp-content/uploads/2021/03/CleanShot-2021-03-11-at-17.19.43.gif" alt="" class="wp-image-8176"/></figure>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Programming your own Solar System with Xojo + MBS SceneKit</title>
		<link>https://blog.xojo.com/2020/02/17/a-solar-system-with-xojo/</link>
		
		<dc:creator><![CDATA[Stefanie Juchmes]]></dc:creator>
		<pubDate>Mon, 17 Feb 2020 10:00:00 +0000</pubDate>
				<category><![CDATA[Fun]]></category>
		<category><![CDATA[Guest Post]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Animation]]></category>
		<category><![CDATA[Graphics]]></category>
		<category><![CDATA[Monkeybread Software]]></category>
		<category><![CDATA[Plugins]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=6604</guid>

					<description><![CDATA[Learn to create a solar system in Xojo with the help of the MBS Xojo Plugin component SceneKit. SceneKit is an Apple framework that supplies functions for graphic and animation designs. 
]]></description>
										<content:encoded><![CDATA[
<p>In this post I will show you how to create you own solar system in Xojo with the help of the <a href="https://www.monkeybreadsoftware.de/xojo/">Monkeybread Software</a> plugin component SceneKit. <a href="https://developer.apple.com/scenekit/">SceneKit</a> is an Apple framework that supplies functions for graphic and animation designs.&nbsp;</p>



<p>Please run a current Xojo version with MBS Xojo Mac64bit Plugin installed. Due to our dependencies list, please add Main, MacCloud, MacBase, MacCocoa, MacControls, MacCG and MacCF plugins too. Start with a new project. To the window we add a SCNControlMBS control from the library and rename it MyControl. Drag it across the entire window size and lock all edges. It is very useful because we want fullscreen mode later.&nbsp;</p>



<p>Then we need two properties MyScene and MyView. MyScene has the type SCNSceneMBS and MyView has the type SCNViewMBS. Afterwards, add the open event of the SceneKit control.&nbsp;</p>



<p>We start with the setting of MyView and MyScene like this:</p>



<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow">
<pre class="wp-block-preformatted">MyView = Me.View 
MyScene = New SCNSceneMBS
MyView.scene = MyScene</pre>
</div></div>



<p>Then we enable the default light and the camera control, because we want to see a 3D effect and want to move the camera using the mouse. We set black as the background color.</p>



<pre class="wp-block-preformatted">myView.autoenablesDefaultLighting = True  
MyView.allowsCameraControl = True&nbsp;  
myView.backgroundColor = NSColorMBS.blackColor&nbsp;</pre>



<p>Next we add our first node to the scene. The center of the scene is the Sun. In basic structure the Sun is a lit up sphere. So we add a sphere geometry with a given size. In this project we can&#8217;t work with the original conditions, because Mercury would be so small that it is impossible to see. Plus, we would have same problem for the distance between the Sun and the planets. Because that, our Sun has a radius of 13. Then we add a node and give it geometric information about the Sun. The position of the node is the origin with the coordinates 0,0,0. Finally, we add the node to our scene.&nbsp;</p>



<pre class="wp-block-preformatted">Dim SunGeometry As New SCNSphereMBS(13)  
Dim Sun As New SCNNodeMBS(SunGeometry)  
Sun.Position = New SCNVector3MBS(0, 0, 0)   
MyScene.rootNode.addChildNode(Sun)</pre>



<p>Then we start our program.&nbsp;</p>



<p>We see a white sphere on the screen. The Sun looks a bit edged because of the segment count. Our Sun sphere is very big and needs more segments then the default segment count. Set the segment count property ahead of adding the node to the scene command.&nbsp;</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="712" height="905" src="https://blog.xojo.com/wp-content/uploads/2020/02/Sun.png" alt="" class="wp-image-6605" srcset="https://blog.xojo.com/wp-content/uploads/2020/02/Sun.png 712w, https://blog.xojo.com/wp-content/uploads/2020/02/Sun-236x300.png 236w" sizes="auto, (max-width: 712px) 100vw, 712px" /></figure></div>



<pre class="wp-block-preformatted">	SunGeometry.segmentCount=100&nbsp;</pre>



<p>Then we set each planet in a similar way. Because the planets look different, we want to change their colors as appropriate or even put a picture as a graphic over each sphere. For the color of an object we have the firstMaterial.diffuse.contents Property. This is how you would set a gray color for Mercury.&nbsp;</p>



<pre class="wp-block-preformatted"> MercuryGeometry.firstMaterial.diffuse.contents = NSColorMBS.grayColor</pre>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="645" src="https://blog.xojo.com/wp-content/uploads/2020/02/Map-1024x645.png" alt="" class="wp-image-6606" srcset="https://blog.xojo.com/wp-content/uploads/2020/02/Map-1024x645.png 1024w, https://blog.xojo.com/wp-content/uploads/2020/02/Map-300x189.png 300w, https://blog.xojo.com/wp-content/uploads/2020/02/Map-768x484.png 768w, https://blog.xojo.com/wp-content/uploads/2020/02/Map.png 1442w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>If we want to map a picture on a geometry, for example for Earth, we add this picture to our project and set it to the geometry. It&#8217;s a bit like covering it with a blanket with a high percentage of elongation. We can imagine that by covering a sphere, we stretch the blanket on the equator more than on the polar caps. Because that, if you look on a map, the longitudes and latitudes are not parallel, but rather bent. In reality the longitude and latitude are parallel. You can see that on a globe. Fortunately for us a world map is already a perfect UV map for a sphere. Thanks to the website <a href="http://www.ginkgomaps.com">www.ginkgomaps.com</a> which supplies world maps to everyone. I used one of these maps in my example. You can customize the map with a graphic program. Then add it to the project and set it in the property.&nbsp;</p>



<pre class="wp-block-preformatted">Dim EarthGeometry As New SCNSphereMBS(1.47)  
EarthGeometry.segmentCount=100  
Dim Earth As New SCNNodeMBS(EarthGeometry)  
EarthGeometry.firstMaterial.diffuse.contents = EarthPic  
Earth.Position = New SCNVector3MBS(25, 0, 0)&nbsp;  
MyScene.rootNode.addChildNode(Earth)</pre>



<p>All other textures I draw myself in a graphic program.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="768" src="https://blog.xojo.com/wp-content/uploads/2020/02/Earth-1024x768.png" alt="" class="wp-image-6608" srcset="https://blog.xojo.com/wp-content/uploads/2020/02/Earth-1024x768.png 1024w, https://blog.xojo.com/wp-content/uploads/2020/02/Earth-300x225.png 300w, https://blog.xojo.com/wp-content/uploads/2020/02/Earth-768x576.png 768w, https://blog.xojo.com/wp-content/uploads/2020/02/Earth.png 1424w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>For the position of the Planets, we must pay attention to the fact that the origin of the single planets are in the center of the sphere and we set in the constructor of the geometry as the radius and not the diameter. The distance between two planets are: radius of planet 1+radius of planet two+ space between them.&nbsp;</p>



<p>Following this same pattern we add the other planets. Saturn has a planetary ring. The ring is a tube with an inner radius that is bigger than the planet and a small hight. I use the same structure on the ring as on the planet. The tube is a bit rotated. We rotate the ring a bit by x and y. The specification of a rotation looks like this:&nbsp;</p>



<pre class="wp-block-preformatted">saturnRing.orientation = New SCNVector4MBS(-0.4, -0.5, 0, 1)</pre>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="558" height="386" src="https://blog.xojo.com/wp-content/uploads/2020/02/PicSaturn.png" alt="" class="wp-image-6609" srcset="https://blog.xojo.com/wp-content/uploads/2020/02/PicSaturn.png 558w, https://blog.xojo.com/wp-content/uploads/2020/02/PicSaturn-300x208.png 300w" sizes="auto, (max-width: 558px) 100vw, 558px" /></figure>



<p><strong>Let&#8217;s Move the Solar System</strong></p>



<p>Now we want to move the Scene. We assume that the planets&#8217; orbits are all parallel to the xz plane and that they are exactly circular. To roate around a certain point, we create a geometry for each rotation. It lies in the point and is a parent node of the geometry. If a parent node moves, a child node moves too. The inverse does not apply. In that way, if we rotate the helping node in the origin, the child node moves around the origin too. We cannot use the Sun as the parent node for all planets because the planets are supposed to move at different speeds.&nbsp;</p>



<p>The creation of the geometry looks similar for each planet:</p>



<pre class="wp-block-preformatted">Dim UranusRotationGeometry As New SCNSphereMBS(1)  
Dim UranusRotation As New SCNNodeMBS(UranusRotationGeometry) 
UranusRotation.Position = New SCNVector3MBS(0, 0, 0)&nbsp; 
MyScene.rootNode.addChildNode(UranusRotation) </pre>



<pre class="wp-block-preformatted">UranusRotation.addChildNode(Uranus)&nbsp;</pre>



<p>These geometries are covered by the Sun.&nbsp;</p>



<p>Then we add the movements. We defined a rotation of the helping node and set the information about the rotation. We want to rotate around the y axis in each cycle about 360°. The information is given in the unit rad. Because of this we must convert 360° to 6.283 rad. The last parameter is about the speed of the operation. In this section we can set the proportion of the speed of the planets. The speed of Earth is the basic value. Everything is based on this value. The assumption is: an Earth year lasts 365 days. For each planet we use the number of Earth days a planet takes to rotate once around the Sun. We divide this value by the days of an Earth year. For Neptune we get a value that is approximate to 164.79 rad. That we can multiply with a variable. The variable can be set by the customer to regulate the speed of the solar system. We want to repeat this movement again and again. In this way we set it. In the last step we set this rotation to the scene. &nbsp;</p>



<pre class="wp-block-preformatted">Dim moveNeptune As SCNActionMBS = SCNActionMBS.rotateBy(0, 6.283, 0, 164.79 * speed)
Dim Neptunerepeat As SCNActionMBS = SCNActionMBS.repeatActionForever(moveNeptune)
NeptuneRotation.runAction(Neptunerepeat)</pre>



<p>Finally, we want to talk about lighting. The Sun is the light source. It is a light that comes from a point and shines in all directions. That type of light source is called an omni light. We define a light as a property from a node. Since our Sun is a node in the scene, we add the light property directly. All nodes that spray light don’t get any light and they are normally black. With the emission property we can make the sphere look like it is glowing. We choose yellow as color.&nbsp;</p>



<pre class="wp-block-preformatted">Dim SunGeometry As New SCNSphereMBS(13) 
Dim Sun As New SCNNodeMBS(SunGeometry) 
sun.Light = New SCNLightMBS 
sun.Light.Type = SCNLightMBS.SCNLightTypeOmni 
sun.Light.Intensity = 2000
sun.light.Color = NSColorMBS.whiteColor sun.Light.Intensity = 2000 SunGeometry.firstMaterial.emission.contents = NSColorMBS.yellowColor SunGeometry.segmentCount = 100 
Sun.Position = New SCNVector3MBS(0, 0, 0)&nbsp; 
MyScene.rootNode.addChildNode(Sun)</pre>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="766" src="https://blog.xojo.com/wp-content/uploads/2020/02/Solarsystem-1024x766.png" alt="" class="wp-image-6610" srcset="https://blog.xojo.com/wp-content/uploads/2020/02/Solarsystem-1024x766.png 1024w, https://blog.xojo.com/wp-content/uploads/2020/02/Solarsystem-300x224.png 300w, https://blog.xojo.com/wp-content/uploads/2020/02/Solarsystem-768x574.png 768w, https://blog.xojo.com/wp-content/uploads/2020/02/Solarsystem.png 1514w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>The scene seems very dark if the Sun is our only light source, so add weak ambient light that lights up all elements in the same way. The unit of the light intensity is lumen. Now you can run the project and admire your own programmed solar system. Have a lot of fun with that.&nbsp;Link to project.</p>



<p>If you have questions about SceneKit don’t hesitate to contact me. And please join my session about SceneKit at the <a href="https://www.xojo.com/xdc/">XOJO.CONNECT</a> conference in Nashville.</p>



<p>Download the <a href="https://blog.xojo.com/wp-content/uploads/2020/02/SolarSystem.zip">project</a>.</p>



<p><em>Stefanie Juchmes studies computer science at the University of Bonn. She came in touch with Xojo due to the work of her brother-in-law and got a junior developer position in early 2019 at<a rel="noreferrer noopener" href="https://www.monkeybreadsoftware.de/xojo/" target="_blank">&nbsp;Monkeybread Software.</a>&nbsp;You may have also read her articles in<a rel="noreferrer noopener" href="http://www.xdevmag.com/" target="_blank">&nbsp;Xojo Developer Magazine</a>.&nbsp;<br></em></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Guest Post: Animating Xojo, Part 4</title>
		<link>https://blog.xojo.com/2019/08/21/guest-post-animating-xojo-part-4/</link>
		
		<dc:creator><![CDATA[Anthony Cyphers]]></dc:creator>
		<pubDate>Wed, 21 Aug 2019 10:00:20 +0000</pubDate>
				<category><![CDATA[Guest Post]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Animation]]></category>
		<category><![CDATA[UI]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=5992</guid>

					<description><![CDATA[In this final part in his 4 part series on Animating Xojo, Anthony Cyphers covers easing, which can make the most drab User Interface interactions beautiful.]]></description>
										<content:encoded><![CDATA[
<p>In <a href="https://blog.xojo.com/2019/07/24/guest-post-historical-methods/">Part 1</a> we covered the history of animating UI effects in Xojo. In <a href="https://blog.xojo.com/2019/07/31/guest-post-animating-xojo-part-2/">Part 2</a> we dug in to linear interpolation. In <a href="https://blog.xojo.com/2019/08/15/guest-post-animating-xojo-part-3/">Part 3</a> saw the addition of support for concurrent animations and color changes. In Part 4 we’ll cover easing, which can make the most drab User Interface interactions beautiful.</p>



<h3 class="wp-block-heading">Easing</h3>



<h4 class="wp-block-heading">What is Easing?</h4>



<p>To quote&nbsp;<a href="https://developers.google.com/web/fundamentals/design-and-ux/animations/the-basics-of-easing">Paul Lewis</a>:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>Nothing in nature moves linearly from one point to another. In reality, things tend to accelerate or decelerate as they move. Our brains are wired to expect this kind of motion, so when animating, you should use this to your advantage. Natural motion makes your users feel more comfortable with your apps, which in turn leads to a better overall experience.</p><cite><a href="https://developers.google.com/web/fundamentals/design-and-ux/animations/the-basics-of-easing">https://developers.google.com/web/fundamentals/design-and-ux/animations/the-basics-of-easing</a></cite></blockquote>



<p>Based on that, we can define easing as a more natural-appearing change in value between a start and end point which is designed to make a user feel more comfortable with changes in the user interface.</p>



<h4 class="wp-block-heading">Types of Easing Functions</h4>



<p>Easing functions can be broken down in to three basic types:</p>



<ul class="wp-block-list"><li><code>In</code>&nbsp;— An animation that starts slowly and increases in speed over time</li><li><code>Out</code>&nbsp;— An animation that starts quickly and decreases in speed over time</li><li><code>InOut</code>&nbsp;— A combination of InOut that begins and ends quickly with a slow transition in the middle.</li></ul>



<h4 class="wp-block-heading">What Does Easing Look Like?</h4>



<p>There are a number of currently standard UI easing functions (as seen in CSS, various JavaScript frameworks, and even OS-provided implementations), but one of the more interesting sets is called Elastic. Elastic easing functions simulate the motion you might observe if you stretched out a piece of elastic then released it. You get a dramatic change as the elastic fibers quickly contract, then a slower series of changes as the momentum dissipates. To visualize that in a diagram:</p>



<figure class="wp-block-image"><img decoding="async" src="https://graffitisuite.com/downloads/ms_17332-768x414.png" alt="" class="wp-image-14561"/></figure>



<p>This can be used to provide some really enthralling UI transitions that’ll make both you and your users much happier as it just feels more natural than making Element A of your UI disappear and Element B appear, or using a linear animation to swap the two elements.</p>



<h4 class="wp-block-heading">What Does an Easing Function Look Like</h4>



<p>Easing functions can be incredibly simple, as you saw in our lerp method in Part 2, or as complex as you can imagine. Our example of Elastic easing, while not the most complex, is pretty interesting mathematically (if you’re terrible at math like I am).</p>



<pre class="wp-block-preformatted">Private Function easeInElastic(startValue as Double, endValue as Double, alphaValue as Double) as Double
   Return ((endValue - startValue) * (0.04 * alphaValue / (alphaValue - 1) * Sin( 25 * (alphaValue - 1) ))) + startValue
 End Function</pre>



<p>Basically what this method is doing, and my grasp of the math is admittedly pretty thin, is it’s taking the start and end value and creating a diminishing sine wave to simulate the change over time. I normally would say that this should be broken down in to multiple lines to make it easier to read, possibly by using no fewer than three variables, but we really want it to be quick.</p>



<p>If we did break it down, it would look more like this:</p>



<pre class="wp-block-preformatted">Private Function easeInElastic(startValue as Double, endValue as Double, alphaValue as Double) as Double
   dim changeValue as Double = endValue - startValue
   dim differenceValue as Double = (0.04 * alphaValue / (alphaValue - 1) * Sin( 25 * (alphaValue - 1) ))
   Return (changeValue * differenceValue) + startValue
 End Function</pre>



<p>Which may be easier to read for some of us, but those variable declarations have a cost.</p>



<p>Many of the easing functions you’ll see in this part of the series are adapted for Xojo (with some heavy modification in most places) from&nbsp;<a href="https://github.com/danro/jquery-easing/blob/master/jquery.easing.js">Robert Penner’s Easing Functions</a>&nbsp;(BSD License). There’s a note on the Animated Canvas project item if you wish to explore the sources.</p>



<h4 class="wp-block-heading">What Types of Easing Functions Should I Use?</h4>



<p>UI animations are, typically, something you want to happen fairly quickly. Given that, you likely won’t use&nbsp;<code>InOut</code>&nbsp;easing functions very often as they can feel slower to your end user.</p>



<p><code>In</code>&nbsp;functions can be off putting to users as the natural expectation of seeing the most movement at the end of an animation is antithetical to&nbsp;<code>In</code>&nbsp;functions and may feel slow or confusing for some users.</p>



<p>Based on those theories, you’ll typically employ&nbsp;<code>Out</code>&nbsp;functions in your UI animations, as they’re both quick and easier for our brains to understand in a UI setting. That said, there will be times when other types of easing functions are more suited to an individual task and you must use your best judgement and listen to your QA/users if they complain about it. Animation type and length are a delicate balance.</p>



<h4 class="wp-block-heading">Easing Lengths</h4>



<p>As I alluded to earlier, the timing of your chosen easing function is incredibly important. The following table should be a good starting point for appropriate animation lengths for different types of operations.</p>



<table class="wp-block-table"><tbody><tr><td>Color (In)</td><td>100-250ms</td></tr><tr><td>Color (Out)</td><td>100-250ms</td></tr><tr><td>Color (InOut)</td><td>500-1000ms</td></tr><tr><td>Dimensions/Position (In)</td><td>800-1200ms</td></tr><tr><td>Dimensions/Position (Out)</td><td>800-1200ms</td></tr><tr><td>Dimensions/Position(InOut)</td><td>1500-2500ms</td></tr></tbody></table>



<p>These are the values I typically start with, and alter them based on the responsiveness of the UI and the desired effect. Your mileage may vary.</p>



<h3 class="wp-block-heading">Code Changes</h3>



<p>While I won’t cover the addition of each of the example easing functions that I’ve provided in the example project, I will cover the functional changes to our existing codebase and the addition of the Elastic easing functions.</p>



<h4 class="wp-block-heading">AnimationEasing Property</h4>



<p>Our first step is to create a new property on our AnimatedCanvas class called AnimationEasing. In our demo window we’ll set this value based on selection in a PopupMenu to make it easy to switch between different easing functions and view their output. It’s going to public and computed so we can show it in the Inspector.</p>



<pre class="wp-block-preformatted">Private Property mAnimationEasing as Easings

 Public Property AnimationEasing as Easings
 Get
   Return mAnimationEasing
 End Get

 Set
   mAnimationEasing = value
 End Set

 End Property</pre>



<h4 class="wp-block-heading">Easings Enumeration</h4>



<p>Next we to create an enum for our various easing functions. It’s pretty straight-forward, and we’ll use it to tell our animation controller code what to do in the animation operations we define in our Dictionary objects.</p>



<pre class="wp-block-preformatted">Public Enum Easings
 Linear
 InQuad
 OutQuad
 InOutQuad
 InCubic
 OutCubic
 InOutCubic
 InElastic
 OutElastic
 InOutElastic
 End Enum</pre>



<h4 class="wp-block-heading">Dictionary Definition</h4>



<p>We are, again, modifying our Dictionary object definition. This time we’re passing along the desired easing effect. Our new definition looks like this:</p>



<pre class="wp-block-preformatted">new Dictionary("op" : &lt;OperationToComplete", "l" : &lt;LengthOfAnimation&gt;, "m" : &lt;EasingFunction&gt;, "t" : &lt;StartTime&gt;, "s" : &lt;StartValue&gt;, "e" : &lt;EndValue&gt;)</pre>



<p>You can see that all we’ve really done from Part 3 is add a Key/Value pair for the easing. I assigned this to the “m” key to represent “method of change”, but you could use anything you like here.</p>



<h4 class="wp-block-heading">MouseEnter and MouseExit</h4>



<p>We actually don’t need any changes here for our color animation, as this will continue to use the&nbsp;<code>lerpColor</code>&nbsp;function we previously defined. Color change animations should typically be quick and applying anything but a linear easing to them can both look and feel bad if done improperly, so I won’t cover it here. When in doubt, for color animation, stick with linear and keep it around 100-250ms.</p>



<h4 class="wp-block-heading">MouseUp</h4>



<p>MouseUp, likewise isn’t changing much. We’re basically just adding the easing Key/Value to our existing Dictionary objects like so:</p>



<pre class="wp-block-preformatted">animQueue_Add(new Dictionary("op" : "width", "l" : manimTime, "m" : mAnimationEasing, "t" : Microseconds, "s" : Width, "e" : 
If(isExpandedWidth, 10, expandedWidth)))</pre>



<h4 class="wp-block-heading">doEasing Function</h4>



<p>We need a function to take our&nbsp;<code>Easings</code>&nbsp;enumeration value and perform the specified easing function. In this example I’m using a&nbsp;<code>Select Case</code>&nbsp;block, but I’ve also implemented a nice jump table using delegates in other projects.</p>



<pre class="wp-block-preformatted">Private Function doEasing(easing as Easings, startValue as Double, endValue as Double, alphaValue as Double) as Double
   select case easing
   case easings.Linear
     Return lerp( startValue, endValue, alphaValue )
   case easings.InQuad
     Return easeInQuad( startValue, endValue, alphaValue )
   case easings.OutQuad
     Return easeOutQuad( startValue, endValue, alphaValue )
   case easings.InOutQuad
     Return easeInOutQuad( startValue, endValue, alphaValue )
   case easings.InCubic
     Return easeInCubic( startValue, endValue, alphaValue )
   case easings.OutCubic
     Return easeInOutCubic( startValue, endValue, alphaValue )
   case easings.InOutCubic
     Return easeInOutCubic( startValue, endValue, alphaValue )
   case easings.InElastic
     Return easeInElastic( startValue, endValue, alphaValue )
   case easings.OutElastic
     Return easeOutElastic( startValue, endValue, alphaValue )
   case easings.InOutElastic
     Return easeInOutElastic( startValue, endValue, alphaValue )
   end select
 End Function</pre>



<p>As you can see, it takes the easing parameter representing the desired function, and the values we need to animate, passes all of that along to the requested easing function, and returns the value. A call to this method will replace our previous call to&nbsp;<code>lerp</code>&nbsp;in our Timer’s Action event handler.</p>



<h4 class="wp-block-heading">Our Easing Functions</h4>



<p>As I said earlier, I won’t cover all of the functions in the article, but I will include the Elastic functions here for your perusal. To see all of the easing functions included, be sure to download the example project at the end of the article.</p>



<pre class="wp-block-preformatted">Private Function easeInElastic(startValue as Double, endValue as Double, alphaValue as Double) as Double
   Return ((endValue - startValue) * (0.04 * alphaValue / (alphaValue - 1) * Sin( 25 * (alphaValue - 1) ))) + startValue
 End Function

 Private Function easeOutElastic(startValue as Double, endValue as Double, alphaValue as Double) as Double
   Return ((endValue - startValue) * ((0.04 - 0.04 / alphaValue) * Sin( 25 * alphaValue ) + 1)) + startValue
 End Function

 Private Function easeInOutElastic(startValue as Double, endValue as Double, alphaValue as Double) as Double
   dim opChange as Double = Abs(endValue - startValue)

 if alphaValue &lt;= 0.5 then
     return easeInElastic(startValue, opChange /  2, alphaValue * 2)
   else
     return easeOutElastic(opChange / 2, endValue, Abs(1 - (alphaValue * 2)))
   end if
 End Function</pre>



<p>We’ve already discussed purpose and expectation for&nbsp;<code>In</code>/<code>Out</code>, but take a look at&nbsp;<code>easeInOutElastic</code>. We accomplish this effect by splitting the run-time of the animation into two distinct parts and executing the appropriate easing function based on where we are in the animation.&nbsp;<code>In</code>&nbsp;happens at &lt;= 50% of our total animation time, and&nbsp;<code>Out</code>happens at &gt; 50% of our animation time. This gives us a nice, seamless transition in our&nbsp;<code>InOut</code>&nbsp;animation as the value at 50% should be close — if not identical — in both easing functions.</p>



<h4 class="wp-block-heading">animTimer_Action</h4>



<p>Our changes in animTimer_Action are also pretty minimal. Since we’re not applying one of the more advanced easing functions to our previously discussed color animation, I’ll only cover the changes we’re making to the Width and Height operations.</p>



<p>First, we need to add a new variable declaration to the top of our method. This is where we’ll store the easing type.</p>



<pre class="wp-block-preformatted">Dim animOpEasing As Easings</pre>



<p>Then, after our&nbsp;<code>Else</code>&nbsp;at line 87, where we get our values from the current&nbsp;<code>animOp</code>&nbsp;Dictionary, we will assign the current operation’s easing (or “m” key) value to our new variable.</p>



<pre class="wp-block-preformatted">animOpEasing = animOp.Value("m")</pre>



<p>Now that we know which easing function we want to apply to the current operation, and we’ve already defined our&nbsp;<code>doEasing</code>&nbsp;function, all we need to do is swap out our line (line 100) that previously used the&nbsp;<code>lerp</code>&nbsp;function to assign the appropriate value to&nbsp;<code>animStepDouble</code>, to use our new&nbsp;<code>doEasing</code>&nbsp;function.</p>



<pre class="wp-block-preformatted">animStepDouble = doEasing(animOpEasing, animStartDouble, animEndDouble, timePercent)</pre>



<h3 class="wp-block-heading">Series Finale</h3>



<p>I do hope that, throughout this series, you’ve learned a little something about how and when to implement animation in user interfaces, some decent practices for doing so in an encapsulated way, and maybe picked up a few other pointers.</p>



<p>I had a lot of fun writing this and interacting with readers who reached out with questions and suggestions, and I hope to do more guest posts on the Xojo blog in the future. I’d like to thank Team Xojo not only for their great product and support, but also for allowing me to stand at their podium for a short time and share with you all.</p>



<p>If you would like to see more easing functions, or how I’ve implemented a full animation controller and the delegate jump table, GraffitiAnimator will soon be coming to GraffitiSuite Desktop Edition, and can be acquired&nbsp;<a href="https://graffitisuite.com/">directly</a>, via the&nbsp;<a href="https://www.xojo.com/store/?utm_content=1565880397&amp;utm_medium=social&amp;utm_source=twitter#addons">Xojo Extras store</a>, or for a limited time as part of the&nbsp;<a href="http://omegabundle.net/">Omega Bundle</a>.</p>



<p>Finally, you can download the example project for Part 4&nbsp;<a href="https://graffitisuite.com/downloads/ms_17333.zip">here</a>.</p>



<p>Thank you all for following along with me!</p>



<p><em>Anthony G. Cyphers is the Lead Developer and Sole Proprietor of&nbsp;</em><a rel="noreferrer noopener" href="https://graffitisuite.com/" target="_blank"><em>GraffitiSuite Solutions</em></a><em>, and has been providing custom Xojo components and contract development since 2003. He runs the&nbsp;</em><a rel="noreferrer noopener" href="https://t.co/WQSD3O2V6R" target="_blank"><em>Xojo User’s Discord server</em></a><em>, and is an administrator in the&nbsp;</em><a rel="noreferrer noopener" href="https://www.facebook.com/groups/xojo.dev/" target="_blank"><em>Xojo User’s Facebook user group</em></a><em>.</em></p>



<figure class="wp-block-image is-resized"><img loading="lazy" decoding="async" src="https://blog.xojo.com/wp-content/uploads/2019/07/AnthonyAndLaura_Small.png" alt="" class="wp-image-5959" width="131" height="133" srcset="https://blog.xojo.com/wp-content/uploads/2019/07/AnthonyAndLaura_Small.png 375w, https://blog.xojo.com/wp-content/uploads/2019/07/AnthonyAndLaura_Small-296x300.png 296w" sizes="auto, (max-width: 131px) 100vw, 131px" /></figure>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Guest Post: Animating Xojo, Part 3</title>
		<link>https://blog.xojo.com/2019/08/15/guest-post-animating-xojo-part-3/</link>
		
		<dc:creator><![CDATA[Anthony Cyphers]]></dc:creator>
		<pubDate>Thu, 15 Aug 2019 10:00:56 +0000</pubDate>
				<category><![CDATA[Guest Post]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Animation]]></category>
		<category><![CDATA[UI]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=5964</guid>

					<description><![CDATA[In Part 1 we covered the basic history of animating in Xojo using pre-calculated chunks to modify the width of our component. In Part 2&#8230;]]></description>
										<content:encoded><![CDATA[
<p>In <a href="https://blog.xojo.com/2019/07/24/guest-post-historical-methods/">Part 1</a> we covered the basic history of animating in Xojo using pre-calculated chunks to modify the width of our component. In <a href="https://blog.xojo.com/2019/07/31/guest-post-animating-xojo-part-2/">Part 2</a> we went a bit further by using linear interpolation (lerp) to calculate our current width at each step of the animation process, and setup for concurrent animation.</p>



<p>In this part we’ll be covering a few different things, chiefly concurrent animations. But that’s not all, as I’ve added a lerpColor function to show you how to animate color changes.</p>



<h3 class="wp-block-heading">Concurrent Animations</h3>



<p>Using self-contained concurrent animations in a UI class is an interesting exercise. You need to have the basic setup for an animation controller complete with a method of adding animation operations to a queue and removing completed animations. Typically, however, if you were building out animations on an application scale, you’d build a class that acted as the animation controller and may raise events for updating the elements as the animation progresses. In this example we’ll just build them straight in to our component because we want this to be entirely independent of the rest of the application architecture.</p>



<p>As this part focuses on concurrent animations, we’re not implementing a keyframe methodology for queuing. We’re using the queue purely to have multiple animations running together.</p>



<h4 class="wp-block-heading">Defining The Queue</h4>



<p>In Part 2 we added the following property to AnimatedCanvas:</p>



<pre class="wp-block-preformatted">animQueue As Dictionary</pre>



<p>For this part, we’re going to make a slight modification to that property definition so that it will support multiple animation operations. We’re just going to turn it into an array:</p>



<pre class="wp-block-preformatted">animQueue() As Dictionary</pre>



<h4 class="wp-block-heading">Dictionary Changes</h4>



<p>If you remember from last time we used the following definition for our Dictionary objects:</p>



<ul class="wp-block-list"><li>Start Time</li><li>Start Width</li><li>End Width</li></ul>



<p>In this part we’re going to further leverage Dictionary’s use of Variant to expand our functionality. While we previously used the following Dictionary structure for our operations:</p>



<pre class="wp-block-preformatted">Dictionary("s" : &lt;StartTimeInMicroseconds&gt;, "sw" :&lt;StartWidth&gt; , "ew" : &lt;EndWidth&gt;)</pre>



<p>We’re now defining our animOp Dictionaries as:</p>



<pre class="wp-block-preformatted">Dictionary("op" : &lt;OperationToAnimate&gt;, "l" : &lt;AnimationLength&gt;, "t" : &lt;StartTimeInMicroseconds&gt;, "s" &lt;StartValue&gt;: , "e" : &lt;EndValue&gt;, "o" : &lt;OptionalOlderAnimationOp&gt;)</pre>



<p>This allows us to create an animation operation for practically anything we can think of as long as we properly code for it in our animation Timer’s Action event handler method, and give it any length we desire rather than a common time for all operations.</p>



<h4 class="wp-block-heading">Adding to the Queue</h4>



<p>We’re going to add a new method to our AnimatedCanvas class called&nbsp;<code>animQueue_Add</code>&nbsp;that takes&nbsp;<code>animOp As Dictionary</code>&nbsp;for its sole parameter. This method will act as a basic out-of-the-loop controller when an animation is to be triggered and determine if this is a new animation operation or one that is already currently in the queue.</p>



<p>In this example I’ve setup for both a Cancel/Start type animation operation (which completely cancels the previous animation and begins a new one with the full animation time), and Continue type animation operation that preserves the original animation time within the new animation time, which is explained in more depth later.</p>



<pre class="wp-block-preformatted">Private Sub animQueue_Add(animOp as Dictionary)
   '// This method is part of our animation controller.
   '   It appends to or modifies our animation queue,
   '   which runs concurrent rather than consecutive
   '   operations.
   '   We first check to make sure that the new animation
   '   operation dictionary isn't nil.
   if IsNull(animOp) then Return

 '// We need to find out if we already have an operation
   '   in the queue for this, so we're going to store our
   '   index in a variable, which we'll get from our new
   '   anim_IndexOf method.
   dim foundIndex as Integer = animQueue_IndexOf(animOp.Value("op"))

 '// If the operation exists, overwrite it. Otherwise,
   '   append it to our queue so that the timer will
   '   pick it up on its next Action.
   if foundIndex &gt;= 0 then

 <code>'// We're also going to implement what I call Time </code>
 <code>'   Preservation. I'm sure there another name that</code>
<code> '   this is more commonly referred to as, but I</code>
<code> '   just don't know it. When PreserveTimes = True</code>
<code> '   then the animation operation overwrite will</code>
<code> '   only use the remaining time of the oldest</code>
<code> '   overriden animation operation. </code>
 <code>if mPreserveTimes then</code>

<code>   '// Grab the oldest op in our override chain so</code>
<code>   '   we can perform the math necessary to calculate</code>
<code>   '   an appropriate time remainder.</code>
<code>   dim oldOp as Dictionary = animQueue_OldestOp(animQueue(foundIndex))</code>

<code>   if not IsNull( oldOp ) then</code>
<code>     '// Set our animation length to the remaining value.</code>
<code>     '   We're getting the assigned length of the animation</code>
<code>     '   and subtracted the difference between our two</code>
<code>     '   operation start times.</code>
<code>     animOp.Value("l") = animOp.Value("l") - ((animOp.Value("t").DoubleValue - oldOp.Value("t").DoubleValue) / 1000)</code>

<code>     '// Set oldOp to our "o" key in case of future overrides.</code>
<code>     animOp.Value("o") = oldOp</code>
<code>   end if</code>
<code> end if </code>

<code>'// Overwrite the operation.</code>
<code> animQueue(foundIndex) = animOp</code>
 else

 <code>'// Add the operation to the queue.</code>
<code> animQueue.Append(animOp)</code>
 end if

 '// Make sure that our animation timer is enabled.
   animTimer.Mode = 2
 End Sub</pre>



<p>As you can see, it’s not an incredibly complex method. We’re just checking our&nbsp;<code>animQueue</code>&nbsp;property to see an animation currently exists for this operation. If we find it, we replace it. If we don’t, we just add it to the tail-end of the queue. The final line, as in the previous version, kicks off our animation timer.</p>



<h4 class="wp-block-heading">Checking Our Queue</h4>



<p>The next new method we’re going to add is our method to check if the animation operation already exists in our queue. It’s a straightforward method where we compare the “op” value of items in the queue to a specified “op” value. If an operation exists for that action, we return the index within the queue, otherwise return -1.</p>



<pre class="wp-block-preformatted">Private Function animQueue_IndexOf(op as String) as Integer
   '// This method will check our queue for the
   '   operation specified in the "op" parameter.
   '   If it exists, we'll return the index. Otherwise
   '   we return -1 to denote that this is a new op.

 '// We're creating our variable before hand so
   '   we're not doing it in each iteration of the
   '   loop, which could slow things down a bit.
   dim currDict as Dictionary

 '// Likewise, we're creating a variable to store
   '   the maximum index of our animQueue array. If
   '   we did this, instead, in the For statement,
   '   the value would be recalculated each time
   '   unless something changed that I don't know about.
   dim intMax as Integer = animQueue.Ubound

 '// We're starting from the end, just in case
   '   the contents of the queue change in the middle,
   '   we're less likely to hit an exception.
   for intCycle as Integer = intMax DownTo 0
     '// We're still going to add exception handling
     '   just in case.
     Try
       currDict = animQueue(intCycle)
     Catch e as OutOfBoundsException
       Continue
     End Try

 <code>'// If our current dictionary's "op" value</code>
<code> '   matches the "op" value we're searching for</code>
<code> '   then we'll return the index. if currDict.Value("op") = op then</code>
<code>   Return intCycle</code>
<code> end if</code>
 next

 '// No matching operation found, so we return -1.
   Return -1
 End Function</pre>



<h3 class="wp-block-heading">Time Preservation</h3>



<p>One new feature we’re implementing is what I call animation time preservation. This shortens subsequent animations of the same operation to honor the original time until one of them is able to complete.</p>



<h4 class="wp-block-heading">PreserveTimes property</h4>



<p>For our animation time preservation, we’re adding a property to the class so we can turn this on and off at will. We’ll make it public and computed so we can add it to the inspector.</p>



<pre class="wp-block-preformatted">Private Property mPreserveTimes as Boolean = True

 Public Property PreserveTimes as Boolean
   Get
     Return mPreserveTimes
   End Get
   Set
     mPreserveTimes = value
   End Set
 End Property</pre>



<h4 class="wp-block-heading">Getting the Oldest Op</h4>



<p>This all really relies on one method,&nbsp;<code>animQueue_OldestOp</code>&nbsp;which checks the “o” key of the specified animation operation to see if an older operation already exists. If it does, we’ll return it, otherwise return the operation passed in to the method. If you take a look at the changes to&nbsp;<code>animQueue_Add</code>&nbsp;above, you’ll see how we use this.</p>



<pre class="wp-block-preformatted">'// In this method we're just checking to see if
 '   there was a pre-existing operation when this
 '   one was created so that we can use its start
 '   time to shorten our new animation time.

 if IsNull(animOp) then Return Nil

 if animOp.HasKey("o") then
   dim oldOp as Dictionary = animOp.Value("o")
   Return oldOp
 end if

 Return animOp</pre>



<h3 class="wp-block-heading">Expanding the Height</h3>



<p>For this example, to highlight multiple concurrent animations, I’ve also added the ability to animate the height in addition to the width. We’re basically just duplicating the existing properties for our width animation, but applying the values to height. This could be modified to use a&nbsp;<code>Point</code>&nbsp;or&nbsp;<code>Rect</code>&nbsp;to achieve the same effect, but this implementation is better for showing how the modifications we’ll be making to the animation Timer’s action actually work by breaking it down independently.</p>



<h4 class="wp-block-heading">Properties</h4>



<p>As with our Width animation, we need to track what our target expanded Height should be as well as the current state of that dimension. For Width we have an&nbsp;<code>expandedWidth</code>&nbsp;property, so we’ll add an&nbsp;<code>expandedHeight</code>&nbsp;property to match.</p>



<pre class="wp-block-preformatted">Private Property expandedHeight as Integer</pre>



<p>In this version, we’re also renaming our old&nbsp;<code>expanded</code>&nbsp;property to&nbsp;<code>isExpandedWidth</code>:</p>



<pre class="wp-block-preformatted">Private Property isExpandedWidth as Boolean = True</pre>



<p>And adding a new corresponding property for Height:</p>



<pre class="wp-block-preformatted">Private Property isExpandedHeight as Boolean = True</pre>



<p>Finally, we need a property that keeps track of whether we’re currently animating our dimensions so that our subsequent clicks during a color-only animation properly toggle our&nbsp;<code>isExpanded*</code>&nbsp;properties. We could do this by searching the&nbsp;<code>animOp</code>&nbsp;array, but just storing it is probably a bit quicker.</p>



<pre class="wp-block-preformatted">Private Property isAnimatingDimensions as Boolean</pre>



<p>There are better ways to implement tacking of these states, but for this example I want the verbosity.</p>



<h3 class="wp-block-heading">MouseUp Changes</h3>



<p>Since we’re now animating both Width and Height and implementing our rudimentary animation controller, we need to make some changes to our MouseUp event handler. Primarily we’re duplicating what we already do for Width to account for our new Height animation, and applying the changes to the properties we’ve already discussed. We check to see if we’re currently animating Width or Height before toggling their values to avoid issues in the animation timer’s Action handler.</p>



<pre class="wp-block-preformatted">Sub MouseUp(X As Integer, Y As Integer) Handles MouseUp
   '// Just in case we hit some strange scenario where
   '   the timer is disposed of. Should, theoretically,
   '   never happen in this case, but better safe than sorry.
   if IsNull(animTimer) then Return

 '// Now we're going to check for a currently running
   '   animation. If an animation operation of this type is
   '   already underway, all we need to do
   '   is switch the direction the animation is running.
   '   In a full animation controller, this would be handled
   '   internally by chaining or cancelling, most likely,
   '   but this works for our purposes.
   if animQueue_IndexOf("width") &gt;= 0 then
     isExpandedWidth = not isExpandedWidth
   end if
   if animQueue_IndexOf("height") &gt;= 0 then
     isExpandedHeight = not isExpandedHeight
   end if

 '// Here we create our dictionary objects containing
   '   everything our Timer's action event needs to do
   '   the work. The current time in Microseconds, which
   '   will be our start time, the start value, and the
   '   expected result value. This "10" is hard-coded
   '   just so that we can actually click on the canvas
   '   again to reverse the animation if it is fully
   '   collapsed. In most scenarios you wouldn't have
   '   a hard-coded value like this and you may even be
   '   triggering the animation from a different element
   '   altogether, so this value is purely for demonstration
   '   purposes in this project.
   '   animQueue_Add is a new method in this part of the
   '   series, and acts as an animation controller.
   animQueue_Add(new Dictionary("op" : "width", "l" : manimTime, "t" : Microseconds, "s" : Width, "e" : If(isExpandedWidth, 10, expandedWidth)))
   animQueue_Add(new Dictionary("op" : "height", "l" : manimTime, "t" : Microseconds, "s" : Height, "e" : If(isExpandedHeight, 10, expandedHeight)))
 
'// Finally, enable the timer to perform the animation.
   animTimer.Mode = 2
 
'// We've added this event, just in case there's
   '   something you want to trigger at the start of the
   '   animation.
   RaiseEvent BeforeAnimate
 End Sub</pre>



<h3 class="wp-block-heading">The New lerpColor</h3>



<p>For Part 3, I wanted to add a little something extra before we roll in to Part 4, just to show how we can use linear interpolation for animating any number of different properties of our AnimatedCanvas class. That means we’re going to animate the background color of our class as well!</p>



<h4 class="wp-block-heading">New Properties</h4>



<p>To support our color animation in this specific example, we need a couple of new properties. These properties give us our start and end points for our color animation, and we’re going to add them to the inspector so that they can be changed when editing a Window or ContainerControl view.</p>



<ul class="wp-block-list"><li>BackgroundColor represents our default background color, which I’ve set to default as red.</li><li>BackgroundColorHover represents the color we want to see when the mouse is over the control, which defaults to blue.</li><li>currentBackgroundColor represents the background color we want to actually apply, and is changed during the animation process.</li></ul>



<pre class="wp-block-preformatted">Public Property BackgroundColor as Color
   Get
     Return mBackgroundColor
   End Get
   Set
     mBackgroundColor = value
   End Set
 End Property
 Public Property BackgroundColorHover as Color
   Get
     Return mBackgroundColorHover
   End Get
   Set
     mBackgroundColorHover = value
   End Set
 End Property

 Private Property mBackgroundColor as Color = &amp;cff0000
 Private Property mBackgroundColorHover as Color = &amp;c0000ff
 Private Property currentBackgroundColor as Color = &amp;cff0000</pre>



<h4 class="wp-block-heading">The Paint Event</h4>



<p>Our Paint event only needs one small modification to account for the changes we’re making. We previously used a static red color&nbsp;<code>&amp;cff0000</code>&nbsp;but we need to switch to using the&nbsp;<code>currentBackgroundColor</code>&nbsp;property to support the animation.</p>



<pre class="wp-block-preformatted">Sub Paint(g As Graphics, areas() As REALbasic.Rect) Handles Paint
   '// Fill the canvas with our current color.
   g.ForeColor = currentBackgroundColor
   g.FillRect(0, 0, g.Width, g.Height)
 End Sub</pre>



<h4 class="wp-block-heading">The MouseEnter Event</h4>



<p>Our first step in animating the color for this example is to implement the MouseEnter event within our class. We’re simply creating a new Dictionary for the animation operation, populating that with our values to be used in the animation timer, then calling&nbsp;<code>animQueue_Add</code>.</p>



<pre class="wp-block-preformatted">Sub MouseEnter() Handles MouseEnter
   '// In this version, we're going to animate color change
   '   based on whether the mouse is over the control.
   '   So in MouseEnter we start animating from our
   '   currentBackgroundColor to our BackgroundColorHover.
   if me.Enabled then
     animQueue_Add(new Dictionary("op" : "color", "l" : 250, "t" : Microseconds, "s" : currentBackgroundColor, "e" : mBackgroundColorHover))
   end if
 End Sub</pre>



<p>You’ll notice that, without the comments, this entire event handler is very short. Part of the goal as I build this functionality is always to make it as easy to implement as possible as I’ll likely use it in a number of different ways for each UI component. Sometimes I have the Dictionary values as parameters of the&nbsp;<code>animQueue_Add</code>&nbsp;method, but I want to show this in this way for this example.</p>



<p>If I’m implementing animation on an application-wide scale, I’ll typically use a custom class called&nbsp;<code>AnimationOperation</code>, with the values for the operation stored as properties and passed via the&nbsp;<code>Constructor</code>method, then a call to add the resulting class instance to the queue for the&nbsp;<code>AnimationController</code>.</p>



<p>We also assign a static 250ms to color change animations, just to test our dynamic animation times, but you may typically want color change animations to be quicker than other animations in your application just so they stand out less.</p>



<h4 class="wp-block-heading">The MouseExit Event</h4>



<p>MouseExit, like MouseEnter, just creates and adds an animation operation dictionary with the values we want to use. In this case, we want to revert the color back to the default background color.</p>



<pre class="wp-block-preformatted">Sub MouseExit() Handles MouseExit
   '// In this version, we're going to animate color change
   '   based on whether the mouse is over the control.
   '   So in MouseExit we start animating from our
   '   currentBackgroundColor to our default BackgroundColor.
   if me.Enabled then
     animQueue_Add(new Dictionary("op" : "color", "l" : 250, "t" : Microseconds, "s" : currentBackgroundColor, "e" : mBackgroundColor))
   end if
 End Sub</pre>



<h4 class="wp-block-heading">The lerpColor Method</h4>



<p>Now that we have our class setup out of the way, we can create our&nbsp;<code>lerpColor</code>&nbsp;method. In this example I’m simply applying linear interpolation to the Red, Green, and Blue values of the passed colors, but you could use any other subset of color properties that you want for your desired effect.</p>



<pre class="wp-block-preformatted">Private Function lerpColor(startColor as Color, endColor as Color, alphaValue as Double) as Color
   '// This method takes starting and ending color values
   '   and applies the lerp method for linear interpolation to
   '   the constituent Red, Green and Blue values to generate
   '   the new color value based on the animation's elapsed
   '   time.
   '   This could be switched from RGB for different effects,
   '   or you could just use Color.Alpha for making objects
   '   fade in or out.
   dim animStepR as Double = Lerp(startColor.Red, endColor.Red, alphaValue)
   dim animStepG as Double = Lerp(startColor.Green, endColor.Green, alphaValue)
   dim animStepB as Double = Lerp(startColor.Blue, endColor.Blue, alphaValue)

   Return RGB(animStepR, animStepG, animStepB)
 End Function</pre>



<h3 class="wp-block-heading">The Timer Action Handler</h3>



<p>This is where we’re making the most changes in a single method. Not only are we implementing the animation controller methodology, but we’re also adding two new animation operations — height and color, in addition to the original width — so a lot of this will look different from Parts 1 &amp; 2 in this series.</p>



<pre class="wp-block-preformatted">Private Sub animTimer_Action(sender as Timer)
   '// We're going to declare all of our variables outside of the
   '   loop so that we're not using precious time and resources
   '   in every iteration of the loop doing it.
   dim animOp as Dictionary
   dim animOpType as String
   dim animStepDouble as Double
   dim animStepColor as Color
   dim animStartTime, timePercent, animLength as Double
   dim animStartDouble, animEndDouble as Double
   dim animStartColor, animEndColor, newColor as Color

 '// Declare our loop maximum variable. Historically each
 '   iteration of the loop was known to traverse the array
 '   to get the maximum value if this wasn't stored in advance.
 '   I haven't tested this myself recently.
 dim intMax as Integer = animQueue.Ubound

 '// We start at Ubound and traverse the array in reverse because
 '   we'll be removing animations from the queue as they complete,
 '   and this is the best way to avoid OutOfBoundsExceptions.
 for intCycle as Integer = animQueue.Ubound DownTo 0

 <code>'// Get our current operation dictionary from the queue. </code>
 <code>animOp = animQueue(intCycle) </code>

<code>'// Our first step is to make sure we actually have an animation </code>
<code>'   to perform. </code>
<code>if IsNull(animOp) then   </code>
  <code>'// For whatever reason, this entry has been cleared. We'll   </code>
  <code>'   just remove it and continue with the next operation.  </code>
<code>  animQueue.Remove(intCycle)   </code>
  <code>Continue </code>
<code>end if </code>

<code>'// Now we'll get our operation values from the dictionary object. </code>
<code>'   it is possible to run into KeyNotFoundExceptions here, since </code>
<code>'   we're not checking first, but if you do, then you've likely </code>
<code>'   made an error when modifying the code. No animQueue Dictionary </code>
<code>'   should be created without the same set of values since we're </code>
<code>'   making use of variant for the values dependiong on the "op" </code>
<code>'   kay's value. </code>
<code>animOpType = animOp.Value("op").StringValue </code>
<code>animStartTime = animOp.Value("t").DoubleValue </code>
<code>animLength = animOp.Value("l").DoubleValue </code>

<code>'// timePercent is used in the lerp function and gives us a basis </code>
<code>'   for dividing up the distance we need to cover in to constituent </code>
<code>'   pieces for animating. We also use this for cutting out of the </code>
<code>'   animation at the appropriate time. This value ranges from </code>
<code>'   0 to 1.0. We subtract our start time from the current time in </code>
<code>'   microseconds, then divide by one thousand to convert that in to </code>
<code>'   milliseconds. We then divide the result of that by our AnimationTime </code>
<code>'   as that's already expressed in milliseconds. </code>
<code>timePercent = (((Microseconds - animStartTime) / 1000) / animLength) </code>

<code>'// In this part of the series, I show how to animate color changes </code>
<code>'   as well as dimensions. This method uses RGB, but you could </code>
<code>'   alter lerpColor to use any other method you wish. </code>
<code>if animOpType = "color" then   </code>
   <code>'// Get our animation start and end values.   </code>
   <code>animStartColor = animOp.Value("s").ColorValue   </code>
   <code>animEndColor = animOp.Value("e").ColorValue   </code>

   <code>'// Now we're going to pass the necessary parameters in to   </code>
   <code>'   our new lerpColor function to get the current expected   </code>
   <code>'   color at this stage of the animation.   </code>
   <code>animStepColor = lerpColor(animStartColor, animEndColor, timePercent)   </code>

   <code>'// Check to see if this animation operation is complete.   </code>
   <code>'   If so, we remove the operation from the queue and   </code>
   <code>'   move on.   </code>
   <code>if animStepColor = animEndColor or timePercent &gt;= 1 then      </code>
     <code>currentBackgroundColor = animEndColor     </code>
     <code>animQueue.Remove(intCycle)     </code>
     <code>Continue   </code>
    <code>end if   </code>

    <code>'// Assign our lerped color value to the currentBackgroundColor property.     </code>
    <code>currentBackgroundColor = animStepColor   </code>

    <code>'// Since we've now moved our color animation to a place where it   </code>
    <code>'   can be animated without changing the dimensions of the control   </code>
    <code>'   we need to tell the control to update when we set a new color value.</code>
    <code>Invalidate(False) </code>

  <code>else   </code>
    <code>'// Get our animation start and end values.</code>
    <code>animStartDouble = animOp.Value("s").DoubleValue   </code>
    <code>animEndDouble = animOp.Value("e").DoubleValue   </code>

    <code>'// Here we pass our start value, end value, and the percentage   </code>
    <code>'   of time passed to our lerp function parameters to   </code>
    <code>'   calculate what the current width should be at this point   </code>
    <code>'   in the total animation time. Note that, in our previous   </code>
    <code>'   version, we used a step value and modified our current width   </code>
    <code>'   but in this version our step value is the entire calculated   </code>
    <code>'   current width.   </code>
    <code>animStepDouble = Lerp(animStartDouble, animEndDouble, timePercent)   </code>

    <code>'// If we've reached our ending width or our alotted time has   </code>
    <code>'   passed then we bail and set the values we expect at the   </code>
    <code>'   end of the animation.   </code>
    <code>select case animOpType   </code>
    <code>case "width"     </code>

      <code>'// Check to see if this animation operation is complete.     </code>
      <code>'   If so, we remove the operation from the queue and     </code>
      <code>'   move on.     </code>
      <code>if animStepDouble = animEndDouble or timePercent &gt;= 1 then       </code>
        <code>me.Width = animEndDouble ' Set our width to the end result.</code>
        <code>isExpandedWidth = not isExpandedWidth ' Toggle the state boolean.     </code>
        <code>animQueue.Remove(intCycle)       </code>
        <code>Continue     </code>
       <code>end if     </code>

      <code>'// Apply our new width value.     </code>
      <code>me.Width = animStepDouble   </code>

 <code>case "height"     </code>

    <code>'// Check to see if this animation operation is complete.     </code>
    <code>'   If so, we remove the operation from the queue and     </code>
    <code>'   move on.     </code>
    <code>if animStepDouble = animEndDouble or timePercent &gt;= 1 then       </code>
    <code>me.Height = animEndDouble       </code>
    <code>isExpandedHeight = not isExpandedHeight  </code>
<code>    animQueue.Remove(animQueue.IndexOf(animOp))       </code>
    <code>Continue     </code>
  <code>end if     </code>

   <code>'// Apply our new height value.     </code>
   <code>me.Height = animStepDouble   </code>

   <code>end select </code>
  <code>end if</code>
 next

 '// At this stage, we want to see if there are any animation operations
 '   that have yet to complete. If everything is done, then we disable
 '   our timer.
 if animQueue.Ubound &lt; 0 then
    sender.Mode = 0
   end if
 End Sub</pre>



<p>You can see from the code that we’ve moved all of our variable declarations to the top of the method. We do this so that we’re not slowing things down inside the loop by disposing of and redeclaring variables that may be used multiple times. In Part 4 we’ll be adding Pragmas all over the place to make sure our code is even more speedy.</p>



<p>Inside the loop we fill our&nbsp;<code>animOp</code>&nbsp;property with the current animation operation and verify that it isn’t Nil. If animOp is Nil, then we need to go ahead and remove it from the queue.</p>



<p>Next we populate our&nbsp;<code>animOpType</code>,&nbsp;<code>animStartTime</code>, and&nbsp;<code>animLength</code>&nbsp;variables with their corresponding values, and calculate our current&nbsp;<code>timePercent</code>&nbsp;for our lerp functions.</p>



<p>The next block is where all of the magic happens. You can see that we’ve just used the same basic methodology from Part 2, but extended it to support animating color and height in addition to width.</p>



<p>One important thing to note is that we’re calling&nbsp;<code>Invalidate(False)</code>&nbsp;at the end of our conditional if the current operation is a color operation. Without this, our color property’s value would be animated, but the UI would not update to reflect that if this were the only operation currently underway as changes to both Width and Height automatically invalidate the control.</p>



<p>We also do a bit of work on our queue when an animation is complete by removing the current operation when it is complete, and instead of checking the&nbsp;<code>animQueue</code>&nbsp;property for Nil at the end of the method as we did in Part 2, we now check if there are any remaining operations and halt the timer if the queue is empty.</p>



<h3 class="wp-block-heading">Final Thoughts</h3>



<p>While this method may not be best for every situation or every coding style, I’ve found it to be versatile and dependable. This minimal animation controller is surprisingly robust.</p>



<p>As I mentioned earlier, this animation controller does not make use of keyframes for chaining animations. This could be implemented fairly easily, and while I have done it for a number of projects in the past, I won’t be covering that in this series as you should have some idea of how to incorporate that if you so desire.</p>



<p>In the next part I plan to cover&nbsp;<a href="https://developers.google.com/web/fundamentals/design-and-ux/animations/the-basics-of-easing">easing</a>&nbsp;to some degree which, like lerp, controls the speed and change in our animation and can add a massive amount of appeal to your user interface.</p>



<p>You can download the example project for Part 3&nbsp;<a href="https://graffitisuite.com/downloads/ms_17272.zip">here</a>.</p>



<p><em>Anthony G. Cyphers is the Lead Developer and Sole Proprietor of&nbsp;</em><a rel="noreferrer noopener" href="https://graffitisuite.com/" target="_blank"><em>GraffitiSuite Solutions</em></a><em>, and has been providing custom Xojo components and contract development since 2003. He runs the&nbsp;</em><a rel="noreferrer noopener" href="https://t.co/WQSD3O2V6R" target="_blank"><em>Xojo User’s Discord server</em></a><em>, and is an administrator in the&nbsp;</em><a rel="noreferrer noopener" href="https://www.facebook.com/groups/xojo.dev/" target="_blank"><em>Xojo User’s Facebook user group</em></a><em>.</em></p>



<figure class="wp-block-image is-resized"><img loading="lazy" decoding="async" src="https://blog.xojo.com/wp-content/uploads/2019/07/AnthonyAndLaura_Small.png" alt="" class="wp-image-5959" width="128" height="130" srcset="https://blog.xojo.com/wp-content/uploads/2019/07/AnthonyAndLaura_Small.png 375w, https://blog.xojo.com/wp-content/uploads/2019/07/AnthonyAndLaura_Small-296x300.png 296w" sizes="auto, (max-width: 128px) 100vw, 128px" /></figure>



<p></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Guest Post: Animating Xojo, Part 2</title>
		<link>https://blog.xojo.com/2019/07/31/guest-post-animating-xojo-part-2/</link>
		
		<dc:creator><![CDATA[Anthony Cyphers]]></dc:creator>
		<pubDate>Wed, 31 Jul 2019 10:00:16 +0000</pubDate>
				<category><![CDATA[Guest Post]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Animation]]></category>
		<category><![CDATA[UI]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=5950</guid>

					<description><![CDATA[Continuing with what we previously learned in Animating Xojo, Part 1, this version introduces the use of linear interpolation to calculate the current stage of the animation at each step, plus switching to a Dictionary object for variable storage to setup for future parts in this series.]]></description>
										<content:encoded><![CDATA[
<p>Continuing with what we previously learned in <a href="https://blog.xojo.com/2019/07/24/guest-post-historical-methods/">Animating Xojo, Part 1</a>, this version introduces the use of linear interpolation to calculate the current stage of the animation at each step, plus switching to a Dictionary object for variable storage to setup for future parts in this series.</p>



<h2 class="wp-block-heading">Linear Interpolation</h2>



<p>Last time we used a static animation step that was calculated in advance to modify the width of our element. That method is fine for many uses, but for more advanced things we want to get a bit more involved with linear interpolation.</p>



<p>The new method will shorten the steps taken if something locks up your application UI so the time you’ve chosen for your animation to take to complete is honored. Previously, if something suspended your application’s main thread, the animation would halt and wait during this period and 250ms could become 100ms before the lockup and 150ms after the lockup. Now, if your selected animation time is 250ms and something suspends UI updates, the animation will complete after the UI updates have resumed as if the UI had never become unresponsive, resulting in a true animation time that roughly matches the specified time (I’ve seen +/- approximately 0.03 seconds using this method with a timer set at the minimum period for the debugging OS).</p>



<h3 class="wp-block-heading">What is Linear Interpolation</h3>



<p>Linear interpolation (or lerp) in animation is used to calculate change based on the total amount of time a process should take, the amount of time passed since the start of the process, and the change in value from start to finish. By using these three values we can determine, at any given point within our animation time-frame, what our current value should be.</p>



<p>You can read more in-depth information about linear interpolation&nbsp;<a href="https://en.wikipedia.org/wiki/Linear_interpolation" target="_blank" rel="noreferrer noopener">here</a>.</p>



<h3 class="wp-block-heading">What Does it Look Like?</h3>



<p>In code, linear interpolation is a fairly simple algorithm. We provide the following:</p>



<ul class="wp-block-list"><li>Starting value (starting width, in our case)</li><li>Ending value (the width after animation)</li><li>The amount of time passed (expressed as a double value between 0 and 1, which is typically referred to as alpha)</li></ul>



<pre class="wp-block-preformatted">Private Function lerp(startValue as Double, endValue as Double, alphaValue as Double) as Double
   '// The lerp function evaluates where we should be in the animation
   '   given a starting point, an ending point, and the amount of time
   '   elapsed. Lerp is shorthand for linear interpolation.
   return (startValue * (1 - alphaValue)) + (endValue * alphaValue)
 End Function</pre>



<p>We can express that graphically with the two red points below representing our starting and ending values, the blue line representing the current position between those two values over time.</p>



<figure class="wp-block-image"><img decoding="async" src="https://ci3.googleusercontent.com/proxy/-8kFNcU0N2t_1hvzbfiBMOT6UYFoOB_gonR7QiYArtDLFjvJQrYKU9v5GVNXwasTiF72iReaHhpK4yy0af8Ci8dhHHT2iiaTHX6nkqkHKxaKU5uNRlp9Bs-35Lu--8mp_5WWY9RG4Zdxv-RcHB4VLxgxkCahRIrM5-VePASmvvOymqzGF0Ig=s0-d-e1-ft#https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/LinearInterpolation.svg/1920px-LinearInterpolation.svg.png" alt=""/></figure>



<p>By&nbsp;<a rel="noreferrer noopener" href="https://commons.wikimedia.org/wiki/User:Berland" target="_blank">Berland</a>. Based on png-version&nbsp;<a rel="noreferrer noopener" href="https://commons.wikimedia.org/wiki/File:Linear_interpolation.png" target="_blank">Image:Linear_interpolation.png</a>. Newer version by&nbsp;<a rel="noreferrer noopener" href="https://commons.wikimedia.org/wiki/User:Krishnavedala" target="_blank">ElectroKid</a>&nbsp;&#8211; Own work, Public Domain,&nbsp;<a rel="noreferrer noopener" href="https://commons.wikimedia.org/w/index.php?curid=2415345" target="_blank">Link</a></p>



<h2 class="wp-block-heading">Applying Linear Interpolation</h2>



<p>Applying this to our previous code requires quite a bit of modification.</p>



<p>First, we need to keep track of when the animation started, the width value when it started, and what we want our width to be at the end. Previously we used properties of the AnimatedCanvas class to track each value we used in our animation. In this version we’re going to use a Dictionary to store values and keep that in a property of the canvas. This gives us a means of throwing away the animated values (setting our Dictionary property to Nil) when we’re not using them, mainly, but also looks a bit cleaner in the Properties listing in our project, and sets up for the future of this project.</p>



<h3 class="wp-block-heading">Properties</h3>



<p>We’re going to add a new property to our AnimatedCanvas class which will hold our calculation values during the animation process:</p>



<pre class="wp-block-preformatted">Private Property animAction as Dictionary</pre>



<p>With the addition of this property, we’re going to get rid of our old animStep property.</p>



<h3 class="wp-block-heading">MouseUp Event</h3>



<p>Our MouseUp handler is quite a bit different in this implementation. Instead of calculating the animation steps based on the timer’s interval and the length of time we want our animation to run, we’re now doing the following:</p>



<pre class="wp-block-preformatted">Sub MouseUp(X As Integer, Y As Integer) Handles MouseUp
   '// Just in case we hit some strange scenario where
   '   the timer is disposed of. Should, theoretically,
   '   never happen in this case, but better safe than sorry.
   if IsNull( animTimer ) then Return
 '// Now we're going to check for a currently running
   '   animation. If we find that the timer is currently
   '   running, then we know that the user wants to
   '   animate in the other direction. All we need to do
   '   is switch the direction the animation is running.
   if animTimer.Mode = 2 then
     expanded = not expanded
   end if
 '// Here we create our dictionary object containing
   '   everything our Timer's action event needs to do
   '   the work. The current time in Microseconds, which
   '   will be our start time, the start width, and the
   '   expected resulting width. This "10" is hard-coded
   '   just so that we can actually click on the canvas
   '   again to reverse the animation if it is fully
   '   collapsed. In most scenarios you wouldn't have
   '   a hard-coded value like this and you may even be
   '   triggering the animation from a different element
   '   altogether, so this value is purely for demonstation
   '   purposes in this project.
   animAction = new Dictionary( "s" : Microseconds, "sw" : Width, "ew" : If( expanded, 10, expandedWidth ) )
 '// Finally, enable the timer to perform the animation.
   animTimer.Mode = 2
 '// We've added this event, just in case there's
   '   something you want to trigger at the start of the
   '   animation.
   RaiseEvent BeforeAnimate
 End Sub</pre>



<p>As you can see from the comments above, we’re constructing the Dictionary object with the current time(s), the current width(w), and the expected width at the end of the animation(ew).</p>



<p>These changes also allow for the user to click again during the animation to reverse it without, theoretically, causing any strangeness such as animation skipping or jumping. The new animation operation just begins when the user clicks, cancelling the old one. Since we’re using linear interpolation, the timer’s Action event handler just keeps trucking along with a calculated width based upon the changes.</p>



<h3 class="wp-block-heading">Timer Action Handler</h3>



<p>Our timer’s action handler method is also quite different. This is where we use the Dictionary we created in the MouseUp event handler and assigned to our animAction property to calculate and apply the new width of our component.</p>



<pre class="wp-block-preformatted">Private Sub animTimer_Action(sender as Timer)
   '// In this version we've moved from having properties to store
   '   the values we use in our animation to a dictionary
   '   because it's both data we don't want to keep around when not 
   '   animating, and it'll be a bit easier to implement multiple
   '   running animations later by looping over an array of these
   '   dictionary objects on each Timer action.
 '// Our first step is to make sure we actually have an animation
   '   to perform.
   if IsNull( animAction ) then
     '// No current animation. The timer shouldn't even be running,
     '   so we'll go ahead and kill it. Theoretically this should
     '   never happen, but it's another case of checking just so
     '   we're not using unnecessary CPU cycles.
     sender.Mode = 0
     Return
   end if
 '// Now we'll get our operation values from the dictionary object.
   '   it is possible to run into KeyNotFoundExceptions here, since
   '   we're not checking first, but if you do, then you've likely
   '   made an error when modifying the code since we create the
   '   Dictionary with the same set of keys every time and always
   '   overwrite the old object with the new one.
   dim animStart as Double = animAction.Value("s").DoubleValue
   dim animStartWidth as Double = animAction.Value("sw").DoubleValue
   dim animEndWidth as Double = animAction.Value("ew").DoubleValue
 '// timePercent is used in the lerp function and gives us a basis
   '   for dividing up the distance we need to cover in to constituent
   '   pieces for animating. We also use this for cutting out of the
   '   animation at the appropriate time. This value ranges from
   '   0 to 1.0. We subtract our start time from the current time in
   '   microseconds, then divide by one thousand to convert that in to
   '   milliseconds. We then divide the result of that by our AnimationTime
   '   as that's already expressed in milliseconds.
   dim timePercent as Double = (((Microseconds - animStart) / 1000) / manimTime)
 '// Here we pass our start value, end value, and the percentage
   '   of time passed to our lerp function parameters to
   '   calculate what the current width should be at this point
   '   in the total animation time. Note that, in our previous
   '   version, we used a step value and modified our current width
   '   but in this version our step value is the entire calculated
   '   current width.
   dim animStep as Double = Lerp( animStartWidth, animEndWidth, timePercent )
 '// If we've reached our ending width or our alotted time has
   '   passed then we bail and set the values we expect at the
   '   end of the animation.
   if animStep = animEndWidth or timePercent &gt;= 1 then
     me.Width = animEndWidth ' Set our width to the end result.
     expanded = not expanded ' Toggle the state boolean.
     animAction = nil ' Set our dictionary to nil since we don't need it.
     sender.Mode = 0 ' Disable the Timer
     RaiseEvent AfterAnimate ' Notify that the animation is done.
 <code>Return ' Bail out.</code>
 end if
 '// If we get here, then we're still somewhere in the middle
   '   of the animation. Apply the new width value, and we're
   '   good to go.
   me.Width = animStep
 End Sub</pre>



<h2 class="wp-block-heading">New Events</h2>



<p>For this version, I’ve also added a couple of new events. These can be used to perform other actions that you may want to carry out when the animation process has started or ended. Here’s our two new event definitions:</p>



<pre class="wp-block-preformatted">Event AfterAnimate()
Event BeforeAnimate()</pre>



<h2 class="wp-block-heading">Other Changes</h2>



<p>When you launch the demo project, you’ll notice that there’s a lot more going on with wndAnimate than the previous version. First, I renamed the animTime property to a computed AnimationTime property and added it to the inspector, so there’s a field on the window to change this value.</p>



<p>Second, there’s a new checkbox captioned “Insert Interruption”. This uses the BeforeAnimate event to cause the app’s main thread to sleep for 50% of the animation time beginning at 25% of the animation time, which results in the UI becoming unresponsive and the animation to halt for the duration of the Sleep. Once the call to sleep is complete, you’ll see the animation pick up where it would have been if there had been no call to sleep.</p>



<p>Then, a group of RadioButtons for verifying that modal elements do not interfere with animation on the main thread. The choices are: None, MenuItem, and Modal Window. When Xojo was still using Carbon for macOS, modal elements would interfere with UI updates to the main window until that modal element was dismissed. There’s all sorts of technical-ness as to why, but all we really care about is that with the move to Cocoa this is no longer an issue, and the demo proves it.</p>



<p>Finally, I’ve moved the instance of AnimatedCanvas to the right of the Window. This isn’t purely aesthetic as I plan to use this setup in a future version to show how to run multiple concurrent animations.</p>



<p>You can download the updated demo project&nbsp;<a rel="noreferrer noopener" href="https://graffitisuite.com/downloads/ms_17049.zip" target="_blank">here</a>.</p>



<p><em>Anthony G. Cyphers is the Lead Developer and Sole Proprietor of&nbsp;</em><a rel="noreferrer noopener" href="https://graffitisuite.com/" target="_blank"><em>GraffitiSuite Solutions</em></a><em>, and has been providing custom Xojo components and contract development since 2003. He runs the&nbsp;</em><a rel="noreferrer noopener" href="https://t.co/WQSD3O2V6R" target="_blank"><em>Xojo User’s Discord server</em></a><em>, and is an administrator in the&nbsp;</em><a rel="noreferrer noopener" href="https://www.facebook.com/groups/xojo.dev/" target="_blank"><em>Xojo User’s Facebook user group</em></a><em>.</em></p>



<div class="wp-block-image"><figure class="alignleft is-resized"><img loading="lazy" decoding="async" src="https://blog.xojo.com/wp-content/uploads/2019/07/AnthonyAndLaura_Small.png" alt="" class="wp-image-5959" width="117" height="119" srcset="https://blog.xojo.com/wp-content/uploads/2019/07/AnthonyAndLaura_Small.png 375w, https://blog.xojo.com/wp-content/uploads/2019/07/AnthonyAndLaura_Small-296x300.png 296w" sizes="auto, (max-width: 117px) 100vw, 117px" /></figure></div>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Guest Post: Animating Xojo, Part 1</title>
		<link>https://blog.xojo.com/2019/07/24/guest-post-historical-methods/</link>
		
		<dc:creator><![CDATA[Anthony Cyphers]]></dc:creator>
		<pubDate>Wed, 24 Jul 2019 10:00:44 +0000</pubDate>
				<category><![CDATA[Guest Post]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Animation]]></category>
		<category><![CDATA[UI]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=5889</guid>

					<description><![CDATA[One of the fun things I get to do regularly is build animations into Xojo desktop components. While incredibly rewarding when you get it right, it can be a long road.]]></description>
										<content:encoded><![CDATA[
<p>One of the fun things I get to do regularly is build animations into Xojo desktop components. While incredibly rewarding when you get it right, it can be a long road.</p>



<span id="more-5889"></span>



<h2 class="wp-block-heading">Historical Methods</h2>



<h3 class="wp-block-heading">The Tight Loop</h3>



<p>A long time ago, to implement animation in Xojo one had to resort to tight loops if the animation needed to be self-contained (in a custom class, for example). This resulted in code that looked a lot like this:</p>



<pre class="wp-block-preformatted">while me.Height &gt; 0
     me.Height = me.Height - 10
     me.Refresh()
     App.DoEvents(10)
 Wend</pre>



<p>Now, however, this is bad for a number of reasons. The most obvious being the use of a tight loop for UI updates. This can result in all kinds of funkiness that’s hard to workaround, and often the code above would’ve been much longer to account for other issues in the UI depending upon your implementation.</p>



<p>Second, the use of Refresh(), Refresh was required because the changes were happening in a tight loop, but it comes with its own set of drawbacks, and there are no shortage of forum posts that detail why to avoid it.</p>



<p>Third, App.DoEvents. Don’t. Use. DoEvents. I can’t stress this enough. Unless building a console app, DoEvents should almost always be avoided. As pointed out in&nbsp;<a rel="noreferrer noopener" href="https://forum.xojo.com/conversation/post/75304" target="_blank">this post</a>, if you think you need DoEvents in a desktop app, you probably actually need a thread.</p>



<h3 class="wp-block-heading">Threads</h3>



<p>Using threads for animation can be a great way to implement it depending on the scenario, but one must remember that threads can no longer access the UI. At one time, however, they could. This gave us the ability to take that tight loop above and shove it in to a thread to avoid locking up the UI and using DoEvents. A typical thread animation Run() event might’ve looked like this:</p>



<pre class="wp-block-preformatted">Sub Run() Handles Run
   while me.Height &gt; 0
     control1.Height = control1.Height - 10
     control1.Refresh()
     me.Sleep(10)
   Wend
 End Sub</pre>



<p>While this was an improvement as it moved the tight loop out of the primary event loop, the old implementation of threads that allowed for directly accessing the UI came with its own set of problems and was unsafe.</p>



<h2 class="wp-block-heading">Today</h2>



<p>Nowadays, the best method is to use a timer. If we want a self-contained animation, then this requires a bit of setup. I’m creating a new class called AnimatedCanvas that shrinks or expands its width when clicked. Its superclass is Canvas.</p>



<h3 class="wp-block-heading">The Properties</h3>



<p>Once we have that, we’re going to add some properties to it:</p>



<pre class="wp-block-preformatted">Private Property expandedWidth as Integer
 Private Property animStep as Integer
 Private Property animTimer as Timer
 Private Property expanded as Boolean = True</pre>



<p>The expandedWidth property is where we’re going to store the width we want when the control is expanded fully.</p>



<p>animStep is where we’ll store the current animation’s step value, or the amount of change to the width at each stage of the animation.</p>



<p>animTimer is our Timer instance that will be doing the heavy-lifting.</p>



<p>The expanded boolean property helps us determine what operation is currently in progress. We set it to True because we’re going to use the default width of the control as our expandedWidth property later on.</p>



<h3 class="wp-block-heading">The Event Handlers</h3>



<p>The first event handler we want to add is the Open event. In this simple example we’re just setting our expandedWidth property to the width of the component, and setting up our animTimer property for use later.</p>



<pre class="wp-block-preformatted">Sub Open() Handles Open
   '// In this example, I'm just setting the expandedWidth to the initial width.
   '   A real-world case would obviously be different.
   expandedWidth = me.Width
 '// Initialize our animation timer. I'm using a period of 20 here,
   '   but this should be adjusted for best performance and smoothness
   '   based on what you're animating.
   animTimer = new Timer
   animTimer.Period = 20
   animTimer.Mode = 0
   AddHandler animTimer.Action, WeakAddressOf animTimer_Action
 End Sub</pre>



<p>Next we’re just going to do something simple in the Paint event so that we can see what’s going on</p>



<pre class="wp-block-preformatted">Sub Paint(g As Graphics, areas() As REALbasic.Rect) Handles Paint
   '// Just fill it red so that we can see it.
   g.ForeColor = &amp;cff0000
   g.FillRect( 0, 0, g.Width, g.Height )
 End Sub</pre>



<p>MouseDown is also simple. We want our animation to occur only if the control is enabled, so we can just return the value of Enabled. If Enabled, then MouseUp will fire next to start our animation.</p>



<pre class="wp-block-preformatted">Function MouseDown(X As Integer, Y As Integer) Handles MouseDown as Boolean
   Return me.Enabled
 End Function</pre>



<p>MouseUp is a little more complex as we’re doing some simple math for animStep and then starting the timer.</p>



<pre class="wp-block-preformatted">'// Just in case we hit some strange scenario where
 '   the timer is disposed of. Should, theoretically,
 '   never happen in this case, but better safe than sorry.
 if IsNull( animTimer ) then Return
 '// Here we setup our animation step to take 1000ms.
 '   We multiple by 20, which is our timer interval.
 '   The minimum built-in timer Interval for macOS
 '   is 10ms and for Windows is 16ms, if I remember
 '   correctly. 20 gets us where want to be, but
 '   could just as easily use a #IF target or the
 '   value of 16.
 animStep = (expandedWidth / 1000) * 20
 '// If our control is currently expanded, then we'll
 '   use a negative value to shrink it.
 if expanded then animStep = -animStep
 '// Finally, enable the timer to perform the animation.
 animTimer.Mode = 2</pre>



<h3 class="wp-block-heading">Timer Action</h3>



<p>Now that we have all of that setup, the last thing we need to do is add our timer’s Action handler method. This is going to do the bulk of the work by calculating the new width, checking the new width for validity, then either applying the new value or ending the animation.</p>



<pre class="wp-block-preformatted">Private Sub animTimer_Action(sender as Timer)
 ‘// We want to calculate the new value ahead of time.
 ’   This gives us the opportunity to bail a little
 '   earlier and not have to apply a corrected value later.
 dim newWidth as Integer = me.Width + animStep
 ' If expanded = True then we’re shrinking.
 if expanded then
  ‘// If our newWidth is going to be less than or equal to
  ’   our minimum width, then we’re done with our animation.
  '   I’m using a hardcoded width of 10 here, but you could
  '   create a property for this.
  if newWidth &lt;= 10 then    
   ‘// Make sure the width is correct for the new state,    
   ’   disable the timer, then set our Expanded property.    
   me.Width = 10    
   sender.Mode = 0    
   expanded = False    
   Return  
 end if 
else  
‘// If our newWidth is going to be greater than or equal  
’   to our expandedWidth, we bail.  
if newWidth &gt;= expandedWidth then
    ‘// Make sure the width is correct for the new state,
    ’   disable the timer, then set our Expanded property.
    me.Width = expandedWidth
    sender.Mode = 0
    expanded = True
    Return
  end if
 end if
 '// If we get here, then we're still somewhere in the middle
   '   of the animation. Apply the new width value.
   me.Width = newWidth
 End Sub</pre>



<h3 class="wp-block-heading">Final Notes</h3>



<p>As you can see, animating in Xojo is a fairly simple concept at its core. The real fun starts when you want to animate multiple virtual elements inside picture objects with varying types of animation, and we won’t even get in to&nbsp;<a href="https://developers.google.com/web/fundamentals/design-and-ux/animations/the-basics-of-easing" target="_blank" rel="noreferrer noopener">easing</a>.</p>



<p>Bear in mind that this is an intentionally simplistic example that’s meant to illustrate the basics of timer-based animation. A full implementation that expects multiple different moving parts in tandem or independently would be much more complex, and likely use something along the lines of an Array or Dictionary to keep track of the animation queue and the expected changes at each step in the process.</p>



<p>I’ve built all of this in to an example project, which you can download&nbsp;<a rel="noreferrer noopener" href="https://graffitisuite.com/downloads/ms_16917.zip" target="_blank">here</a>.</p>



<p><em>Anthony G. Cyphers is the Lead Developer and Sole Proprietor of&nbsp;</em><a rel="noreferrer noopener" href="https://graffitisuite.com/" target="_blank"><em>GraffitiSuite Solutions</em></a><em>, and has been providing custom Xojo components and contract development since 2003. He runs the&nbsp;</em><a rel="noreferrer noopener" href="https://t.co/WQSD3O2V6R" target="_blank"><em>Xojo User&#8217;s Discord server</em></a><em>, and is an administrator in the&nbsp;</em><a rel="noreferrer noopener" href="https://www.facebook.com/groups/xojo.dev/" target="_blank"><em>Xojo User&#8217;s Facebook user group</em></a><em>.</em></p>



<figure class="wp-block-image is-resized"><img loading="lazy" decoding="async" src="https://blog.xojo.com/wp-content/uploads/2019/07/AnthonyAndLaura_Small.png" alt="" class="wp-image-5959" width="106" height="108" srcset="https://blog.xojo.com/wp-content/uploads/2019/07/AnthonyAndLaura_Small.png 375w, https://blog.xojo.com/wp-content/uploads/2019/07/AnthonyAndLaura_Small-296x300.png 296w" sizes="auto, (max-width: 106px) 100vw, 106px" /></figure>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Web: Create Sliding-Animated Menus</title>
		<link>https://blog.xojo.com/2019/01/30/web-create-sliding-animated-menus/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Wed, 30 Jan 2019 10:00:32 +0000</pubDate>
				<category><![CDATA[Learning]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Animation]]></category>
		<category><![CDATA[webdev]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=5368</guid>

					<description><![CDATA[Sometime ago a Xojo user asked if it is possible to use Xojo Web to create the kind of animated menus seen in several regular websites. After some investigation (and the invaluable help of Greg O'Lone), the answer is: yes, you can do that! ]]></description>
										<content:encoded><![CDATA[<p>Sometime ago a Xojo user asked if it is possible to use Xojo Web to create the kind of animated menus seen in several <em>regular</em> websites. After some investigation (and the invaluable help of Greg O&#8217;Lone), the answer is: yes, you can do that! If you are interested in seeing how to achieve this, continue reading!<span id="more-5368"></span></p>
<p>We&#8217;ll start with a <a href="http://documentation.xojo.com/api/user_interface/web/webcontainer.html">WebContainer</a>, responsible for including all the menu elements. For this particular example, a couple of <a href="http://documentation.xojo.com/api/user_interface/web/weblabel.html">WebLabel</a> controls that when clicked, will display the associated web page; a <em>template</em> web page (<a href="http://documentation.xojo.com/api/user_interface/web/webpage.html">WebPage</a>), that will be used to create all the web pages driven by the menu so they can display all the common elements; a couple of Web styles, to set the menu opacity and menu items text color; and a bit of <b>JavaScript</b> to animate the menu itself.</p>
<h2>Creating the styles</h2>
<p>With Xojo running with a new Web project, we will start adding a couple of styles (<a href="http://documentation.xojo.com/api/user_interface/web/webstyle.html">WebStyle</a>) to the project from the Library. Select the first of the just added styles in order to access the <strong>Styles Editor</strong> and change the <code>Name</code> property to <code>MenuStyle</code> in the Inspector. Now, add the <b>Background</b> property using the Style editor and set the background color to the one you want to use. Maybe you want to set the <b>Opacity</b> property so it is not 100% solid when the menu is displayed over the webpages.</p>
<p>Choose the second style in the Navigator and change its <code>Name</code> property to <code>TextWhite</code> (or other name of your election) in the Inspector, setting the <b>Text Color</b> property to the one you want (white in the example). This is the style to be applied on the <b>WebLabel</b> controls of the menu.</p>
<h2>Creating the WebContainer-based menu</h2>
<p>Add now a WebContainer from the Library to the Navigator. This is the control that will include all the links to the webpages of the web app; and also will contain the button responsible of closing the menu using a sliding animation on the right side of the webpage. Of course, you can easily change these UI controls to other ones that fits better in your app design.</p>
<p>With the WebContainer selected in the Navigator, use the Inspector to set the following properties:</p>
<ul>
<li><b>Name</b>: CCMenu</li>
<li><b>Style</b>: MenuStyle</li>
</ul>
<p>You don&#8217;t need to modify the size of the control; this is something we will set using the control locking options in the Inspector once we add it to our template webpage.</p>
<p>The next control that we add to the WebContainer is the button that will hide the menu, and also the WebLabels that will link to the webpages we want to drive from the menu. Don&#8217;t forget to set the property <code>Style</code> to <code>TextWhite</code> (or the name set in the previous step) to the WebLabels using the Inspector.</p>
<p>At this point, the WebContainer <code>CCMenu</code> should be similar to the one displayed in this screenshot:</p>
<p><img loading="lazy" decoding="async" class="size-full wp-image-5369 aligncenter" src="https://blog.xojo.com/wp-content/uploads/2019/01/CCMenu.jpg" alt="" width="400" height="336" /></p>
<h3>Adding Behavior to the Menu</h3>
<p>The next step is adding the behavior to the WebContainer, so it is hidden or displayed when directed from our web app; so add the a new method to the <code>CCMenu</code> WebContainer using the following signature:</p>
<p><code>ShowMenu( show as Boolean = True )</code></p>
<p>And set its <b>Scope</b> to <code>Private</code>. Then, write the following snippet of code in the associated Code Editor:</p>
<pre>Dim sa() As String
// We get the unique ID for the WebContainer
sa.Append "var el = document.getElementById('" + Me.ControlID + "');"

// accessing its Style property
sa.Append "var st = el.style;"

// If the 'show' variable is set to True, then
// that means that we want to display the menu
If show Then
  // we set the position and animation properties
  // so the menu is displayed sliding from
  // the right margin of the webpage
  sa.Append "st.transitionProperty = 'right';"
  sa.Append "st.transitionDuration = '1s';"
  sa.Append "st.transitionTimingFunction = 'ease-in-out';"
  sa.Append "st.right = '0px';"
Else
  // If the value is set to False, then
  // we will hide the menu, sliding it outside
  // of the right bound of the webpage
  sa.Append "st.right =  '-" + str(me.width) + "px';"
End If

// we compose the JavaScript sentence to execute
Dim js As String = Join(sa, "")

// executing it on the current webpage
ExecuteJavaScript(js)</pre>
<p>While this is the method in charge of doing the real work, we will add a couple of convenient public methods to make more explicit the task of displaying and hiding the menu. Add thus the first of such methods to the WebContainer <code>CCMenu</code> using the following values in the associated Inspector:</p>
<ul>
<li><b>Method Name</b>: Show</li>
<li><b>Scope</b>: Public</li>
</ul>
<p>And put this line of code in the associated Code Editor:</p>
<p><code>ShowMenu(True)</code></p>
<p>That is, it will call the previously created private method passing along the <code>True</code> value, so it will instruct to display the menu.</p>
<p>Add the second method, using these values:</p>
<ul>
<li><b>Method Name</b>: Hide</li>
<li><b>Scope</b>: Public</li>
</ul>
<p>And put this line of code in the associated Code Editor:</p>
<p><code>ShowMenu(False)</code></p>
<p>These are all the methods needed. Now select the button added to the WebContainer and change its name to <code>Close</code> from the Inspector Panel. Next, add the <code>Action</code> <b>Event Handler</b> to it and write the following line of code in the associated Code Editor:</p>
<p><code>Hide</code></p>
<p>That is, when the web app user clicks the button it will call the method in charge of hiding the Menu.</p>
<p>Now is time to add the functionality to the labels responsible for showing the associated webpages; that is, the menu option themselves. For this, we are using a really simple approach in order to simplify the example and focus in the main topic of this tutorial. For this, the text displayed by the labels is the name of the webpages to be displayed. Select the first of the labels and set the following property using the Inspector:</p>
<ul>
<li><b>Text</b>: WebPage1</li>
</ul>
<p>Adding next the <code>MouseDown</code> Event Handler and writing the following couple of lines of code in the associated Code Editor:</p>
<pre>If Me.Page.Name = Me.Text Then Exit

WebPage1.Show</pre>
<p>Now repeat the process for the second label setting the following property from the Inspector:</p>
<ul>
<li><b>Text</b>: WebPage2</li>
</ul>
<p>And this code in the associated Code Editor for the <code>MouseDown</code> Event Handler:</p>
<pre>If Me.Page.Name = Me.Text Then Exit

WebPage2.Show</pre>
<p>Now we have everything we need for our example menu.</p>
<h2>Creating the Template Webpage</h2>
<p>Now it is time to add the webpage acting as a <em>template</em> for all the app webpages <em>subclassed</em> from it using the menu.</p>
<p>Add a new WebPage to the project from the Library and change its name to <code>WPBase</code> using the Inspector. Next, add the <code>CCMenu</code> WebContainer to it from the Navigator and a button from the Library, so the result is similar to the one displayed in the following screenshot:</p>
<p><img loading="lazy" decoding="async" class="size-full wp-image-5370 aligncenter" src="https://blog.xojo.com/wp-content/uploads/2019/01/WPBase.png" alt="" width="1854" height="1384" /></p>
<p>Notice the Locking values for the added WebContainer displayed in the Inspector on the screenshot, so it is <em>locked</em> to the same width and height of the webpage when we run the app.</p>
<p>Select now the button and add the <code>Action</code> Event Handler writing the following line of code in the associated Code Editor:</p>
<p><code>ccmenu1.Show</code></p>
<p>As you can see, this simply calls the public <code>show</code>  method previously added to the <code>CCMenu</code> WebContainer, so it displays the menu. This is everything we need to do.</p>
<h2>Creating the Example WebPages</h2>
<p>We have mainly everything we need to run our example. We just need to add a couple of additional webpages to the project from the Library. Change its names to <code>WebPage1</code> and <code>WebPage2</code>, because this is the property whose value has to match with the text of the labels added to the menu, in order to show the right page from the menu.</p>
<p><img loading="lazy" decoding="async" class="size-full wp-image-5371 aligncenter" src="https://blog.xojo.com/wp-content/uploads/2019/01/WPMenuDemo.gif" alt="" width="400" height="250" /></p>
<p>The main point here is set the <code>Super</code> property for both webpages to <code>WPBase</code>, so they <em>inherit</em> all the elements from the <em>template</em> webpage created in the previous step. Finally, add any controls you want to each webpage simply so you can distinguish one from other when selected from the menu.</p>
<p>Click the <b>Run</b> button in the Xojo IDE toolbar and test the menu! You can download and play with the project this tutorial is based on from <a href="https://www.dropbox.com/s/hwzsniid4yh5nlc/SlideMenu.zip?dl=1" target="_blank" rel="noopener">this link</a>.</p>
<p><em>Javier Rodri­guez has been the Xojo Spanish Evangelist since 2008, he’s also a Developer, Consultant and Trainer who has be using Xojo since 1998. He manages <a href="http://www.aprendexojo.com">AprendeXojo.com</a> and is the developer behind the GuancheMOS plug-in for Xojo Developers, Markdown Parser for Xojo, HTMLColorizer for Xojo and the Snippery app, among others.</em></p>
<p>*<a href="https://www.aprendexojo.com/2019/01/web-crear-menus-deslizantes-con-animacion/" target="_blank" rel="noopener">Read this post in Spanish</a></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Animating the Web: Fading Images in-out</title>
		<link>https://blog.xojo.com/2018/12/19/animating-the-web-fading-images-in-out/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Wed, 19 Dec 2018 10:00:29 +0000</pubDate>
				<category><![CDATA[Learning]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Animation]]></category>
		<category><![CDATA[webdev]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=5232</guid>

					<description><![CDATA[This tutorial will show you how easy it is to create animations on components of Xojo web apps, thanks to the use of the Style Editor and the WebAnimator class. Learn how to do a fade effect between two images that you can expand and adapt to your web apps.]]></description>
										<content:encoded><![CDATA[<p>This tutorial will show you how easy it is to create animations on components of Xojo web apps, thanks to the use of the <a href="http://developer.xojo.com/userguide/web-styles$style-editor">Style Editor</a> and the <a href="http://documentation.xojo.com/WebAnimator">WebAnimator</a> class. Learn how to do a fade effect between two images that you can expand and adapt to your web apps.</p>
<p>In order to recreate this fade effect we&#8217;ll mainly use a couple of styles (<a href="http://documentation.xojo.com/api/user_interface/web/webstyle.html">WebStyle</a> class) to set the initial status for each one of our images (instances from the <a href="http://documentation.xojo.com/WebImageView">WebImageView</a> class). These will be overlaped in the web page, sharing the same position. Then we&#8217;ll add a button to the web page so it will fire the animation every time it is clicked.</p>
<p><span id="more-5232"></span></p>
<p>Let&#8217;s see how we can do this, step by step.</p>
<h2>Creating Styles</h2>
<p>The style creation process is really simple in Xojo Web thanks to the integrated Style Editor. For example, drag two instances of a WebStyle from the Library panel to the Navigator (the leftmost column in the Xojo IDE). Now select the first of these style instances in the Navigator and you will see the Style Editor.</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-5233" src="https://blog.xojo.com/wp-content/uploads/2018/12/Estilo.png" alt="" width="1626" height="324" /></p>
<p>The first thing to do is change the style name using the <b>Name</b> attribute in the Inspector. For example, type <code>ZeroOpacity</code> as the name. As you can guess, this will be the style that applies a 0% of opacity on any control it is attached to. For this, access the properties popup menu and click on the <b>Add Property</b> button in the Editor then select the <b>Opacity</b> option under the <b>Miscellaneous</b> section. The Editor will add the property to the editor, where we only need to set the value to 0%.</p>
<p>Repeat the process for the second style, except that in this case the name will be <code>MaxOpacity</code>, leaving the default value associated with the <b>Opacity</b> property once the style has been added.</p>
<p>As you can see, the Style Editor also allows us to create styles that implements other additional properties like fonts, shadows, color, borders, etc., with several variations for every possible status of a control: Normal, the cursor is over the control, the control has been clicked, or is an already &#8220;visited&#8221; link, for example. These are the common statuses for any object or control on a web page of a web app.</p>
<h2>Applying Styles to Controls</h2>
<p>With the webpage added by default to the project selected (<code>WebPage1</code>), add two instances of the <b>WebImageView</b> control from the Library to the web page. Set their sizes so they are the same, and set their positions so they are located in the same place (Left and Top properties). Next, add two images to the web project; it is best if they have the same size as the one set to the WebImageView instances.</p>
<p>The next step is setting each image to each <strong>WebImageView</strong> instance, at the same time that we set the style created in the previous step to each one of these instances. Both operations are done using the Inspector.</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-5234" src="https://blog.xojo.com/wp-content/uploads/2018/12/Layout.png" alt="" width="1278" height="998" /></p>
<p>Choose the first of these instances, <code>ImageView1</code> and in the Inspector choose one of the two added images selecting the popup menu associated with the <b>Picture</b> property under the <b>Behavior</b> section. Next, select the <code>ZeroOpacity</code> style option in the <b>Style</b> popup menu under the <b>Style</b> section.</p>
<p>Repeat this operation for the <code>ImageView2</code> instance and use the Inspector to select the other image and the style <code>MaxOpacity</code>.</p>
<h2>Starting the Animation object</h2>
<p>The use of the <b>WebAnimator</b> class is really easy. Just set a control derived from the <b>WebControl</b> class over we want it to work in order to apply any operation of Scale, Movement, Resizing, Rotation… and also animate its opacity value. That is what we want to achieve in this example. Then set the amount of time for the animation (in seconds) and the value of the attribute or attributes we want to modify (for the opacity, only set one property).</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-5235" src="https://blog.xojo.com/wp-content/uploads/2018/12/Efecto.jpg" alt="" width="1171" height="659" /></p>
<p>Of course the animation can be smoothier (or more detailed) using keyframes references. The best part is that the animations are done in the client side of the web app; that is, the browser. This means that you&#8217;ll be away from latency derived problems or communication speed problems because the app doesn&#8217;t needs to talk with the server.</p>
<p>For our example the operation is really simple. Once we create the instance from the <b>WebAnimator</b> class (drag it from the Library to the Webpage1, so it is added to the Shelf in the bottom of the Editor), we will animate the image in the upper position (with the Style at 100% opacity) to a 0% opacity. Then, animate the second image, in a lower layer, doing exactly the opposite so its opacity gets a 100% value. Once the animation has finished, we will change the variables in charge of setting the opacity level for each image, so the process is reversed the next time the button is clicked.</p>
<p>Thus, we can add the <b>Action</b> Event Handler to our button (use the Insert &gt; Event Handler menu option for that), and add the following snippet of code to it using the Code Editor:</p>
<pre>Static first As Integer = 0 // Variable to set the opacity to a 0%
Static second As Integer = 100 // Variable in charge of setting the opacity to a 100% value

Animator1.Opacity(ImageView1, first, 1) // We set the property we want to animate into the Animation instance
Animator1.Play // And execute it so it efectively animates the opacity property to the passed value
animator1.Opacity(ImageView2,second, 1) // We repeat the process for the second image
Animator1.Play
If first = 0 Then // And we interchange the variables values, so they do the opossite action next time the Event Handler is called
  first = 100
  second = 0
Else
  first = 0
  second = 100
End If</pre>
<p>Of course, you can expand it (or adapt the code) so it is more flexible if you decide to include, for example, the ImageView controls into a ContainerControl, or you add an Array to the mix in order to apply this fade effect to more than just two images, even at a specified period of time. Do you dare?</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-5285" src="https://blog.xojo.com/wp-content/uploads/2018/12/FadeInOut.gif" alt="" width="320" height="212" /></p>
<p><em>Javier Rodri­guez has been the Xojo Spanish Evangelist since 2008, he’s also a Developer, Consultant and Trainer who has be using Xojo since 1998. He manages <a href="http://www.aprendexojo.com">AprendeXojo.com</a> and is the developer behind the GuancheMOS plug-in for Xojo Developers, Markdown Parser for Xojo, HTMLColorizer for Xojo and the Snippery app, among others.</em></p>
<p>*Watch a <a href="https://www.youtube.com/watch?v=BSsi3LOmUtI">video of this Tutorial in Spanish</a></p>
<p>*<a href="https://www.aprendexojo.com/2018/10/animaciones-en-la-web/">Read this post in Spanish</a></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Contrast Illusion Animation</title>
		<link>https://blog.xojo.com/2017/11/29/contrast-illusion-animation/</link>
		
		<dc:creator><![CDATA[Paul Lefebvre]]></dc:creator>
		<pubDate>Wed, 29 Nov 2017 19:41:31 +0000</pubDate>
				<category><![CDATA[Fun]]></category>
		<category><![CDATA[Animation]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=3543</guid>

					<description><![CDATA[In addition to being a cool illusion (eyes are weird), this project is a good excuse for me to again show how easily you can do animation with Xojo.]]></description>
										<content:encoded><![CDATA[<p>I was reading Twitter recently and came across this Tweet:</p>
<blockquote class="twitter-tweet" data-width="500" data-dnt="true">
<p lang="en" dir="ltr">Reality shatter. The two objects are traveling in exactly the same manner. Watch when it turns gray. <a href="https://t.co/gkRKyfNnyI">https://t.co/gkRKyfNnyI</a> <a href="https://t.co/HpZsudeXSG">pic.twitter.com/HpZsudeXSG</a></p>
<p>&mdash; Cliff Pickover (@pickover) <a href="https://twitter.com/pickover/status/934632406174371840?ref_src=twsrc%5Etfw">November 26, 2017</a></p></blockquote>
<p><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script></p>
<p>So of course, I though that would be cool to try in Xojo. After a few minutes of playing around I quickly had it.</p>
<p><span id="more-3543"></span></p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-3545" src="https://blog.xojo.com/wp-content/uploads/2017/11/ContrastIllusion.gif" alt="" width="600" height="422" /></p>
<p>In addition to being a cool illusion (eyes are weird), this project is a good excuse for me to again show how easily you can <a href="http://developer.xojo.com/webinar-retro-gaming">do animation with Xojo</a>.</p>
<p>Essentially, you just need a Timer that tells a Canvas to update regularly. The Canvas then redraws itself using your objects.</p>
<p>I added a Block class to serve as the blocks that move across the stripe pattern. This class has properties for the X, Y, color and a method to draw itself.</p>
<p>In the Open event of the Canvas, the block objects are initialized:</p>
<pre>Block1 = New Block // property on Window
Block1.X = 0
Block1.Y = Canvas1.Height / 3
Block1.BlockColor = &amp;cFFFF00

Block2 = New Block // property on Window
Block2.X = 0
Block2.Y = (Canvas1.Height / 3) * 2
Block2.BlockColor = &amp;c0000ff</pre>
<p>A Timer is added to the Window (Period = 10) with code to update the block&#8217;s X coordinates:</p>
<pre>Block1.X = Block1.X + 1
Block2.X = Block2.X + 1

If Block1.X &gt; Canvas1.Width Then Block1.X = 0
If Block2.X &gt; Canvas1.Width Then Block2.X = 0

Canvas1.Invalidate(False)</pre>
<p>The Paint event then draws the stripe pattern (or not if a hide checkbox is selected):</p>
<pre>If HideStripeCheck.Value Then
  g.ForeColor = &amp;ccccccc
  g.FillRect(0, 0, g.Width, g.Height)
Else
  g.ForeColor = &amp;c000000
  g.FillRect(0, 0, g.Width, g.Height)
  Dim showStripe As Boolean
  For i As Integer = 0 To g.Width Step 25
    If showStripe Then
      g.ForeColor = &amp;cffffff
      g.FillRect(i, 0, 25, g.Height)
    End If
    showStripe = Not showStripe
  Next
End If

Block1.Draw(g)
Block2.Draw(g)</pre>
<p>Download the illusion project and be amazed at how your eyes play tricks on you:</p>
<p><a href="http://files.xojo.com/BlogExamples/Illusion.xojo_binary_project.zip">Illusion Project</a></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
