You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

143 lines
3.7 KiB

  1. import { ANGLE_RATIO } from './constants';
  2. /**
  3. * Returns the value of a number upto 2 decimal places.
  4. * @param {Number} d Any number
  5. */
  6. export function floatTwo(d) {
  7. return parseFloat(d.toFixed(2));
  8. }
  9. /**
  10. * Returns whether or not two given arrays are equal.
  11. * @param {Array} arr1 First array
  12. * @param {Array} arr2 Second array
  13. */
  14. export function arraysEqual(arr1, arr2) {
  15. if (arr1.length !== arr2.length) return false;
  16. let areEqual = true;
  17. arr1.map((d, i) => {
  18. if (arr2[i] !== d) areEqual = false;
  19. });
  20. return areEqual;
  21. }
  22. /**
  23. * Shuffles array in place. ES6 version
  24. * @param {Array} array An array containing the items.
  25. */
  26. export function shuffle(array) {
  27. // Awesomeness: https://bost.ocks.org/mike/shuffle/
  28. // https://stackoverflow.com/a/2450976/6495043
  29. // https://stackoverflow.com/questions/6274339/how-can-i-shuffle-an-array?noredirect=1&lq=1
  30. for (let i = array.length - 1; i > 0; i--) {
  31. let j = Math.floor(Math.random() * (i + 1));
  32. [array[i], array[j]] = [array[j], array[i]];
  33. }
  34. return array;
  35. }
  36. /**
  37. * Fill an array with extra points
  38. * @param {Array} array Array
  39. * @param {Number} count number of filler elements
  40. * @param {Object} element element to fill with
  41. * @param {Boolean} start fill at start?
  42. */
  43. export function fillArray(array, count, element, start = false) {
  44. if (!element) {
  45. element = start ? array[0] : array[array.length - 1];
  46. }
  47. let fillerArray = new Array(Math.abs(count)).fill(element);
  48. array = start ? fillerArray.concat(array) : array.concat(fillerArray);
  49. return array;
  50. }
  51. /**
  52. * Returns pixel width of string.
  53. * @param {String} string
  54. * @param {Number} charWidth Width of single char in pixels
  55. */
  56. export function getStringWidth(string, charWidth) {
  57. return (string + "").length * charWidth;
  58. }
  59. export function bindChange(obj, getFn, setFn) {
  60. return new Proxy(obj, {
  61. set: function (target, prop, value) {
  62. setFn();
  63. return Reflect.set(target, prop, value);
  64. },
  65. get: function (target, prop) {
  66. getFn();
  67. return Reflect.get(target, prop);
  68. }
  69. });
  70. }
  71. // https://stackoverflow.com/a/29325222
  72. export function getRandomBias(min, max, bias, influence) {
  73. const range = max - min;
  74. const biasValue = range * bias + min;
  75. var rnd = Math.random() * range + min, // random in range
  76. mix = Math.random() * influence; // random mixer
  77. return rnd * (1 - mix) + biasValue * mix; // mix full range and bias
  78. }
  79. export function getPositionByAngle(angle, radius) {
  80. return {
  81. x: Math.sin(angle * ANGLE_RATIO) * radius,
  82. y: Math.cos(angle * ANGLE_RATIO) * radius,
  83. };
  84. }
  85. /**
  86. * Check if a number is valid for svg attributes
  87. * @param {object} candidate Candidate to test
  88. * @param {Boolean} nonNegative flag to treat negative number as invalid
  89. */
  90. export function isValidNumber(candidate, nonNegative = false) {
  91. if (Number.isNaN(candidate)) return false;
  92. else if (candidate === undefined) return false;
  93. else if (!Number.isFinite(candidate)) return false;
  94. else if (nonNegative && candidate < 0) return false;
  95. else return true;
  96. }
  97. /**
  98. * Round a number to the closes precision, max max precision 4
  99. * @param {Number} d Any Number
  100. */
  101. export function round(d) {
  102. // https://floating-point-gui.de/
  103. // https://www.jacklmoore.com/notes/rounding-in-javascript/
  104. return Number(Math.round(d + 'e4') + 'e-4');
  105. }
  106. /**
  107. * Creates a deep clone of an object
  108. * @param {Object} candidate Any Object
  109. */
  110. export function deepClone(candidate) {
  111. let cloned, value, key;
  112. if (candidate instanceof Date) {
  113. return new Date(candidate.getTime());
  114. }
  115. if (typeof candidate !== "object" || candidate === null) {
  116. return candidate;
  117. }
  118. cloned = Array.isArray(candidate) ? [] : {};
  119. for (key in candidate) {
  120. value = candidate[key];
  121. cloned[key] = deepClone(value);
  122. }
  123. return cloned;
  124. }