UNPKG

canvas-size

Version:

Determine the maximum area, height, width, and custom dimensions of an HTML canvas element.

404 lines (403 loc) 17 kB
/*! * canvas-size * v2.0.0 * https://github.com/jhildenbiddle/canvas-size * (c) 2015-2024 John Hildenbiddle <http://hildenbiddle.com> * MIT license */ (function(global, factory) { typeof exports === "object" && typeof module !== "undefined" ? module.exports = factory() : typeof define === "function" && define.amd ? define(factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, global.canvasSize = factory()); })(this, (function() { "use strict"; function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (;!(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0) ; } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } } function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter((function(r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; }))), t.push.apply(t, o); } return t; } function _objectSpread2(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach((function(r) { _defineProperty(e, r, t[r]); })) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach((function(r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); })); } return e; } function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : String(i); } function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; } function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; } function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); } function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); } function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); } function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; } function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function canvasTest(settings) { var size = settings.sizes.shift(); var width = Math.max(Math.ceil(size[0]), 1); var height = Math.max(Math.ceil(size[1]), 1); var fill = [ width - 1, height - 1, 1, 1 ]; var testTimeStart = performance.now(); var isWorker = typeof WorkerGlobalScope !== "undefined" && self instanceof WorkerGlobalScope; var cropCvs, testCvs; if (isWorker) { cropCvs = new OffscreenCanvas(1, 1); testCvs = new OffscreenCanvas(width, height); } else { cropCvs = document.createElement("canvas"); cropCvs.width = 1; cropCvs.height = 1; testCvs = document.createElement("canvas"); testCvs.width = width; testCvs.height = height; } var cropCtx = cropCvs.getContext("2d"); var testCtx = testCvs.getContext("2d"); if (testCtx) { testCtx.fillRect.apply(testCtx, fill); cropCtx.drawImage(testCvs, width - 1, height - 1, 1, 1, 0, 0, 1, 1); } var isTestPass = cropCtx && cropCtx.getImageData(0, 0, 1, 1).data[3] !== 0; var testTime = parseInt(performance.now() - testTimeStart); [ cropCvs, testCvs ].forEach((function(cvs) { cvs.height = 0; cvs.width = 0; })); if (isWorker) { postMessage({ width: width, height: height, testTime: testTime, isTestPass: isTestPass }); if (!isTestPass && settings.sizes.length) { setTimeout((function() { canvasTest(settings); }), 0); } } else if (isTestPass) { settings.onSuccess({ width: width, height: height, testTime: testTime }); } else { settings.onError({ width: width, height: height, testTime: testTime }); if (settings.sizes.length) { setTimeout((function() { canvasTest(settings); }), 0); } } return isTestPass; } var testSizes = { area: [ 16384, 14188, 11402, 11180, 10836, 8192, 4096, 1 ], height: [ 8388607, 65535, 32767, 16384, 8192, 4096, 1 ], width: [ 4194303, 65535, 32767, 16384, 8192, 4096, 1 ] }; var _excluded = [ "onError", "onSuccess" ]; var defaults = { max: null, min: 1, sizes: [], step: 1024, useWorker: false, onError: Function.prototype, onSuccess: Function.prototype }; var workerJobs = {}; function createSizesArray(settings) { var isArea = settings.width === settings.height; var isWidth = settings.height === 1; var isHeight = settings.width === 1; var sizes = []; if (!settings.width || !settings.height) { settings.sizes.forEach((function(testSize) { var width = isArea || isWidth ? testSize : 1; var height = isArea || isHeight ? testSize : 1; sizes.push([ width, height ]); })); } else { var testMin = settings.min || defaults.min; var testStep = settings.step || defaults.step; var testSize = Math.max(settings.width, settings.height); while (testSize >= testMin) { var width = isArea || isWidth ? testSize : 1; var height = isArea || isHeight ? testSize : 1; sizes.push([ width, height ]); testSize -= testStep; } } return sizes; } function handleMethod(settings) { var isBrowser = typeof window !== "undefined"; var hasPromiseSupport = isBrowser && "Promise" in window; var hasCanvasSupport = isBrowser && "HTMLCanvasElement" in window; var hasOffscreenCanvasSupport = isBrowser && "OffscreenCanvas" in window; var jobID = URL.createObjectURL(new Blob([])).slice(-36); var totalTimeStart = performance.now(); var _onError = settings.onError, _onSuccess = settings.onSuccess, settingsWithoutCallbacks = _objectWithoutProperties(settings, _excluded); var getTotalTime = function getTotalTime() { return parseInt(performance.now() - totalTimeStart); }; var worker = null; if (!hasCanvasSupport) { return false; } if (settings.useWorker && hasOffscreenCanvasSupport) { var js = "\n var canvasTest = ".concat(canvasTest.toString(), ";\n onmessage = function(e) {\n canvasTest(e.data);\n };\n "); var blob = new Blob([ js ], { type: "application/javascript" }); var blobURL = URL.createObjectURL(blob); worker = new Worker(blobURL); URL.revokeObjectURL(blobURL); worker.onmessage = function(e) { var _e$data = e.data, width = _e$data.width, height = _e$data.height, testTime = _e$data.testTime, isTestPass = _e$data.isTestPass; var results = { width: width, height: height, testTime: testTime, totalTime: getTotalTime() }; if (isTestPass) { workerJobs[jobID].onSuccess(results); delete workerJobs[jobID]; } else { workerJobs[jobID].onError(results); } }; } if (hasPromiseSupport) { return new Promise((function(resolve) { var promiseSettings = _objectSpread2(_objectSpread2({}, settings), {}, { onError: function onError(_ref) { var width = _ref.width, height = _ref.height, testTime = _ref.testTime; var results = { width: width, height: height, testTime: testTime, totalTime: getTotalTime() }; var isLastTest; if (settings.sizes.length === 0) { isLastTest = true; } else { var _settings$sizes$slice = settings.sizes.slice(-1), _settings$sizes$slice2 = _slicedToArray(_settings$sizes$slice, 1), _settings$sizes$slice3 = _slicedToArray(_settings$sizes$slice2[0], 2), lastWidth = _settings$sizes$slice3[0], lastHeight = _settings$sizes$slice3[1]; isLastTest = width === lastWidth && height === lastHeight; } _onError(results); if (isLastTest) { resolve(_objectSpread2(_objectSpread2({}, results), {}, { success: false })); } }, onSuccess: function onSuccess(_ref2) { var width = _ref2.width, height = _ref2.height, testTime = _ref2.testTime; var results = { width: width, height: height, testTime: testTime, totalTime: getTotalTime() }; _onSuccess(results); resolve(_objectSpread2(_objectSpread2({}, results), {}, { success: true })); } }); if (worker) { var onError = promiseSettings.onError, onSuccess = promiseSettings.onSuccess; workerJobs[jobID] = { onError: onError, onSuccess: onSuccess }; worker.postMessage(settingsWithoutCallbacks); } else { canvasTest(promiseSettings); } })); } else { if (worker) { workerJobs[jobID] = { onError: _onError, onSuccess: _onSuccess }; worker.postMessage(settingsWithoutCallbacks); } else { return canvasTest(settings); } } } var canvasSize = { maxArea: function maxArea() { var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var sizes = createSizesArray({ width: options.max, height: options.max, min: options.min, step: options.step, sizes: _toConsumableArray(testSizes.area) }); var settings = _objectSpread2(_objectSpread2(_objectSpread2({}, defaults), options), {}, { sizes: sizes }); return handleMethod(settings); }, maxHeight: function maxHeight() { var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var sizes = createSizesArray({ width: 1, height: options.max, min: options.min, step: options.step, sizes: _toConsumableArray(testSizes.height) }); var settings = _objectSpread2(_objectSpread2(_objectSpread2({}, defaults), options), {}, { sizes: sizes }); return handleMethod(settings); }, maxWidth: function maxWidth() { var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var sizes = createSizesArray({ width: options.max, height: 1, min: options.min, step: options.step, sizes: _toConsumableArray(testSizes.width) }); var settings = _objectSpread2(_objectSpread2(_objectSpread2({}, defaults), options), {}, { sizes: sizes }); return handleMethod(settings); }, test: function test() { var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var settings = _objectSpread2(_objectSpread2({}, defaults), options); settings.sizes = _toConsumableArray(settings.sizes); if (settings.width && settings.height) { settings.sizes = [ [ settings.width, settings.height ] ]; } return handleMethod(settings); } }; return canvasSize; })); //# sourceMappingURL=canvas-size.js.map