使用d3画横向组织架构图,兼容ie8(一)

在新单位上班半个月了,干的活都是小儿科的活,今天部门经理给了个图,让我写个组件来实现,图是一个横向的组织架构图。
好久之前就想写个组件来实现的,但由于一直感觉价值不大就没有动手。

网上搜索了下 说是用d3来实现,一顿忙活后,发现大工告成:
这里写图片描述

代码如下:

 <!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title></title>
    <style>
        .node {
            font: 12px sans-serif;
        }

        .textDiv{
            position: absolute;
        }
        .link {
            fill: none;
            stroke: #ccc;
            stroke-width: 1.5px;
        }
    </style>
</head>
<body>
<script type="text/javascript" src="d3.js" ></script>
<script type="text/javascript" src="jquery.js" ></script>
<!--[if lte IE 8]><script src="r2d3.js" charset="utf-8"></script><![endif]-->
<div id="test">2222222222</div>
<script>
    var width = 700,height =720;

    var cluster = d3.layout.tree().size([width, height - 290]);

    var diagonal = d3.svg.diagonal()
            .projection(function(d) {
                return [d.y, d.x];
            });

    var svg = d3.select("body").append("svg")
            .attr("width", width)
            .attr("height", height)
            .append("g")
            .attr("transform", "translate(40,0)");
    var marginTop=19;

    d3.json("data.json", function(error, root) {
        var nodes = cluster.nodes(root);
        var links = cluster.links(nodes);
        var link = svg.selectAll(".link")
                .data(links)
                .enter()
                .append("path")
                .attr("class", "link")
                .attr("d", function(d){
                    return "M"+d.source.y+" "+d.source.x+
                            "L"+(d.source.y+125)+" "+(d.source.x+5)+
                            " L"+(d.source.y+125)+" "+(d.target.x+5)+" L"+
                            d.target.y+" "+(d.target.x+5);

                })
                .attr("style",function(){
                    return "stroke:#F7881F"
                });

        var node = svg.selectAll(".node")
                .data(nodes)
                .enter()
                .append("g")
                .attr("class", "node")
                .attr("transform", function(d) {
                    return "translate(" +( d.y-15) + "," + (d.x+ -10) + ")";
                })



        node.append("rect")
                .attr("width",120)
                .attr("height",30)
                .attr("x",0)
                .attr("y",0)
                .attr("style","fill:#35AD5B;");

        node.append("text")
                .attr("dx", function(d) {
                    return 30;
                })
                .attr("dy", marginTop)
                .style("text-anchor", function(d) {
                    return "middle";
                })
                .style("fill","#fff")
                .text(function(d) { return d.name; });

        node.append("text")
                .attr("dx", function(d) {
                    return 80;
                })
                .attr("dy", marginTop)
                .style("text-anchor", function(d) {
                    return "middle";
                })
                .style("fill","#fff")
                .text(function(d) { return d.number; });
    });
    var getElementPosition = function(el){
        var ua = navigator.userAgent.toLowerCase();
        var isOpera = (ua.indexOf('opera') != -1);
        var isIE = (ua.indexOf('msie') != -1 && !isOpera);
        // not opera spoof
        if(el.parentNode === null || el.style.display == 'none'){
            return false;
        }
        var parent = null;
        var pos = [];
        var box;
        if(el.getBoundingClientRect){//IE
            box = el.getBoundingClientRect();
            var scrollTop = Math.max(document.documentElement.scrollTop, document.body.scrollTop);
            var scrollLeft = Math.max(document.documentElement.scrollLeft, document.body.scrollLeft);
            return {x:box.left + scrollLeft, y:box.top + scrollTop};
        }else if(document.getBoxObjectFor){ // gecko
            box = document.getBoxObjectFor(el);
            var borderLeft = (el.style.borderLeftWidth)?parseInt(el.style.borderLeftWidth):0;
            var borderTop = (el.style.borderTopWidth)?parseInt(el.style.borderTopWidth):0;
            pos = [box.x - borderLeft, box.y - borderTop];
        }else{// safari & opera
            pos = [el.offsetLeft, el.offsetTop];
            parent = el.offsetParent;
            if (parent != el) {
                while (parent) {
                    pos[0] += parent.offsetLeft;
                    pos[1] += parent.offsetTop;
                    parent = parent.offsetParent;
                }
            }
            if (ua.indexOf('opera') != -1|| ( ua.indexOf('safari') != -1 && el.style.position == 'absolute')){
                pos[0] -= document.body.offsetLeft;
                pos[1] -= document.body.offsetTop;
            }
        }
        if (el.parentNode){
            parent = el.parentNode;
        }else{
            parent = null;
        }
        while (parent && parent.tagName != 'BODY' && parent.tagName != 'HTML'){ // account for any scrolled ancestors
            pos[0] -= parent.scrollLeft;         pos[1] -= parent.scrollTop;
            if (parent.parentNode) {
                parent = parent.parentNode;
            }else {
                parent = null;
            }
        }
        return {x:pos[0], y:pos[1]};
    }

