utils.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. ///////////////////////
  2. /// UTILS ///
  3. ///////////////////////
  4. export const distance = (p1, p2) => {
  5. const dx = p2.x - p1.x;
  6. const dy = p2.y - p1.y;
  7. return Math.sqrt((dx * dx) + (dy * dy));
  8. };
  9. export const angle = (p1, p2) => {
  10. const dx = p2.x - p1.x;
  11. const dy = p2.y - p1.y;
  12. return degrees(Math.atan2(dy, dx));
  13. };
  14. export const findCoord = (p, d, a) => {
  15. const b = {x: 0, y: 0};
  16. a = radians(a);
  17. b.x = p.x - d * Math.cos(a);
  18. b.y = p.y - d * Math.sin(a);
  19. return b;
  20. };
  21. export const radians = (a) => {
  22. return a * (Math.PI / 180);
  23. };
  24. export const degrees = (a) => {
  25. return a * (180 / Math.PI);
  26. };
  27. export const isPressed = (evt) => {
  28. if (isNaN(evt.buttons)) {
  29. return evt.pressure !== 0;
  30. }
  31. return evt.buttons !== 0;
  32. };
  33. const timers = new Map();
  34. export const throttle = (cb) => {
  35. if (timers.has(cb)) {
  36. clearTimeout(timers.get(cb));
  37. }
  38. timers.set(cb, setTimeout(cb, 100));
  39. };
  40. export const bindEvt = (el, arg, handler) => {
  41. const types = arg.split(/[ ,]+/g);
  42. let type;
  43. for (let i = 0; i < types.length; i += 1) {
  44. type = types[i];
  45. if (el.addEventListener) {
  46. el.addEventListener(type, handler, false);
  47. } else if (el.attachEvent) {
  48. el.attachEvent(type, handler);
  49. }
  50. }
  51. };
  52. export const unbindEvt = (el, arg, handler) => {
  53. const types = arg.split(/[ ,]+/g);
  54. let type;
  55. for (let i = 0; i < types.length; i += 1) {
  56. type = types[i];
  57. if (el.removeEventListener) {
  58. el.removeEventListener(type, handler);
  59. } else if (el.detachEvent) {
  60. el.detachEvent(type, handler);
  61. }
  62. }
  63. };
  64. export const trigger = (el, type, data) => {
  65. const evt = new CustomEvent(type, data);
  66. el.dispatchEvent(evt);
  67. };
  68. export const prepareEvent = (evt) => {
  69. evt.preventDefault();
  70. return evt.type.match(/^touch/) ? evt.changedTouches : evt;
  71. };
  72. export const getScroll = () => {
  73. const x = (window.pageXOffset !== undefined) ?
  74. window.pageXOffset :
  75. (document.documentElement || document.body.parentNode || document.body)
  76. .scrollLeft;
  77. const y = (window.pageYOffset !== undefined) ?
  78. window.pageYOffset :
  79. (document.documentElement || document.body.parentNode || document.body)
  80. .scrollTop;
  81. return {
  82. x: x,
  83. y: y
  84. };
  85. };
  86. export const applyPosition = (el, pos) => {
  87. if (pos.top || pos.right || pos.bottom || pos.left) {
  88. el.style.top = pos.top;
  89. el.style.right = pos.right;
  90. el.style.bottom = pos.bottom;
  91. el.style.left = pos.left;
  92. } else {
  93. el.style.left = pos.x + 'px';
  94. el.style.top = pos.y + 'px';
  95. }
  96. };
  97. export const getTransitionStyle = (property, values, time) => {
  98. const obj = configStylePropertyObject(property);
  99. for (let i in obj) {
  100. if (obj.hasOwnProperty(i)) {
  101. if (typeof values === 'string') {
  102. obj[i] = values + ' ' + time;
  103. } else {
  104. let st = '';
  105. for (let j = 0, max = values.length; j < max; j += 1) {
  106. st += values[j] + ' ' + time + ', ';
  107. }
  108. obj[i] = st.slice(0, -2);
  109. }
  110. }
  111. }
  112. return obj;
  113. };
  114. export const getVendorStyle = (property, value) => {
  115. const obj = configStylePropertyObject(property);
  116. for (let i in obj) {
  117. if (obj.hasOwnProperty(i)) {
  118. obj[i] = value;
  119. }
  120. }
  121. return obj;
  122. };
  123. export const configStylePropertyObject = (prop) => {
  124. const obj = {};
  125. obj[prop] = '';
  126. const vendors = ['webkit', 'Moz', 'o'];
  127. vendors.forEach(function (vendor) {
  128. obj[vendor + prop.charAt(0).toUpperCase() + prop.slice(1)] = '';
  129. });
  130. return obj;
  131. };
  132. export const extend = (objA, objB) => {
  133. for (let i in objB) {
  134. if (objB.hasOwnProperty(i)) {
  135. objA[i] = objB[i];
  136. }
  137. }
  138. return objA;
  139. };
  140. // Overwrite only what's already present
  141. export const safeExtend = (objA, objB) => {
  142. const obj = {};
  143. for (let i in objA) {
  144. if (objA.hasOwnProperty(i) && objB.hasOwnProperty(i)) {
  145. obj[i] = objB[i];
  146. } else if (objA.hasOwnProperty(i)) {
  147. obj[i] = objA[i];
  148. }
  149. }
  150. return obj;
  151. };
  152. // Map for array or unique item.
  153. export const map = (ar, fn) => {
  154. if (ar.length) {
  155. for (let i = 0, max = ar.length; i < max; i += 1) {
  156. fn(ar[i]);
  157. }
  158. } else {
  159. fn(ar);
  160. }
  161. };
  162. // Clamp position within the range
  163. export const clamp = (pos, nipplePos, size) => ({
  164. // left-clamping right-clamping
  165. x: Math.min(Math.max(pos.x, nipplePos.x - size), nipplePos.x + size),
  166. // top-clamping bottom-clamping
  167. y: Math.min(Math.max(pos.y, nipplePos.y - size), nipplePos.y + size)
  168. });