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



核心代码:

     
     
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 .})();

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值