Tôi đang xem xét việc tạo một biểu đồ dòng thời gian chỉ có một khối hình chữ nhật ở phía dưới. Nó được sử dụng như một máy chà sàn chính.
// hiện tại - http://jsfiddle.net/NYEaX/2427/
trong đó phần chà là - tôi muốn chỉ có một hình chữ nhật cơ sở. Tôi nên thực hiện loại sửa đổi nào cho cơ sở mã hiện tại
// mới nhất của tôi - https://jsfiddle.net/2mvhjr7z/2/
$(document).ready(function() {
var $this = $('.timelinechart');
var w = $this.data("width");
var h = $this.data("height");
//var data = $this.data("data");
var data = [
{
"label": "person a",
"icon": "4",
"times": [
{"text": "Test 1", "starting_time": 1355752800000, "ending_time": 1355759900000},
{"text": "Test 2", "starting_time": 1355767900000, "ending_time": 1355774400000},
{"text": "Test 6", "starting_time": 1355761900000, "ending_time": 1355764520000},
{"text": "Test 7", "starting_time": 1355767900000, "ending_time": 1355774400000}
]
},
{
"label": "person b",
"icon": "5",
"times": [
{"text": "Test 8", "starting_time": 1355752800000, "ending_time": 1355759900000},
{"text": "Test 9", "starting_time": 1355767900000, "ending_time": 1355774400000},
{"text": "Test 10", "starting_time": 1355767900000, "ending_time": 1355867900000}
]
}
];
var lanes = [];
var times = [];
var icons = [];
$.each(data, function(index, value) {
lanes.push(value.label);
//icons.push(_avatarList[value.icon].image);
$.each(value.times, function(i, v) {
v["lane"] = index;
});
times.push(value.times);
});
var laneLength = lanes.length;
var items = [].concat.apply([], times);
$.each(items, function(i, v) {
v["id"] = i;
});
var timeBegin = d3.min(items, function(d) { return d["starting_time"]; });
var timeEnd = d3.max(items, function(d) { return d["ending_time"]; });
var m = [25, 80, 15, 105], //top right bottom left
w = w - m[1] - m[3],
h = h - m[0] - m[2],
miniHeight = laneLength * 12 + 50,
mainHeight = h - miniHeight - 50;
//scales
var x = d3.scaleTime()
.range([0, w])
.domain([timeBegin, timeEnd]);
var x1 = d3.scaleLinear()
.range([0, w]);
var y1 = d3.scaleLinear()
.range([0, mainHeight])
.domain([0, laneLength]);
var y2 = d3.scaleLinear()
.range([0, miniHeight])
.domain([0, laneLength]);
var xAxis = d3.axisBottom(x)
.ticks(d3.timeMonth)
.tickFormat(d=>d3.timeFormat("%B %Y")(d));
var scaleFactor = (1/(timeEnd - timeBegin)) * (w);
var chartWidth = w + m[1] + m[3];
var chartHeight = h + m[0] + m[2];
var chart = d3.select($this[0])
.append("svg")
.attr("width", chartWidth)
.attr("height", chartHeight)
.attr("viewBox", "0 0 "+chartWidth+" "+chartHeight)
.attr("preserveAspectRatio", "xMidYMid meet")
.append("g")
.attr("class", "timelinechartg");
chart.append("defs").append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", w)
.attr("height", mainHeight);
var main = chart.append("g")
.attr("transform", "translate(" + m[3] + "," + m[0] + ")")
.attr("width", w)
.attr("height", mainHeight)
.attr("class", "main");
var mini = chart.append("g")
.attr("transform", "translate(" + m[3] + "," + (mainHeight + m[0]) + ")")
.attr("width", w)
.attr("height", miniHeight)
.attr("class", "mini");
var gX = chart.append("g")
.attr("class", "axis")
.attr("transform", "translate(" + m[3] + "," + (mainHeight + miniHeight) + ")")
.call(xAxis);
//background colors
function colores_background(n) {
var colores_g = ["#f8dd2f", "#e9168a", "#448875", "#2b2d39", "#c3bd75", "#1b91dc"];
return colores_g[n % colores_g.length];
}
//foreground colors
function colores_foreground(n) {
var colores_g = ["#553814", "#311854", "#f7b363", "#c12f39", "#89191d", "#2b2d39"];
return colores_g[n % colores_g.length];
}
//main lanes and texts
main.append("g").selectAll(".laneLines")
.data(items)
.enter().append("line")
.attr("x1", 0)
.attr("y1", function(d) {return y1(d.lane);})
.attr("x2", w)
.attr("y2", function(d) {return y1(d.lane);})
.attr("stroke", "lightgray")
var defs = main.append('svg:defs');
main.append("g").selectAll(".laneText")
.data(lanes)
.enter().append("text")
.text(function(d) {return d;})
.attr("x", (-m[1] + 10))
.attr("y", function(d, i) {
return y1(i + .5);
})
.attr("dy", ".5ex")
.attr("text-anchor", "end")
.attr("class", "laneText");
//mini lanes and texts
mini.append("g").selectAll(".laneLines")
.data(items)
.enter().append("line")
.attr("x1", 0)
.attr("y1", function(d) {
return y2(d.lane);
})
.attr("x2", w)
.attr("y2", function(d) {
return y2(d.lane);
})
.attr("stroke", "lightgray");
mini.append("g").selectAll(".laneText")
.data(lanes)
.enter().append("text")
.text(function(d) {return d;})
.attr("x", -m[1] + 40)
.attr("y", function(d, i) {return y2(i + .5);})
.attr("dy", ".5ex")
.attr("text-anchor", "end")
.attr("class", "laneText");
var itemRects = main.append("g")
.attr("clip-path", "url(#clip)");
//mini item rects
mini.append("g").selectAll("miniItems")
.data(items)
.enter().append("rect")
.attr("class", function(d) {return "miniItem "+d.state;})
.attr("x", function(d) {return x(d.starting_time);})
.attr("y", function(d) {return y2(d.lane + .5) - 5;})
.attr("fill", function(d, i) {
return colores_background(d.lane);
})
.attr("width", function(d) {
return (d.ending_time - d.starting_time) * scaleFactor;
})
.attr("height", 10);
//mini labels
mini.append("g").selectAll(".miniLabels")
.data(items)
.enter().append("text")
.text(function(d) {return d.text;})
.attr("class", function(d) {return d.state;})
.attr("x", function(d) {return x(d.starting_time);})
.attr("y", function(d) {
return y2(d.lane + .5);
})
.attr("fill", function(d, i) {
return colores_foreground(d.lane);
})
.attr("dy", ".5ex");
$.each(icons, function(index, value) {
defs.append('svg:pattern')
.attr('id', "--"+index)
.attr('width', 1)
.attr('height', 1)
.append('svg:image')
.attr('image-rendering', "optimizeQuality")
.attr('preserveAspectRatio', "xMidYMid meet")
.attr('xlink:href', value)
.attr('x', 0)
.attr('y', 0)
.attr('width', 50)
.attr('height', 50);
defs.append('svg:pattern')
.attr('id', "--m"+index)
.attr('width', 1)
.attr('height', 1)
.append('svg:image')
.attr('image-rendering', "optimizeQuality")
.attr('preserveAspectRatio', "xMidYMid meet")
.attr('xlink:href', value)
.attr('x', 0)
.attr('y', 0)
.attr('width', 20)
.attr('height', 20);
main.append("g")
.attr("transform", function(d, i) {
return "translate("+(-m[1] + 5)+","+ (y1(index + .5) - 50) +")";
})
.append("circle")
.attr("class", "user")
.style("stroke", "gray")
.style("fill", "url(#--"+index+")")
.attr("r", 25)
.attr("cx", 40)
.attr("cy", 50);
mini.append("g")
.attr("transform", function(d, i) {
return "translate("+(-m[1] + 40)+","+ (y2(index + .5) - 20) +")";
})
.append("circle")
.attr("class", "user")
.style("stroke", "gray")
.style("fill", "url(#--m"+index+")")
.attr("r", 10)
.attr("cx", 20)
.attr("cy", 20);
});
var brush = d3.brushX()
.extent([[0, 0], [w, miniHeight]])
.on("brush", brushed);
mini.append("g")
.attr("class", "x brush")
.call(brush)
.selectAll("rect")
.attr("y", 1)
.attr("height", miniHeight - 1);
function brushed() {
var selection = d3.event.selection;
var timeSelection = selection.map(x.invert, x);
//console.log("selection: " + selection);
//console.log("start: " + timeSelection[0]);
//console.log("end: " + timeSelection[1]);
var rects;
var labels;
var minExtent = timeSelection[0];
var maxExtent = timeSelection[1];
var visItems = items.filter(function(d) {return d.starting_time < maxExtent && d.ending_time > minExtent;});
//mini.select(".brush")
//.call(brush.extent([minExtent, maxExtent]));
x1.domain([minExtent, maxExtent]);
//update main item rects
rects = itemRects.selectAll("rect")
.data(visItems, function(d) { return d.id; })
.attr("x", function(d) {return x1(d.starting_time);})
.attr("width", function(d) {return x1(d.ending_time) - x1(d.starting_time);});
rects.enter().append("rect")
.attr("class", function(d) {return "miniItem "+d.state;})
.attr("x", function(d) {return x1(d.starting_time);})
.attr("y", function(d) {return y1(d.lane) + 10;})
.attr("fill", function(d, i) {
return colores_background(d.lane);
})
.attr("width", function(d) {return x1(d.ending_time) - x1(d.starting_time);})
.attr("height", function(d) {return .8 * y1(1);});
rects.exit().remove();
//update the item labels
labels = itemRects.selectAll("text")
.data(visItems, function (d) { return d.id; })
.attr("x", function(d) {return x1(Math.max(d.starting_time, minExtent) + 2);});
labels.enter().append("text")
.text(function(d) {return d.text;})
.attr("class", function(d) {return d.state;})
.attr("x", function(d) {return x1(Math.max(d.starting_time, minExtent));})
.attr("y", function(d) {return y1(d.lane + .5);})
.attr("fill", function(d, i) {
return colores_foreground(d.lane);
})
.attr("text-anchor", "start");
labels.exit().remove();
}
});
body {
background: #eeeeee;
}
#holder {
overflow: hidden;
}
/*
.chart {
shape-rendering: crispEdges;
}
*/
.timelinechart{
/*width:100%;
border: 1px solid red;*/
}
.timelinechart svg{
width:100%;
/*border: 1px solid green;*/
}
.timelinechartg{
}
.mini text {
font: 10px sans-serif;
}
.main text {
font: 12px sans-serif;
}
.miniItem {
/*fill: darksalmon;*/
stroke-width: 6;
}
.miniItem.future{
fill: #448875;
}
text.future {
fill: #f7b363;
}
.brush .extent {
stroke: #b6b8b9;
fill: #57585b;
fill-opacity: .365;
stroke-width: .2;
}
.laneImg{
border-radius: 25px;
}
<script type='text/javascript' src='//code.jquery.com/jquery-1.9.1.js'></script>
<script type='text/javascript' src="http://d3js.org/d3.v4.min.js"></script>
<div class="timelinechart" data-role="timelinechart" data-width=500 data-height=300 data-data="" ></div>
thiết kế mới nhất là như thế này
và khi bộ lọc hiển thị chi tiết hơn - như phạm vi ngày 1 tháng - định dạng của thang đo trở nên chi tiết hơn