Skip to content
Permalink
Browse files

[giow] (0) Add ellipse support to canvas.

Affected topics: Canvas

git-svn-id: http://svn.whatwg.org/webapps@7025 340c8d12-0b0e-0410-8428-c7bf67bfef74
  • Loading branch information...
Hixie committed Mar 13, 2012
1 parent 5a344dd commit e25d3f909451285947de75dc56bdba2fad14692c
Showing with 665 additions and 116 deletions.
  1. +213 −38 complete.html
  2. +213 −38 index
  3. +239 −40 source

<header class=head id=head><p><a class=logo href=http://www.whatwg.org/><img alt=WHATWG height=101 src=/images/logo width=101></a></p>
<hgroup><h1 class=allcaps>HTML</h1>
<h2 class="no-num no-toc">Living Standard &mdash; Last Updated 10 March 2012</h2>
<h2 class="no-num no-toc">Living Standard &mdash; Last Updated 13 March 2012</h2>
</hgroup><dl><dt><strong>Web developer edition:</strong></dt>
<dd><strong><a href=http://developers.whatwg.org/>http://developers.whatwg.org/</a></strong></dd>
<dt>Multiple-page version:</dt>
void <a href=#dom-context-2d-quadraticcurveto title=dom-context-2d-quadraticCurveTo>quadraticCurveTo</a>(double cpx, double cpy, double x, double y);
void <a href=#dom-context-2d-beziercurveto title=dom-context-2d-bezierCurveTo>bezierCurveTo</a>(double cp1x, double cp1y, double cp2x, double cp2y, double x, double y);
void <a href=#dom-context-2d-arcto title=dom-context-2d-arcTo>arcTo</a>(double x1, double y1, double x2, double y2, double radius); <!-- see ARC-ORDER note below -->
void <a href=#dom-context-2d-arcto title=dom-context-2d-arcTo>arcTo</a>(double x1, double y1, double x2, double y2, double radiusX, double radiusY, double rotation); <!-- see ARC-ORDER note below -->
void <a href=#dom-context-2d-rect title=dom-context-2d-rect>rect</a>(double x, double y, double w, double h);
void <a href=#dom-context-2d-arc title=dom-context-2d-arc>arc</a>(double x, double y, double radius, double startAngle, double endAngle, optional boolean anticlockwise); <!-- see ARC-ORDER note below -->
void <a href=#dom-context-2d-arc title=dom-context-2d-arc>arc</a>(double x, double y, double radius, double startAngle, double endAngle, optional boolean anticlockwise = false); <!-- see ARC-ORDER note below -->
void <a href=#dom-context-2d-ellipse title=dom-context-2d-ellipse>ellipse</a>(double x, double y, double radiusX, double radiusY, double rotation, double startAngle, double endAngle, boolean anticlockwise); <!-- see ARC-ORDER note below -->
};

