diff --git a/config/sync/core.extension.yml b/config/sync/core.extension.yml index ec9d810..a4cebfa 100644 --- a/config/sync/core.extension.yml +++ b/config/sync/core.extension.yml @@ -48,6 +48,7 @@ module: entity_browser: 0 entity_browser_enhanced: 0 entity_reference_revisions: 0 + erable_mod: 0 faq: 0 field: 0 field_group: 0 diff --git a/config/sync/page_manager.page_variant.home-panels_variant-0.yml b/config/sync/page_manager.page_variant.home-panels_variant-0.yml index 854900e..1536265 100644 --- a/config/sync/page_manager.page_variant.home-panels_variant-0.yml +++ b/config/sync/page_manager.page_variant.home-panels_variant-0.yml @@ -7,6 +7,7 @@ dependencies: - views.view.actus - views.view.home_blocks module: + - erable_mod - panels - views id: home-panels_variant-0 @@ -55,6 +56,15 @@ variant_settings: region: content weight: 1 uuid: 0e39f25a-d433-49bd-84d4-3e6c11c16c47 + 41595e31-d8d6-4940-a1e5-8687c04af5a5: + id: sitesmap_block + label: 'Sites map Block' + label_display: '0' + provider: erable_mod + context_mapping: { } + region: content + weight: 0 + uuid: 41595e31-d8d6-4940-a1e5-8687c04af5a5 page_title: '' layout: layout_onecol layout_settings: diff --git a/web/modules/custom/erable_mod/assets/css/carte-interactive.css b/web/modules/custom/erable_mod/assets/css/carte-interactive.css new file mode 100644 index 0000000..09af117 --- /dev/null +++ b/web/modules/custom/erable_mod/assets/css/carte-interactive.css @@ -0,0 +1,98 @@ +@font-face { + font-family: 'gilroy-semibold'; + src: url('../css/fonts/Gilroy/gilroy-semibold-webfont.woff') format('woff'); +} +#sites-map-container { + background-color: transparent; + text-align: center; + position: relative; + width: 100%; /* Prend toute la largeur du conteneur parent */ + max-width: 800px; /* Optionnel : Limiter la largeur maximale */ + margin: 0 auto; /* Centrer le conteneur */ + height: auto; /* Permet à la hauteur de s'ajuster automatiquement */ + @media (max-width: 810px) { + width: 80%; /* Prend toute la largeur du conteneur parent */ + } + @media (max-width: 530px) { + width: 100%; /* Prend toute la largeur du conteneur parent */ + height: 485px; + } + @media (max-width: 400px) { + width: 100%; /* Prend toute la largeur du conteneur parent */ + height: 430px; + } +} + + + +/* Changer la couleur au survol (hover) */ +#sites-map-container .site-link:hover{ + cursor: pointer; +} + + +/* Styles du popup (caché par défaut) */ +#sites-map-container #popup { + font-family: 'gilroy-light'; + display: none; + position: absolute; + z-index: 1000; + text-align: left; + padding-left: 1rem; + pointer-events: none; + @media (max-width: 1090px) { + bottom: 20px; + } + +} + +/* Position du popup à droite lorsque l'écran est plus grand que 1090px */ +@media (min-width: 1090px) { + #sites-map-container #popup { + top: 50%; /* Centrer verticalement */ + left: 80%; /* Placer le popup à droite de la carte */ + transform: translateY(-50%); /* Ajuster pour centrer verticalement */ + width: 300px; + } +} + + +#sites-map-container strong{ + color: #f7002b; + font-family: 'gilroy-bold'; +} +#sites-map-container a{ + display: none; + align-items: center; + color: white; + background: black; + text-transform: uppercase; + font-size: 0.8rem; + padding-left: 0.5rem; + text-decoration: none; + margin-top: 0.7rem; + height: 1.3rem; +} +#sites-map-container a:after{ + display: inline-flex; + content: url("../img/noun-arrow-to-right.svg"); + padding-right: 0.2rem; + padding-left: 0.2rem; + +} + +#popup-content{ + width: 300px; + padding-right: 30px; + + p{ + font-size: 0.7rem; + } + @media (max-width : 810px) { + width: 300px; + background-color: white; + border-radius: 5px; + padding: 0.5rem; + padding-left: 1rem; + } +} diff --git a/web/modules/custom/erable_mod/assets/css/fonts/Gilroy/gilroy-semibold-webfont.woff b/web/modules/custom/erable_mod/assets/css/fonts/Gilroy/gilroy-semibold-webfont.woff new file mode 100644 index 0000000..8abd458 Binary files /dev/null and b/web/modules/custom/erable_mod/assets/css/fonts/Gilroy/gilroy-semibold-webfont.woff differ diff --git a/web/modules/custom/erable_mod/assets/js/carte-interactive.js b/web/modules/custom/erable_mod/assets/js/carte-interactive.js new file mode 100644 index 0000000..30abdbc --- /dev/null +++ b/web/modules/custom/erable_mod/assets/js/carte-interactive.js @@ -0,0 +1,116 @@ +// // Sélection des éléments principaux +const svgElement = document.querySelector('#sites-map-container svg'); +const popup = document.querySelector('#sites-map-container #popup'); +const popupContent = document.querySelector('#sites-map-container #popup-content'); +const modalBackground = document.querySelector('#sites-map-container #modal-background'); + +// Vérifiez si la page contient la classe '.node-type-site' +const isSitePage = document.body.classList.contains('node-type-site'); + + +// Fonction pour afficher le popup +function showPopup(content, x, y, isLeftHalf) { + // Si on est sur une page avec la classe 'node-type-site', ne pas afficher le popup + if (isSitePage) return; + + popupContent.innerHTML = content; + + + // Afficher le popup et le fond de modal + popup.style.display = 'block'; + modalBackground.style.display = 'block'; + +} + +// Fonction pour fermer le popup +function closePopup() { + popup.style.display = 'none'; + modalBackground.style.display = 'none'; // Désactiver le fond modal +} + +// Gérer le survol des cercles (au lieu du clic) +svgElement.addEventListener('mouseover', function(event) { + if (event.target.classList.contains('site-link')) { + const content = event.target.getAttribute('data-content'); + + // Afficher le popup avec la position et l'alignement adaptés + showPopup(content); + } + + // Gestion du changement de couleur sur le cercle + if (event.target.tagName === 'circle') { + event.target.setAttribute('fill', 'red'); + } +}); + +// Fermer le popup lorsque la souris quitte le cercle +svgElement.addEventListener('mouseout', function(event) { + if (event.target.classList.contains('site-link')) { + closePopup(); + } + + // Réinitialiser la couleur du cercle au survol de la souris + if (event.target.tagName === 'circle') { + event.target.setAttribute('fill', 'black'); // Remettre en noir + } +}); + + +// Mettre à jour la logique de calcul des positions +function recalculateSitePositions() { + const allSites = document.querySelectorAll('.site-link'); + + allSites.forEach((site, index) => { + const geofield = site.getAttribute('data-geofield'); // Assurez-vous que ces attributs sont bien définis + const lon = parseFloat(geofield.split(',')[0]); + const lat = parseFloat(geofield.split(',')[1]); + + const x = round((lon - lonLeft) / (lonRight - lonLeft) * vp_w); + const y = round((latTop - lat) / (latTop - latBottom) * vp_h); + + site.setAttribute('transform', `translate(${x}, ${y})`); + }); +} + +window.addEventListener('resize', function() { + recalculateSitePositions(); + if (popup.style.display === 'block') { + const currentPopupRect = popup.getBoundingClientRect(); + const rect = svgElement.getBoundingClientRect(); + showPopup(popupContent.innerHTML, currentPopupRect.left - rect.left, currentPopupRect.top - rect.top); + } +}); + +// Gérer le clic ou le toucher des cercles +function handleCircleClick(content) { + showPopup(content, event.clientX, event.clientY, event.target.getAttribute('data-left-half') === 'true'); +} + +// Écouter les événements de clic et de toucher sur le SVG +svgElement.addEventListener('click', function(event) { + if (event.target.classList.contains('site-link') || event.target.tagName === 'rect') { + const content = event.target.getAttribute('data-content'); + handleCircleClick(content); + } +}); + + +///////////////////// page site point rouge quand sur page /////////////////////// + +// Récupérer l'ID de la page depuis la classe du body +const body = document.querySelector('body'); +const pageId = body.className.match(/node-id-(\d+)/)[1]; // Extraire l'ID de la page + +// Sélectionner le groupe SVG qui a l'ID correspondant +const matchingGroup = document.querySelector(`#site-${pageId}`); + +// Si un groupe correspondant est trouvé, changer la couleur du cercle à l'intérieur +if (matchingGroup) { + const circle = matchingGroup.querySelector('circle'); // Sélectionner le cercle à l'intérieur du groupe + if (circle) { + circle.setAttribute('fill', 'red'); // Changer la couleur du cercle + } +} + + + diff --git a/web/modules/custom/erable_mod/erable_mod.info.yml b/web/modules/custom/erable_mod/erable_mod.info.yml new file mode 100644 index 0000000..a73f431 --- /dev/null +++ b/web/modules/custom/erable_mod/erable_mod.info.yml @@ -0,0 +1,7 @@ +name: erable_mod +type: module +description: Provides additional functionality for the site. +package: Custom +core_version_requirement: ^9 || ^10 +dependencies: + - drupal:block \ No newline at end of file diff --git a/web/modules/custom/erable_mod/erable_mod.libraries.yml b/web/modules/custom/erable_mod/erable_mod.libraries.yml new file mode 100644 index 0000000..50a42b1 --- /dev/null +++ b/web/modules/custom/erable_mod/erable_mod.libraries.yml @@ -0,0 +1,7 @@ +sites_map_block: + css: + theme: + assets/css/fontface.scss: {} + assets/css/carte-interactive.css: {} + js: + assets/js/carte-interactive.js: {} \ No newline at end of file diff --git a/web/modules/custom/erable_mod/erable_mod.module b/web/modules/custom/erable_mod/erable_mod.module new file mode 100644 index 0000000..ee58c18 --- /dev/null +++ b/web/modules/custom/erable_mod/erable_mod.module @@ -0,0 +1,17 @@ + array( + 'variables' => array('vpw' => null, 'vph' => null, 'sites' => []), + ), + ); +} \ No newline at end of file diff --git a/web/modules/custom/erable_mod/src/Plugin/Block/SitesMap.php b/web/modules/custom/erable_mod/src/Plugin/Block/SitesMap.php new file mode 100644 index 0000000..9533366 --- /dev/null +++ b/web/modules/custom/erable_mod/src/Plugin/Block/SitesMap.php @@ -0,0 +1,115 @@ +getStorage('node') + ->loadByProperties(['type' => 'projet', 'status' => 1]); + + $sites_paths = ""; + + $vp_w = 600; + $vp_h = 600; + + // Coordonnées géographiques des coins de la carte (France) + $latTop = 52.0; // Nord-Ouest (coin supérieur gauche) + $lonLeft = -6.0; + $latBottom = 40.0; // Sud-Est (coin inférieur droit) + $lonRight = 11.0; + + + foreach($allSites as $index => $site){ + $title = $site->get('title')->getString(); + $subtitle = $site->get('field_sous_titre')->getString(); + + $link_options = ['absolute' => FALSE, 'attributes' => ['class' => 'site-link']]; + $site_link_object = Link::createFromRoute("voir le site", 'entity.node.canonical', ['node' => $site->id()], $link_options); + $link = $site_link_object->toString()->getGeneratedLink(); + + $datacontent = htmlspecialchars("$title
$subtitle
$link"); + + $geofield = $site->get('field_carte')->get(0); + $lon = $geofield->lon; + $lat = $geofield->lat; + $geofieldData = "$lon,$lat"; // Utiliser une chaîne pour stocker la position + + $x = round(($lon - $lonLeft) / ($lonRight - $lonLeft) * $vp_w); + $y = round(($latTop - $lat) / ($latTop - $latBottom) * $vp_h); + + $r = 10; + $m = -$r+4; + $l = $r*2-7; + $sites_paths .= << + > + + + + + + + + SVGSITEPATH; + } + + + $return = [ + '#cache' => [ + 'max-age' => 0, + ], + 'svg_mapsites' => [ + '#theme' => 'svg_mapsites', + '#sites' => $sites_paths, + '#vpw' => $vp_w, + '#vph' => $vp_h, + '#attached' => [ + 'library' => [ + 'erable_mod/sites_map_block', + ], + ], + ] + ]; + + return $return; + // return [ + // '#markup' => $this->t('Hello, Sites Map!'), + // ]; + } + public function getCacheMaxAge() { + return 0; + } +} \ No newline at end of file diff --git a/web/modules/custom/erable_mod/templates/svg-mapsites.html.twig b/web/modules/custom/erable_mod/templates/svg-mapsites.html.twig new file mode 100644 index 0000000..b0e1544 --- /dev/null +++ b/web/modules/custom/erable_mod/templates/svg-mapsites.html.twig @@ -0,0 +1,52 @@ +
+ {# + + #} + + + + + + + + + + {{ sites|raw }} + + + + + + + + +
\ No newline at end of file