blob: 81a58abafa6422fa26736b9096755a0047f161b0 [file] [log] [blame]
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta http-equiv="CACHE-CONTROL" content="NO-CACHE"><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Working with vector graphics</title><link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"><link rel="stylesheet" href="/css/styles.css"><link rel="shortcut icon" href="/img/favicon.ico"></head><body class="page post" id="main"><header class="docs-header"><div class="container"><div class="topbar"><div class="topbar-left"><a href="/"><span class="site-title">Apache Royale</span></a></div><div class="topbar-center"></div><div class="topbar-right"><button class="topMenu-dropbtn"><i class="fa fa-bars"></i>&nbsp;Menu</button><ul class="topMenu"><li><a href="/features">Features</a></li><li><a href="https://apache.github.io/royale-docs/get-started">Get Started</a></li><li><a href="/download">Download</a></li><li><a href="/docs">Docs</a></li><li><a href="/blog">Blog</a></li><li><a href="https://github.com/apache/royale-asjs/wiki/Apache-Royale-Source-Code-Repositories"><i class="fa fa-github"></i> GitHub</a></li></ul></div></div><div class="post-header"><h1>Working with vector graphics</h1><div class="post-meta">by Carlos Rovira on March 29, 2020</div></div></div></header><div class="page-content"><div class="container"><article><p>This example shows some ways you can work with vector graphics in Apache Royale. Since Royale draws in part from the sources of Flash and Flex technologies, you'll find that <a href="https://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/Graphics.html">the powerful Flash drawing API</a> is supported for JavaScript and SWF applications. On the other hand, Apache Royale also supports use of <a href="https://en.wikipedia.org/wiki/Scalable_Vector_Graphics">SVG graphics</a>.</p><p>In this example we create an Erlenmeyer flask, a measuring and mixing container for laboratories, that we can fill with some kind of strange green fluid. We can change the level of the fill with a Jewel <strong>HSlider</strong>, and use a <strong>ToggleButton</strong> to show or hide an indicator of the maximum level the liquid can reach. The bottle is be a static SVG shape and the fluid is drawn at runtime as the code responds when the slider value changes.</p><h2>Example structure</h2><p>We're using the <strong>Jewel UI set</strong> to build a simple interface as a placeholder for the example. We use a Jewel <strong>Card</strong>; the Jewel <strong>HorizontalCenteredLayout</strong> centers the card in the card on both axes.</p><p>As usual, the <strong>Card</strong> has three sections: a <strong>CardHeader</strong> (with the title), a <strong>CardPrimaryContent</strong> (that holds the bottle) and a <strong>CardActions</strong> (with some controls).</p><p>This is the main structure:</p><pre><code class="language-mxml">&lt;j:Card width=&quot;460&quot; height=&quot;680&quot;&gt;
&lt;j:CardHeader&gt;
&lt;html:H3 text=&quot;Working with vector graphics&quot; className=&quot;primary-normal&quot;/&gt;
&lt;/j:CardHeader&gt;
&lt;j:CardPrimaryContent itemsHorizontalAlign=&quot;itemsCentered&quot;&gt;
&lt;!-- Here will have the bottle --&gt;
&lt;/j:CardPrimaryContent&gt;
&lt;j:CardActions itemsHorizontalAlign=&quot;itemsRight&quot; itemsVerticalAlign=&quot;itemsCentered&quot;&gt;
&lt;j:BarSection width=&quot;50%&quot;&gt;
&lt;!-- Here will go the ToggleButton --&gt;
&lt;/j:BarSection&gt;
&lt;j:BarSection width=&quot;50%&quot; itemsHorizontalAlign=&quot;itemsRight&quot;&gt;
&lt;!-- Here will go the Slider --&gt;
&lt;/j:BarSection&gt;
&lt;/j:CardActions&gt;
&lt;/j:Card&gt;
</code></pre><p>With this code in place we can…</p><h2>Create the bottle</h2><p>We use SVG graphics to assemble the flask, and <strong>ActionScript 3</strong> code using the powerful <strong>Flash drawing API</strong> to create and manage the liquid. We're using both to show you both options so you have more weapons in your arsenal.</p><p>For the flask, I created three SVG files using a design tool. You can use whatever tool you prefer to draw vector art and export it in SVG format. I used <a href="https://affinity.serif.com/">Affinity Designer</a> software to create it since I think it's one of the best professional and modern tools available today. But many other free, open source and commercial options are available, so choose whatever you want.</p><p>The flask's three files are: A <strong>mask</strong>, a <strong>shade</strong> (with some reflections and gradients) and the <strong>main flask shape</strong>. I loaded the files with the <strong>svg:Image</strong> Royale component. Then I added a red indicator line coded In SVG directly in Royale to show that option with <strong>svg:Rect</strong>. Finally the fluid uses the <strong>UIGraphicsBase</strong> class that lets you work with the Flash drawing API.</p><p>I added all the parts to a Jewel <strong>Container</strong> so I can position them in relation to each other as layers. The Container clips the content so things that fall outside the container boundaries are hidden.</p><p>You can see all the pieces in perspective in the following image:</p><p><img src="/img/blog/bottle-layers-perspective.png" alt=""></p><p>Here is the final code of the <strong>Container</strong> that composes all the graphic parts:</p><pre><code class="language-mxml">&lt;j:Container localId=&quot;fgShape&quot; width=&quot;400&quot; height=&quot;500&quot;&gt;
&lt;!-- liquid --&gt;
&lt;js:UIGraphicsBase localId=&quot;bgShape&quot; width=&quot;400&quot; height=&quot;500&quot;/&gt;
&lt;!-- rule --&gt;
&lt;j:Group&gt;
&lt;svg:Rect localId=&quot;rule&quot; x=&quot;180&quot; y=&quot;{bgShape.height - rule.height}&quot; width=&quot;6&quot; height=&quot;350&quot;&gt;
&lt;svg:fill&gt;
&lt;js:SolidColor color=&quot;#ff0000&quot; alpha=&quot;.5&quot;/&gt;
&lt;/svg:fill&gt;
&lt;/svg:Rect&gt;
&lt;/j:Group&gt;
&lt;!-- fill mask --&gt;
&lt;svg:Image src=&quot;assets/bottle-mask.svg&quot; width=&quot;400&quot; height=&quot;500&quot;/&gt;
&lt;!-- inner shade --&gt;
&lt;svg:Image src=&quot;assets/bottle-shade.svg&quot; width=&quot;400&quot; height=&quot;500&quot;/&gt;
&lt;!-- main shape --&gt;
&lt;svg:Image src=&quot;assets/bottle-main.svg&quot; width=&quot;400&quot; height=&quot;500&quot;/&gt;
&lt;/j:Container&gt;
</code></pre><p>Notice that the fluid is declared first so the other shapes can hide the fluid that is outside the flask shape.</p><h2>Fluid controls</h2><p>To provide some interactivity we add a <strong>ToogleButton</strong> and an <strong>HSlider</strong>. The button lets you show and hide the indicator line; move the slider to change the fluid level from empty to full.</p><p>The <strong>ToogleButton</strong> has the following code:</p><pre><code class="language-mxml">&lt;j:ToggleButton localId=&quot;ruleVisibility&quot;
outlined=&quot;true&quot; emphasis=&quot;emphasized&quot;
text=&quot;Hide Rule&quot; selectedText=&quot;Show Rule&quot; selected=&quot;true&quot;&gt;
&lt;j:icon&gt;
&lt;js:ToggleFontIcon text=&quot;{MaterialIconType.VISIBILITY_OFF}&quot; selectedText=&quot;{MaterialIconType.VISIBILITY}&quot; material=&quot;true&quot;/&gt;
&lt;/j:icon&gt;
&lt;/j:ToggleButton&gt;
</code></pre><p>It uses an outlined style with emphasized coloring, and <a href="https://www.material.io/resources/icons/?style=baseline">material icons</a> and texts for both selected and unselected states.</p><h2>Show and Hide the indicator with binding</h2><p>We control the visibility of the red indicator line with the <strong>data binding</strong> Royale feature:</p><p>First add <strong>ApplicationDataBinding</strong> to the application beads to make Royale support binding at that level (Remember that Royale is <a href="https://apache.github.io/royale-docs/features/payg">PAYG</a>, so we only add code when it is really necessary instead of adding lots of code that you probably will never use to every component).</p><p>Then add the binding to the <strong>Group</strong> that holds the rule.</p><pre><code class="language-mxml">&lt;!-- rule --&gt;
&lt;j:Group visible=&quot;{ruleVisibility.selected}&quot;&gt;
</code></pre><p>When you run the application, click the button to show and hide the red indicator.</p><h2>Add the slider</h2><p>We finish the action controls part by adding a label and a slider in the last <strong>BarSection</strong> of the <strong>CardActions</strong>. The slider lets you change the fluid level.</p><pre><code class="language-mxml">&lt;j:Label text=&quot;Slide to fill&quot;/&gt;
&lt;j:HSlider localId=&quot;slider&quot; value=&quot;0&quot; minimum=&quot;0&quot; maximum=&quot;500&quot;/&gt;
</code></pre><h2>Drawing the fluid</h2><p>Using the drawing API in Royale is easy, and well-supported by both <strong>JavaScript</strong> and <strong>SWF</strong>. We get the <strong>Graphics</strong> instance of the <strong>UIGraphicsBase</strong> object in the following way:</p><pre><code class="language-as3">var g:Graphics = Graphics.getInstanceFor(bgShape);
</code></pre><p>Now we can use the graphics object to invoke drawing functions like <strong>moveTo</strong>, <strong>lineTo</strong>, and more.</p><p>To draw the fluid we use the following function using fills, lines and quadratic bezier curves:</p><pre><code class="language-as3">/**
* Draw the liquid to fill the bottle
*/
private function drawLiquid(g:Graphics, color:Number, alpha:Number, x:int, y:int, width:int, height:int, wave:int):void {
if(y &gt; height)
y = height;
g.beginFill(color, alpha);
g.moveTo(x, height);
g.lineTo(x, y);
g.curveTo(width / 4, y - wave, width / 2, y);
g.lineTo(width / 2, y)
g.curveTo(width * 3 / 4, y + wave, width, y);
g.lineTo(width, height);
g.lineTo(x, height);
g.endFill();
}
</code></pre><p>Then to join all the pieces we add a <strong>valueChange</strong> event handler to the <strong>HSlider</strong>:</p><pre><code class="language-mxml">&lt;j:HSlider localId=&quot;slider&quot; value=&quot;0&quot; minimum=&quot;0&quot; maximum=&quot;500&quot; valueChange=&quot;changeFill(event)&quot;/&gt;
</code></pre><p>The <strong>changeFill</strong> function is the following:</p><pre><code class="language-as3">/**
* Fill the bottle
*/
private function changeFill(event:ValueChangeEvent):void {
var g:Graphics = Graphics.getInstanceFor(bgShape);
var newHeight:Number = transformValueFromRange(slider.value, slider.minimum, slider.maximum, 0, rule.height);
var newY:Number = fgShape.height - newHeight;
g.clear();
drawLiquid(g, liquidColor, .5, 0, newY, 400, 500, -15);
drawLiquid(g, liquidColor, 1, 0, newY, 400, 500, 30);
}
</code></pre><p>When we change the <strong>HSlider</strong> position, the code calls the function, gets the graphic object, calculates the new height value based on the current container height (transforming ranges), clears all drawings and redraws two different liquids with some displacement on X and change on the wave length with the new values.</p><p>And that's all! I hope you like this drawing feature in Royale. You'll be able to do many creative things in your Royale applications with it!</p><p>As always, enjoy!</p><h2>Where to go from here</h2><ul><li><a href="https://apache.github.io/royale-docs/features/data-binding">Apache Royale Data Binding documentation page</a></li><li><a href="https://apache.github.io/royale-docs/component-sets/jewel">Apache Royale Jewel UI Set documentation page</a></li><li><a href="https://apache.github.io/royale-docs/component-sets/jewel/hslider">Jewel HSlider Royale Docs page</a></li><li><a href="https://apache.github.io/royale-docs/component-sets/jewel/card">Jewel Card Royale Docs page</a></li></ul><p>The result of this code snippet is the following:</p><iframe width="100%" height="800" src="/blog-examples/BE0014_Working_with_vector_graphics/index.html"></iframe><p>(We're using an iframe to host the actual results of this example compilation. To see the example in a separate window click <a href="/blog-examples/BE0014_Working_with_vector_graphics/index.html" target="_blank">this link</a>.)</p><p>Full project with source code can be found <a href="https://github.com/apache/royale-asjs/tree/develop/examples/blog/BE0014_Working_with_vector_graphics">here</a>:</p><p><a class="btn btn-download" href="https://github.com/apache/royale-asjs/tree/develop/examples/blog/BE0014_Working_with_vector_graphics"><i class="fa fa-download"></i> Project Source Code</a></p></article></div></div><footer class="footer"><div class="footer-row"><div class="footer-column"><ul class="footer-list"><li class="apacheroyale"><a href="/">Apache Royale</a></li><li><a href="/">Home</a></li><li><a href="/features">Features</a></li><li><a href="/download">Download</a></li><li><a href="/ides">IDEs and Editors</a></li><li><a href="/showcase">Showcase</a></li><li><a href="/blog">Blog</a></li><li><a href="/team">Team</a></li><li><a href="/thanks-to">Thanks To</a></li><li><a href="https://apache.org/logos/#royale"><i class="fa fa-external-link-square"></i> Logos</a></li><li><a href="https://www.apache.org/licenses/"><i class="fa fa-external-link-square"></i> Apache License v2.0</a></li></ul></div><div class="footer-column"><ul class="footer-list"><li class="documentation"><a href="/docs">Documentation</a></li><li><a href="https://apache.github.io/royale-docs/get-started">Get Started</a></li><li><a href="/docs">Docs</a></li><li><a href="/asdoc">API Reference</a></li><li><a href="https://github.com/apache/royale-asjs/wiki"><i class="fa fa-github"></i>Wiki</a></li><li><a href="https://stackoverflow.com/questions/tagged/apache-royale"><i class="fa fa-stack-overflow"></i> StackOverFlow Tag</a></li></ul><ul class="footer-list"><li class="community"><a href="/get-involved">Community</a></li><li><a href="/get-involved">Get Involved</a></li><li><a href="/mailing-lists">Mailing Lists</a></li><li><a href="/faq">FAQ</a></li></ul><ul class="footer-list"><li class="development"><a href="/source-code">Development</a></li><li><a href="https://github.com/apache/royale-asjs/wiki/Apache-Royale-Source-Code-Repositories"><i class="fa fa-github"></i> Github</a></li><li><a href="https://github.com/apache/royale-asjs/issues"><i class="fa fa-github"></i> Issues</a></li><li><a href="/source-code"><i class="fa fa-code"></i> Source Code</a></li></ul></div><div class="footer-column"><ul class="footer-list"><li class="social_t">Social</li><li><a href="https://twitter.com/apacheroyale"><i class="fa fa-twitter"></i> Twitter</a></li><li><a href="https://facebook.com/ApacheRoyaleSDK/"><i class="fa fa-facebook"></i> Facebook</a></li><li><a href="https://www.linkedin.com/groups/12118437"><i class="fa fa-linkedin"></i> LinkedIn</a></li><li><a href="/feed/index.xml"><i class="fa fa-rss"></i> RSS</a></li></ul><ul class="footer-list"><li class="apache"><a href="https://www.apache.org/">Apache</a></li><li><a href="https://www.apache.org/"><i class="fa fa-external-link-square"></i> Apache</a></li><li><a href="https://www.apache.org/foundation/contributing.html"><i class="fa fa-external-link-square"></i> Donations</a></li><li><a href="https://www.apache.org/events/current-event"><i class="fa fa-external-link-square"></i> Events</a></li><li><a href="https://www.apache.org/foundation/sponsorship.html"><i class="fa fa-external-link-square"></i> Sponsorship</a></li><li><a href="https://www.apache.org/foundation/thanks.html"><i class="fa fa-external-link-square"></i> Thanks</a></li><li><a href="https://www.apache.org/security/"><i class="fa fa-external-link-square"></i>Security</a></li></ul></div><div class="aboutusdiv"><p class="aboutus">About Us</p><p class="aboutus_p"><img class="aboutus-logo" src="/img/apache-royale-logo-footer-circle-grey.svg"><a href="/" class="aboutus_a">Apache Royale™</a> is a highly productive open source application technology for building expressive frontend applications that outputs to different formats and deploy consistently on all major browsers, desktops and devices.</p><p><img class="aboutus-apache-logo" src="/img/Apache_PoweredBy.svg"> <a href="/" class="aboutus_a">Apache Royale™</a>, <a href="https://www.apache.org" class="aboutus_a">Apache™</a> and the <a href="https://www.apache.org/foundation/press/kit/" class="aboutus_a">Apache feather logo™</a> are trademarks of The Apache Software Foundation. All other marks mentioned may be trademarks or registered trademarks of their respective owners. Read more about our privacy policy on our <a href="/privacy-policy">Privacy Policy page</a>.</p></div></div><div class="asf">Copyright &copy; 2017-2022 <a href="https://www.apache.org">The Apache Software Foundation</a>, Licensed under the <a href="https://www.apache.org/licenses/LICENSE-2.0">Apache License, Version 2.0</a></div></footer></body></html>