Skip to content

Instantly share code, notes, and snippets.

@powersparks
Last active March 18, 2017 16:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save powersparks/a4ffbd43a4f59f932d99e40d2b500095 to your computer and use it in GitHub Desktop.
Save powersparks/a4ffbd43a4f59f932d99e40d2b500095 to your computer and use it in GitHub Desktop.
d3 axis clipping works for circle, but not working for svg group element
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
<!DOCTYPE html>
<meta charset="utf-8">
<style>
.axis--grid .domain { fill: #ddd; stroke: none; }
.axis--grid .tick--minor line { stroke-opacity: .5; }
.axis--x .domain, .axis--grid .tick line { stroke: #333; }
rect.zoom{ cursor: move;; }
.axis--x, .axis--y, .tick, .domain, .axis--grid .tick { shape-rendering: crispEdges; border: thin; border-color:black; }
.brush .selection{ cursor: ew-resize; fill:rgba(0, 0, 0, 0.75); pointer-events: all;shape-rendering: crispEdges; border: thin; stroke:none; }
.brush .handle{ cursor: col-resize; fill: none; }
.line{ border: solid 1px steelblue; margin: 4px; padding: 4px; background-color: #eeeeec; fill: none;}
.timeline-container{ margin: 0px; padding: 0px ; border:1px solid blue ; }
.zoom { fill: none; pointer-events: all; }
</style>
<div id="timelineContainerDivId" width="100%" height="90px" class="timeline-container">
<svg id="timeFilterId" viewBox="0 0 800 80" preserveAspectRatio="xMidYMid"></svg>
</div>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var divWidth = document.getElementById('timelineContainerDivId').clientWidth-10;
// 1) ESTABLISH LAYOUT SETTINGS
var svg = d3.select("svg").attr("viewBox","0 0 " + divWidth +" 80"),
h = 80, w = divWidth,
rwidth = svg.attr("width") ? svg.attr("width") : w,
rheight = svg.attr("height") ? svg.attr("height") : h,
margin = {top: 11, right: 20, bottom: 30, left: 40},
margin2 = {top: 60, right: 20, bottom: 20, left: 40},
width = w - margin.left - margin.right - 10,
height = h - margin.top - margin.bottom,
height2 = (svg.attr("height") ? + svg.attr("height") : h) - margin2.top - margin2.bottom;
// 2) SCALE TIME RANGE on x and y
var x = d3.scaleTime().range([0, width]),
x2 = d3.scaleTime().range([0, width]),
y = d3.scaleLinear().range([height, 0]),
y2 = d3.scaleLinear().range([height2, 0]);
// 3) AXIS ORIENTATION and TICKS
var xAxis = d3.axisTop(x).tickSizeInner(height-5).tickSizeOuter( height).tickPadding(-height *0.2),
yAxis = d3.axisRight(y).ticks(0).tickSize(width);
// 4) INSTANTIATE d3 ZOOM
var zoom = d3.zoom()
.scaleExtent([1, Infinity])
.translateExtent([[0, 0], [width, height]])
.extent([[0, 0], [width, height]])
.on("zoom", zoomed);
// 5) APPEND FOCUS g element as the TIMELINE
var focus = svg.append("g")
.attr("class", "focus")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// 5.1) APPEND rect to use as a zoom interface. (see 7.8) moved out of data block.
focus.append("rect")
.attr("class", "zoom ")
.attr("width", width)
.attr("height", height * 2)
.attr("transform", "translate(" + 0 + "," + 0 + ")")
// .call(drag)
// .call(brush_sensor)
//.call(brush_sensor.move, [width - Math.floor(width / 2) - ( width / 5), width - Math.floor( width / 2) + (width / 5)])
//on("drag", function() { d3.event.stopImmediatePropagation(); });
.call(zoom);
// 5.2) Setup Brush for time filter
var brush_sensor = d3.brushX()
.extent([[0, 0], [width, (height/2 + 5)]])
.on("brush end", focus_brush_feedback );
// 5.3) Append the brush; (see 7.9) moved out of data block
focus.append("g")
.attr("class", "brush")
.attr("height", height/2)
.attr("transform", "translate(" + 2+ "," + Math.floor( margin.top + 5) + ")")
// .attr("cursor", "default !important")
.call(brush_sensor)
.call(brush_sensor.move, [width - Math.floor(width / 2) - ( width / 5), width - Math.floor( width / 2) + (width / 5)])
.on("wheel",function() { d3.event.preventDefault(); });
// 6) PARSE TIME FORMAT
var parseDate = d3.timeParse("%b %Y");
// 6.2) example of adding an svg as an object.
var xmlSvg;
d3.xml("blog.svg").mimeType("image/svg+xml").get(function(error, xml) {
if (error) throw error;
xmlSvg = xml.documentElement;
document.body.appendChild(xml.documentElement);
//});//xml
// 6.6) trying out some len's filters
//// create filter with id #drop-shadow
// height=130% so that the shadow is not clipped
/*
var filter = defs.append("filter")
.attr("id", "drop-shadow")
.attr("height", "100%");
*/
// SourceAlpha refers to opacity of graphic that this filter will be applied to
// convolve that with a Gaussian with standard deviation 3 and store result
// 7) SETUP DATA WITH CALLBACK AND FORMAT DATE TYPE
d3.csv("sp500_2.csv", type, function(error, data) {
if (error) throw error;
// 7.2) STARTING DOMAIN of x and y axis
x.domain(d3.extent(data, function(d) { return d.date; }));
y.domain([0, d3.max(data, function(d) { return d.price; })]);
// 7.3) STARING DOMAIN FOR ALTERNATE axis
x2.domain(x.domain());
y2.domain(y.domain());
// 7.4) moved to 6.4, then moved back.
//revelation - if appending the axis before the domain, it will not be scaled to the new domain.
// 7.5) moved to 6.5, then moved back.
//revelation - if appending the axis before the domain, it will not be scaled to the new domain.
// 6.4) APPEND x-axis. (see 7.4) this was in the "data" block, but doesn't need to be.
focus.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
// 6.5) APPEND y-axis. (see 7.5) this was in the "data" block, but doesn't need to be
focus.append("g")
.attr("class", "axis axis--y")
.call(yAxis);
// 7.6) Select all the circle's within the Chart
focus.selectAll("circle")
.data(data).enter().append("circle")
.attr("clip-path", "url('#clip')")
.attr("class","dot")
.attr("r", 4.5)
.attr("opacity", 0.7)
.style("fill", "steelblue");
var xmlSvgB = d3.select(xmlSvg).select('#b').node();
var gXml = focus.selectAll(".icon")
.data(data ).enter().append(function(){return xmlSvgB.cloneNode(true);})
.attr("clip-path", 'url("#clip2")')
.attr('class', 'icon')
.attr("opacity", 0.7)
.attr('id',function(d){return 'b_' + d.date.getTime();})
.attr('transform', function(d){
var xdate = x(d.date) - 11;
return "translate(" + xdate + "," + 15 + ") scale(0.8)" ;});
// 7.7) Select class dot and apply anyomous function
focus.selectAll(".dot")
.attr('cx', function(d) { return x(d.date); })
.attr('cy', height * 0.5);
// 7.8) moved to 5.1
// 7.9) moved to 5.3
focus.selectAll('.tick line')
.attr("y1", function(d){
return -height;
});
//move the brush infront of everything.
d3.selectAll(".brush").raise();
// 6.1) append culling to be used for a clip area.
var defs = focus.append("defs");
defs.append("clipPath")
.attr("id", "clip")
//.attr("clipPathUnits", "objectBoundingBox")//"userSpaceOnUse")
.append("rect")
.attr("x", 0)
.attr("y",0)
.attr("width", width )
.attr("height", height);
defs.append("clipPath")
.attr("id", "clip2")
//.attr("clipPathUnits", "userSpaceOnUse")
.append("rect")
.attr("x", 0)
.attr("y",0)
.attr("width", width )
.attr("height", height)
;
}); //end of data call
}); //end of xml call
function focus_brush_feedback(){
if(!d3.event.select)return;
console.info("focus_brush_feedback");
console.info(d3.event.select);
}
// 8) Method for zooming
function zoomed() {
if(d3.event.select)return;
// 8.1) confirm the right events are used
if (d3.event.sourceEvent == null || d3.event.sourceEvent.type == null || d3.event.sourceEvent.type === '') return;
if (d3.event.sourceEvent && d3.event.sourceEvent.type === "brush") return;
// 8.2) INSTANTIATE d3 transform event
var t = d3.event.transform;
// 8.3) RESET the X DOMAIN using the Transform, Rescale X based on the x2 domain
x.domain(t.rescaleX(x2).domain());
// 8.4) Select the Chart's element to rescale.
focus.selectAll(".dot")
.attr('cx', function(d) { return x(d.date); })
.attr('cy', height * 0.5);
focus.selectAll('.icon')
.attr('transform', function(d){
var xdate = x(d.date) - 11;
return "translate(" + xdate + "," + 15 + ") scale(0.8)" ;});
// 8.5) Select the Chart's axis--x class, call xAxis to reset it(how?)
focus.select(".axis--x").call(xAxis);
focus.selectAll('.tick line')
.attr("y1", function(d){
return -height;
});
}
function type(d) {
d.date = parseDate(d.date);
d.price = +d.price;
return d;
}
</script>
date price
Jan 2000 1394.46
Jul 2009 1140.45
Feb 2010 1140.45
Apr 2016 1140.45
Mar 2017 1240.45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment