现在的位置: 首页 > 综合 > 正文

用JavaScript画直线、圆、椭圆(不用VML,Canvas)来自greatghoul(http://greatghoul.iteye.com)

2013年12月09日 ⁄ 综合 ⁄ 共 5331字 ⁄ 字号 评论关闭


核心代码:

1./** 2. * GCanvas 1.2 3. * @author GreatGhoul 4. * @email: greatghoul@gmail.com 5. * @blog: http://greatghoul.iteye.com 6. */ 7.(function() { 8. // 创建GCanvas构造方法的闭包和全局引用 9. var GCanvas = window.GCanvas = function(id, w, h) { 10. return new Canvas(id, w, h); 11. } 12. 13. /** 14. * 用指定的id, 长和宽构造一个画板 15. * 16. * @param id html元素的id 17. * @param w 指定的画板宽度 18. * @param h 指定的画板高度 19. */ 20. var Canvas = function(id, w, h) { 21. // 只想Canvas实例,以修正this指针的引用错误. 22. var self = this; 23. 24. // 缓冲器 25. var cache = []; 26. 27. // 画板绑定到的html元素的引用 28. var canvas = document.getElementById(id); 29. 30. // 画板底色, 默认为浅灰色 31. var bgColor = "lightgray"; 32. 33. // 笔刷的颜色, 默认为黑色 34. var fgColor = "black"; 35. 36. // 原点坐标, 初始为(0, 0) 37. var oX = 0, oY = 0; 38. 39. // 是否允许点画到画板边界以外 40. var allowOutside = false; 41. 42. // 渲染html元素 43. canvas.onselectstart = function() {return false;} 44. canvas.style.overflow = "hidden"; 45. canvas.style.background = "lightblue"; 46. canvas.style.width = (w ? w : 400) + "px"; 47. canvas.style.height = (h ? h : 400) + "px"; 48. 49. this.copyright = function() { 50. var c = "# G2W GCanvas [Version 1.2]\n" 51. + "# (C) Copyright 2009-2010 G2W Blog.\n" 52. + "# http://greatghoul.iteye.com \n"; 53. 54. return c; 55. } 56. 57. /** 58. * 获取画板左上角的在文档中的绝对坐标 59. * 60. * @return 形如{x, y}的坐标 61. */ 62. this.pos = function() { 63. var rect = canvas.getClientRects()[0]; 64. return { 65. x: rect.left, 66. y: rect.top 67. }; 68. } 69. 70. /** 71. * 清空画板 72. */ 73. this.clear = function() { 74. cache = []; 75. canvas.innerHTML = ""; 76. } 77. 78. /** 79. * 设置或取得画板的大小, 如果缓存不为空,则设置无效 80. * 81. * @param w 新的宽度 82. * @param h 新的高度 83. * @return 形如{width, height}的尺寸 84. */ 85. this.size = function(w, h) { 86. if (w && h) { 87. if (cache.length != 0) return; 88. canvas.style.width = w + "px"; 89. canvas.style.height = h + "px"; 90. } else { 91. return { 92. width: parseInt(canvas.style.width), 93. height: parseInt(canvas.style.width) 94. }; 95. } 96. } 97. 98. /** 99. * 设置或取得是否允许点显示到画板边界以外 100. * 101. * @param flag true为允许显示,false为不允许,其它为不做改变 102. * @return 是否允许显示 103. */ 104. this.allowOutside = function(flag) { 105. if (flag == true || flag == false) 106. allowOutside = flag; 107. return allowOutside; 108. } 109. 110. /** 111. * 设置或取得笔刷颜色 112. * 颜色的格式为: 113. * rgb(r, g, b) 其中r, g, b为0-255的整数 114. * #000000 ~ #FFFFFF 115. * 字符串描述 如: red, blue, black, lightblue 116. * 117. * @param color 新的笔刷颜色 118. * @return 当前笔刷颜色 119. */ 120. this.fgColor = function(color) { 121. fgColor = (color ? color: fgColor); 122. return fgColor; 123. } 124. 125. /** 126. * 设置或取得画布颜色 127. * 颜色的格式为: 128. * rgb(r, g, b) 其中r, g, b为0-255的整数 129. * #000000 ~ #FFFFFF 130. * 字符串描述 如: red, blue, black, lightblue 131. * 132. * @param color 新的画布颜色 133. * @return 当前画布颜色 134. */ 135. this.bgColor = function(color) { 136. bgColor = (color ? color: bgColor); 137. canvas.style.background = bgColor; 138. return bgColor; 139. } 140. 141. /** 142. * 在给定的坐标出画点 143. * 144. * @param x x坐标 145. * @param y y坐标 146. */ 147. this.point = function(x, y) { 148. var pos = self.pos(); 149. var size = self.size(); 150. x = pos.x + oX + x; 151. y = pos.y + oY + y; 152. 153. // 如果不允许在边界外显示点,则不讲该点推入缓存 154. if (!allowOutside 155. && !((x >= pos.x && x <= pos.x + size.width) 156. && (y >= pos.y && y <= pos.y + size.height))) 157. return; 158. cache.push("<div style='width:1px;height:1px;position:absolute;left:" + x +"px;top:" + y + "px;background-color:" + fgColor + ";font-size:0px;z-index:999;'></div>"); 159. } 160. 161. /** 162. * 数值微分法画直线 163. * 164. * @param x0 起点x坐标 165. * @param y0 起点y坐标 166. * @param x1 终点x坐标 167. * @param y1 终点y坐标 168. */ 169. function line_DDA(x0, y0, x1, y1) { 170. var px = x0, py = y0; 171. var dx = x1 - x0; 172. var dy = y1 - y0; 173. var incX = 0, incY = 0; 174. var epsl = Math.abs(dx) > Math.abs(dy) ? Math.abs(dx) : Math.abs(dy); 175. incX = dx / epsl; 176. incY = dy / epsl; 177. for (var i = 0; i < epsl; i++) { 178. self.point(parseInt(px + 0.5), parseInt(py + 0.5)); 179. px += incX; 180. py += incY; 181. } 182. } 183. 184. /** 185. * 用给定的起点和终点坐标画直线 186. * 187. * @param x0 起点x坐标 188. * @param y0 起点y坐标 189. * @param x1 终点x坐标 190. * @param y1 终点y坐标 191. */ 192. this.line = function(x0, y0, x1, y1) { 193. line_DDA(x0, y0, x1, y1); 194. } 195. 196. /** 197. * 用中点Bresenham法画圆 198. * 199. * @param x 圆心x坐标 200. * @param y 圆心y坐标 201. * @param r 圆的半径 202. */ 203. function circle_MidBresenham(x, y, r) { 204. var px, py, d; 205. px = 0; py = r; d = 1 - r; 206. while (px < py) { 207. self.point(x + px, y + py); 208. self.point(x + py, y + px); 209. self.point(x - px, y + py); 210. self.point(x + py, y - px); 211. self.point(x + px, y - py); 212. self.point(x - py, y + px); 213. self.point(x - px, y - py); 214. self.point(x - py, y - px); 215. if (d < 0) d += 2 * px + 3; 216. else { 217. d += 2 * (px - py) + 5; 218. py--; 219. } 220. px++; 221. } 222. } 223. 224. /** 225. * 用给定的圆心坐标和半径画圆 226. * 227. * @param x 圆心x坐标 228. * @param y 圆心y坐标 229. * @param r 圆的半径 230. */ 231. this.circle = function(x, y, r) { 232. circle_MidBresenham(x, y, r); 233. } 234. 235. /** 236. * 用中点Bresenham法画椭圆 237. * 238. * @param x 圆心x坐标 239. * @param y 圆心y坐标 240. * @param a 长半轴长度 241. * @param b 短半轴长度 242. */ 243. function MidBresenhamEllipse(x, y, a, b) { 244. var px, py; 245. var d1, d2; 246. px = 0; 247. py = b; 248. d1 = b * b + a * a * (-b + 0.25); 249. self.point(x + px, y + py); 250. self.point(x - px, y - py); 251. self.point(x - px, y + py); 252. self.point(x + px, y - py); 253. while (b * b * (px + 1) < a * a * (py - 0.5)) { 254. if (d1 <= 0) { 255. d1 += b * b * (2 * px + 3); 256. px++; 257. } else { 258. d1 += b * b * (2 * px + 3) + a * a * (-2 * py + 2); 259. px++; 260. py--; 261. } 262. self.point(x + px, y + py); 263. self.point(x - px, y - py); 264. self.point(x - px, y + py); 265. self.point(x + px, y - py); 266. } 267. d2 = b * b * (px + 0.5) * (px + 0.5) + a * a * (py - 1) * (py - 1) - a * a * b * b; 268. while (py > 0) { 269. if (d2 <= 0) { 270. d2 += b * b * (2 * px + 2) + a * a * (-2 * py + 3); 271. px++; 272. py--; 273. } else { 274. d2 += a * a * (-2 * py + 3); 275. py--; 276. } 277. self.point(x + px, y + py); 278. self.point(x - px, y - py); 279. self.point(x - px, y + py); 280. self.point(x + px, y - py); 281. } 282. } 283. 284. /** 285. * 用给定的圆心坐标和长短半轴画椭圆 286. * 287. * @param x 圆心x坐标 288. * @param y 圆心y坐标 289. * @param a 长半轴长度 290. * @param b 短半轴长度 291. */ 292. this.ellipse = function(x, y, a, b) { 293. MidBresenhamEllipse(x, y, a, b); 294. } 295. 296. 297. /** 298. * 将缓存中的图像显示到画板上,并清空缓存 299. */ 300. this.paint = function() { 301. canvas.innerHTML += cache.join("");; 302. cache = []; 303. } 304. } 305.})();

抱歉!评论已关闭.