interface <dfn id=canvasgradient>CanvasGradient</dfn> {

</dd>

<dt><var title="">context</var> . <code title=dom-context-2d-arcTo><a href=#dom-context-2d-arcto>arcTo</a></code>(<var title="">x1</var>, <var title="">y1</var>, <var title="">x2</var>, <var title="">y2</var>, <var title="">radius</var>)</dt>
<dt><var title="">path</var> . <code title=dom-context-2d-arcTo><a href=#dom-context-2d-arcto>arcTo</a></code>(<var title="">x1</var>, <var title="">y1</var>, <var title="">x2</var>, <var title="">y2</var>, <var title="">radius</var>)</dt>
<dt><var title="">context</var> . <code title=dom-context-2d-arcTo><a href=#dom-context-2d-arcto>arcTo</a></code>(<var title="">x1</var>, <var title="">y1</var>, <var title="">x2</var>, <var title="">y2</var>, <var title="">radiusX</var> [, <var title="">radiusY</var>, <var title="">rotation</var> ])</dt>
<dt><var title="">path</var> . <code title=dom-context-2d-arcTo><a href=#dom-context-2d-arcto>arcTo</a></code>(<var title="">x1</var>, <var title="">y1</var>, <var title="">x2</var>, <var title="">y2</var>, <var title="">radius</var> [, <var title="">radiusY</var>, <var title="">rotation</var> ])</dt>

<dd>

<p>Adds an arc with the given control points and radius to the
current subpath, connected to the previous point by a straight
line.</p>

<p>If two radii are provided, the first controls the width of the
arc's ellipse, and the second controls the height. If only one is
provided, or if they are the same, the arc is from a circle. In
the case of an ellipse, the rotation argument controls the
anti-clockwise inclination of the ellipse relative to the x-axis.</p>

<p>Throws an <code><a href=#indexsizeerror>IndexSizeError</a></code> exception if the given
radius is negative.</p>

</dd>
<figure class=diagrams><!-- if anyone wants to try writing alternative text for these,
be my guest. I can't work out how to describe them. --><img alt="" src=http://images.whatwg.org/arcTo1.png><img alt="" src=http://images.whatwg.org/arcTo2.png><img alt="" src=http://images.whatwg.org/arcTo3.png></figure><!--

c.clearRect(0, 0, 640, 480);
c.save();
try {
var x0 = 150;
var y0 = 100;
var x1 = 375;
var y1 = 100;
var x2 = x1;
var y2 = 250;
var r = 50;

var bottom = 210;
var center = 100;

var fontSize = 16;
var margin = 50;
var dotHalfSize = 5;

// (also update the label positions at the bottom)


// ========

function extendLine(xa,ya,xb,yb) {
var dx = xb-xa;
var dy = yb-ya;
var theta = Math.atan2(dx,dy);
var extX = margin * Math.sin(theta);
var extY = margin * Math.cos(theta);
c.beginPath();
c.moveTo(xa-extX,ya-extY);
c.lineTo(xb+extX,yb+extY);
c.stroke();
}

function dot(x,y,s) {
c.beginPath();
c.arc(x,y,dotHalfSize,0,Math.PI*2);
c.fill();
c.textAlign = 'left';
c.textBaseline = 'top';
c.fillText(s,x+dotHalfSize,y);
}

c.font = fontSize + 'px Gill Sans';
c.fillStyle = 'black';
c.lineWidth = 1;
c.strokeStyle = 'red';
extendLine(x0,y0,x1,y1);
extendLine(x1,y1,x2,y2);

c.lineWidth = 1;
c.strokeStyle = 'silver';
c.beginPath();
c.moveTo(x0,y0);

// based on http://lists.freedesktop.org/archives/cairo/2005-August/004801.html
var angle0, angle1, angle2, angled;
var xc, yc, dc;
angle0 = Math.atan2(y0 - y1, x0 - x1);
angle2 = Math.atan2(y2 - y1, x2 - x1);
angle1 = (angle0 + angle2) / 2;
angled = angle2 - angle0;
if (angled > Math.PI || (angled < 0 && angled > -Math.PI)) {
angle1 += Math.PI;
angled = 2 * Math.PI - angled;
angle0 += Math.PI*2;
angle2 -= Math.PI*2;
} else {
angle0 -= Math.PI*2;
angle2 += Math.PI*2;
}
dc = r / Math.sin (angled / 2);
yc = Math.sin(angle1);
xc = Math.cos(angle1);
xc = x1 + xc * dc;
yc = y1 + yc * dc;

c.lineWidth = 1;
c.strokeStyle = 'blue';
c.beginPath();
c.moveTo(xc,yc);
c.arc(xc,yc,r, Math.PI*3/4, Math.PI*(3/4));
c.stroke();
c.beginPath();
c.strokeStyle = 'silver';
c.arc(xc,yc,r, Math.PI*3/4,Math.PI*(2+3/4));
c.stroke();
c.save();
try {
c.translate(xc, yc);
c.rotate(-Math.PI/4);
c.textAlign = 'center';
c.textBaseline = 'top';
c.fillText("radius", -r/2, 0);
} finally {
c.restore();
}

c.lineWidth = 15;
c.lineCap = 'round';
c.strokeStyle = 'rgba(20,200,40,0.8)';
c.beginPath();
c.moveTo(x0,y0);
c.arcTo(x1,y1,x2,y2,r);
c.stroke();

dot(x0,y0, "x\u2080,y\u2080");
dot(x1,y1, "x\u2081,y\u2081");
dot(x2,y2, "x\u2082,y\u2082");
dot(xc,yc, '');

c.textAlign = 'left';
c.textBaseline = 'alphabetic';
var L = 0;

function print(s) {
c.fillText(s, center, bottom+L*fontSize*1.3);
L += 1;
}
print('// the thick line corresponds to:');
print('context.moveTo(x\u2080, y\u2080)');
print('context.arcTo(x\u2081, y\u2081, x\u2082, y\u2082, radius)');
print('context.stroke()');

c.fillStyle = 'green';
c.fillText("\u25be initial line", 160, 70);
c.textAlign = 'right';
c.fillText("arc \u25b8", x1-25, 115);

} finally {
c.restore();
}

--></dd>

<dt><var title="">context</var> . <code title=dom-context-2d-arc><a href=#dom-context-2d-arc>arc</a></code>(<var title="">x</var>, <var title="">y</var>, <var title="">radius</var>, <var title="">startAngle</var>, <var title="">endAngle</var> [, <var title="">anticlockwise</var> ] )</dt>
<dt><var title="">path</var> . <code title=dom-context-2d-arc><a href=#dom-context-2d-arc>arc</a></code>(<var title="">x</var>, <var title="">y</var>, <var title="">radius</var>, <var title="">startAngle</var>, <var title="">endAngle</var> [, <var title="">anticlockwise</var> ] )</dt>

</dd>

<dt><var title="">context</var> . <code title=dom-context-2d-ellipse><a href=#dom-context-2d-ellipse>ellipse</a></code>(<var title="">x</var>, <var title="">y</var>, <var title="">radiusX</var>, <var title="">radiusY</var>, <var title="">rotation</var>, <var title="">startAngle</var>, <var title="">endAngle</var>, <var title="">anticlockwise</var>)</dt>
<dt><var title="">path</var> . <code title=dom-context-2d-ellipse><a href=#dom-context-2d-ellipse>ellipse</a></code>(<var title="">x</var>, <var title="">y</var>, <var title="">radiusX</var>, <var title="">radiusY</var>, <var title="">rotation</var>, <var title="">startAngle</var>, <var title="">endAngle</var>, <var title="">anticlockwise</var>)</dt>

<dd>

<p>Adds points to the subpath such that the arc described by the
circumference of the ellipse described by the arguments, starting
at the given start angle and ending at the given end angle, going
in the given direction (defaulting to clockwise), is added to the
path, connected to the previous point by a straight line.</p>

<p>Throws an <code><a href=#indexsizeerror>IndexSizeError</a></code> exception if the given
radius is negative.</p>

</dd>

<dt><var title="">context</var> . <code title=dom-context-2d-rect><a href=#dom-context-2d-rect>rect</a></code>(<var title="">x</var>, <var title="">y</var>, <var title="">w</var>, <var title="">h</var>)</dt>
<dt><var title="">path</var> . <code title=dom-context-2d-rect><a href=#dom-context-2d-rect>rect</a></code>(<var title="">x</var>, <var title="">y</var>, <var title="">w</var>, <var title="">h</var>)</dt>

curve with control points (<var title="">cp1x</var>, <var title="">cp1y</var>) and (<var title="">cp2x</var>, <var title="">cp2y</var>). Then, it must add the point (<var title="">x</var>, <var title="">y</var>) to the subpath. <a href=#refsBEZIER>[BEZIER]</a></p>

<hr><p>The <dfn id=dom-context-2d-arcto title=dom-context-2d-arcTo><code>arcTo(<var title="">x1</var>, <var title="">y1</var>, <var title="">x2</var>,
<var title="">y2</var>, <var title="">radius</var>)</code></dfn>
method must first <a href=#ensure-there-is-a-subpath>ensure there is a subpath</a> for <span title="">(<var title="">x1</var>, <var title="">y1</var>)</span>. Then, the behavior depends on the
arguments and the last point in the subpath, as described below.</p>
<var title="">y2</var>, <var title="">radiusX</var>, <var title="">radiusY</var>, <var title="">rotation</var>)</code></dfn>
method must first <a href=#ensure-there-is-a-subpath>ensure there is a subpath</a> for <span title="">(<var title="">x1</var>, <var title="">y1</var>)</span>.
Then, the behavior depends on the arguments and the last point in
the subpath, as described below.</p>

