Table of Contents
 OpenLaszlo provides capability to do two-dimensional graphics. You use procedural code in
                  a <drawview> element to draw lines and fill in shapes. In
                  this tutorial we'll look at some of the key parts of the API and show some interesting effects
                  that you can get with a few lines of code. 
         
The Web Hypertext Application Technology Working Group ("WHATWG") is "a loose unofficial collaboration of Web browser manufacturers and interested parties who wish to develop new technologies designed to allow authors to write and deploy Applications over the World Wide Web." This group published a specification for drawing (which can be found here).
 OpenLaszlo implements a subset of the whatwg drawing APIs. For a
                        discussion of where OpenLaszlo differs from the full whatwg
                        specification, please see the LZX Reference
                              Manual. 
            
 The <drawview> class extends the
                           <view> class. Thus, it inherits all the
                           <view> properties; a
                        <drawview> tag creates a rectangular view. At first glance
                        a view seems like just another view:
            
Example 13.1. view and drawview
<canvas width="100%" height="75" proxied="false">
      <simplelayout spacing="5" axis="x"/>
      <view height="50" width="50" bgcolor="red"/>
      <drawview height="50" width="50" bgcolor="blue"/>
    </canvas>
<!-- * X_LZ_COPYRIGHT_BEGIN ***************************************************
* Copyright 2007, 2008 Laszlo Systems, Inc.  All Rights Reserved.                   *
* Use is subject to license terms.                                            *
* X_LZ_COPYRIGHT_END ****************************************************** -->
                  
| ![[Note]](images/note.png) | Note | 
|---|---|
| Previously,  | 
 There are no additional tag attributes in the drawview class
                        beyond those of view. However, drawview has four
                        attributes in addition to those it inherits: 
            
fillStyle
globalAlpha
lineWidth
strokeStyle
 These attributes can be accessed and manipulated by procedural (script) code inside
                           <method> tags inside a
                           <drawview> element. The drawview class has ten methods
                        associated with it. We'll take a look at them below, after explaining some more concepts. 
            
To draw a line shape (or "path"), you position a logical pen at a starting point and then move it sequentially to x and y coordinates connecting points either by straight or quadratic lines. This line remains invisible until you "stroke" it. When you stroke a path you apply to it the defined line width and style, thereby making it visible.
For example, this code produces nothing visible:
Example 13.2. invisble drawing
    <canvas height="200" proxied="false">
      <drawview height="50" width="50">
         <handler name="oncontext">
         this.moveTo(100,100)
         this.lineTo(200,100)
         this.quadraticCurveTo(120, 200, 300, 100)
        </handler>
      </drawview>
    </canvas>
 But by adding the line this.stroke() we produce the following: 
               
Example 13.3. Stroking the line
<canvas width="100%" height="200" proxied="false">
  <drawview height="200" width="200">
    <handler name="oncontext">
     this.moveTo(100,100);
     this.lineTo(200,100);
     this.quadraticCurveTo(120, 200, 300, 100);
     this.stroke();
    </handler>
  </drawview>
</canvas>
<!-- * X_LZ_COPYRIGHT_BEGIN ***************************************************
* Copyright 2008 Laszlo Systems, Inc.  All Rights Reserved.                   *
* Use is subject to license terms.                                            *
* X_LZ_COPYRIGHT_END ****************************************************** -->
                      The closePath method
                              draws a line back to the beginning of the current path: 
               
Example 13.4. Stroking the line
<canvas width="100%" height="200" proxied="false">
      <drawview height="200" width="200">
        <handler name="oncontext">
         this.moveTo(100,100);
         this.lineTo(200,100);
         this.quadraticCurveTo(120, 200, 300, 100)
         this.closePath()
         this.stroke()
        </handler>
      </drawview>
    </canvas>
<!-- * X_LZ_COPYRIGHT_BEGIN ***************************************************
* Copyright 2008 Laszlo Systems, Inc.  All Rights Reserved.                   *
* Use is subject to license terms.                                            *
* X_LZ_COPYRIGHT_END ****************************************************** -->
                      Now that we have a closed shape, we can fill it. First we define a
                                 fillStyle, and then we fill the shape. 
               
Example 13.5. fillstyle
<canvas width="100%" height="200" proxied="false">
      <drawview height="200" width="200">
        <handler name="oncontext">
         this.moveTo(100,100);
         this.lineTo(200,100);
         this.quadraticCurveTo(120, 200, 300, 100)
         this.stroke()
         //fillSytles are hex numbers representing color. 
         this.fillStyle = 0xff00ff
         this.fill()
        </handler>
      </drawview>
    </canvas>
