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 }