Mobile Web

The ShapeEditor sample application demonstrates how you can create and edit various shapes using SVG (Scalable Vector Graphics).

For information on creating the sample application project in the IDE, see Creating Sample Applications.

The following figure illustrates the main screens of the ShapeEditor.

Figure: ShapeEditor screens

ShapeEditor screens

The application opens with a blank SVG canvas with the action buttons at the bottom:

  • Click Shape to select a specific shape and the size of the shape.
  • Click Color to select the color of the shape from a color picker.
  • Click Clear to remove all the shapes on the SVG canvas.

Source Files

You can create and view the sample application project including the source files in the IDE.

File name Description
config.xml This file contains the application information for the platform to install and launch the application, including the view mode and the icon to be used in the device menu.
css/style.css This file contains CSS styling for the application UI.
index.html This is a starting file from which the application starts loading. It contains the layout of the application screen.
js/main.js This file contains the code for handling the main application functionalities.

Implementation

To implement SVG features:

  1. Use graphic elements to create various shapes, and define attributes, such as location, size, and color of the shapes:

    <svg class="shape-svg" viewBox="0 0 200 200">
       <rect class="shape-element" id="select-rect" width="200" height="200" />
    </svg>
    <svg class="shape-svg" viewBox="0 0 200 200">
       <ellipse class="shape-element" id="select-ellipse" cx="100" cy="100" rx="100" ry="100" />
    </svg>
    <svg class="shape-svg" viewBox="0 0 200 200">
       <polygon class="shape-element" id="select-triangle" points="100,0 0,200 200,200" />
    </svg>
  2. Handle touch events:
    • The touchStartHandler() method is called when the touchstart event is triggered. It uses the changedTouches array event property to access the data of the current touch object. The current touch data is saved to the drawPath object, which is an associative array indexed with the identifier parameter of the current touch object.

      function bindEvents() 
      {
         svgBoard.addEventListener('touchstart', touchStartHandler, false);
      }
      
      function touchStartHandler(e) 
      {
         var touch = e.changedTouches[0];
      
         drawPath[touch.identifier] = touch;
         timer = setTimeout(longtouchHandler, touchDuration);
      }
    • The touchEndHandler() method is called when the touchend event is triggered, and it adds a new shape into the SVG board. The pageX and pageY properties of the touch object represent the coordinates of the touch point. After a new shape is inserted, the method resets the drawPath object to remove the information about the touch that no longer exists.

      function bindEvents() 
      {
         svgBoard.addEventListener('touchend', touchEndHandler, false);
      }
      
      function touchEndHandler(e) 
      {
         var touch = e.changedTouches[0],
            x = 0,
            y = 0;
      
         /* Add a new shape into the SVG board */
         if (!isLongTouch) 
         {
            x = touch.pageX - content.offsetLeft - (0.25 * shapeSize * 100);
            y = touch.pageY - content.offsetTop - (0.25 * shapeSize * 100);
      
            innerHtmlSvg("svg-board", "shape" + shapeIndex, svgShapeTag, shapeSize, x, y);
            delete drawPath[touch.identifier];
         }
      
         /* Stop short touches from firing the event */
         isLongTouch = 0;
         if (timer) 
         {
            clearTimeout(timer);
         }
      }
      
  3. Since SVG is essentially graphics defined in XML format, the innerHtml property is not supported in the svg elements.

    A workaround method is used for adding new svg elements into the SVG board:

    function innerHtmlSvg(boardId, shapeId, shapeTag, shapeRatio, traslateX, traslateY) 
    {
       var tempDiv = document.createElement('div'), /* Create a dummy tempDiv */
           /* Wrap the svg string to a svg object */
           svgFragment = '<svg>' + shapeTag + '</svg>'; 
    
       tempDiv.innerHTML = svgFragment; /* Add all svg to the tempDiv */
       Array.prototype.slice.call(tempDiv.childNodes[0].childNodes).forEach(function(el) 
       {
          document.querySelector('#' + boardId).appendChild(el);
       }); /* Copy the children of the tempDiv's SVG to the actual body's SVG */
    }