<!-- * X_LZ_COPYRIGHT_BEGIN ***************************************************
* Copyright 2008 Laszlo Systems, Inc.  All Rights Reserved.                   *
* Use is subject to license terms.                                            *
* X_LZ_COPYRIGHT_END ****************************************************** -->
                      Note that if you don't close a path but call the fill() method,
                              the path will be closed implicitly. Please consult the reference page for particulars.
                           
               
 The globalAlpha attribute is used to set the opacity of lines and
                              fills. It takes a value between zero (transparent) and one (opaque). 
               
Example 13.6. Using globalAlpha
<canvas width="100%" height="200" proxied="false">
      <drawview height="200" width="200">
        <handler name="oncontext">
         this.moveTo(100,100);
         this.lineTo(200,100);
         this.quadraticCurveTo(120, 200, 300, 100)
         this.stroke()
         this.fillStyle = 0xff00ff
         this.globalAlpha= .3
         this.fill()
        </handler>
      </drawview>
    </canvas>
<!-- * X_LZ_COPYRIGHT_BEGIN ***************************************************
* Copyright 2008 Laszlo Systems, Inc.  All Rights Reserved.                   *
* Use is subject to license terms.                                            *
* X_LZ_COPYRIGHT_END ****************************************************** -->
                      Remember that the code here is procedural, so alpha values apply to
                                 fillStyles and lineStyles that are in effect at
                              the time that a stroke() or fill() method is
                              called. In the above example, the globalAlpha value is 1 (the
                              default) when the line is stroked and .3 when the color is filled in. 
               
 A fillStyle can be a color gradient, that is, a pattern that
                              blends colors over its area. To use a gradient, first create it using the appropriate
                              (linear or radial) constructor function, then set the fillStyle to be
                              the gradient. A gradient is an object of the type lz.CanvasGradient;
                              you define the parameters of the gradient by using methods such as
                              addColorStop on it. addColorStop takes two
                              arguments: the number of the stop, and the color. 
               
Example 13.7. Adding a gradient
<canvas width="100%" height="200" proxied="false">
      <drawview height="200" width="200">
        <handler name="oncontext">
         this.moveTo(100,100);
         this.lineTo(200,100);
         this.quadraticCurveTo(120, 200, 300, 100)
         this.stroke()
         //the gradient starts at the x and y where the curved line starts
         var g = this.createLinearGradient(200,100, 150, 300)
         //opacity is 0 -- the fill is invisible
         this.globalAlpha = 0;
         //starting color is black
         g.addColorStop(0, 0x000000);
         //now the opacity is set to opaque
         this.globalAlpha = 1;
         //the gradient goes from black to purple
         g.addColorStop(1, 0xff00ff);
         this.fillStyle = g;
         this.fill();
        </handler>
      </drawview>
    </canvas>
<!-- * X_LZ_COPYRIGHT_BEGIN ***************************************************
* Copyright 2008 Laszlo Systems, Inc.  All Rights Reserved.                   *
* Use is subject to license terms.                                            *
* X_LZ_COPYRIGHT_END ****************************************************** -->
                     To get a sense of what gradients look like, try varying the parameters of the ending x and y.
 Also, remember that drawviews have background colors. You can use
                              them in conjunction with gradients and alpha values: 
               
Example 13.8. Backgrounds and gradients
<canvas width="100%" height="200" proxied="false">
      <drawview height="150" width="300" bgcolor="blue">
        <handler name="oncontext">
         this.moveTo(100,100);
         this.lineTo(200,100);
         this.quadraticCurveTo(120, 200, 300, 100)
         this.stroke()
         var g = this.createLinearGradient(200,100, 150, 300)
         this.globalAlpha = 0;
         g.addColorStop(0, 0xffffff);
         this.globalAlpha = 1;
         g.addColorStop(.3, 0xff00ff);
         this.fillStyle = g;
         this.fill();
        </handler>
      </drawview>
    </canvas>
<!-- * X_LZ_COPYRIGHT_BEGIN ***************************************************
* Copyright 2008 Laszlo Systems, Inc.  All Rights Reserved.                   *
* Use is subject to license terms.                                            *
* X_LZ_COPYRIGHT_END ****************************************************** -->
                     The gradient can be linear or radial (for details, see the Reference).
 We've said that drawing a line is like moving a pen. So, how do you pick up the pen
                              in order to move it to another spot on the canvas? Use the beginPath method. 
               
