• 用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. 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='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.})();

  • 相关阅读:
    POJ-3026 Borg Maze(BFS+最小生成树)
    HDU-1875 畅通工程再续(最小生成树+判断是否存在)
    POJ-1679 The Unique MST(次小生成树、判断最小生成树是否唯一)
    POJ-1751 Highways(最小生成树消边+输出边)
    POJ-2349 Arctic Network(最小生成树+减免路径)
    POJ-2031 Building a Space Station (球的最小生成树)
    八皇后问题 2n皇后问题
    约瑟夫环
    判断1/N是否为无限小数
    HDU-4004 The Frog's Games (分治)
  • 原文地址:https://www.cnblogs.com/Mygirl/p/2093576.html
Copyright © 2020-2023  润新知