tooltip overflow wrapping

This commit is contained in:
2024-10-25 19:36:41 +02:00
parent 37b20cbe57
commit cf85f4a97b
5 changed files with 48 additions and 28 deletions
+3 -3
View File
@@ -1,11 +1,11 @@
const CapitalIcon = () => ( const CapitalIcon = () => (
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="SVGRepo_bgCarrier" stroke-width="0"></g> <g id="SVGRepo_bgCarrier" strokeWidth="0"></g>
<g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g> <g id="SVGRepo_tracerCarrier" strokeLinecap="round" strokeLinejoin="round"></g>
<g id="SVGRepo_iconCarrier"> <g id="SVGRepo_iconCarrier">
<path <path
d="M4.5 14L3 15V21H7M7 21H10M7 21V13L9.5 11V6L12 3L14.5 6V11L17 13V21M10 21H14M10 21V17C10 15.8954 10.8954 15 12 15C13.1046 15 14 15.8954 14 17V21M14 21H17M17 21H21V15L19.5 14" d="M4.5 14L3 15V21H7M7 21H10M7 21V13L9.5 11V6L12 3L14.5 6V11L17 13V21M10 21H14M10 21V17C10 15.8954 10.8954 15 12 15C13.1046 15 14 15.8954 14 17V21M14 21H17M17 21H21V15L19.5 14"
stroke="#ffffff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path> stroke="#ffffff" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"></path>
</g> </g>
</svg> </svg>
); );
+4 -4
View File
@@ -1,10 +1,10 @@
const DescriptionIcon = () => ( const DescriptionIcon = () => (
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="SVGRepo_bgCarrier" stroke-width="0"></g> <g id="SVGRepo_bgCarrier" strokeWidth="0"></g>
<g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g> <g id="SVGRepo_tracerCarrier" strokeLinecap="round" strokeLinejoin="round"></g>
<g id="SVGRepo_iconCarrier"> <g id="SVGRepo_iconCarrier">
<path d="M3 10H16M3 14H21M3 18H16M3 6H21" stroke="#ffffff" stroke-width="2" stroke-linecap="round" <path d="M3 10H16M3 14H21M3 18H16M3 6H21" stroke="#ffffff" strokeWidth="2" strokeLinecap="round"
stroke-linejoin="round"></path> strokeLinejoin="round"></path>
</g> </g>
</svg> </svg>
); );
+3 -3
View File
@@ -1,11 +1,11 @@
const PopulationIcon = () => ( const PopulationIcon = () => (
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="SVGRepo_bgCarrier" stroke-width="0"></g> <g id="SVGRepo_bgCarrier" strokeWidth="0"></g>
<g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g> <g id="SVGRepo_tracerCarrier" strokeLinecap="round" strokeLinejoin="round"></g>
<g id="SVGRepo_iconCarrier"> <g id="SVGRepo_iconCarrier">
<path <path
d="M13 20V18C13 15.2386 10.7614 13 8 13C5.23858 13 3 15.2386 3 18V20H13ZM13 20H21V19C21 16.0545 18.7614 14 16 14C14.5867 14 13.3103 14.6255 12.4009 15.6311M11 7C11 8.65685 9.65685 10 8 10C6.34315 10 5 8.65685 5 7C5 5.34315 6.34315 4 8 4C9.65685 4 11 5.34315 11 7ZM18 9C18 10.1046 17.1046 11 16 11C14.8954 11 14 10.1046 14 9C14 7.89543 14.8954 7 16 7C17.1046 7 18 7.89543 18 9Z" d="M13 20V18C13 15.2386 10.7614 13 8 13C5.23858 13 3 15.2386 3 18V20H13ZM13 20H21V19C21 16.0545 18.7614 14 16 14C14.5867 14 13.3103 14.6255 12.4009 15.6311M11 7C11 8.65685 9.65685 10 8 10C6.34315 10 5 8.65685 5 7C5 5.34315 6.34315 4 8 4C9.65685 4 11 5.34315 11 7ZM18 9C18 10.1046 17.1046 11 16 11C14.8954 11 14 10.1046 14 9C14 7.89543 14.8954 7 16 7C17.1046 7 18 7.89543 18 9Z"
stroke="#ffffff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path> stroke="#ffffff" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"></path>
</g> </g>
</svg> </svg>
); );
+3 -3
View File
@@ -1,11 +1,11 @@
const RulerIcon = () => ( const RulerIcon = () => (
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="SVGRepo_bgCarrier" stroke-width="0"></g> <g id="SVGRepo_bgCarrier" strokeWidth="0"></g>
<g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g> <g id="SVGRepo_tracerCarrier" strokeLinecap="round" strokeLinejoin="round"></g>
<g id="SVGRepo_iconCarrier"> <g id="SVGRepo_iconCarrier">
<path <path
d="M4 8L6 20H18L20 8M4 8L5.71624 9.37299C6.83218 10.2657 7.39014 10.7121 7.95256 10.7814C8.4453 10.8421 8.94299 10.7173 9.34885 10.4314C9.81211 10.1051 10.0936 9.4483 10.6565 8.13476L12 5M4 8C4.55228 8 5 7.55228 5 7C5 6.44772 4.55228 6 4 6C3.44772 6 3 6.44772 3 7C3 7.55228 3.44772 8 4 8ZM20 8L18.2838 9.373C17.1678 10.2657 16.6099 10.7121 16.0474 10.7814C15.5547 10.8421 15.057 10.7173 14.6511 10.4314C14.1879 10.1051 13.9064 9.4483 13.3435 8.13476L12 5M20 8C20.5523 8 21 7.55228 21 7C21 6.44772 20.5523 6 20 6C19.4477 6 19 6.44772 19 7C19 7.55228 19.4477 8 20 8ZM12 5C12.5523 5 13 4.55228 13 4C13 3.44772 12.5523 3 12 3C11.4477 3 11 3.44772 11 4C11 4.55228 11.4477 5 12 5ZM12 4H12.01M20 7H20.01M4 7H4.01" d="M4 8L6 20H18L20 8M4 8L5.71624 9.37299C6.83218 10.2657 7.39014 10.7121 7.95256 10.7814C8.4453 10.8421 8.94299 10.7173 9.34885 10.4314C9.81211 10.1051 10.0936 9.4483 10.6565 8.13476L12 5M4 8C4.55228 8 5 7.55228 5 7C5 6.44772 4.55228 6 4 6C3.44772 6 3 6.44772 3 7C3 7.55228 3.44772 8 4 8ZM20 8L18.2838 9.373C17.1678 10.2657 16.6099 10.7121 16.0474 10.7814C15.5547 10.8421 15.057 10.7173 14.6511 10.4314C14.1879 10.1051 13.9064 9.4483 13.3435 8.13476L12 5M20 8C20.5523 8 21 7.55228 21 7C21 6.44772 20.5523 6 20 6C19.4477 6 19 6.44772 19 7C19 7.55228 19.4477 8 20 8ZM12 5C12.5523 5 13 4.55228 13 4C13 3.44772 12.5523 3 12 3C11.4477 3 11 3.44772 11 4C11 4.55228 11.4477 5 12 5ZM12 4H12.01M20 7H20.01M4 7H4.01"
stroke="#ffffff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path> stroke="#ffffff" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"></path>
</g> </g>
</svg> </svg>
); );
+35 -15
View File
@@ -18,6 +18,7 @@ interface MapProps {
const Map: React.FC<MapProps> = ({ imageUrl, regions = [], cities = [], pois = [], capitals = [] }) => { const Map: React.FC<MapProps> = ({ imageUrl, regions = [], cities = [], pois = [], capitals = [] }) => {
const svgRef = useRef<SVGSVGElement | null>(null); const svgRef = useRef<SVGSVGElement | null>(null);
const gRef = useRef<SVGGElement | null>(null); const gRef = useRef<SVGGElement | null>(null);
const tooltipRef = useRef<HTMLDivElement | null>(null); // Ref for the tooltip
const [tooltip, setTooltip] = useState<{ visible: boolean; x: number; y: number; content: JSX.Element | null }>({ const [tooltip, setTooltip] = useState<{ visible: boolean; x: number; y: number; content: JSX.Element | null }>({
visible: false, visible: false,
x: 0, x: 0,
@@ -45,9 +46,8 @@ const Map: React.FC<MapProps> = ({ imageUrl, regions = [], cities = [], pois = [
}; };
const handleMouseMove = (e: MouseEvent) => { const handleMouseMove = (e: MouseEvent) => {
if (!isDragging) return; if (!isDragging || scale <= 1) return;
// Increase deltaX and deltaY by the drag sensitivity factor
const deltaX = (e.clientX - startX) * dragSensitivity; const deltaX = (e.clientX - startX) * dragSensitivity;
const deltaY = (e.clientY - startY) * dragSensitivity; const deltaY = (e.clientY - startY) * dragSensitivity;
setTranslate(prev => ({ setTranslate(prev => ({
@@ -59,13 +59,10 @@ const Map: React.FC<MapProps> = ({ imageUrl, regions = [], cities = [], pois = [
}; };
const handleMouseUp = () => setIsDragging(false); const handleMouseUp = () => setIsDragging(false);
const handleWheel = (e: WheelEvent) => { const handleWheel = (e: WheelEvent) => {
e.preventDefault(); e.preventDefault();
const zoomFactor = e.deltaY > 0 ? 0.9 : 1.1; const zoomFactor = e.deltaY > 0 ? 0.9 : 1.1;
const newScale = Math.min(Math.max(scale * zoomFactor, 1), 6); const newScale = Math.min(Math.max(scale * zoomFactor, 1), 6);
// If zooming out to the minimum scale, reset translation
if (newScale === 1) { if (newScale === 1) {
setTranslate({ x: 0, y: 0 }); setTranslate({ x: 0, y: 0 });
} else { } else {
@@ -73,7 +70,6 @@ const Map: React.FC<MapProps> = ({ imageUrl, regions = [], cities = [], pois = [
svgPoint.x = e.clientX; svgPoint.x = e.clientX;
svgPoint.y = e.clientY; svgPoint.y = e.clientY;
const mousePoint = svgPoint.matrixTransform(svgElement.getScreenCTM()?.inverse()); const mousePoint = svgPoint.matrixTransform(svgElement.getScreenCTM()?.inverse());
const newTranslateX = translate.x - (mousePoint.x - translate.x) * (newScale / scale - 1); const newTranslateX = translate.x - (mousePoint.x - translate.x) * (newScale / scale - 1);
const newTranslateY = translate.y - (mousePoint.y - translate.y) * (newScale / scale - 1); const newTranslateY = translate.y - (mousePoint.y - translate.y) * (newScale / scale - 1);
setTranslate({ x: newTranslateX, y: newTranslateY }); setTranslate({ x: newTranslateX, y: newTranslateY });
@@ -97,30 +93,54 @@ const Map: React.FC<MapProps> = ({ imageUrl, regions = [], cities = [], pois = [
} }
}, [isDragging, startX, startY, scale]); }, [isDragging, startX, startY, scale]);
// Tooltip handling remains unchanged const setDynamicTooltipPosition = (clientX: number, clientY: number) => {
if (tooltipRef.current) {
const { width, height } = tooltipRef.current.getBoundingClientRect();
// console.log("Width:", width, "Height:", height);
let tooltipX = clientX + 10;
let tooltipY = clientY + 10;
if (tooltipX + width > window.innerWidth) {
// console.log("Horizontal overflow");
tooltipX = clientX - width - 10;
}
if (tooltipY + height > window.innerHeight) {
// console.log("Vertical overflow");
tooltipY = clientY - height - 10;
}
return { tooltipX, tooltipY };
}
return { tooltipX: clientX, tooltipY: clientY };
};
const handleMouseEnterRegion = (event: React.MouseEvent<SVGPolygonElement>, region: MapRegion) => { const handleMouseEnterRegion = (event: React.MouseEvent<SVGPolygonElement>, region: MapRegion) => {
const { tooltipX, tooltipY } = setDynamicTooltipPosition(event.pageX, event.pageY);
setTooltip({ setTooltip({
visible: true, visible: true,
x: event.clientX + 10, x: tooltipX,
y: event.clientY + 10, y: tooltipY,
content: <MapRegionTooltip region={region} />, content: <MapRegionTooltip region={region} />,
}); });
}; };
const handleMouseEnterLocation = (event: React.MouseEvent<SVGGElement>, location: MapLocation) => { const handleMouseEnterLocation = (event: React.MouseEvent<SVGGElement>, location: MapLocation) => {
const { tooltipX, tooltipY } = setDynamicTooltipPosition(event.clientX, event.clientY);
setTooltip({ setTooltip({
visible: true, visible: true,
x: event.clientX + 10, x: tooltipX,
y: event.clientY + 10, y: tooltipY,
content: <MapLocationTooltip location={location} />, content: <MapLocationTooltip location={location} />,
}); });
}; };
const handleMouseMove = (event: React.MouseEvent) => { const handleMouseMove = (event: React.MouseEvent) => {
const { tooltipX, tooltipY } = setDynamicTooltipPosition(event.clientX, event.clientY);
setTooltip(prev => ({ setTooltip(prev => ({
...prev, ...prev,
x: event.clientX + 10, x: tooltipX,
y: event.clientY + 10, y: tooltipY,
})); }));
}; };
@@ -130,7 +150,7 @@ const Map: React.FC<MapProps> = ({ imageUrl, regions = [], cities = [], pois = [
return ( return (
<> <>
<svg ref={svgRef} id="map" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2641 2035"> <svg ref={svgRef} id="map" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2641 2035" onMouseMove={handleMouseMove}>
<g ref={gRef} transform={`translate(${translate.x}, ${translate.y}) scale(${scale})`}> <g ref={gRef} transform={`translate(${translate.x}, ${translate.y}) scale(${scale})`}>
<image href={imageUrl} width="100%" /> <image href={imageUrl} width="100%" />
{regions.map((region, index) => ( {regions.map((region, index) => (
@@ -142,7 +162,6 @@ const Map: React.FC<MapProps> = ({ imageUrl, regions = [], cities = [], pois = [
stroke="transparent" stroke="transparent"
strokeWidth={4} strokeWidth={4}
onMouseEnter={(e) => handleMouseEnterRegion(e, region)} onMouseEnter={(e) => handleMouseEnterRegion(e, region)}
onMouseMove={handleMouseMove}
onMouseLeave={handleMouseLeave} onMouseLeave={handleMouseLeave}
/> />
))} ))}
@@ -177,6 +196,7 @@ const Map: React.FC<MapProps> = ({ imageUrl, regions = [], cities = [], pois = [
</svg> </svg>
{tooltip.visible && !isDragging && ( {tooltip.visible && !isDragging && (
<div <div
ref={tooltipRef} // Attach the ref here
id={"tooltip"} id={"tooltip"}
className={"tooltip"} className={"tooltip"}
style={{ style={{