Переместите всплывающую подсказку относительно элемента SVG для адаптивной страницы.

Я использую прямоугольный и текстовый элемент SVG в качестве всплывающей подсказки. Оба они находятся внутри элемента SVG, представляющего собой карту округов США.

Всплывающая подсказка работает нормально, если моя карта имеет фиксированную высоту (я просто смещаю координаты для svg рядом с моей мышью), но всплывающая подсказка теряет функциональность, если я делаю свою карту отзывчивой или если пользователь решает увеличить данную область. .

Смотрите фото: http://imgur.com/a/ae1Bd

Мой файл SVG находится по адресу https://codeshare.io/GcJIS, так как он слишком длинный для этого сайта.

Я просто потерян. Первоначально я пытался создать простую всплывающую подсказку div (используя CSS) вместо использования SVG, но это делает мой контейнер div для моей карты svg «прыгающим», как сумасшедший. Я попробовал 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>


person Eric Matthew    schedule 03.06.2016    source источник


Ответы (1)


Вам нужно использовать функцию 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)
person Paul LeBeau    schedule 04.06.2016
comment
Спасибо за ваш ответ, я все еще очень новичок в программировании, и мне было интересно, используете ли вы вечную библиотеку для использования с javascript/SVG в документе HTML (я получаю svgDoc.createSVGPoint не ошибка функции) или если я должен поместить этот скрипт в сам объект SVG? - person Eric Matthew; 05.06.2016
comment
createSVGPoint() — это стандартная функция DOM для объекта SVGSVGElement DOM, который соответствует элементу <svg>. В вашем случае svgDoc установлено значение HTMLObjectElement.contentDocument, которое является объектом Document. Чтобы получить ссылку на корневой элемент SVG, вам нужно будет использовать svg = svgDoc.documentElement. - person Paul LeBeau; 05.06.2016
comment
Спасибо!! Я заработал. Кажется, виновником была библиотека svg-pan-zoom.min.js (помимо отсутствия у меня знаний и компетенции), и Firefox по какой-то причине просто больше не хочет работать. Еще раз спасибо, я многому научился. - person Eric Matthew; 05.06.2016
comment
@EricMatthew, не могли бы вы случайно опубликовать свое решение? Я также использую библиотеку svgPanZoom и пытаюсь расположить элемент относительно панорамирования/масштабирования svg. - person KFE; 03.01.2018