<p>Negative values for <var title="">radius</var> must cause the
implementation to throw an <code><a href=#indexsizeerror>IndexSizeError</a></code>
exception.</p>
<p>Negative values for <var title="">radiusX</var> or <var title="">radiusY</var> must cause the implementation to throw an
<code><a href=#indexsizeerror>IndexSizeError</a></code> exception. If <var title="">radiusY</var> is omitted, user agents must act as if it had
the same value as <var title="">radiusX</var>.</p>

<p>Let the point (<var title="">x0</var>, <var title="">y0</var>) be
the last point in the subpath.</p>
equal to the point (<var title="">x1</var>, <var title="">y1</var>),
or if the point (<var title="">x1</var>, <var title="">y1</var>) is
equal to the point (<var title="">x2</var>, <var title="">y2</var>),
or if the radius <var title="">radius</var> is zero, then the method
must add the point (<var title="">x1</var>, <var title="">y1</var>)
to the subpath, and connect that point to the previous point (<var title="">x0</var>, <var title="">y0</var>) by a straight line.</p>
or if both <var title="">radiusX</var> and <var title="">radiusY</var> are zero, then the method must add the point
(<var title="">x1</var>, <var title="">y1</var>) to the subpath, and
connect that point to the previous point (<var title="">x0</var>,
<var title="">y0</var>) by a straight line.</p>

