JavaScript SVG分叉树

来源:互联网 发布:淘宝客销量不计入权重 编辑:程序博客网 时间:2024/04/28 06:43
<!-- <!DOCTYPE> 声明不是 HTML 标签;它是指示 web 浏览器关于页面使用哪个 HTML 版本进行编写的指令。 --><!-- 下面这个是HTML5标志 --><!DOCTYPE html><html>    <head>        <meta charset="utf8" />        <title>SVG Fractal Tree</title>        <style type="text/css">            body {                /* 背景是银色,注意CSS中仅"多行注释"这一种注释有效 */                background-color: silver;            }            svg {                border: 1px dashed black;            }            svg line {                stroke: black;                stroke-width: .05;            }        </style>    </head>    <body>        <!-- SVG和Canvas一样,width和height设置在style中是无效的 -->        <svg xmlns="http://www.w3.org/2000/svg"            xmlns:xlink="http://www.w3.org/1999/xlink"            id="svg" width="100" height="100" >            <defs id="defs">                <line id="stem" x1="0" y1="0" x2="0" y2="-1" />            </defs>        </svg>        <script type="text/javascript">            //SVG 名空间            var xmlns_svg = "http://www.w3.org/2000/svg";            //xlink 名空间            var xmlns_xlink = "http://www.w3.org/1999/xlink";            var svg = document.getElementById("svg");            var defs = document.getElementById("defs");            //茎ID            var stemId = "stem";            //树ID            var treeId = "tree";            //树的最大深度            var maxDepth = 9;            //绘制间隔(单位:毫秒)            var drawInterval = 500;            var dx = 400;            var dy = 350;            //创建SVG标签            function createSvgElem(elemTag) {                return document.createElementNS(xmlns_svg, elemTag);            }            //组合成树的transform属性            function formTreeTransform(dx, dy) {                return "translate(" + dx + "," + dy + ") scale(100)";            }            //组合成茎的transform属性            function formStemTransform(degree) {                return "translate(0,-1) rotate(" + degree + ") scale(.7)";            }            //树            var Tree = function(elem, degree) {                //当前深度                this.depth = 1;                this.stemLeftTransform = formStemTransform(-1 * degree);                this.stemRightTransform = formStemTransform(degree);                console.log(degree +","+this.depth+" init");                //画下一级的枝干                this.grow = function() {                    console.log(degree+","+this.depth);                    //这里用直接用诸如_this=tree是不合法的,因为没有使用var声明的都是全局变量,会呼吸影响                    var prevId = "#" + degree + "_" + (this.depth - 1) + "_" + stemId;                    var id = degree + "_" + this.depth + "_" + stemId;                    var g = createSvgElem("g");                    var use1 = createSvgElem("use");                    var use2 = createSvgElem("use");                    var use3 = createSvgElem("use");                    g.setAttribute("id", id);                    //g.setAttributeNS(null, "id", id);                    use1.setAttributeNS(xmlns_xlink, "xlink:href", prevId);                    use1.setAttribute("transform", this.stemLeftTransform);                    //use1.setAttributeNS(null, "transform", this.stemLeftTransform);                    use2.setAttributeNS(xmlns_xlink, "xlink:href", prevId);                    use2.setAttribute("transform", this.stemRightTransform);                    //use2.setAttributeNS(null, "transform", this.stemRightTransform);                    use3.setAttributeNS(xmlns_xlink, "xlink:href", "#" + stemId);                    defs.appendChild(g);                    g.appendChild(use1);                    g.appendChild(use2);                    g.appendChild(use3);                    elem.setAttributeNS(xmlns_xlink, "xlink:href", "#" + id);                    update(this);                }                //由于函数是全局的,因此内部没有定义this对象                function update(tree) {                    if(tree.depth < maxDepth) {                        tree.depth++;                        //setTimeout的参数必须是一个函数,而不能是函数变量,所以必须使用匿名函数做转接                        setTimeout(function(){                            tree.grow();                        }, drawInterval);                    }                }            }            function init() {                var degrees = new Uint8Array([15, 25, 35, 45]);                //svg只能用setAttribute的方式设置宽高,不能像canvas一样直接用width=value来设置                svg.setAttribute("width", dx * 2);                svg.setAttribute("height", dy * Math.floor(degrees.length / 2) + 20);                for(var i=0; i < degrees.length; i++) {                    var id = degrees[i] + "_" + treeId;                    var use = createSvgElem("use");                    use.setAttributeNS(null, "transform", formTreeTransform((.5 + i % 2) * dx, Math.floor(i / 2 + 1) * dy));                    svg.appendChild(use);                    var tree = new Tree(use, degrees[i]);                    tree.grow();                    /*                    这里使用setTimeout,会导致只有循环的最后一个tree的grow方法有效,                    通过全局变量和参数传递的方式也不能解决                    原因未知????????????                    setTimeout(function(){                        tree.grow();                    }, drawInterval);                    */                }            }            init();        </script>    </body></html>

这里写图片描述

2 0