一、首先引用D3.js插件庫,還有jquery.js,因?yàn)檫@個(gè)demo是基于jquery實(shí)現(xiàn)的。
二、D3圖demo主文件 -- index.html
<!DOCTYPE html >
<html xmlns="http://www.w3.org/1999/xhtml">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script src="jquery-2.1.0.js"></script>
<script src="checkDate.js"></script>
<script src="d3.min.js"></script>?
<body>
<!--<a id="cropButton"? title="保存為圖片"? href="javascript:void(0);" ><img src="../../images/save2.png"? style="width:25px;height:25px;"/></a>-->
<div id="chart" style="width:100%;overflow:auto;">
</div>
<div class="flag" id="ddd" style="left: 724px; top: 66px; display: none; opacity: 1;">
</div>
<div id="bgDiv">
<div id="agen" >
<div id="agenda">
</div>
</div>
</div>
<script>
? ? var bgDiv=document.getElementById("bgDiv");
? ? var sHeight=window.screen.height-200;
? ? var aHeight=(sHeight-200)/2;
? ? if(aHeight<0){
? ? ? ? aHeight=0;
? ? }
? ? bgDiv.style.display="block";
? ? $("#agen").attr("style","margin-top:"+aHeight+"px");
? ? var w = 850,
? ? ? ? ? ? h = 500,
? ? ? ? ? ? i = 0,
? ? ? ? ? ? barHeight = 20,
? ? ? ? ? ? duration = 400,
? ? ? ? ? ? root,
? ? ? ? ? ? item_w=13,
? ? ? ? ? ? item_h=13,
? ? ? ? ? ? timeTick=0;
? ? var tree = d3.layout.tree()
? ? ? ? ? ? .size([h, 100]);
? ? var itemImg,vis;
? ? var xTime = d3.time.scale().range([0, w-300]);
? ? var color = d3.scale.category10();
? ? var color1 = ["gray","#fe6263","orange","#2196F3","#69c970"];
? ? var parseDate = d3.time.format("%Y/%m/%d").parse;
? ? var diagonal = d3.svg.diagonal()
? ? ? ? ? ? .projection(function(d) { return [d.y,d.x] });
? ? var mintime;
? ? var maxtime;
? ? var id="1508738733433";
? ? var leveljson;?
var data = {
"data": {
"total": 7,
"data": {
"redu": 3,
"color": 0,
"children": [{
"summary": "考試人員為符合公司專業(yè)、學(xué)歷等要求,2.有相關(guān)工作經(jīng)驗(yàn)者優(yōu)先錄用,具有專業(yè)相關(guān)工作經(jīng)歷者優(yōu)先,符合招聘崗位工作要求,376985322@qq.com 寧夏寧東擔(dān)保有限公司招人 一、招聘崗位及要求 (一)公司副總經(jīng)理 1.全日制大學(xué)本科及以上學(xué)歷,依據(jù)筆試、面試成績和國家電網(wǎng)公司要求, 二、組織招聘考試 1.公司按照國家電網(wǎng)公司安排2018年4月1日組織第二批統(tǒng)一考試,3.有房地產(chǎn)/代理公司工作經(jīng)驗(yàn)者優(yōu)先錄用,一招聘崗位及要求 1.大學(xué)??萍耙陨蠈W(xué)歷,是公司發(fā)布招聘信息、應(yīng)聘者報(bào)名的唯一渠道",
"redu": 3,
"color": 0,
"children": null,
"tendency": 0,
"name": "寧夏這些單位正在大量招人,找工作的快來!",
"endtime": "2018/03/16",
"id": 2393,
"source": null,
"starttime": "2018/03/15",
"url": null,
"docPublishtime": null
}, {
"summary": "有意應(yīng)聘者請登錄交通銀行招聘網(wǎng)站進(jìn)行簡歷投遞,金融同業(yè)的正式員工相關(guān)工作經(jīng)驗(yàn)可放寬至一年,金融同業(yè)的正式員工相關(guān)工作經(jīng)驗(yàn)可放寬至一年,交通銀行是中國境內(nèi)主要綜合金融服務(wù)提供商之一,(5)具有會計(jì)從業(yè)資格證或銀行從業(yè)資格證等相關(guān)資格證書者優(yōu)先,(5)具有會計(jì)從業(yè)資格證或銀行從業(yè)資格證等相關(guān)資格證書者優(yōu)先,符合交通銀行親屬回避規(guī)定,運(yùn)行管理 職位信息,? (5)?具有相關(guān)資格證書者或具有金融IT從業(yè)經(jīng)歷者優(yōu)先,交通銀行寧波分行組建于1987年10月26日",
"redu": 2,
"color": 0,
"children": null,
"tendency": 0,
"name": "【HR招聘】交通銀行股份有限公司寧波分行",
"endtime": "2018/03/15",
"id": 2392,
"source": null,
"starttime": "2018/03/15",
"url": null,
"docPublishtime": null
}, {
"summary": "中國最低工資是世界平均工資的21%,中國最低工資是平均工資的21%,? 世界最低工資平均是人均GDP的58%,因?yàn)槭澜缍鄶?shù)國家公務(wù)員工資是最低工資的2倍,? 中國最低工資是人均GDP的25%,平均每年增長1.52%. ? 2.公務(wù)員工資是最低工資的2倍 ? 可對比性工資制度被世界多數(shù)國家改采納,最低工資與人均GDP的比值世界平均為58%(國際勞工組織《世界工資報(bào)告08/09》的數(shù)據(jù)是60%,最低工資是人均GDP的58%,目前中國的最低工資只是人均GDP的25%,中國公務(wù)員工資是最低工資的6倍",
"redu": 2,
"color": 0,
"children": null,
"tendency": 0,
"name": "讓國人震驚的“工資調(diào)查”",
"endtime": "2018/03/15",
"id": 2394,
"source": null,
"starttime": "2018/03/15",
"url": null,
"docPublishtime": null
}],
"tendency": null,
"name": "交通銀行",
"endtime": "2018/03/16",
"id": 152117033395127300,
"source": null,
"starttime": "2018/03/15",
"url": null,
"docPublishtime": null
}
},
"httpCode": 200,
"msg": "請求成功",
"timestamp": 1521538054458
};
? ? ? ? ? ? if(data.httpCode==200){
? ? ? ? ? ? ? ? if(data.data!=undefined){
? ? ? ? ? ? ? ? ? root= data.data.data;
? ? ? ? ? ? ? ? ? ? root.x0 = 0;
? ? ? ? ? ? ? ? ? ? root.y0 = 0;
? ? ? ? ? ? ? ? ? ? if(root!=null){
? ? ? ? ? ? ? ? ? ? ? ? bgDiv.style.display="none";
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? //給d3.js傳數(shù)據(jù)。
? ? ? ? ? ? ? ? ? ? var nodes = tree.nodes(root);
? ? ? ? ? ? ? ? ? ? var wh;
? ? ? ? ? ? ? ? ? ? // Compute the "layout".
? ? ? ? ? ? ? ? ? ? nodes.forEach(function(n, i) {
? ? ? ? ? ? ? ? ? ? ? ? n.x = i * barHeight*1.2;
? ? ? ? ? ? ? ? ? ? ? ? n.x= n.x+20;
? ? ? ? ? ? ? ? ? ? ? ? wh=n.x;
? ? ? ? ? ? ? ? ? ? });
? ? ? ? ? ? ? ? ? ? leveljson = root;
? ? ? ? ? ? ? ? ? ? var mynodes = tree.nodes(root);
? ? ? ? ? ? ? ? ? ? var mintime = d3.min(mynodes,function(d){return d.starttime});
? ? ? ? ? ? ? ? ? ? var maxtime = d3.max(mynodes,function(d){return d.endtime});
? ? ? ? ? ? ? ? ? ? xTime.domain([parseDate(mintime),parseDate(maxtime)]);
? ? ? ? ? ? ? ? ? ? var reg=new RegExp("\/","g");
? ? ? ? ? ? ? ? ? ? var tt1=mintime.replace(reg,"-");
? ? ? ? ? ? ? ? ? ? var tt2=maxtime.replace(reg,"-");
? ? ? ? ? ? ? ? ? ? var days =dateDiff(tt1,tt2);
? ? ? ? ? ? ? ? ? ? //timeTick=days<8?1:(days<16?2:4);
? ? ? ? ? ? ? ? ? ? if(days<8){
? ? ? ? ? ? ? ? ? ? ? ? timeTick=1;
? ? ? ? ? ? ? ? ? ? }else{
? ? ? ? ? ? ? ? ? ? ? ? timeTick=Math.floor(days/8);
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? var xAxisTime = d3.svg.axis()
? ? ? ? ? ? ? ? ? ? ? ? ? ? .scale(xTime)
? ? ? ? ? ? ? ? ? ? ? ? ? ? .orient("top")
? ? ? ? ? ? ? ? ? ? ? ? ? ? .ticks(d3.time.days, timeTick)
? ? ? ? ? ? ? ? ? ? ? ? ? ? .tickFormat(d3.time.format('%m'+'/'+'%d'));
? ? ? ? ? ? ? ? ? ? //alert(timeTick);
? ? ? ? ? ? ? ? ? ? vis = d3.select("#chart").append("svg:svg")
? ? ? ? ? ? ? ? ? ? ? ? ? ? .attr("width", w)
? ? ? ? ? ? ? ? ? ? ? ? ? ? .attr("height", wh+100)
? ? ? ? ? ? ? ? ? ? ? ? ? ? .append("svg:g")
? ? ? ? ? ? ? ? ? ? ? ? ? ? .attr("transform", "scale(1,1)translate(30,30)");
? ? ? ? ? ? ? ? ? ? vis.append("g")
? ? ? ? ? ? ? ? ? ? ? ? ? ? .attr("class", "x axis")
? ? ? ? ? ? ? ? ? ? ? ? ? ? .style("fill","none")
? ? ? ? ? ? ? ? ? ? ? ? ? ? .style("stroke","gray")
.style("font-size", "12px")
? ? ? ? ? ? ? ? ? ? ? ? ? ? .attr("transform", "translate(0,3)")
? ? ? ? ? ? ? ? ? ? ? ? ? ? .call(xAxisTime)
? ? ? ? ? ? ? ? ? ? ? ? ? ? .style("opacity",1)
? ? ? ? ? ? ? ? ? ? ? ? ? ? .append("text")
? ? ? ? ? ? ? ? ? ? ? ? ? ? .attr("class", "xlabel")
? ? ? ? ? ? ? ? ? ? ? ? ? ? .attr("x", w - 150)
? ? ? ? ? ? ? ? ? ? ? ? ? ? .attr("y", 0)
? ? ? ? ? ? ? ? ? ? ? ? ? ? .style("text-anchor", "end")
.style("font-size", "12px")
? ? ? ? ? ? ? ? ? ? ? ? ? ? .text("時(shí)間");
? ? ? ? ? ? ? ? ? ? update(root);
? ? ? ? ? ? ? ? }else{
? ? ? ? ? ? ? ? ? ? $("#chart").html("無數(shù)據(jù)");
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
function update(source) {
? // Compute the flattened node list. TODO use d3.layout.hierarchy.
? var nodes = tree.nodes(root);
? // Compute the "layout".
? nodes.forEach(function(n, i) {
? ? n.x = i * barHeight*1.2;
n.x= n.x+20;
? });
? // Update the nodes…
? var node = vis.selectAll("g.node")
? ? ? .data(nodes, function(d) { return d.id || (d.id = ++i); });
? var nodeEnter = node.enter().append("svg:g") ;
? nodeEnter.append("svg:rect")
? .attr("rx","9px")
? ? ? .attr("y", -barHeight / 2 )
? ? ? .attr("height", barHeight)
? ? ? .attr("stroke-width",3)
? ? ? .attr("stroke",function(d,i) {
? ? ? ? ? if(d.tendency==1){
? ? ? ? ? ? ? return color1[4];
? ? ? ? ? }else if(d.tendency==0){
? ? ? ? ? ? ? return color1[3];
? ? ? ? ? }else if(d.tendency==-1){
? ? ? ? ? ? ? return color1[1];
? ? ? ? ? }else{
? ? ? ? ? ? ? return color1[0];
? ? ? ? ? }
? ? ? ? // return color1[d.color];
? ? ? })
? .attr("width",function(d,i) { if(i==0){return 300}else{return 270}})
? ? ? .style("fill","none");
? /*添加圖像*/
? itemImg=nodeEnter.append("svg:image")
? .attr("class", function(d,i){ return "image_item"+d.id;})
.filter(function(d) { return d.children; })
// .style("fill", "url(#MyGradient2)")
.attr("xlink:href", function(d) {return "images/subtract.png"; })
? .attr("y", function(d) { return -barHeight / 2+2; })
.attr("width", item_w)
.attr("height", item_h)
? .style("opacity",0.8) ;
? nodeEnter.append("svg:text")
? ? ? .attr("dy", 3.5)
? ? ? .attr("dx", 5.5)
? ? ? .attr("transform", "translate(10,0)")
? ? ? .style("fill","black")//設(shè)置字體顏色
? .style("font-size", "12px")
? ? ? .text(function(d,i) {if(i!=0 && d.name.length>20){return d.name.substring(0,21)+"..."}else{return d.name;} });
? // Transition nodes to their new position.
? nodeEnter.transition()
? ? ? .duration(duration)
? ? ? .attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; })
? ? ? .style("opacity", opacity);
? node.transition()
? ? ? .duration(duration)
.attr("transform", function(d) { return "translate(" + xTime(parseDate(d.starttime)) + "," + d.x + ")"; })
? ? ? .style("opacity", opacity)
? ? .select("rect") ;
? // Transition exiting nodes to the parent's new position.
? node.exit().transition()
? ? ? .duration(duration)
? ? ? .attr("transform", function(d) { return "translate(" + source.y + "," + source.x + ")"; })
? ? ? .style("opacity", 1e-6)
? ? ? .remove();
? ? var ldate=tree.links(nodes);
? // Update the links…
? var link = vis.selectAll("path.link")
? ? ? .data(tree.links(nodes), function(d) { return d.target.id; });
? // Enter any new links at the parent's previous position.
? link.enter().insert("svg:path", "g")
? ? ? .attr("class", "link")
? .style("opacity", 0.6)
? .style("stroke", function(d,i){
? ? ? ? ? if(d.target.tendency==1){
? ? ? ? ? ? ? return color1[4];
? ? ? ? ? }else if(d.target.tendency==0){
? ? ? ? ? ? ? return color1[3];
? ? ? ? ? }else if(d.target.tendency==-1){
? ? ? ? ? ? ? return color1[1];
? ? ? ? ? }else{
? ? ? ? ? ? ? return color1[0];
? ? ? ? ? }
// return color1[d.target.color]
? })
? .style("fill","none")
? ? .style("stroke-width","1.5px")
? ? ? .attr("d", function(d) {
? ? ? var o = {x: d.source.x, y: xTime(parseDate(d.source.starttime))};
? ? ? ? return diagonal({source: o, target: o});
? ? ? })
? ? .transition()
? ? ? .duration(duration)
? ? ? .attr("d", function(d) {
? ? ? ? var o = {x: d.source.x, y:xTime(parseDate(d.source.starttime)) };
var ot = {x: d.target.x, y:xTime(parseDate(d.target.starttime)) };;
? ? ? ? return diagonal({source: o, target: ot});
? ? ? });
? // Transition links to their new position.
? link.transition()
? ? ? .duration(duration)
? .style("opacity", 0.6)
? ? ? .attr("d", function(d,i) {
? ? ? ? var o = {x:d.source.x , y: xTime(parseDate(d.source.starttime))};
var ot = {x: d.target.x, y:xTime(parseDate(d.target.starttime)) };;
? ? ? ? return diagonal({source: o, target: ot});
? ? ? });
? // Transition exiting nodes to the parent's new position.
? link.exit().transition()
? ? ? .duration(duration)
? .style("opacity", 0)
? ? ? .attr("d", function(d) {
? ? ? var o = {x: d.source.x, y:xTime(parseDate(d.source.starttime)) };
? ? ? ? return diagonal({source: o, target: o})
? ? ? })
? ? ? .remove();
}
// Toggle children on click.
function click(d) {
? if (d.children) {
? ? d._children = d.children;
? ? d.children = null;
? } else {
? ? d.children = d._children;
? ? d._children = null;
? }
? this.update(d);
}
function opacity(d) {
? return d._children ? 1 : d.children ? 0.8 : 0.8;
}
var u = navigator.userAgent;
</script>
</body>
</html>
三、D3圖自行封裝的時(shí)間方法 -- checkDate.js
function isLeapYear(year){
? ? ? ? if(year % 4 == 0 && ((year % 100 != 0) || (year % 400 == 0)))
? ? ? ? ? ? {
? ? ? ? ? ? ? ? return true;
? ? ? ? ? ? }
? ? ? ? return false;
}
function validatePeriod(fyear,fmonth,fday,byear,bmonth,bday){
? ? ? ? if(fyear < byear){
? ? ? ? ? ? return true;
? ? ? ? }else if(fyear == byear){
? ? ? ? ? ? if(fmonth < bmonth){
? ? ? ? ? ? ? ? return true;
? ? ? ? ? ? } else if (fmonth == bmonth){
? ? ? ? ? ? ? ? ? if(fday <= bday){
? ? ? ? ? ? ? ? ? ? ? ? return true;
? ? ? ? ? ? ? ? ? ? }else {
? ? ? ? ? ? ? ? ? ? ? ? return false;
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? return false;
? ? ? ? ? ? }
? ? ? ? }else {
? ? ? ? ? ? return false;
? ? ? ? }
function dateDiff(d1,d2){
var disNum=compareDate(d1,d2);
return disNum;
}
function compareDate(date1,date2){
var regexp=/^(\d{1,4})[-|\.]{1}(\d{1,2})[-|\.]{1}(\d{1,2})$/;
var monthDays=[0,3,0,1,0,1,0,0,1,0,0,1];
regexp.test(date1);
var date1Year=RegExp.$1;
var date1Month=RegExp.$2;
var date1Day=RegExp.$3;
regexp.test(date2);
var date2Year=RegExp.$1;
var date2Month=RegExp.$2;
var date2Day=RegExp.$3;
if(validatePeriod(date1Year,date1Month,date1Day,date2Year,date2Month,date2Day)){
firstDate=new Date(date1Year,date1Month,date1Day);
secondDate=new Date(date2Year,date2Month,date2Day);
result=Math.floor((secondDate.getTime()-firstDate.getTime())/(1000*3600*24));
for(j=date1Year;j<=date2Year;j++){
if(isLeapYear(j)){
monthDays[1]=2;
}else{
monthDays[1]=3;
}
for(i=date1Month-1;i<date2Month;i++){
result=result-monthDays[i];
}
}
return result;
}else{
alert('有錯(cuò)誤');
exit;
}
}