<p>Otherwise, if the points (<var title="">x0</var>, <var title="">y0</var>), (<var title="">x1</var>, <var title="">y1</var>), and (<var title="">x2</var>, <var title="">y2</var>) all lie on a single straight line, then the
method must add the point (<var title="">x1</var>, <var title="">y1</var>) to the subpath, and connect that point to the
previous point (<var title="">x0</var>, <var title="">y0</var>) by a
straight line.</p>

<p>Otherwise, let <var title="">The Arc</var> be the shortest arc
given by circumference of the circle that has radius <var title="">radius</var>, and that has one point tangent to the
given by circumference of the ellipse that has radius <var title="">radiusX</var> on the major axis and radius <var title="">radiusY</var> on the minor axis, and whose semi-major axis
is rotated <var title="">rotation</var> radians anti-clockwise from
the positive x-axis, and that has one point tangent to the
half-infinite line that crosses the point (<var title="">x0</var>,
<var title="">y0</var>) and ends at the point (<var title="">x1</var>, <var title="">y1</var>), and that has a different
point tangent to the half-infinite line that ends at the point (<var title="">x1</var>, <var title="">y1</var>) and crosses the point
(<var title="">x2</var>, <var title="">y2</var>). The points at
which this circle touches these two lines are called the start and
which this ellipse touches these two lines are called the start and
end tangent points respectively. The method must connect the point
(<var title="">x0</var>, <var title="">y0</var>) to the start
tangent point by a straight line, adding the start tangent point to
tangent point to the subpath.</p>

<hr><p>The <dfn id=dom-context-2d-arc title=dom-context-2d-arc><code>arc(<var title="">x</var>, <var title="">y</var>, <var title="">radius</var>,
<var title="">startAngle</var>, <var title="">endAngle</var>, <var title="">anticlockwise</var>)</code></dfn> method draws an arc. If
the object's path has any subpaths, then the method must add a
straight line from the last point in the subpath to the start point
of the arc. In any case, it must draw the arc between the start
point of the arc and the end point of the arc, and add the start and
end points of the arc to the subpath. The arc and its start and end
<var title="">startAngle</var>, <var title="">endAngle</var>, <var title="">anticlockwise</var>)</code></dfn> and <dfn id=dom-context-2d-ellipse title=dom-context-2d-ellipse><code>ellipse(<var title="">x</var>,
<var title="">y</var>, <var title="">radiusX</var>, <var title="">radiusY</var>, <var title="">rotation</var>, <var title="">startAngle</var>, <var title="">endAngle</var>, <var title="">anticlockwise</var>)</code></dfn> methods draw arcs.</p>

