/ src / Util.ts
Util.ts
 1  /**
 2   * Affiche le morceau `index` de l'image `img` sur la zone de dessin `ctx` à la
 3   * position `(x, y)` et de taille `(frameWidth, frameHeight)`.
 4   *
 5   * L'image est découpée en morceaux en fonction de `(frameWidth, frameHeight)`.
 6   *
 7   * L'indexation se fait ainsi (exemple), en commençant à 0 :
 8   *
 9   * +---+---+---+
10   * | 0 | 1 | 2 |
11   * +---+---+---+
12   * | 3 | 4 | 5 |
13   * +---+---+---+
14   * | 6 | 7 | 8 |
15   * +---+---+---+
16   */
17  export function drawImageByIndex(
18    ctx: CanvasRenderingContext2D,
19    img: HTMLImageElement,
20    x: number,
21    y: number,
22    index: number,
23    frameWidth: number,
24    frameHeight: number,
25  ): void {
26    // Nombre de tuiles par ligne
27    const nbTilesByLine = Math.ceil(img.width / frameWidth)
28  
29    // Position x depuis laquelle découper le morceau
30    const baseX = (index % nbTilesByLine) * frameWidth
31  
32    // Position y depuis laquelle découper le morceau
33    const baseY = Math.floor(index / nbTilesByLine) * frameHeight
34  
35    // Afficher le morceau d'image
36    ctx.drawImage(
37      img,
38      baseX,
39      baseY,
40      frameWidth,
41      frameHeight,
42      x,
43      y,
44      frameWidth,
45      frameHeight,
46    )
47  }
48  
49  /**
50   * Délimitation de valeur.
51   *
52   * - Si `num` est inférieur à `min`, retourne `min`  ;
53   * - Si `num` est supérieur à `max`, retourne `max`  ;
54   * - Sinon retourne `num`.
55   */
56  export function clamp(num: number, min: number, max: number): number {
57    return Math.min(max, Math.max(min, num))
58  }
59  
60  // @todo Retenir le résultat afin d'éviter de le recalculer à chaque appel.
61  /**
62   * L'appareil utilisé possède-t-il un écran tactile ?
63   *
64   * @see https://stackoverflow.com/a/4819886
65   */
66  export function isTouchDevice(): boolean {
67    const prefixes = ' -webkit- -moz- -o- -ms- '.split(' ')
68  
69    const mq = function(mediaQuery: string): boolean {
70      return window.matchMedia(mediaQuery).matches
71    }
72  
73    if ('ontouchstart' in window) {
74      return true
75    }
76  
77    const query = ['(', prefixes.join('touch-enabled),('), 'heartz', ')'].join('')
78  
79    return mq(query)
80  }