JavaScript中画坐标_ide


核心代码:



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