<p>The <code title=dom-context-2d-arc><a href=#dom-context-2d-arc>arc()</a></code> method is
equivalent to the <code title=dom-context-2d-ellipse><a href=#dom-context-2d-ellipse>ellipse()</a></code> method in the case
where the two radii are equal. When the <code title=dom-context-2d-arc><a href=#dom-context-2d-arc>arc()</a></code> method is invoked, it must
act as if the <code title=dom-context-2d-ellipse><a href=#dom-context-2d-ellipse>ellipse()</a></code>
method had been invoked with the <var title="">radiusX</var> and
<var title="">radiusY</var> arguments set to the value of the <var title="">radius</var> argument, the <var title="">rotation</var>
argument set to zero, and the other arguments set to the same values
as their identically named arguments on the <code title=dom-context-2d-arc><a href=#dom-context-2d-arc>arc()</a></code> method.</p>

<p>When the <code title=dom-context-2d-ellipse><a href=#dom-context-2d-ellipse>ellipse()</a></code>
method is invoked, it must proceed as follows. First, if the
object's path has any subpaths, then the method must add a straight
line from the last point in the subpath to the start point of the
arc. Then, it must add the start and end points of the arc to the
subpath, and connect them with an arc. The arc and its start and end
points are defined as follows:</p>

<p>Consider a circle that has its origin at (<var title="">x</var>,
<var title="">y</var>) and that has radius <var title="">radius</var>. The points at <var title="">startAngle</var>
and <var title="">endAngle</var> along this circle's circumference,
measured in radians clockwise from the positive x-axis, are the
start and end points respectively.</p>
<p>Consider an ellipse that has its origin at (<var title="">x</var>, <var title="">y</var>), that has a major-axis
radius <var title="">radiusX</var> and a minor-axis radius <var title="">radiusY</var>, and that is rotated about its origin such
that its semi-major axis is inclined <var title="">radius</var>
radians anti-clockwise from the x-axis. The points at <var title="">startAngle</var> and <var title="">endAngle</var> along
this circle's circumference, measured in radians clockwise from the
ellipse's semi-major axis, are the start and end points
respectively.</p>

<p>If the <var title="">anticlockwise</var> argument is omitted or
false and <span title=""><var title="">endAngle</var>-<var title="">startAngle</var></span> is equal to or greater than <span title="">2&pi;</span>, or, if the <var title="">anticlockwise</var>
<p>If the <var title="">anticlockwise</var> argument false and <span title=""><var title="">endAngle</var>-<var title="">startAngle</var></span> is equal to or greater than <span title="">2&pi;</span>, or, if the <var title="">anticlockwise</var>
argument is <em>true</em> and <span title=""><var title="">startAngle</var>-<var title="">endAngle</var></span> is
equal to or greater than <span title="">2&pi;</span>, then the arc
is the whole circumference of this circle.</p>
is the whole circumference of this ellipse.</p>

<p>Otherwise, the arc is the path along the circumference of this
circle from the start point to the end point, going anti-clockwise
ellipse from the start point to the end point, going anti-clockwise
if the <var title="">anticlockwise</var> argument is true, and
clockwise otherwise. Since the points are on the circle, as opposed
clockwise otherwise. Since the points are on the ellipse, as opposed
to being simply angles from zero, the arc can never cover an angle
greater than <span title="">2&pi;</span> radians. If the two points
are the same, or if the radius is zero, then the arc is defined as
being of zero length in both directions.</p>
greater than <span title="">2&pi;</span> radians.</p>

<p>Negative values for <var title="">radius</var> must cause the
implementation to throw an <code><a href=#indexsizeerror>IndexSizeError</a></code>
exception.</p>
<p>Negative values for <var title="">radiusX</var> or <var title="">radiusY</var> must cause the implementation to throw an
<code><a href=#indexsizeerror>IndexSizeError</a></code> exception.</p>

<hr><p>The <dfn id=dom-context-2d-rect title=dom-context-2d-rect><code>rect(<var title="">x</var>, <var title="">y</var>, <var title="">w</var>, <var title="">h</var>)</code></dfn> method must create a new subpath
containing just the four points (<var title="">x</var>, <var title="">y</var>), (<var title="">x</var>+<var title="">w</var>,

0 comments on commit e25d3f9

Please sign in to comment.
You can’t perform that action at this time.