D3.v3 刷怪行为
D3.v3 Brush Strange Behavior
我正在尝试在直方图上画笔。画笔控件仅在单击事件后出现(而不是在初始页面加载时)。显然,这不是期望的行为。
如何在第一次点击事件之前在初始页面加载时实例化图表和画笔?
// TEST Data //
var caldata = [
{"cal_start_yr": "1945"}, {"cal_start_yr": "1948"},
{"cal_start_yr": "1945"}, {"cal_start_yr": "1950"},
{"cal_start_yr": "1945"}, {"cal_start_yr": "1941"},
{"cal_start_yr": "1944"}, {"cal_start_yr": "1949"}
];
// CROSSFILTER Aggregations //
var cals = crossfilter(caldata);
var total = cals.groupAll().reduceCount().value();
var year = cals.dimension(function(d) {
return d.cal_start_yr;
});
var countYear = year.group().reduceCount();
var yearCount = countYear.all();
// Some helper AGGREGATION Values
var keys = countYear.all().map(function(d) {return d.value;}),
min = d3.min(countYear.all(), function(d) {return d.key;}),
max = d3.max(countYear.all(), function(d) {return d.key;}),
range = max - min;
// Histogram dimensions
var margin = {top: 10, right: 20, bottom: 10,left: 10 },
height = 250 - margin.top - margin.bottom,
width = 450 - margin.left - margin.right,
barPadding = 5;
// Histogram SCALES
var xScale = d3.scale.linear()
.domain([min, max])
.range([0, width]);
var yScale = d3.scale.linear()
.domain([0, d3.max(countYear.all(), function(d) {return d.value;})])
.range([height / 2, 0]);
// D3 Tool Tip
var tip = d3.tip()
.attr('class', 'd3-tip')
.html(function(d) {return d.key});
// CANVAS setup //
var histogram1 = d3.select("#histogram1").append("svg:svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g");
// Initiate Tooltip //
histogram1.call(tip);
// DRAW Histogram //
histogram1.selectAll("rect")
.data(yearCount)
.enter().append("rect")
.attr("x", function(d) {
return xScale(d.key) + 0.5 * (width / range)
})
.attr("width", width / range)
.attr("y", function(d) {
return yScale(d.value);
})
.attr("height", function(d) {
return (height / 2 - yScale(d.value));
})
.attr("fill", "green")
.attr("fill-opacity", .25)
.attr("stroke", "white")
.on("mouseover", tip.show)
.on("mouseout", tip.hide);
// X AXIS //
var xAxis = d3.svg.axis()
.scale(xScale)
.ticks(5)
.orient("bottom")
.tickFormat(d3.format("d"));
histogram1.append("g")
.attr("class", "axis")
.call(xAxis)
.attr("transform", "translate(" + margin.left + "," + height / 2 + ")");
var brush = d3.svg.brush()
.x(xScale)
.extent([xScale(+1945), xScale(+1946)])
.on("brush", function(d) {console.log(d);});
var brushg = histogram1.append("g")
.attr("class", "brush")
.call(brush)
brushg.selectAll("rect")
.attr("height", height / 2);
brushg.selectAll(".resize")
.append("path")
.attr("d", resizePath);
function resizePath(d) {
// Style the brush resize handles. No idea what these vals do...
var e = +(d == "e"),
x = e ? 1 : -1,
y = height / 4; // Relative positon if handles
return "M" + (.5 * x) + "," + y + "A6,6 0 0 " + e + " " + (6.5 * x) + "," + (y + 6) + "V" + (2 * y - 6) + "A6,6 0 0 " + e + " " + (.5 * x) + "," + (2 * y) + "Z" + "M" + (2.5 * x) + "," + (y + 8) + "V" + (2 * y - 8) + "M" + (4.5 * x) + "," + (y + 8) + "V" + (2 * y - 8);
}
/*** d3-tip styles */
.as-console-wrapper { max-height: 20% !important;}
.d3-tip {
line-height: 1.5;
padding: 8px;
background: rgba(0, 0, 0, 0.8);
color: #fff;
border-radius: 0px;
text-align: center;
}
.d3-tip:after {
box-sizing: border-box;
display: inline;
font-size: 10px;
width: 100%;
line-height: 1;
color: rgba(0, 0, 0, 0.8);
content: "BC";
position: absolute;
text-align: center;
}
.d3-tip.n:after {
top: 100%;
left: 0;
margin: -1px 0 0;
}
/*** D3 brush */
.brush .extent {
stroke: #222;
fill-opacity: .125;
shape-rendering: crispEdges;
}
<script src="https://d3js.org/d3.v3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3-tip/0.7.1/d3-tip.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crossfilter/1.3.12/crossfilter.min.js"></script>
<div id="histogram1"></div>
笔刷的范围设置为比例域的值,而不是范围!来自 docs:
The scale is typically defined as a quantitative scale, in which case the extent is in data space from the scale's domain
要设置您必须使用的初始范围
.extent([1945, 1946])
而不是
.extent([xScale(+1945), xScale(+1946)])
有关工作演示,请查看更新后的代码段:
// TEST Data //
var caldata = [
{"cal_start_yr": "1945"}, {"cal_start_yr": "1948"},
{"cal_start_yr": "1945"}, {"cal_start_yr": "1950"},
{"cal_start_yr": "1945"}, {"cal_start_yr": "1941"},
{"cal_start_yr": "1944"}, {"cal_start_yr": "1949"}
];
// CROSSFILTER Aggregations //
var cals = crossfilter(caldata);
var total = cals.groupAll().reduceCount().value();
var year = cals.dimension(function(d) {
return d.cal_start_yr;
});
var countYear = year.group().reduceCount();
var yearCount = countYear.all();
// Some helper AGGREGATION Values
var keys = countYear.all().map(function(d) {return d.value;}),
min = d3.min(countYear.all(), function(d) {return d.key;}),
max = d3.max(countYear.all(), function(d) {return d.key;}),
range = max - min;
// Histogram dimensions
var margin = {top: 10, right: 20, bottom: 10,left: 10 },
height = 250 - margin.top - margin.bottom,
width = 450 - margin.left - margin.right,
barPadding = 5;
// Histogram SCALES
var xScale = d3.scale.linear()
.domain([min, max])
.range([0, width]);
var yScale = d3.scale.linear()
.domain([0, d3.max(countYear.all(), function(d) {return d.value;})])
.range([height / 2, 0]);
// D3 Tool Tip
var tip = d3.tip()
.attr('class', 'd3-tip')
.html(function(d) {return d.key});
// CANVAS setup //
var histogram1 = d3.select("#histogram1").append("svg:svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g");
// Initiate Tooltip //
histogram1.call(tip);
// DRAW Histogram //
histogram1.selectAll("rect")
.data(yearCount)
.enter().append("rect")
.attr("x", function(d) {
return xScale(d.key) + 0.5 * (width / range)
})
.attr("width", width / range)
.attr("y", function(d) {
return yScale(d.value);
})
.attr("height", function(d) {
return (height / 2 - yScale(d.value));
})
.attr("fill", "green")
.attr("fill-opacity", .25)
.attr("stroke", "white")
.on("mouseover", tip.show)
.on("mouseout", tip.hide);
// X AXIS //
var xAxis = d3.svg.axis()
.scale(xScale)
.ticks(5)
.orient("bottom")
.tickFormat(d3.format("d"));
histogram1.append("g")
.attr("class", "axis")
.call(xAxis)
.attr("transform", "translate(" + margin.left + "," + height / 2 + ")");
var brush = d3.svg.brush()
.x(xScale)
.extent([1945, 1946])
.on("brush", function(d) {console.log(brush.extent());});
var brushg = histogram1.append("g")
.attr("class", "brush")
.call(brush)
brushg.selectAll("rect")
.attr("height", height / 2);
brushg.selectAll(".resize")
.append("path")
.attr("d", resizePath);
function resizePath(d) {
// Style the brush resize handles. No idea what these vals do...
var e = +(d == "e"),
x = e ? 1 : -1,
y = height / 4; // Relative positon if handles
return "M" + (.5 * x) + "," + y + "A6,6 0 0 " + e + " " + (6.5 * x) + "," + (y + 6) + "V" + (2 * y - 6) + "A6,6 0 0 " + e + " " + (.5 * x) + "," + (2 * y) + "Z" + "M" + (2.5 * x) + "," + (y + 8) + "V" + (2 * y - 8) + "M" + (4.5 * x) + "," + (y + 8) + "V" + (2 * y - 8);
}
/*** d3-tip styles */
.d3-tip {
line-height: 1.5;
padding: 8px;
background: rgba(0, 0, 0, 0.8);
color: #fff;
border-radius: 0px;
text-align: center;
}
.d3-tip:after {
box-sizing: border-box;
display: inline;
font-size: 10px;
width: 100%;
line-height: 1;
color: rgba(0, 0, 0, 0.8);
content: "BC";
position: absolute;
text-align: center;
}
.d3-tip.n:after {
top: 100%;
left: 0;
margin: -1px 0 0;
}
/*** D3 brush */
.brush .extent {
stroke: #222;
fill-opacity: .125;
shape-rendering: crispEdges;
}
.as-console-wrapper { max-height: 30% !important;}
<script src="https://d3js.org/d3.v3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3-tip/0.7.1/d3-tip.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crossfilter/1.3.12/crossfilter.min.js"></script>
<div id="histogram1"></div>
我正在尝试在直方图上画笔。画笔控件仅在单击事件后出现(而不是在初始页面加载时)。显然,这不是期望的行为。
如何在第一次点击事件之前在初始页面加载时实例化图表和画笔?
// TEST Data //
var caldata = [
{"cal_start_yr": "1945"}, {"cal_start_yr": "1948"},
{"cal_start_yr": "1945"}, {"cal_start_yr": "1950"},
{"cal_start_yr": "1945"}, {"cal_start_yr": "1941"},
{"cal_start_yr": "1944"}, {"cal_start_yr": "1949"}
];
// CROSSFILTER Aggregations //
var cals = crossfilter(caldata);
var total = cals.groupAll().reduceCount().value();
var year = cals.dimension(function(d) {
return d.cal_start_yr;
});
var countYear = year.group().reduceCount();
var yearCount = countYear.all();
// Some helper AGGREGATION Values
var keys = countYear.all().map(function(d) {return d.value;}),
min = d3.min(countYear.all(), function(d) {return d.key;}),
max = d3.max(countYear.all(), function(d) {return d.key;}),
range = max - min;
// Histogram dimensions
var margin = {top: 10, right: 20, bottom: 10,left: 10 },
height = 250 - margin.top - margin.bottom,
width = 450 - margin.left - margin.right,
barPadding = 5;
// Histogram SCALES
var xScale = d3.scale.linear()
.domain([min, max])
.range([0, width]);
var yScale = d3.scale.linear()
.domain([0, d3.max(countYear.all(), function(d) {return d.value;})])
.range([height / 2, 0]);
// D3 Tool Tip
var tip = d3.tip()
.attr('class', 'd3-tip')
.html(function(d) {return d.key});
// CANVAS setup //
var histogram1 = d3.select("#histogram1").append("svg:svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g");
// Initiate Tooltip //
histogram1.call(tip);
// DRAW Histogram //
histogram1.selectAll("rect")
.data(yearCount)
.enter().append("rect")
.attr("x", function(d) {
return xScale(d.key) + 0.5 * (width / range)
})
.attr("width", width / range)
.attr("y", function(d) {
return yScale(d.value);
})
.attr("height", function(d) {
return (height / 2 - yScale(d.value));
})
.attr("fill", "green")
.attr("fill-opacity", .25)
.attr("stroke", "white")
.on("mouseover", tip.show)
.on("mouseout", tip.hide);
// X AXIS //
var xAxis = d3.svg.axis()
.scale(xScale)
.ticks(5)
.orient("bottom")
.tickFormat(d3.format("d"));
histogram1.append("g")
.attr("class", "axis")
.call(xAxis)
.attr("transform", "translate(" + margin.left + "," + height / 2 + ")");
var brush = d3.svg.brush()
.x(xScale)
.extent([xScale(+1945), xScale(+1946)])
.on("brush", function(d) {console.log(d);});
var brushg = histogram1.append("g")
.attr("class", "brush")
.call(brush)
brushg.selectAll("rect")
.attr("height", height / 2);
brushg.selectAll(".resize")
.append("path")
.attr("d", resizePath);
function resizePath(d) {
// Style the brush resize handles. No idea what these vals do...
var e = +(d == "e"),
x = e ? 1 : -1,
y = height / 4; // Relative positon if handles
return "M" + (.5 * x) + "," + y + "A6,6 0 0 " + e + " " + (6.5 * x) + "," + (y + 6) + "V" + (2 * y - 6) + "A6,6 0 0 " + e + " " + (.5 * x) + "," + (2 * y) + "Z" + "M" + (2.5 * x) + "," + (y + 8) + "V" + (2 * y - 8) + "M" + (4.5 * x) + "," + (y + 8) + "V" + (2 * y - 8);
}
/*** d3-tip styles */
.as-console-wrapper { max-height: 20% !important;}
.d3-tip {
line-height: 1.5;
padding: 8px;
background: rgba(0, 0, 0, 0.8);
color: #fff;
border-radius: 0px;
text-align: center;
}
.d3-tip:after {
box-sizing: border-box;
display: inline;
font-size: 10px;
width: 100%;
line-height: 1;
color: rgba(0, 0, 0, 0.8);
content: "BC";
position: absolute;
text-align: center;
}
.d3-tip.n:after {
top: 100%;
left: 0;
margin: -1px 0 0;
}
/*** D3 brush */
.brush .extent {
stroke: #222;
fill-opacity: .125;
shape-rendering: crispEdges;
}
<script src="https://d3js.org/d3.v3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3-tip/0.7.1/d3-tip.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crossfilter/1.3.12/crossfilter.min.js"></script>
<div id="histogram1"></div>
笔刷的范围设置为比例域的值,而不是范围!来自 docs:
The scale is typically defined as a quantitative scale, in which case the extent is in data space from the scale's domain
要设置您必须使用的初始范围
.extent([1945, 1946])
而不是
.extent([xScale(+1945), xScale(+1946)])
有关工作演示,请查看更新后的代码段:
// TEST Data //
var caldata = [
{"cal_start_yr": "1945"}, {"cal_start_yr": "1948"},
{"cal_start_yr": "1945"}, {"cal_start_yr": "1950"},
{"cal_start_yr": "1945"}, {"cal_start_yr": "1941"},
{"cal_start_yr": "1944"}, {"cal_start_yr": "1949"}
];
// CROSSFILTER Aggregations //
var cals = crossfilter(caldata);
var total = cals.groupAll().reduceCount().value();
var year = cals.dimension(function(d) {
return d.cal_start_yr;
});
var countYear = year.group().reduceCount();
var yearCount = countYear.all();
// Some helper AGGREGATION Values
var keys = countYear.all().map(function(d) {return d.value;}),
min = d3.min(countYear.all(), function(d) {return d.key;}),
max = d3.max(countYear.all(), function(d) {return d.key;}),
range = max - min;
// Histogram dimensions
var margin = {top: 10, right: 20, bottom: 10,left: 10 },
height = 250 - margin.top - margin.bottom,
width = 450 - margin.left - margin.right,
barPadding = 5;
// Histogram SCALES
var xScale = d3.scale.linear()
.domain([min, max])
.range([0, width]);
var yScale = d3.scale.linear()
.domain([0, d3.max(countYear.all(), function(d) {return d.value;})])
.range([height / 2, 0]);
// D3 Tool Tip
var tip = d3.tip()
.attr('class', 'd3-tip')
.html(function(d) {return d.key});
// CANVAS setup //
var histogram1 = d3.select("#histogram1").append("svg:svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g");
// Initiate Tooltip //
histogram1.call(tip);
// DRAW Histogram //
histogram1.selectAll("rect")
.data(yearCount)
.enter().append("rect")
.attr("x", function(d) {
return xScale(d.key) + 0.5 * (width / range)
})
.attr("width", width / range)
.attr("y", function(d) {
return yScale(d.value);
})
.attr("height", function(d) {
return (height / 2 - yScale(d.value));
})
.attr("fill", "green")
.attr("fill-opacity", .25)
.attr("stroke", "white")
.on("mouseover", tip.show)
.on("mouseout", tip.hide);
// X AXIS //
var xAxis = d3.svg.axis()
.scale(xScale)
.ticks(5)
.orient("bottom")
.tickFormat(d3.format("d"));
histogram1.append("g")
.attr("class", "axis")
.call(xAxis)
.attr("transform", "translate(" + margin.left + "," + height / 2 + ")");
var brush = d3.svg.brush()
.x(xScale)
.extent([1945, 1946])
.on("brush", function(d) {console.log(brush.extent());});
var brushg = histogram1.append("g")
.attr("class", "brush")
.call(brush)
brushg.selectAll("rect")
.attr("height", height / 2);
brushg.selectAll(".resize")
.append("path")
.attr("d", resizePath);
function resizePath(d) {
// Style the brush resize handles. No idea what these vals do...
var e = +(d == "e"),
x = e ? 1 : -1,
y = height / 4; // Relative positon if handles
return "M" + (.5 * x) + "," + y + "A6,6 0 0 " + e + " " + (6.5 * x) + "," + (y + 6) + "V" + (2 * y - 6) + "A6,6 0 0 " + e + " " + (.5 * x) + "," + (2 * y) + "Z" + "M" + (2.5 * x) + "," + (y + 8) + "V" + (2 * y - 8) + "M" + (4.5 * x) + "," + (y + 8) + "V" + (2 * y - 8);
}
/*** d3-tip styles */
.d3-tip {
line-height: 1.5;
padding: 8px;
background: rgba(0, 0, 0, 0.8);
color: #fff;
border-radius: 0px;
text-align: center;
}
.d3-tip:after {
box-sizing: border-box;
display: inline;
font-size: 10px;
width: 100%;
line-height: 1;
color: rgba(0, 0, 0, 0.8);
content: "BC";
position: absolute;
text-align: center;
}
.d3-tip.n:after {
top: 100%;
left: 0;
margin: -1px 0 0;
}
/*** D3 brush */
.brush .extent {
stroke: #222;
fill-opacity: .125;
shape-rendering: crispEdges;
}
.as-console-wrapper { max-height: 30% !important;}
<script src="https://d3js.org/d3.v3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3-tip/0.7.1/d3-tip.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crossfilter/1.3.12/crossfilter.min.js"></script>
<div id="histogram1"></div>