Understanding the configurable origin-based coordinate system
GCanvas uses a top-left based coordinate system by default, matching web conventions
(CSS, DOM, and standard Canvas API). The origin property allows you to configure the
pivot point for positioning, rotation, and scaling.
| Origin | Behavior | Use Case |
|---|---|---|
origin: "top-left" (default) |
(x, y) = top-left corner | UI elements, layouts, web-style positioning |
origin: "center" |
(x, y) = center point | Game objects, rotation, scaling |
originX: 0.5, originY: 1 |
Bottom-center | Sprites standing on ground |
originX: 1, originY: 0 |
Top-right corner | Right-aligned elements |
The origin property defines the pivot point of a shape. It accepts either a string
shorthand or explicit originX/originY values (0-1 normalized).
| Value | originX | originY | Description |
|---|---|---|---|
"top-left" |
0 | 0 | Default - position is top-left corner |
"center" |
0.5 | 0.5 | Position is center point |
"top-center" |
0.5 | 0 | Top edge, horizontally centered |
"bottom-center" |
0.5 | 1 | Bottom edge, horizontally centered |
"top-right" |
1 | 0 | Top-right corner |
"bottom-left" |
0 | 1 | Bottom-left corner |
"bottom-right" |
1 | 1 | Bottom-right corner |
// Top-left origin (default) - x,y is the top-left corner
const rect1 = new Rectangle({
x: 100, y: 100,
width: 80, height: 60,
color: "#0f0"
// origin defaults to "top-left" (originX: 0, originY: 0)
});
// Center origin - x,y is the center point
const rect2 = new Rectangle({
x: 100, y: 100,
width: 80, height: 60,
color: "#0ff",
origin: "center" // shorthand for originX: 0.5, originY: 0.5
});
// Custom origin - bottom-center for sprites
const sprite = new Rectangle({
x: 100, y: groundY,
width: 32, height: 48,
originX: 0.5,
originY: 1 // feet at x,y position
});
The origin point is the pivot for all transformations: positioning, rotation, and scaling all happen relative to the origin.
// Same position, different origins = different rotation behavior
// Rotates around top-left corner
const rect1 = new Rectangle({
x: 150, y: 100,
width: 60, height: 40,
rotation: Math.PI / 4,
origin: "top-left"
});
// Rotates around center
const rect2 = new Rectangle({
x: 300, y: 100,
width: 60, height: 40,
rotation: Math.PI / 4,
origin: "center"
});
// Rotates around bottom-center
const rect3 = new Rectangle({
x: 450, y: 100,
width: 60, height: 40,
rotation: Math.PI / 4,
origin: "bottom-center"
});
Scaling expands or contracts from the origin point. This is especially important for animations and hover effects.
// Hover effect: scale from center (natural feel)
button.on('hover', () => {
button.scaleX = 1.1;
button.scaleY = 1.1;
});
// With origin: "center", button grows equally in all directions
// Scale from bottom (character jumping)
character.originY = 1; // bottom-center
character.scaleY = 0.8; // squash
// Character compresses toward the ground
GCanvas originally used center-based positioning. The new top-left default matches web conventions better. Here's how to migrate:
origin: "center" to shapes that need center-based positioning.
// x,y was the center
const rect = new Rectangle({
x: 100, y: 100,
width: 80, height: 60
});
// Center was at (100, 100)
// Corners at (60,70) to (140,130)
// x,y is now the top-left
const rect = new Rectangle({
x: 100, y: 100,
width: 80, height: 60,
origin: "center" // Add this!
});
// Now behaves like old version
| Old Code | New Code |
|---|---|
new Circle(50, { x: 100, y: 100 }) |
new Circle(50, { x: 100, y: 100, origin: "center" }) |
new Rectangle({ x: 100, y: 100, ... }) |
new Rectangle({ x: 100, y: 100, ..., origin: "center" }) |
| Shapes in Groups | Add origin: "center" to each shape |
TextShape uses the standard align and baseline properties
which work independently from the origin system.
// Text alignment is controlled separately
const text = new TextShape("Hello World", {
x: 200, y: 100,
color: "#0f0",
font: "16px monospace",
align: "center", // horizontal: left, center, right
baseline: "middle" // vertical: top, middle, bottom
});
// Origin still affects transforms (rotation, scale)
text.origin = "center";
text.rotation = 0.1; // Rotates around text center
For circles, the origin is based on the bounding box, not the visual circle. This ensures consistent behavior with other shapes.
// Circle origin uses bounding box
const circle = new Circle(30, {
x: 100, y: 100,
color: "#0f0",
origin: "center" // Center of bounding box = center of circle
});
// For top-left origin:
// (x,y) is top-left of the bounding box
// Circle center is at (x + radius, y + radius)
// Character sprite standing on ground
const player = new Sprite(this, {
x: groundX,
y: groundY,
originX: 0.5,
originY: 1 // Feet at position
});
// Jump animation - position is always feet location
player.y = groundY - jumpHeight;
// Button centered on screen
const button = new Button(this, {
x: this.width / 2,
y: this.height / 2,
origin: "center"
});
// Hover scale effect works naturally
button.on('hover', () => {
button.scaleX = button.scaleY = 1.1;
});
// Score at top-left
const score = new Text(this, "Score: 0", {
x: 10, y: 10,
origin: "top-left" // Default
});
// Lives at top-right
const lives = new Text(this, "Lives: 3", {
x: this.width - 10,
y: 10,
origin: "top-right"
});
| Use Case | Recommended Origin | Why |
|---|---|---|
| UI layouts | "top-left" |
Matches CSS/web conventions |
| Game objects | "center" |
Natural rotation/scaling pivot |
| Characters | originX: 0.5, originY: 1 |
Feet stay on ground |
| Buttons/hover effects | "center" |
Scale grows in all directions |
| Right-aligned UI | "top-right" |
Easy to anchor to right edge |
| 3D objects | "center" |
Rotation around center |