Example 13.9. beginPath
<canvas width="100%" height="200" proxied="false">
      <drawview height="200" width="200">
        <handler name="oncontext">
         this.moveTo(100,100);
         this.lineTo(200,100);
         this.quadraticCurveTo(120, 200, 300, 100)
         this.closePath()
         this.stroke()
         this.beginPath()
         this.moveTo(200,000);
         this.lineTo(100,200);
         this.quadraticCurveTo(120, 200, 300, 100)
         this.closePath()
         this.stroke()
        </handler>
      </drawview>
    </canvas>
<!-- * X_LZ_COPYRIGHT_BEGIN ***************************************************
* Copyright 2008 Laszlo Systems, Inc.  All Rights Reserved.                   *
* Use is subject to license terms.                                            *
* X_LZ_COPYRIGHT_END ****************************************************** -->
                      The clear method wipes the slate clean, so to speak. 
               
Example 13.10. Clearing the view
<canvas width="100%" height="200" proxied="false">
        <drawview height="200" width="200">
            <handler name="oncontext">
            this.moveTo(40,40)
            this.lineTo(80,40)
            this.lineTo(80, 80)
            this.lineTo(40,90)
            this.closePath()
            this.stroke()
    
            this.fillStyle = 0xff00ff;
            this.fill()
            </handler>
            <button onclick="parent.clear()" text="clear"/>
       </drawview>
    </canvas>
<!-- * X_LZ_COPYRIGHT_BEGIN ***************************************************
* Copyright 2008 Laszlo Systems, Inc.  All Rights Reserved.                   *
* Use is subject to license terms.                                            *
* X_LZ_COPYRIGHT_END ****************************************************** -->
                      Although the <drawview> API is procedural, it's simple to blend the procedural drawing
                        API with the declarative LZX style. The following little program illustrates this. The
                           r attribute is modulated in by an <animator> element; when r changes, the redraw method is evoked. 
            
Example 13.11. Drawview with animator
<canvas width="100%" height="300" debug="false">
    <class name="circle" extends="drawview" width="200" height="200">
        <attribute name="circlecolor" type="color" value="white"/>
        <attribute name="r" value="100"/>
        <handler name="oncontext">
          this.redraw();
        </handler>
        <handler name="onr">
          this.redraw();
        </handler>
        <method name="redraw"><![CDATA[
            if (! this.context) return;
            this.clear();
            this.beginPath();
            this.moveTo(x+r, y);
            var a = Math.tan(22.5 * Math.PI/180);
            for (var angle = 45; angle<=360; angle += 45) {
                // endpoint:
                var endx = r*Math.cos(angle*Math.PI/180);
                var endy = r*Math.sin(angle*Math.PI/180);
                // control:
                // (angle-90 is used to give the correct sign)
                var cx =endx + r*a*Math.cos((angle-90)*Math.PI/180);
                var cy =endy + r*a*Math.sin((angle-90)*Math.PI/180);
                this.quadraticCurveTo(cx+x, cy+y, endx+x, endy+y);
            }
          
            var g = this.createLinearGradient(0, 0, x+r, y+r)
            this.globalAlpha = 1;
            g.addColorStop(0, 0xffffff);
            this.globalAlpha = 0;
            g.addColorStop(1, this.circlecolor);
            this.fillStyle = g;
            this.fill()
            this.globalAlpha = 1;
            this.linewidth= 5;
            this.stroke();
        
        ]]></method>
    </class>
    <circle r="50" x="50" y="50" circlecolor="blue"/>
    <circle x="50" y="50" circlecolor="teal">
       <animatorgroup process="sequential" repeat="Infinity">
        <animator attribute="r" from="20" to="0" duration="3000"/>
        <animator attribute="r" from="0" to="20" duration="3000"/>
      </animatorgroup>
    </circle>
     
</canvas>
<!-- * X_LZ_COPYRIGHT_BEGIN ***************************************************
* Copyright 2008, 2010 Laszlo Systems, Inc.  All Rights Reserved.                   *
* Use is subject to license terms.                                            *
* X_LZ_COPYRIGHT_END ****************************************************** -->
                  OpenLaszlo developers have already used the drawview API to create a color chooser and a paint program. See what you can do. Have fun!
Copyright © 2002-2010 Laszlo Systems, Inc. All Rights Reserved. Unauthorized use, duplication or distribution is strictly prohibited. This is the proprietary information of Laszlo Systems, Inc. Use is subject to license terms.