</script>

</body>
</html>

以为可以交差了,也没难度嘛,但知道部门经理说必须支持ie8,哭都来不急哦。网上度娘一番,度娘说可以通过r2d3.js来解决ie8的兼容,又松了空气,一顿忙活,在js引入的地方加入:

<!--[if lte IE 8]><script src="r2d3.js" charset="utf-8"></script><![endif]-->

效果如下:

这里写图片描述

真是坑爹啊,这叫兼容啊,线条颜色没了,字也没咯,线条加粗也没咯,怎么拿出来见人啊。
本打算去修改r2d3.js来实现功能,发现不现实。1w多行代码,而且写的一个字评价就是乱。

最后只能放弃r2d3.js了,自己写个组件来兼容ie8了,思路还是比较简单的就是判断如果是ie8浏览器采用vml来画图,如果是其他浏览器或者ie9或者ie9以上都采用d3.js来画图。

ie8下画vml,需要修改html的属性,在画图前执行该函数。(申明下:不考虑兼容ie8以下的浏览器)

第一步:修改html的属性,调用该函数后就可以通过js动态来添加图了。

function addVmlParam() {
    if (!document.namespaces['v']) {
        if (document.documentMode && document.documentMode >= 8) {
            var o = document.getElementsByTagName("HTML") || document.getElementsByTagName["html"];
            o[0].setAttribute("xmlns:v", "urn:schemas-microsoft-com:vml");
            $('<style>v\:rect,v\:Line,v\:oval,v\:PolyLine{ display:inline-block }</style>').appendTo(document.body);
        }
    }
}

第二步:ie8 下添加vml元素需要添加

 if ($.browser.msie8) {
        $('<?import namespace="v" implementation="#default#VML" ?>' +
            '<v:PolyLine filled="false" Points="0,0" style="position:absolute;z-index:80"/>'
        ).appendTo(document.body);
    }

第三步:就是根据d3.js生产的svg元素来转换成vml图元素。

//根据后台url来加载数据 返回一个json字符串
HTreeImg.prototype.loadJson = function (url, fun) {
    d3.json(url, function (error, root) {
        fun(root);
    });
    //如果是ie8  则进行转换
    if ($.browser.msie8) {
        var htreeImg = this;
        var changeTimeout = setTimeout(function () {
            htreeImg.changeNodesToVml();
            htreeImg.changeLinksToVml();
        }, 100);
        changeTimeout = null;
    }
}

核心代码

HTreeImg.prototype.changeNodesToVml = function (root) {
    function guid() {
        function S4() {
            return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
        }

        return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4());
    }

    function addTexts(texts, htmls) {
        var curLeft = 0;
        if (texts.length == 1) {
            var text = $(texts.get(0)).attr("textContent");
            var left = $(texts.get(0)).attr("dx");
            left = left - curLeft;
            curLeft = curLeft + left;
            htmls.push('<div class="textContent" style="text-align: center;width:100%;">' + text + '</div>');
        } else {
            //循环里面的所有text节点 并进行添加操作
            texts.each(function () {
                var text = $(this).attr("textContent");
                var left = $(this).attr("dx");
                left = left - curLeft;
                curLeft = curLeft + left;
                htmls.push('<div class="textContent" style="left:' + left + 'px">' + text + '</div>');
            });
        }

    }

    var hTreeImg = this;
    var _options = this.nodeOptions;
    //获取所有节点 并且进行循环
    var nodes = $("svg").find(".node");
    var orgTree=this;
    nodes.each(function () {
        var transform = $(this).attr("transform");
        var ary = _getXYPosition(transform);
        var texts = $(this).find("text");
        var htmls = [];
        addTexts(texts, htmls);
        var nodeId=$(this).find("rect").attr("nodeId");
        var nodeDepth=$(this).find("rect").parent().attr("depth");
        console.log(nodeDepth)
        //对第一个节点进行处理
        var leftPx = ary.x;
        //根据传入的左边距 对所有节点进行边距移动操作
        leftPx = ary.x + hTreeImg._marginLeft;
        var nodeDivId = guid();
        $("<div id='" + nodeDivId + "' nodeId='"+nodeId+"' class='textDiv text_clearFix' " +
            "style='top:" + (ary.y + 8) + "px;" +
            "width:" + _options["width"] + "px;" +
            "height:" + _options["height"] + "px;" +
            "background-color:" + _options["bgColor"] + ";" +
            "left:" + (leftPx) + "px'>"
            + htmls.join("\n")
            + "</div>").appendTo(document.body);
        //注册点击事件
        if (_options["fun"] != null) {
            $("#" + nodeDivId).click(function () {
                var nodeData=orgTree.data[$(this).attr("nodeId")];
                if(nodeData!=null){
                    _options["fun"](nodeData);
                }
                nodeData=null;
            })
        }
    })
}
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值