Getting Started
Vector graphics—the use of geometric "primitives" orshapes—is a time-honored way of creating images by using mathematical formulae to describe how to render something;unlike raster-based images (such as PNG and JPG files), which use a two dimensional array of colors. Oftenvector-based images (such as those made with a program like Illustrator or InkScape) are more efficient becausethey are not rendered until the viewing device interprets the math behind it.
The Dojo Toolkit features dojox/gfx
(GFX), a vector graphic creation library capable of creating extremely powerfulvector graphics. Features of GFX include:
- Works on almost all devices
- Can render images (including charts) with SVG, VML, Silverlight, or Canvas.
- Evaluates the client and uses whichever renderer will work most efficiently
- Allows for the developer to decide which renderer to use
- Allows for linear and radial gradients within shapes (and even works in Internet Explorer!)
Creating an Image using dojox/gfx
The following is a general timeline for the creation of most vector graphics:
- Create the surface (or "canvas")
- Create the shapes (paths, lines, rectangles, text, etc.)
- Create groups of shapes (grouping shapes together)
- Animate shapes or groups of shapes (transform, scale, etc.)
- Add shape events
Creating Shapes
With a surface created, the next step is creating shapes. GFX provides many shapes, including:
- Rect: A basic rectangle
- Circle: A basic circle
- Ellipse: A basic ellipse, more flexible than a circle
- Line: A basic line
- PolyLine: A multi-point line
- Image: The Image shape allows for loading of bitmap images
- Text: Allows for creation of text
- TextPath: A shape that flows text along an arbitrary path. TextPath properties are based on the text shape properties
- Path: Most versatile geometric shape, which can emulate all other geometric shapes
<!doctype html>
<html lang="en" dir="ltr">
<head>
<title>surface_basic_shape</title>
<link rel="stylesheet" href="dijit/themes/claro/claro.css" />
<style type="text/css">
body, html { font-family:helvetica,arial,sans-serif; font-size:90%; }
</style>
<script src="dojo/dojo.js" data-dojo-config="async: true, parseOnLoad:true"></script>
<script>
require(["dojox/gfx", "dojo/domReady!"], function(gfx) {
surface = gfx.createSurface("surfaceElement", 400, 400);
// Create a rectangle
surface.createRect({ x: 100, y: 50, width: 200, height: 100 })
.setFill("yellow")
.setStroke("blue");
// Add a circle
surface.createCircle({ cx: 100, cy: 300, r:50 })
.setFill("green")
.setStroke("pink");
// Now an ellipse
surface.createEllipse({ cx: 300, cy: 200, rx:50, r:25 })
.setFill("#fff")
.setStroke("#999");
// And a line
surface.createLine({ x1: 10, y1: 50, x2:400, y2:400 })
.setStroke("green");
// How about a polyline?
surface.createPolyline([
{x: 250, y: 250},
{x: 300, y: 300},
{x: 250, y: 350},
{x: 200, y: 300},
{x: 110, y: 250}
]).setStroke("blue");
// Add in an image
surface.createImage({
x:100, y:300, width: 123, height: 56, src: "../images/logo.png"
});
// With some text
surface.createText({ x: 64, y: 220, text: "Vector Graphics Rock!", align: "start" })
.setFont({ family: "Arial", size: "20pt", weight: "bold" }) //set font
.setFill("blue");
// And an advanced textpath
var textShape = surface.createTextPath({ text: "TextPath!" })
.moveTo(125, 70)
.lineTo(285, 20)
.setFont({ family: "Verdana", size: "2em" })
.setFill("black");
// And a simple path
surface.createPath("m100 100 100 0 0 100c0 50-50 50-100 0s-50-100 0-100z")
.setStroke("black");
});
</script>
</head>
<body class="claro">
<div id="surfaceElement"></div>
</body>
</html>
Shapes generated by dojox/gfx
also include numerous methods for modification. A few key methods include:
- applyTransform: Allows for transforming of a shape (scaling and skewing, for example)
- getFill/setFill: Get and set fill colors
- getStroke/setStroke: Get and set stroke colors
- moveToBack/moveToFront: Moves shapes based on "z-indexing"
<!doctype html>
<html lang="en" dir="ltr">
<head>
<title>surface_style_shape </title>
<link rel="stylesheet" href="dijit/themes/claro/claro.css" />
<style type="text/css">
body, html { font-family:helvetica,arial,sans-serif; font-size:90%; }
</style>
<script src="dojo/dojo.js" data-dojo-config="async: true, parseOnLoad:true"></script>
<script>
require(["dojox/gfx", "dojo/domReady!"], function(gfx) {
surface = gfx.createSurface("surfaceElement", 400, 400);
// Create a circle with a set "blue" color
surface.createCircle({ cx: 50, cy: 50, rx:50, r:25 }).setFill("blue");
// Crate a circle with a set hex color
surface.createCircle({ cx: 300, cy: 300, rx:50, r:25 }).setFill("#f00");
// Create a circle with a linear gradient
surface.createRect({ x: 180, y: 40, width: 200, height: 100 }).
setFill({ type:"linear",
x1:0,
y1:0, //x: 0=>0, consistent gradient horizontally
x2:0, //y: 0=>420, changing gradient vertically
y2:420,
colors: [
{ offset: 0, color: "#003b80" },
{ offset: 0.5, color: "#0072e5" },
{ offset: 1, color: "#4ea1fc" }
]
});
// Create a circle with a radial gradient
surface.createEllipse({
cx: 120,
cy: 260,
rx: 100,
ry: 100
}).setFill({
type: "radial",
cx: 150,
cy: 200,
colors: [
{ offset: 0, color: "#4ea1fc" },
{ offset: 0.5, color: "#0072e5" },
{ offset: 1, color: "#003b80" }
]
});
});
</script>
</head>
<body class="claro">
<div id="surfaceElement"></div>
</body>
</html>
The colors
array accepts objects with offset
and color
keys. The offset
property represents a number between 0 and 1, and the color
property represents the color at that offset. You may provide any number of colors
objects.
Setting a Stroke on a Shape
The setStroke
method styles the shape's stroke (like a border or outline). The setStroke
method accepts a color string (hex, named color, rgb, etc.) or an object with more specific stroke properties:
Properties may include:
- style: the style of the line (solid, dotted, dashed)
- width: the width of stroke in pixels
- color: the stroke's color
- cap: the shape of the end of the stroke
<!doctype html>
<html lang="en" dir="ltr">
<head>
<title>surface_stroke_shape </title>
<link rel="stylesheet" href="dijit/themes/claro/claro.css" />
<style type="text/css">
body, html { font-family:helvetica,arial,sans-serif; font-size:90%; }
</style>
<script src="dojo/dojo.js" data-dojo-config="async: true, parseOnLoad:true"></script>
<script>
require(["dojox/gfx", "dojo/domReady!"], function(gfx) {
var surface = gfx.createSurface("surfaceElement", 400, 400);
// Create a rectangle with a basic black border
surface.createRect({x: 100, y: 50, width: 200, height: 100 }).setStroke("#000");
// Create a circle with a 3-pixel dotted red border
surface.createCircle({ cx: 300, cy: 300, rx: 50, r: 25 }).setStroke({
style: "Dot", width: 3, cap: "round", color: "#f00"
});
// Create a circle with a 3-pixel dotted red border
surface.createCircle({ cx: 150, cy: 250, rx: 100, r: 50 }).setStroke({
style: "Dash", width: 3, cap: "butt", color: "#00f"
});
});
</script>
</head>
<body class="claro">
<div id="surfaceElement"></div>
</body>
</html>
Choosing a Font
Both the Text and TextPath shapes allow for a specific font family, size, and weight. Usage of setFont
is easy:
// Create the initial text, set the font to 20pt Arial Bold, and fill it blue
surface.createText({ x: 64, y: 220, text: "This is my text", align: "start"}).
setFont({ family: "Arial", size: "20pt", weight: "bold" }).
setFill("blue");
Grouping Shapes Together
Individual shapes may be "glued" together in groups, so that the shapes within a group can be treated like they are a single shape.Groups are especially important when animating related shapes and attaching events to said shapes. The best thing about using groups isthat they feature the same animation methods as individual shapes:
<!doctype html>
<html lang="en" dir="ltr">
<head>
<title>surface_grouping_shape </title>
<link rel="stylesheet" href="dijit/themes/claro/claro.css" />
<style type="text/css">
body, html { font-family:helvetica,arial,sans-serif; font-size:90%; }
</style>
<script src="dojo/dojo.js" data-dojo-config="async: true, parseOnLoad:true"></script>
<script>
require(["dojox/gfx", "dojo/domReady!"], function(gfx) {
var surface = gfx.createSurface("surfaceElement", 400, 400);
// Create a group
var group = surface.createGroup();
// Add a shape directly to the group instead of the surface
var rectShape = group.createRect({ x: 0, y: 0, width: 200, height: 100 })
.setFill("#0000ae");
});
</script>
</head>
<body class="claro">
<div id="surfaceElement"></div>
</body>
</html>
Shapes can also be added to the group at any time:
// Create the shape on the surface
var rectShape = shape.createRect({ x: 0, y: 0, width: 200, height: 100 })
.setFill("#0000ae");
// Move it to the group!
group.add(rectShape);
Groups are especially useful when creating moveable shapes:
// Require the resource
require("dojox/gfx", "dojox/gfx/Moveable", function(gfx, Moveable) {
// Make all shapes within the group move together!
new Moveable(group);
});
The above snippet allows users to click and hold any shape within the group to move every shape in the group around.