box.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. /**
  2. * @fileOverview
  3. *
  4. * 表示一个矩形区域
  5. */
  6. define(function(require, exports, module) {
  7. /**
  8. * @class kity.Box
  9. * @description 表示一个矩形区域
  10. */
  11. var Box = require('../core/class').createClass('Box', {
  12. /**
  13. * @constructor
  14. * @for kity.Box
  15. *
  16. * @grammar new kity.Box(x, y, width, height)
  17. * @grammar new kity.Box(box)
  18. *
  19. * @param {Number} x|box.x 矩形区域的 x 坐标
  20. * @param {Number} y|box.y 矩形区域的 y 坐标
  21. * @param {Number} width|box.width 矩形区域的宽度
  22. * @param {Number} height|box.height 矩形区域的高度
  23. *
  24. * @example
  25. *
  26. * ```js
  27. * var box = new kity.Box(10, 20, 50, 50);
  28. * var box2 = new kity.Box({x: 10, y: 20, width: 50, height: 50});
  29. * ```
  30. */
  31. constructor: function(x, y, width, height) {
  32. var box = arguments[0];
  33. if (box && typeof(box) === 'object') {
  34. x = box.x;
  35. y = box.y;
  36. width = box.width;
  37. height = box.height;
  38. }
  39. if (width < 0) {
  40. x -= (width = -width);
  41. }
  42. if (height < 0) {
  43. y -= (height = -height);
  44. }
  45. /**
  46. * @property x
  47. * @for kity.Box
  48. * @type {Number}
  49. * @readOnly
  50. * @description 矩形区域的 x 坐标
  51. */
  52. this.x = x || 0;
  53. /**
  54. * @property y
  55. * @for kity.Box
  56. * @type {Number}
  57. * @readOnly
  58. * @description 矩形区域的 y 坐标
  59. */
  60. this.y = y || 0;
  61. /**
  62. * @property width
  63. * @for kity.Box
  64. * @type {Number}
  65. * @readOnly
  66. * @description 矩形区域的宽度
  67. */
  68. this.width = width || 0;
  69. /**
  70. * @property height
  71. * @for kity.Box
  72. * @type {Number}
  73. * @readOnly
  74. * @description 矩形区域的高度
  75. */
  76. this.height = height || 0;
  77. /**
  78. * @property left
  79. * @for kity.Box
  80. * @type {Number}
  81. * @readOnly
  82. * @description 矩形区域的最左侧坐标,等价于 x 的值
  83. */
  84. this.left = this.x;
  85. /**
  86. * @property right
  87. * @for kity.Box
  88. * @type {Number}
  89. * @readOnly
  90. * @description 矩形区域的最右侧坐标,等价于 x + width 的值
  91. */
  92. this.right = this.x + this.width;
  93. /**
  94. * @property top
  95. * @for kity.Box
  96. * @type {Number}
  97. * @readOnly
  98. * @description 矩形区域的最上侧坐标,等价于 y 的值
  99. */
  100. this.top = this.y;
  101. /**
  102. * @property bottom
  103. * @for kity.Box
  104. * @type {Number}
  105. * @readOnly
  106. * @description 矩形区域的最下侧坐标,等价于 y + height 的值
  107. */
  108. this.bottom = this.y + this.height;
  109. /**
  110. * @property cx
  111. * @for kity.Box
  112. * @type {Number}
  113. * @readOnly
  114. * @description 矩形区域的中心 x 坐标
  115. */
  116. this.cx = this.x + this.width / 2;
  117. /**
  118. * @property cy
  119. * @for kity.Box
  120. * @type {Number}
  121. * @readOnly
  122. * @description 矩形区域的中心 y 坐标
  123. */
  124. this.cy = this.y + this.height / 2;
  125. },
  126. /**
  127. * @method getRangeX()
  128. * @for kity.Box
  129. * @description 获得矩形区域的 x 值域
  130. *
  131. * @grammar getRangeX() => {Number[]}
  132. *
  133. * @example
  134. *
  135. * var box = new kity.Box(10, 10, 30, 50);
  136. * console.log(box.getRangeX()); // [10, 40]
  137. */
  138. getRangeX: function() {
  139. return [this.left, this.right];
  140. },
  141. /**
  142. * @method getRangeY()
  143. * @for kity.Box
  144. * @description 获得矩形区域的 y 值域
  145. *
  146. * @grammar getRangeY() => {Number[]}
  147. *
  148. * @example
  149. *
  150. * var box = new kity.Box(10, 10, 30, 50);
  151. * console.log(box.getRangeY()); // [10, 60]
  152. */
  153. getRangeY: function() {
  154. return [this.top, this.bottom];
  155. },
  156. /**
  157. * @method merge()
  158. * @for kity.Box
  159. * @description 把当前矩形区域和指定的矩形区域合并,返回一个新的矩形区域(即包含两个源矩形区域的最小矩形区域)
  160. *
  161. * @grammar merge(another) => {kity.Box}
  162. * @param {kity.Box} another 要合并的矩形区域
  163. *
  164. * @example
  165. *
  166. * ```js
  167. * var box1 = new kity.Box(10, 10, 50, 50);
  168. * var box2 = new kity.Box(30, 30, 50, 50);
  169. * var box3 = box1.merge(box2);
  170. * console.log(box3.valueOf()); // [10, 10, 70, 70]
  171. * ```
  172. */
  173. merge: function(another) {
  174. if (this.isEmpty()) {
  175. return new Box(another.x, another.y, another.width, another.height);
  176. }
  177. var left = Math.min(this.left, another.left),
  178. right = Math.max(this.right, another.right),
  179. top = Math.min(this.top, another.top),
  180. bottom = Math.max(this.bottom, another.bottom);
  181. return new Box(left, top, right - left, bottom - top);
  182. },
  183. /**
  184. * @method intersect()
  185. * @for kity.Box
  186. * @description 求当前矩形区域和指定的矩形区域重叠的矩形区域
  187. *
  188. * @grammar intersect(another) => {kity.Box}
  189. * @param {kity.Box} another 要求重叠的矩形区域
  190. *
  191. * @example
  192. *
  193. * ```js
  194. * var box1 = new kity.Box(10, 10, 50, 50);
  195. * var box2 = new kity.Box(30, 30, 50, 50);
  196. * var box3 = box1.intersect(box2);
  197. * console.log(box3.valueOf()); // [30, 30, 20, 20]
  198. * ```
  199. */
  200. intersect: function(another) {
  201. if (!another instanceof Box) {
  202. another = new Box(another);
  203. }
  204. var left = Math.max(this.left, another.left),
  205. right = Math.min(this.right, another.right),
  206. top = Math.max(this.top, another.top),
  207. bottom = Math.min(this.bottom, another.bottom);
  208. if (left > right || top > bottom) return new Box();
  209. return new Box(left, top, right - left, bottom - top);
  210. },
  211. /**
  212. * @method expand()
  213. * @for kity.Box
  214. * @description 扩展(或收缩)当前的盒子,返回新的盒子
  215. *
  216. * @param {Number} top
  217. * 矩形区域的上边界往上扩展的值;如果是负数,则上边界往下收缩
  218. *
  219. * @param {Number} right
  220. * [Optional] 矩形区域的右边界往右拓展的值;
  221. * 如果是负数,则右边界往左收缩;
  222. * 如果不设置该值,使用和 top 同样的值。
  223. *
  224. * @param {Number} bottom
  225. * [Optional] 矩形区域的下边界往下拓展的值;
  226. * 如果是负数,则下边界往上收缩;
  227. * 如果不设置该值,使用和 top 同样的值。
  228. *
  229. * @param {Number} left
  230. * [Optional] 矩形区域的左边界往左拓展的值;
  231. * 如果是负数,则左边界往右收缩;
  232. * 如果不设置该值,使用和 right 同样的值。
  233. *
  234. * @example
  235. *
  236. * ```js
  237. * var box = new kity.Box(10, 10, 20, 20);
  238. * var box1 = box.expand(10); // [0, 0, 40, 40]
  239. * var box2 = box.expand(10, 20); // [0, -10, 40, 60]
  240. * var box3 = box.expand(1, 2, 3, 4); // [9, 8, 24, 26]
  241. * ```
  242. */
  243. expand: function(top, right, bottom, left) {
  244. if (arguments.length < 1) {
  245. return new Box(this);
  246. }
  247. if (arguments.length < 2) {
  248. right = top;
  249. }
  250. if (arguments.length < 3) {
  251. bottom = top;
  252. }
  253. if (arguments.length < 4) {
  254. left = right;
  255. }
  256. var x = this.left - left,
  257. y = this.top - top,
  258. width = this.width + right,
  259. height = this.height + top;
  260. return new Box(x, y, width, height);
  261. },
  262. /**
  263. * @method valueOf()
  264. * @for kity.Box
  265. * @description 返回当前盒子的数组表示
  266. *
  267. * @grammar valueOf() => {Number[]}
  268. *
  269. * @example
  270. *
  271. * ```js
  272. * var box = new kity.Box(0, 0, 200, 50);
  273. * console.log(box.valueOf()); // [0, 0, 200, 50]
  274. * ```
  275. */
  276. valueOf: function() {
  277. return [this.x, this.y, this.width, this.height];
  278. },
  279. /**
  280. * @method toString()
  281. * @for kity.Box
  282. * @description 返回当前盒子的字符串表示
  283. *
  284. * @grammar toString() => {String}
  285. *
  286. * @example
  287. *
  288. * ```js
  289. * var box = new kity.Box(0, 0, 200, 50);
  290. * console.log(box.toString()); // "0 0 200 50"
  291. */
  292. toString: function() {
  293. return this.valueOf().join(' ');
  294. },
  295. /**
  296. * @method isEmpty()
  297. * @for kity.Box
  298. * @description 判断当前盒子是否具有尺寸(面积大
  299. *
  300. * @grammar isEmpty() => {boolean}
  301. *
  302. * @example
  303. * ```js
  304. * var box = new kity.Box(0, 0, 0, 100000);
  305. * console.log(box.isEmpty()); // true
  306. * ```
  307. */
  308. isEmpty: function() {
  309. return !this.width || !this.height;
  310. }
  311. });
  312. /**
  313. * @method parse()
  314. * @static
  315. * @for kity.Box
  316. * @description 解析一个字符串或数组为 kity.Box 对象
  317. *
  318. * @grammar kity.Box.parse(any) => {kity.Box}
  319. *
  320. * @param {Number[]|String} any 要解析的字符串或数组
  321. *
  322. * @example
  323. *
  324. * ```js
  325. * console.log(kity.Box.parse('0 0 100 200'));
  326. * console.log(kity.Box.parse([0, 0, 100, 200]));
  327. * ```
  328. */
  329. Box.parse = function(any) {
  330. if (typeof(any) == 'string') {
  331. return Box.parse(any.split(/[\s,]+/).map(parseFloat));
  332. }
  333. if (any instanceof Array) {
  334. return new Box(any[0], any[1], any[2], any[3]);
  335. }
  336. if ('x' in any) return new Box(any);
  337. return null;
  338. };
  339. return Box;
  340. });