Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reposition tooltip relative to SVG element for responsive page

I'm using a SVG rect and text element as a tooltip. They are both within a SVG element that is a map of U.S. counties.

The tooltip work's fine if my map is a fixed height (I'm simply off-setting the coordinates for svg near my mouse) but the tooltip loses functionality if I make my map responsive or if a user decides to zoom in on a given area.

See pics : https://i.sstatic.net/eRPT8.jpg

My SVG file is at https://codeshare.io/GcJIS since it is too lengthy for this site.

I'm just lost. I originally tried making a simple div tooltip (using CSS) instead of using SVG but it makes my div container for my svg map 'bounce' like crazy. I tried D3 but found myself more confused. I feel as there is something simple I am simply overlooking but I've been beating myself up over trying to implement this 'simple' feature. Any help or guidance is appreciated.

window.onload=function() {
			
				var panZoom = window.panZoom = svgPanZoom('#svgObj', {
					zoomEnabled: true,
					controlIconsEnabled: true,
					dblClickZoomEnabled: false,
				});
				
				 $(window).resize(function(){
			          panZoom.resize();
			          panZoom.fit();
			          panZoom.center();
			        })
	
			        var eastCoastStates = [ 'MA', 'RI', 'CT', 'NJ',
			                                'DE', 'MD', 'DC', 'ME', 'NH', 'NY', 'PA',
			                                'VA', 'NC', 'SC', 'FL', 'GA', 'WV', 'VT' ];
	
				var svgDoc = $("#svgObj")[0].contentDocument; // Get the document object for the SVG
				var county;
				$("path", svgDoc).each(function(){	
					county = $(this).attr('inkscape:label');	//name of the county and state abbr i.e. "Travis County, TX
						$(this).attr("title", county);
						$(this).append("<title>"+ county+ "</title>"); 
						$(this).removeAttr('inkscape:label');
				});

				var cssValue; //global variable, stores fill color on mouse enter for use in mouseout
				
				$("path", svgDoc).mouseenter(function(event){		
				
					var current_id = $(this).attr('id');
					if (current_id != "separator"       //ignore anything not a county
							&& current_id != "State_Lines"
							&& current_id != "metadata3671"
							&& current_id != "defs9561"
							&& current_id != "base"
							&& current_id != "State_borders") {

						var countySt = $(this).attr('title');
						var countyStArray = countySt.split(",");
						var stateAbbr = countyStArray[1].trim();


						var countyBahAmount = countiesBah[countySt];
						if (countyBahAmount == undefined)
							countyBahAmount = "Unknown Bah Amount";

						var width = 4.7 * ($(this).attr('title').length + 2 + countyBahAmount.length); //defines the length of the SVG text box based on the inside text length

						$("#textBox", svgDoc).attr('width', width);
						$("#textSvg", svgDoc).text(
								$(this).attr('title') + ": "
										+ countyBahAmount);

						var xPos = event.pageX;
						var yPos = event.pageY;
						
						
						
						if (eastCoastStates.indexOf(stateAbbr) > -1) { // Check to see if the element is a East Coast State, 
																	   // this will offset the tooltip to the left so it's not out of view
																	   // made some readjustments, need to fix
							$("#textSvg", svgDoc).attr('x', xPos - 300);
							$("#textBox", svgDoc).attr('x', xPos - 300);

							$("#textSvg", svgDoc).attr('y', yPos - 91);
							$("#textBox", svgDoc).attr('y', yPos - 100);
						} else {

							$("#textSvg", svgDoc).attr('x', xPos - 153);
							$("#textBox", svgDoc).attr('x', xPos - 155);

							$("#textSvg", svgDoc).attr('y', yPos - 120);
							$("#textBox", svgDoc).attr('y', yPos - 130);

						}
						
						$("#textSvg", svgDoc).attr('visibility','display');
						$("#textBox", svgDoc).attr('visibility','display');

					}
	
					

					cssValue       = $(this).css('fill');						 
					var classAttr  = $(this).attr('class');
					var current_id = $(this).attr('id');
					if (current_id    != "separator"   	 && current_id != "State_Lines" 
						&& current_id != "svg9559"  	 && current_id != "metadata3671" 
						&& current_id != "defs9561" 	 && current_id != "base" 
						&& current_id != "State_borders" && current_id != "svg-pan-zoom-reset-pan-zoom" 
						&& classAttr != "svg-pan-zoom-control-element" && classAttr !="svg-pan-zoom-control-background"){
						$(this, svgDoc).css("fill", "lime");
					}  
					
				});

				$("path", svgDoc).mouseout(function(){ 

					$("#textSvg", svgDoc).attr('visibility', 'hidden');
					$("#textBox", svgDoc).attr('visibility', 'hidden');
					
					var classAttr  = $(this).attr('class');
					var current_id = $(this).attr('id');
					
					if (current_id    != "separator" && current_id != "State_Lines"   
						&& current_id != "svg9559"   && current_id != "metadata3671" 
						&& current_id != "defs9561"  && current_id !="base"
						&& classAttr  != "svg-pan-zoom-control-element" && classAttr !="svg-pan-zoom-control-background"){
						$(this, svgDoc).css("fill", cssValue);  		 //fill the path element back to it's original color
					}  
				});

				$("path", svgDoc).dblclick(function(){
					var nameSt    = $(this).attr('title');
					var index     = nameSt.indexOf(",");
					var county    = nameSt.substring(0, index);
					var stateAbbr = nameSt.substring(index + 1);
					
					$("#var1").val(county.trim() + " County");
					$("#var2").val(stateAbbr.trim());
					$("#form").submit();
				});
				
				
				
};
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Choropleth of Avg Bah Rate Per County</title>

<script src="js/jquery.min.js"></script>
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script src="js/svg-pan-zoom.min.js"></script>
<script src="js/countiesBahRates.js"></script>
<script src="js/choropleth.js"></script>

<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" />

<style>
.svg-container { 
	display: inline-block;
	position: relative;
	width: 67%;
	padding-bottom: 50%; 
	vertical-align: middle; 
	overflow: hidden;
}
.svg-content { 
	display: inline-block;
	position: absolute;
	top: 0;
	left: 0;
}


</style>
</head>
<body>
	<form style="display: hidden" action="CountyColleges" method="GET" id="form">
		<input type="hidden" id="var1" name="countyName" value="" /> 
		<input type="hidden" id="var2" name="stateAbbr" value="" />
	</form>
	<div class="container">
		<div class="row">
			<div class="col-md-2">
		      <p>  Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has 
		        Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the indust
		        Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has
			  </p>
		
		</div>

			<div class="col-md-10" style="background:#F0F8FF;text-align:center; border:3px;border-style:inset;">
		
				<object  id="svgObj" data="UnitedStatesCounties.svg" type="image/svg+xml" 
					width="100%" height="100%" > </object>
			</div>
		</div>
	</div>
</body>
</html>
like image 998
Eric Matthew Avatar asked Oct 24 '25 18:10

Eric Matthew


1 Answers

You need to use the SVG's getCTM() function to get the current transform matrix. Then you can transform a screen point back to an internal SVG coordinate. Then you have the location to place your tooltip.

// create an SVG DOM point object
pt = pt = svg.createSVGPoint();
pt.x = screenXPosWithinSVG;
pt.y = screenYPosWithinSVG;

// Transform it back to SVG coordinate space
var svgCoord = pt.matrixTransform(svg.getCTM().inverse());

// Place tooltip at (svgCoord.x, svgCoord.y)
like image 91
Paul LeBeau Avatar answered Oct 26 '25 06:10

Paul LeBeau



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!