javascript - 相对于响应式页面的 SVG 元素重新定位工具提示

标签 javascript jquery svg tooltip responsive

我使用 SVG 矩形和文本元素作为工具提示。它们都在一个 SVG 元素中,该元素是美国各县的 map 。

如果我的 map 是固定高度(我只是在鼠标附近偏移 svg 的坐标),工具提示工作正常,但如果我使 map 响应或用户决定放大,工具提示将失去功能给定的区域。

见图片:http://imgur.com/a/ae1Bd

我的 SVG 文件位于 https://codeshare.io/GcJIS因为它对于这个网站来说太长了。

我只是迷路了。我最初尝试制作一个简单的 div 工具提示(使用 CSS)而不是使用 SVG,但它使我的 svg map 的 div 容器像疯了一样“弹跳”。我尝试了 D3,但发现自己更加困惑。我觉得有一些简单的东西我只是忽略了,但我一直在努力实现这个“简单”的功能。任何帮助或指导表示赞赏。

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>

最佳答案

您需要使用 SVG 的 getCTM() 函数来获取当前的变换矩阵。然后您可以将屏幕点转换回内部 SVG 坐标。然后您就有了放置工具提示的位置。

// 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)

关于javascript - 相对于响应式页面的 SVG 元素重新定位工具提示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37620028/

相关文章:

javascript - 非常简单,非常流畅,JavaScript 跑马灯

javascript - 仅当不为 null 时才向对象添加值 - 不起作用

javascript - 如何根据 Jquery 中的屏幕大小移动绝对位置元素

javascript - 通过 javascript 调整 SVG viewBox 行为

javascript - 在 node.js 回调函数中循环

javascript - 多个特定目的的设置间隔或单个 super 间隔

javascript - jCarousel、计数器,怎么样?

css - 浏览器未显示正确的 SVG

xslt - 需要使用 XSL FO 缩放图像以适应

javascript - 两个 Action 不能同时进行