util.ts 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. /**
  2. * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author Alexander Rose <alexander.rose@weirdbyte.de>
  5. */
  6. /** Set canvas size taking `devicePixelRatio` into account */
  7. export function setCanvasSize(canvas: HTMLCanvasElement, width: number, height: number, scale = 1) {
  8. canvas.width = Math.round(window.devicePixelRatio * scale * width);
  9. canvas.height = Math.round(window.devicePixelRatio * scale * height);
  10. Object.assign(canvas.style, { width: `${width}px`, height: `${height}px` });
  11. }
  12. /** Resize canvas to container element taking `devicePixelRatio` into account */
  13. export function resizeCanvas (canvas: HTMLCanvasElement, container: HTMLElement, scale = 1) {
  14. let width = window.innerWidth;
  15. let height = window.innerHeight;
  16. if (container !== document.body) {
  17. // fixes issue #molstar/molstar#147, offsetWidth/offsetHeight is correct size when css transform:scale is used
  18. width = container.offsetWidth;
  19. height = container.offsetHeight;
  20. }
  21. setCanvasSize(canvas, width, height, scale);
  22. }
  23. function _canvasToBlob(canvas: HTMLCanvasElement, callback: BlobCallback, type?: string, quality?: any) {
  24. const bin = atob(canvas.toDataURL(type, quality).split(',')[1]);
  25. const len = bin.length;
  26. const len32 = len >> 2;
  27. const a8 = new Uint8Array(len);
  28. const a32 = new Uint32Array(a8.buffer, 0, len32);
  29. let j = 0;
  30. for (let i = 0; i < len32; ++i) {
  31. a32[i] = bin.charCodeAt(j++) |
  32. bin.charCodeAt(j++) << 8 |
  33. bin.charCodeAt(j++) << 16 |
  34. bin.charCodeAt(j++) << 24;
  35. }
  36. let tailLength = len & 3;
  37. while (tailLength--) a8[j] = bin.charCodeAt(j++);
  38. callback(new Blob([a8], { type: type || 'image/png' }));
  39. }
  40. export async function canvasToBlob(canvas: HTMLCanvasElement, type?: string, quality?: any): Promise<Blob> {
  41. return new Promise((resolve, reject) => {
  42. const callback = (blob: Blob | null) => {
  43. if (blob) resolve(blob);
  44. else reject('no blob returned');
  45. };
  46. if (!HTMLCanvasElement.prototype.toBlob) {
  47. _canvasToBlob(canvas, callback, type, quality);
  48. } else {
  49. canvas.toBlob(callback, type, quality);
  50. }
  51. });
  52. }