Resize.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  1. //缩放程序
  2. var Resize = Class.create();
  3. Resize.prototype = {
  4. //缩放对象
  5. initialize: function(obj, options) {
  6. this._obj = $(obj);//缩放对象
  7. this._styleWidth = this._styleHeight = this._styleLeft = this._styleTop = 0;//样式参数
  8. this._sideRight = this._sideDown = this._sideLeft = this._sideUp = 0;//坐标参数
  9. this._fixLeft = this._fixTop = 0;//定位参数
  10. this._scaleLeft = this._scaleTop = 0;//定位坐标
  11. this._mxSet = function(){};//范围设置程序
  12. this._mxRightWidth = this._mxDownHeight = this._mxUpHeight = this._mxLeftWidth = 0;//范围参数
  13. this._mxScaleWidth = this._mxScaleHeight = 0;//比例范围参数
  14. this._fun = function(){};//缩放执行程序
  15. //获取边框宽度
  16. var _style = CurrentStyle(this._obj);
  17. this._borderX = (parseInt(_style.borderLeftWidth) || 0) + (parseInt(_style.borderRightWidth) || 0);
  18. this._borderY = (parseInt(_style.borderTopWidth) || 0) + (parseInt(_style.borderBottomWidth) || 0);
  19. //事件对象(用于绑定移除事件)
  20. this._fR = BindAsEventListener(this, this.Resize);
  21. this._fS = Bind(this, this.Stop);
  22. this.SetOptions(options);
  23. //范围限制
  24. this.Max = !!this.options.Max;
  25. this._mxContainer = $(this.options.mxContainer) || null;
  26. this.mxLeft = Math.round(this.options.mxLeft);
  27. this.mxRight = Math.round(this.options.mxRight);
  28. this.mxTop = Math.round(this.options.mxTop);
  29. this.mxBottom = Math.round(this.options.mxBottom);
  30. //宽高限制
  31. this.Min = !!this.options.Min;
  32. this.minWidth = Math.round(this.options.minWidth);
  33. this.minHeight = Math.round(this.options.minHeight);
  34. //按比例缩放
  35. this.Scale = !!this.options.Scale;
  36. this.Ratio = Math.max(this.options.Ratio, 0);
  37. this.onResize = this.options.onResize;
  38. this._obj.style.position = "absolute";
  39. !this._mxContainer || CurrentStyle(this._mxContainer).position == "relative" || (this._mxContainer.style.position = "relative");
  40. },
  41. //设置默认属性
  42. SetOptions: function(options) {
  43. this.options = {//默认值
  44. Max: false,//是否设置范围限制(为true时下面mx参数有用)
  45. mxContainer:"",//指定限制在容器内
  46. mxLeft: 0,//左边限制
  47. mxRight: 9999,//右边限制
  48. mxTop: 0,//上边限制
  49. mxBottom: 9999,//下边限制
  50. Min: false,//是否最小宽高限制(为true时下面min参数有用)
  51. minWidth: 50,//最小宽度
  52. minHeight: 50,//最小高度
  53. Scale: false,//是否按比例缩放
  54. Ratio: 0,//缩放比例(宽/高)
  55. onResize: function(){}//缩放时执行
  56. };
  57. Extend(this.options, options || {});
  58. },
  59. //设置触发对象
  60. Set: function(resize, side) {
  61. var resize = $(resize), fun;
  62. if(!resize) return;
  63. //根据方向设置
  64. switch (side.toLowerCase()) {
  65. case "up" :
  66. fun = this.Up;
  67. break;
  68. case "down" :
  69. fun = this.Down;
  70. break;
  71. case "left" :
  72. fun = this.Left;
  73. break;
  74. case "right" :
  75. fun = this.Right;
  76. break;
  77. case "left-up" :
  78. fun = this.LeftUp;
  79. break;
  80. case "right-up" :
  81. fun = this.RightUp;
  82. break;
  83. case "left-down" :
  84. fun = this.LeftDown;
  85. break;
  86. case "right-down" :
  87. default :
  88. fun = this.RightDown;
  89. };
  90. //设置触发对象
  91. addEventHandler(resize, "mousedown", BindAsEventListener(this, this.Start, fun));
  92. },
  93. //准备缩放
  94. Start: function(e, fun, touch) {
  95. //防止冒泡(跟拖放配合时设置)
  96. e.stopPropagation ? e.stopPropagation() : (e.cancelBubble = true);
  97. //设置执行程序
  98. this._fun = fun;
  99. //样式参数值
  100. this._styleWidth = this._obj.clientWidth;
  101. this._styleHeight = this._obj.clientHeight;
  102. this._styleLeft = this._obj.offsetLeft;
  103. this._styleTop = this._obj.offsetTop;
  104. //四条边定位坐标
  105. this._sideLeft = e.clientX - this._styleWidth;
  106. this._sideRight = e.clientX + this._styleWidth;
  107. this._sideUp = e.clientY - this._styleHeight;
  108. this._sideDown = e.clientY + this._styleHeight;
  109. //top和left定位参数
  110. this._fixLeft = this._styleLeft + this._styleWidth;
  111. this._fixTop = this._styleTop + this._styleHeight;
  112. //缩放比例
  113. if(this.Scale){
  114. //设置比例
  115. this.Ratio = Math.max(this.Ratio, 0) || this._styleWidth / this._styleHeight;
  116. //left和top的定位坐标
  117. this._scaleLeft = this._styleLeft + this._styleWidth / 2;
  118. this._scaleTop = this._styleTop + this._styleHeight / 2;
  119. };
  120. //范围限制
  121. if(this.Max){
  122. //设置范围参数
  123. var mxLeft = this.mxLeft, mxRight = this.mxRight, mxTop = this.mxTop, mxBottom = this.mxBottom;
  124. //如果设置了容器,再修正范围参数
  125. if(!!this._mxContainer){
  126. mxLeft = Math.max(mxLeft, 0);
  127. mxTop = Math.max(mxTop, 0);
  128. mxRight = Math.min(mxRight, this._mxContainer.clientWidth);
  129. mxBottom = Math.min(mxBottom, this._mxContainer.clientHeight);
  130. };
  131. //根据最小值再修正
  132. mxRight = Math.max(mxRight, mxLeft + (this.Min ? this.minWidth : 0) + this._borderX);
  133. mxBottom = Math.max(mxBottom, mxTop + (this.Min ? this.minHeight : 0) + this._borderY);
  134. //由于转向时要重新设置所以写成function形式
  135. this._mxSet = function(){
  136. this._mxRightWidth = mxRight - this._styleLeft - this._borderX;
  137. this._mxDownHeight = mxBottom - this._styleTop - this._borderY;
  138. this._mxUpHeight = Math.max(this._fixTop - mxTop, this.Min ? this.minHeight : 0);
  139. this._mxLeftWidth = Math.max(this._fixLeft - mxLeft, this.Min ? this.minWidth : 0);
  140. };
  141. this._mxSet();
  142. //有缩放比例下的范围限制
  143. if(this.Scale){
  144. this._mxScaleWidth = Math.min(this._scaleLeft - mxLeft, mxRight - this._scaleLeft - this._borderX) * 2;
  145. this._mxScaleHeight = Math.min(this._scaleTop - mxTop, mxBottom - this._scaleTop - this._borderY) * 2;
  146. };
  147. };
  148. //mousemove时缩放 mouseup时停止
  149. addEventHandler(document, "mousemove", this._fR);
  150. addEventHandler(document, "mouseup", this._fS);
  151. if(isIE){
  152. addEventHandler(this._obj, "losecapture", this._fS);
  153. this._obj.setCapture();
  154. }else{
  155. addEventHandler(window, "blur", this._fS);
  156. e.preventDefault();
  157. };
  158. },
  159. //缩放
  160. Resize: function(e) {
  161. //清除选择
  162. window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();
  163. //执行缩放程序
  164. this._fun(e);
  165. //设置样式,变量必须大于等于0否则ie出错
  166. with(this._obj.style){
  167. width = this._styleWidth + "px"; height = this._styleHeight + "px";
  168. top = this._styleTop + "px"; left = this._styleLeft + "px";
  169. }
  170. //附加程序
  171. this.onResize();
  172. },
  173. //缩放程序
  174. //上
  175. Up: function(e) {
  176. this.RepairY(this._sideDown - e.clientY, this._mxUpHeight);
  177. this.RepairTop();
  178. this.TurnDown(this.Down);
  179. },
  180. //下
  181. Down: function(e) {
  182. this.RepairY(e.clientY - this._sideUp, this._mxDownHeight);
  183. this.TurnUp(this.Up);
  184. },
  185. //右
  186. Right: function(e) {
  187. this.RepairX(e.clientX - this._sideLeft, this._mxRightWidth);
  188. this.TurnLeft(this.Left);
  189. },
  190. //左
  191. Left: function(e) {
  192. this.RepairX(this._sideRight - e.clientX, this._mxLeftWidth);
  193. this.RepairLeft();
  194. this.TurnRight(this.Right);
  195. },
  196. //右下
  197. RightDown: function(e) {
  198. this.RepairAngle(
  199. e.clientX - this._sideLeft, this._mxRightWidth,
  200. e.clientY - this._sideUp, this._mxDownHeight
  201. );
  202. this.TurnLeft(this.LeftDown) || this.Scale || this.TurnUp(this.RightUp);
  203. },
  204. //右上
  205. RightUp: function(e) {
  206. this.RepairAngle(
  207. e.clientX - this._sideLeft, this._mxRightWidth,
  208. this._sideDown - e.clientY, this._mxUpHeight
  209. );
  210. this.RepairTop();
  211. this.TurnLeft(this.LeftUp) || this.Scale || this.TurnDown(this.RightDown);
  212. },
  213. //左下
  214. LeftDown: function(e) {
  215. this.RepairAngle(
  216. this._sideRight - e.clientX, this._mxLeftWidth,
  217. e.clientY - this._sideUp, this._mxDownHeight
  218. );
  219. this.RepairLeft();
  220. this.TurnRight(this.RightDown) || this.Scale || this.TurnUp(this.LeftUp);
  221. },
  222. //左上
  223. LeftUp: function(e) {
  224. this.RepairAngle(
  225. this._sideRight - e.clientX, this._mxLeftWidth,
  226. this._sideDown - e.clientY, this._mxUpHeight
  227. );
  228. this.RepairTop(); this.RepairLeft();
  229. this.TurnRight(this.RightUp) || this.Scale || this.TurnDown(this.LeftDown);
  230. },
  231. //修正程序
  232. //水平方向
  233. RepairX: function(iWidth, mxWidth) {
  234. iWidth = this.RepairWidth(iWidth, mxWidth);
  235. if(this.Scale){
  236. var iHeight = this.RepairScaleHeight(iWidth);
  237. if(this.Max && iHeight > this._mxScaleHeight){
  238. iHeight = this._mxScaleHeight;
  239. iWidth = this.RepairScaleWidth(iHeight);
  240. }else if(this.Min && iHeight < this.minHeight){
  241. var tWidth = this.RepairScaleWidth(this.minHeight);
  242. if(tWidth < mxWidth){ iHeight = this.minHeight; iWidth = tWidth; }
  243. }
  244. this._styleHeight = iHeight;
  245. this._styleTop = this._scaleTop - iHeight / 2;
  246. }
  247. this._styleWidth = iWidth;
  248. },
  249. //垂直方向
  250. RepairY: function(iHeight, mxHeight) {
  251. iHeight = this.RepairHeight(iHeight, mxHeight);
  252. if(this.Scale){
  253. var iWidth = this.RepairScaleWidth(iHeight);
  254. if(this.Max && iWidth > this._mxScaleWidth){
  255. iWidth = this._mxScaleWidth;
  256. iHeight = this.RepairScaleHeight(iWidth);
  257. }else if(this.Min && iWidth < this.minWidth){
  258. var tHeight = this.RepairScaleHeight(this.minWidth);
  259. if(tHeight < mxHeight){ iWidth = this.minWidth; iHeight = tHeight; }
  260. }
  261. this._styleWidth = iWidth;
  262. this._styleLeft = this._scaleLeft - iWidth / 2;
  263. }
  264. this._styleHeight = iHeight;
  265. },
  266. //对角方向
  267. RepairAngle: function(iWidth, mxWidth, iHeight, mxHeight) {
  268. iWidth = this.RepairWidth(iWidth, mxWidth);
  269. if(this.Scale){
  270. iHeight = this.RepairScaleHeight(iWidth);
  271. if(this.Max && iHeight > mxHeight){
  272. iHeight = mxHeight;
  273. iWidth = this.RepairScaleWidth(iHeight);
  274. }else if(this.Min && iHeight < this.minHeight){
  275. var tWidth = this.RepairScaleWidth(this.minHeight);
  276. if(tWidth < mxWidth){ iHeight = this.minHeight; iWidth = tWidth; }
  277. }
  278. }else{
  279. iHeight = this.RepairHeight(iHeight, mxHeight);
  280. }
  281. this._styleWidth = iWidth;
  282. this._styleHeight = iHeight;
  283. },
  284. //top
  285. RepairTop: function() {
  286. this._styleTop = this._fixTop - this._styleHeight;
  287. },
  288. //left
  289. RepairLeft: function() {
  290. this._styleLeft = this._fixLeft - this._styleWidth;
  291. },
  292. //height
  293. RepairHeight: function(iHeight, mxHeight) {
  294. iHeight = Math.min(this.Max ? mxHeight : iHeight, iHeight);
  295. iHeight = Math.max(this.Min ? this.minHeight : iHeight, iHeight, 0);
  296. return iHeight;
  297. },
  298. //width
  299. RepairWidth: function(iWidth, mxWidth) {
  300. iWidth = Math.min(this.Max ? mxWidth : iWidth, iWidth);
  301. iWidth = Math.max(this.Min ? this.minWidth : iWidth, iWidth, 0);
  302. return iWidth;
  303. },
  304. //比例高度
  305. RepairScaleHeight: function(iWidth) {
  306. return Math.max(Math.round((iWidth + this._borderX) / this.Ratio - this._borderY), 0);
  307. },
  308. //比例宽度
  309. RepairScaleWidth: function(iHeight) {
  310. return Math.max(Math.round((iHeight + this._borderY) * this.Ratio - this._borderX), 0);
  311. },
  312. //转向程序
  313. //转右
  314. TurnRight: function(fun) {
  315. if(!(this.Min || this._styleWidth)){
  316. this._fun = fun;
  317. this._sideLeft = this._sideRight;
  318. this.Max && this._mxSet();
  319. return true;
  320. }
  321. },
  322. //转左
  323. TurnLeft: function(fun) {
  324. if(!(this.Min || this._styleWidth)){
  325. this._fun = fun;
  326. this._sideRight = this._sideLeft;
  327. this._fixLeft = this._styleLeft;
  328. this.Max && this._mxSet();
  329. return true;
  330. }
  331. },
  332. //转上
  333. TurnUp: function(fun) {
  334. if(!(this.Min || this._styleHeight)){
  335. this._fun = fun;
  336. this._sideDown = this._sideUp;
  337. this._fixTop = this._styleTop;
  338. this.Max && this._mxSet();
  339. return true;
  340. }
  341. },
  342. //转下
  343. TurnDown: function(fun) {
  344. if(!(this.Min || this._styleHeight)){
  345. this._fun = fun;
  346. this._sideUp = this._sideDown;
  347. this.Max && this._mxSet();
  348. return true;
  349. }
  350. },
  351. //停止缩放
  352. Stop: function() {
  353. removeEventHandler(document, "mousemove", this._fR);
  354. removeEventHandler(document, "mouseup", this._fS);
  355. if(isIE){
  356. removeEventHandler(this._obj, "losecapture", this._fS);
  357. this._obj.releaseCapture();
  358. }else{
  359. removeEventHandler(window, "blur", this._fS);
  360. }
  361. }
  362. };