ECMAScript-Praktikum 2011: Problemstellung 6 (Entwickeln einer Canvas-Bibliothek)

HTML5 ermöglicht die eingebettete Verwendung von Canvas-Elementen, die als Grafik-Flächen dienen. Die Canvas-Unterstützung erfordert ECMAScript. Canvas bietet eine infache "nativ"-Schnittstelle (siehe z.B. whatwg: the-canvas-element , en.wikipedia: Canvas_element ). Die Browser-Unterstützung zeigt en.wikipedia: Comparison_of_layout_engines_&HTML5_Canvas

Anstelle von Device-Koordinaten soll die Bibliothek eine isotrope 2D-Welt unterstützen. Es soll eine robuste, einfach zu nutzende Bibliothek entwickelt werden, die "Befehlsverkettungen" erlaubt. Es soll ein eigens "Design Custem Shape" entworfen und getestet und dynamisch bewegt werden. Es sind hinreichend viele Test durchzuführen.


Einstieg (allgemeine Infos) Wie fange ich an?

Im Internet gibt es zahlreiche Tutorials, die meist die "nativ"-Schnittstelle direkt verwenden (siehe z.B. opera: html-5-canvas-the-basics mozilla: Canvas tutorial apple: Safari HTML5 Canvas Guide

W3C-Schnittstelle Wie sehen die Befehle aus?

Dies ist aus W3C herauskopiert und dient lediglich der Schnittstellen-Übersicht:

The canvas state

Each context maintains a stack of drawing states. 
Drawing states consist of:

    The current transformation matrix.
    The current clipping region.
    The current values of the following attributes:
     
    strokeStyle, fillStyle, globalAlpha, lineWidth, lineCap, 
    lineJoin, miterLimit, shadowOffsetX, shadowOffsetY, 
    shadowBlur, shadowColor, globalCompositeOperation, 
    font, textAlign, textBaseline.

interface CanvasRenderingContext2D {

  // back-reference to the canvas
  readonly attribute HTMLCanvasElement canvas;

  // state
  void save();    // push state on state stack
  void restore(); // pop state stack and restore state

  // transformations (default transform is the identity matrix)
  void scale(in double x, in double y);
  void rotate(in double angle);
  void translate(in double x, in double y);
  void transform(in double a, in double b, in double c, in double d, in double e, in double f);
  void setTransform(in double a, in double b, in double c, in double d, in double e, in double f);

  // compositing
       attribute double globalAlpha; // (default 1.0)
       attribute DOMString globalCompositeOperation; // (default source-over)

  // colors and styles
      attribute any strokeStyle; // (default black)
      attribute any fillStyle; // (default black)
  CanvasGradient createLinearGradient(in double x0, in double y0, in double x1, in double y1);
  CanvasGradient createRadialGradient(in double x0, in double y0, in double r0, in double x1, in double y1, in double r1);
  CanvasPattern createPattern(in HTMLImageElement image, in DOMString repetition);
  CanvasPattern createPattern(in HTMLCanvasElement image, in DOMString repetition);
  CanvasPattern createPattern(in HTMLVideoElement image, in DOMString repetition);

  // line caps/joins
      attribute double lineWidth;   // (default 1)
      attribute DOMString lineCap;  // "butt", "round", "square" (default "butt")
      attribute DOMString lineJoin; // "round", "bevel", "miter" (default "miter")
      attribute double miterLimit;  // (default 10)

  // shadows
      attribute double shadowOffsetX;  // (default 0)
      attribute double shadowOffsetY;  // (default 0)
      attribute double shadowBlur;     // (default 0)
      attribute DOMString shadowColor; // (default transparent black)

  // rects
  void clearRect(in double x, in double y, in double w, in double h);
  void fillRect(in double x, in double y, in double w, in double h);
  void strokeRect(in double x, in double y, in double w, in double h);

  // path API
  void beginPath();
  void closePath();
  void moveTo(in double x, in double y);
  void lineTo(in double x, in double y);
  void quadraticCurveTo(in double cpx, in double cpy, in double x, in double y);
  void bezierCurveTo(in double cp1x, in double cp1y, in double cp2x, in double cp2y, in double x, in double y);
  void arcTo(in double x1, in double y1, in double x2, in double y2, in double radius);
  void rect(in double x, in double y, in double w, in double h);
  void arc(in double x, in double y, in double radius, in double startAngle, in double endAngle, in optional boolean anticlockwise);
  void fill();
  void stroke();
  void clip();
  boolean isPointInPath(in double x, in double y);

  // focus management
  boolean drawFocusRing(in Element element, in double xCaret, in double yCaret, in optional boolean canDrawCustom);

  // text
       attribute DOMString font; // (default 10px sans-serif)
       attribute DOMString textAlign; // "start", "end", "left", "right", "center" (default: "start")
       attribute DOMString textBaseline; // "top", "hanging", "middle", "alphabetic", "ideographic", "bottom" (default: "alphabetic")
  void fillText(in DOMString text, in double x, in double y, in optional double maxWidth);
  void strokeText(in DOMString text, in double x, in double y, in optional double maxWidth);
  TextMetrics measureText(in DOMString text);

  // drawing images
  void drawImage(in HTMLImageElement image, in double dx, in double dy, in optional double dw, in double dh);
  void drawImage(in HTMLImageElement image, in double sx, in double sy, in double sw, in double sh, in double dx, in double dy, in double dw, in double dh);
  void drawImage(in HTMLCanvasElement image, in double dx, in double dy, in optional double dw, in double dh);
  void drawImage(in HTMLCanvasElement image, in double sx, in double sy, in double sw, in double sh, in double dx, in double dy, in double dw, in double dh);
  void drawImage(in HTMLVideoElement image, in double dx, in double dy, in optional double dw, in double dh);
  void drawImage(in HTMLVideoElement image, in double sx, in double sy, in double sw, in double sh, in double dx, in double dy, in double dw, in double dh);

  // pixel manipulation
  ImageData createImageData(in double sw, in double sh);
  ImageData createImageData(in ImageData imagedata);
  ImageData getImageData(in double sx, in double sy, in double sw, in double sh);
  void putImageData(in ImageData imagedata, in double dx, in double dy, in optional double dirtyX, in double dirtyY, in double dirtyWidth, in double dirtyHeight);
};

interface CanvasGradient {  // opaque object
  void addColorStop(in double offset, in DOMString color);
};

interface CanvasPattern {  // opaque object
};

interface TextMetrics {  readonly attribute double width;
};

interface ImageData {
  readonly attribute unsigned long width;
  readonly attribute unsigned long height;
  readonly attribute CanvasPixelArray data;
};

interface CanvasPixelArray {
  readonly attribute unsigned long length;
  getter octet (in unsigned long index);
  setter void  (in unsigned long index, in octet value);
};
Transformationen Wie funktioniert das?

Als Transformationen gibt es translate, scale, rotate:

translate
1, 0, tx     a11, a12, a13        a11, a12, a13 + tx
0, 1, ty  .  a21, a22, a23    -   a21, a22, a23 + ty
0, 0,  1      0,   0,   1          0,    0,     1

scale
sx, 0, 0     a11, a12, a13       a11·sx, a12·sx  a13·sx
0, sy, 0  .  a21, a22, a23    -  a21·sy, a22·sy, a23·sy
0, 0, 1       0,   0,   1          0,       0,     1

rotate
ca, -sa, 0      a11, a12, a13      a11·ca - a21·sa, a12·ca - a22·sa, a13·ca - a23·sa
sa,  ca, 0   .  a21, a22, a23   -  a11·sa + a21·ca, a22·ca + a12·sa, a13·sa + a23·ca
 0,   0, 1       0,   0,   1              0,               0,               1
Wie anfangen? Was soll konkret gemacht werden?

Ein guter Bibliotheksentwurf erfordert gute Kenntnisse (ECMAScript, Grafik) und hinreichendee Erfahrungen mit der "Nativ-Schnittstelle". Hier finden sie einen Anfang, der noch fehlerhaft ist und nicht getestet ist. Dier Anfang ist "durchschaubar" und kann die Aufgabe erleichtern test-nativ test-isotrop

Wie umfangreich? Was soll dokumentiert werden?

Der Lernfortschritt und die Durchführung soll erkennbar sein und dokumentiert werden.

Viel Freude bei der Ausarbeitung!