前军教程网

中小站长与DIV+CSS网页布局开发技术人员的首选CSS学习平台

不用 canvas 不用 svg 弄个绘图程序

首先声明,这个没啥用处,纯粹是为了研究一下算法,各位看官看看就好。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    aa
    <div id="c1" style="width:400px;height:300px;overflow:hidden;border:solid 1px #ccc;"></div>
    <script>
        (function () {
            //初始化一绘图容器
            function Draw(container) {
                var ifrm = document.createElement("iframe");        //在 iframe 里画,避免干扰(iframe将成为我们的画纸)
                ifrm.style.position = "absolute";                   //iframe 用绝对定位方式
                ifrm.style.width = container.offsetWidth + "px";    //iframe 和 container 一样宽
                ifrm.style.height = container.offsetHeight + "px";  //iframe 和 container 一样高
                ifrm.style.top = container.top + "px";              //iframe 和 cotnainer 一个top
                ifrm.style.left = container.left + "px";            //iframe 和 container 一个left
                ifrm.style.backgroundColor = "#ccc";                //iframe 背景弄成灰色(你想弄啥颜色弄啥颜色)
                ifrm.style.overflow = "hidden";                     //iframe 中的内容超出iframe的size后隐藏,不显示滚动条
                ifrm.style.fontSize = "0px";                        //iframe 中的 font-size 不为0px 的话,空格啥的会影响绘图效果
                ifrm.style.border = "none";                         //去掉 iframe 的边框
                ifrm.style.padding = "0px";                         //去掉 iframe 的 padding
                ifrm.style.margin = "0px";                          //去掉 iframe 的 margin
                ifrm.style.lineHeight = "0px";                      //iframe 行高设为0
                container.appendChild(ifrm);                        //将iframe加载到容器中
                this.inContainer = ifrm.contentWindow.document.body; //将 iframe 的 body 作为画纸
                this.inContainer.style.margin = "0px";              //去掉画纸 margin
                this.inContainer.style.padding = "0px";             //去掉画纸 padding
                this.inContainer.style.width = "100%";              //将画纸宽度设置为 100%,和iframe 一样宽
                this.inContainer.style.height = "100%";             //将画纸高度设置为 100%,和iframe 一样高
                this.inContainer.style.overflow = "hidden";         //内容超出size边界,自动隐藏,不显示滚动条
                this.maxWidth = container.offsetWidth;              //给画纸自定义一个属性叫最大宽度,并将其设置为当前宽度
                this.maxHeight = container.offsetHeight;            //给画纸自定义一个属性叫最大高度,并将其设置为当前高度
            }

            //在画纸上画点,是最最基础的一个绘图,有了点就可以组成任意图线,线、框、圆等
            Draw.prototype.Point = function (x1, y1, opt) {         //为了画点,需要三个参数,x坐标,y坐标,opt 可选属性
                if (x1 >= this.maxWidth || x1 <= 0) return;         //如果点x坐标的范围超出画纸,直接返回
                if (y1 >= this.maxHeight || y1 <= 0) return;        //如果点y坐标的范围超出画纸,直接返回
                
                var p = document.createElement("div");              //create一个div(这里你可以用任意标签,我们的绘图程序,不依赖 canvas、svg 等内容)
                p.style.position = "absolute"                       //div设置为绝对定位
                p.style.backgroundColor = opt?opt.color:"#000";     //如果opt传递了color则设置点的颜色
                p.style.top = y1 + "px";                            //设置 点的 y 坐标
                p.style.left = x1 + "px";                           //设置 点的 x 坐标
                p.style.width = "1px";                              //既然是点,它只有一个像素宽
                p.style.height = "1px";                             //既然是点,它只有一个像素高
                p.style.overflow = "hidden";                        //因为是用 div 来模拟点,如果 div 里头有内容,会把点撑开,所以如果有内容要隐藏,但不能隐藏div本身
                p.style.display = "inline-block";                   //div设置成 inline-block 模式
                p.style.fontSize = "0px";                           //font-szie 设置成 0px,相当于去除空格对尺寸的影响
                p.style.border = "none";                            //div的边框设置成0px
                p.style.padding = "0px";                            //去掉div的padding
                p.style.margin = "0px";                             //去掉div的margin
                p.style.lineHeight = "0px";                         //div行高为0
                this.inContainer.appendChild(p);                    //显示我们用 div 模拟的“点”,这一步相当于把“点”真正的画出来了
            }

            //用上面定义的点来画线
            Draw.prototype.Line = function(x1, y1, x2, y2, opt) {   //画线需要五个参数,起始x坐标、y坐标,结束的x坐标、y坐标,以及可选参数 opt
                var dx = Math.abs(x2 - x1);                         //x坐标 差值                
                var sdx = x2 >= x1 ? 1 : -1;                        //起始 x坐标 和 结束 x坐标 的方向,从左到右为正向,从右到左为反向
                var dy = Math.abs(y2 - y1);                         //y坐标 差值 
                var sdy = y2 >= y1 ? 1 : -1;                        //起始 y坐标 和 结束 y坐标 的方向,从上到下为正向,从下到上为反向

                if (dx==0 && dy==0) {                               //如果线段的起始坐标和结束坐标一致,相当于画个点就完了
                    this.Point(x1,y1,opt);
                } else if (dy == 0) {                               //如果 y1 = y2,相当于画竖线
                    for (var c=0;c<=dx;c++) {                       //从上到下,一个像素一个点
                        this.Point(x1+c*sdx, y1, opt);              //从 x1 画到 x2, sdx 为方向
                    }
                } else if (dx == 0) {                               //如果 x1 = x2, 相当于画横线
                    for (var c=0;c<=dy;c++) {                       //从左到右,一个像素一个点
                        this.Point(x1, y1+c*sdy, opt);              //从 y1 画到 y2, sdy 为方向
                    }
                } else if (dy >= dx) {                              //y坐标差值大于 x坐标差值
                    for (var c=0;c<=dy;c++) {                       //我们就以 y 坐标为基础,按像素递增(如果用短的做递增,那么会出现中间断开的现像)
                        var y = sdy * c;                            //y 没啥说的,一个像素一个像素的递增(sdy表示方向)
                        var x = sdx * y * dx / dy;                  // (x2 - x1) / (y2 - y1) 叫作斜率 dx/dy, 任意思一个点的 x/y 都等于这个斜率,所以 x = y * dx / dy
                        this.Point(x1 + x, y1 + y, opt);            //要把初始值加进去哈
                    }
                } else {                                            //x坐标差值大于 y坐标差值
                    for (var c=0;c<=dx;c++) {                       //我们就以 x 坐标为基础,按像素递增(如果用短的做递增,那么会出现中间断开的现像)
                        var x = sdx * c;                            //x 没啥说的,一个像素一个像素的递增(sdx表示方向)
                        var y = sdy * x * dy / dx;                  // (x2 - x1) / (y2 - y1) 叫作斜率 dx/dy, 任意思一个点的 x/y 都等于这个斜率,所以 y = x / (dx / dy) = x * dy / dx
                        this.Point(x1 + x, y1 + y, opt);            //要把初始值加进去哈
                    }
                }
            }

            //通过点画圆
            Draw.prototype.Circle = function(x, y, r, opt) {        //画圆需要四个参数,圆心(x坐标,y坐标),半径r,以及可选属性 opt
                for (var c = 0; c < r; c++) {                       //从0 开始,一直到半径的长度,一个像素一个像素的递增
                    var drt = Math.sqrt(Math.pow(r,2) - Math.pow(r - c, 2)); 
                                                                    //半径构成斜边,半径 - c 构成 x 轴上的直角三角形边长,y 轴上的边长可通过勾股定理得出

                    //在 x 轴上以像素为单位平移
                    var x1 = x - r + c;                             //2,3 象限圆狐上某两个点的 x 坐标
                    var x2 = x + r - c;                             //1,4 像限圆狐上某两个点的 x 坐标
                    var y1 = y + drt                                //1,2 象限圆狐上某两个点的 y 坐标
                    var y2 = y - drt;                               //3,4 象限圆狐上某两个点的 y 坐标

                    this.Point(x1, y1, opt);                        //2 象限中的点
                    this.Point(x1, y2, opt);                        //3 象限中的点
                    this.Point(x2, y1, opt);                        //1 象限中的点
                    this.Point(x2, y2, opt);                        //4 象限中的点

                    
                    //在 y 轴上以像素为单位平移
                    var y1 = y - r + c;                             //1,2 象限上圆狐上某两个点的 y 坐标
                    var y2 = y + r - c;                             //3, 4 象限上圆狐上某两个点的 y 坐标
                    var x1 = x + drt;                               //1,3 象限上圆狐上某两个点的 x 坐标
                    var x2 = x - drt;                               //2,4 象限上圆狐上某两个点的 x 坐标
                    
                    this.Point(x1, y1, opt);                        //1 象限中的点
                    this.Point(x1, y2, opt);                        //3 象限中的点
                    this.Point(x2, y1, opt);                        //4 象限中的点
                    this.Point(x2, y2, opt);                        //2 象限中的点
                }
            }

            this.Draw = Draw;
        })();  



        //以下是调用测试 
        var d = new Draw(document.getElementById("c1"));

        var x1 = 50; y1 = 50; opt = { color:"#f00" };
        
        d.Point(x1, y1, opt);                           //点
        d.Circle(x1, y1, 3,  { color:"#00f" });         //上面的点看不清楚,用圆框出

        d.Line(x1, y1 + 100, x1, y1 + 100, opt);        //以线画点
        d.Circle(x1, y1 + 100, 3, { color:"#00f" });    //上面的点看不清楚,用圆框出

        d.Line(x1,         y1 + 10,     x1 + 100,   y1 + 10 );        //横线
        d.Line(x1 + 10,    y1,          x1 + 10,    y1 + 100 );       //竖线

        d.Line(x1 + 10,    y1 + 10,     x1 + 100,   y1 + 100);        //45度左上到右下
        d.Line(x1 + 100,   y1 + 10,     x1 + 10,    y1 + 100);        //45度右上到左下

        d.Line(x1 + 10,    y1 + 120,     x1 + 200,   y1 + 130);         //左上右下,小于 45度
        d.Line(x1 + 10,    y1 + 130,     x1 + 200,   y1 + 120);         //右上左下,小于 45度

        d.Line(x1 + 120,    y1 + 20,     x1 + 130,   y1 + 200);         //左上右下,大于 45度
        d.Line(x1 + 130,    y1 + 20,     x1 + 120,   y1 + 200);         //右上左下,大于 45度

        d.Circle(x1 + 100, y1 + 100, 30, opt);
        d.Circle(x1 + 100, y1 + 100, 50, opt);
    </script>
    bb
</body>
</html>

效果如下:

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言