For classic tiled sprite sheets.

Currently supports drawing a tile with rotation or scaling.

Fully hardware-accelerated on Chrome, IE9, iOS & (AFAIK) OSX Safari (but not Windows Safari)

Code:
unit SpriteSheet;

interface

uses w3ctrls, w3graphics, w3system;

type

   TW3SpriteSheet = Class(TObject)
      private
         FImage : TW3Image;
         FRows, FColumns : Integer;
         FTotal : Integer;
         FWidth, FHeight : Integer;
         FHalfWidth, FHalfHeight : Integer;
         FReady : Boolean;
         FOnReady : TNotifyEvent;

         procedure   HandleImageReady(sender : TObject);
         Procedure   setWidth(aValue : Integer);
         procedure   setheight(aValue : Integer);
         Procedure   ReCalcInfo;

      protected

         class var vSinCosReady : Boolean;
         class var vCosTable : array of Float;
         class var vSinTable : array of Float;
         class procedure InitSinCos;

      public
         Constructor Create;virtual;
         destructor  Destroy;Override;

         procedure   LoadImage(aUrl : String); overload;
         procedure   LoadImage(aUrl : String; aSpriteWidth, aSpriteHeight : Integer); overload;

         // top left anchored
         Procedure   Draw(Canvas : TW3Canvas; dx,dy : Integer; FrameIndex : Integer); overload;
         Procedure   Draw(Canvas : TW3Canvas; dx,dy : Integer; FrameIndex : Integer;
                          rotationDegrees : Integer); overload;

         // center anchored
         procedure   DrawScaled(canvas : TW3Canvas; dx,dy : Float; FrameIndex : Integer;
                                scale : Float); overload;

         Property    SpriteWidth:Integer read FWidth write setWidth;
         Property    SpriteHeight:Integer read FHeight write setHeight;
         property    SpriteHalfWidth : Integer read FHalfWidth;
         property    SpriteHalfHeight : Integer read FHalfHeight;
         property    Rows : Integer read FRows;
         property    Columns : Integer read FColumns;
         property    NbFrames : Integer read FTotal;

         Property    Ready : Boolean read FReady;
         property    OnReady : TNotifyEvent read FOnReady write FOnReady;
   End;

implementation

Constructor TW3SpriteSheet.Create;
Begin
  inherited Create;
  FImage:=TW3Image.Create(NIL);
  FImage.OnLoad:=HandleImageReady;
  FWidth:=32;
  FHeight:=32;
  InitSinCos;
end;

destructor TW3SpriteSheet.Destroy;
Begin
  FImage.onLoad:=NIL;
  FImage.free;
  inherited;
end;

class procedure TW3SpriteSheet.InitSinCos;
var
   i : Integer;
begin
   if vSinCosReady then Exit;

   vSinCosReady:=True;

   for i:=0 to 359 do begin
      var a := DegToRad(i);
      vCosTable.Add(Cos(a));
      vSinTable.Add(Sin(a));
   end;
end;

Procedure TW3SpriteSheet.setWidth(aValue:Integer);
Begin
  FWidth:=Max(aValue,4);
  ReCalcInfo;
end;

procedure TW3SpriteSheet.setheight(aValue:Integer);
Begin
  FHeight:=Max(aValue,4);
  ReCalcInfo;
end;

Procedure TW3SpriteSheet.ReCalcInfo;
var
   img : Variant;
Begin
  if FReady then Begin
    img:=ObjToVariant(FImage.TagRef);
    FColumns:=(img.width+1) div FWidth;
    FRows:=(img.height+1) div FHeight;
    FTotal:=FColumns * FRows;
  end else Begin
    FColumns:=0;
    FRows:=0;
    FTotal:=0;
  end;
  FHalfHeight:=FWidth shr 1;
  FHalfWidth:=FHalfHeight shr 1;
end;

procedure TW3SpriteSheet.HandleImageReady(sender:TObject);
Begin
   FReady:=True;
   ReCalcInfo;
   if Assigned(FOnReady) then
      FOnReady(Self);
end;

Procedure TW3SpriteSheet.LoadImage(aUrl:String);
Begin
  FReady:=False;
  ReCalcInfo;
  FImage.LoadFromUrl(aUrl);
end;

procedure TW3SpriteSheet.LoadImage(aUrl : String; aSpriteWidth, aSpriteHeight : Integer);
begin
   LoadImage(aURL);
   SpriteWidth:=aSpriteWidth;
   SpriteHeight:=aSpriteHeight;
end;

Procedure TW3SpriteSheet.Draw(Canvas:TW3Canvas;
          dx,dy:Integer;FrameIndex:Integer);
var
   sx,sy:  Integer;
Begin
   if FReady then Begin
      sy:=FrameIndex div FColumns;
      sx:=FrameIndex-sy*FColumns;
      Canvas.DrawImageF(ObjToVariant(FImage.TagRef),
                        sx*SpriteWidth, sy*SpriteHeight,
                        SpriteWidth, SpriteHeight,
                        dx, dy, SpriteWidth, SpriteHeight);
   end;
end;

Procedure TW3SpriteSheet.Draw(Canvas:TW3Canvas;
          dx,dy:Integer;FrameIndex:Integer; rotationDegrees : Integer);
var
   sx,sy:  Integer;
begin
   if rotationDegrees=0 then begin
      Draw(Canvas, dx, dy, FrameIndex);
      exit;
   end;
   if FReady then begin
      sy:=FrameIndex div FColumns;
      sx:=FrameIndex-sy*FColumns;
      Canvas.Save;
      case rotationDegrees of
         0 : Canvas.Translate(dx, dy);
         90 : Canvas.Transform(0, -1, 1, 0, dx, dy+SpriteHeight);
         180 : Canvas.Transform(-1, 0, 0, -1, dx+SpriteWidth, dy+SpriteHeight);
         270 : Canvas.Transform(0, 1, -1, 0, dx+SpriteWidth, dy);
      else
         while rotationDegrees<0 do
            rotationDegrees+=360;
         while rotationDegrees>=360 do
            rotationDegrees-=360;
         var c := vCosTable[rotationDegrees];
         var s := vSinTable[rotationDegrees];
         if rotationDegrees>=360-45 then
            rotationDegrees+=45-360
         else rotationDegrees+=45;
         var c2 := vCosTable[rotationDegrees];
         var s2 := vSinTable[rotationDegrees];
         const r2 = Sqrt(2)/2;
         Canvas.Transform(c, -s, s, c, dx+SpriteWidth*(0.5-r2*s2), dy+SpriteHeight*(0.5-r2*c2));
      end;
      Canvas.DrawImageF(ObjToVariant(FImage.TagRef),
                        sx*SpriteWidth, sy*SpriteHeight,
                        SpriteWidth, SpriteHeight,
                        0, 0, SpriteWidth, SpriteHeight);
      Canvas.Restore;
  end;
end;

procedure TW3SpriteSheet.DrawScaled(canvas : TW3Canvas; dx, dy : Float; frameIndex : Integer;
                                    scale : Float);
var
   sx, sy :  Integer;
   sw, sh : Float;
begin
   if FReady then Begin
      sy:=FrameIndex div FColumns;
      sx:=FrameIndex-sy*FColumns;
      sw:=SpriteWidth*scale;
      sh:=SpriteHeight*scale;

      Canvas.DrawImageF(ObjToVariant(FImage.TagRef),
                        sx*SpriteWidth, sy*SpriteHeight,
                        SpriteWidth, SpriteHeight,
                        dx-sw*0.5, dy-sh*0.5, sw, sh);
   end;
end;