ELITE 10 2CH

Plage de prix : 499,00 € à 589,00 €

UGS : ELITE 9 2CH Catégorie :

Description

Découvrez l’ELITE 10 en vidéo

 

<?php


/**
 * ============================================================================
 *  EDR GALLERY  —  Galerie mosaïque zoomable pour WooCommerce
 * ============================================================================
 *  Auteur   : MOOVIKA / EDR Auto
 *  Usage    : À coller dans un snippet "Code Snippets" (exécution : Partout / PHP).
 *
 *  Fonctions :
 *   - Metabox sur la fiche produit pour ajouter des photos (médiathèque WP)
 *   - Rotation par photo (0 / 90 / 180 / 270°) modifiable dans l'admin
 *   - Réordonnancement (◀ ▶) et suppression par photo
 *   - Affichage front en mosaïque 6 colonnes (autant de lignes que nécessaire)
 *   - Vignettes rectangulaires 60/40 (réglable), ombre portée, survol grisé + loupe
 *   - Pagination auto au-delà de N lignes (défaut 10) avec compteur « 1 / 2 »
 *   - Responsive : sur mobile (≤768px) colonnes ÷2 et lignes/page ÷2 automatiquement
 *   - Zoom plein écran (lightbox maison, navigation clavier)
 *   - Filigrane "EDRAUTO.FR" : motif répété sur les vignettes, UN SEUL centré au zoom
 *
 *  Affichage :
 *   - Shortcode : [edr_gallery]                        (produit courant, 6 col · 60/40)
 *   - Options   : [edr_gallery id="123" cols="6" gap="6" ratio="60/40" rows="10" opacity="0.4" watermark="EDRAUTO.FR"]
 *   - Elementor : insérer un widget "Shortcode" avec [edr_gallery]
 *   - Auto      : décommenter le hook tout en bas pour l'insérer automatiquement
 * ============================================================================
 */

if ( ! defined( 'ABSPATH' ) ) { exit; }

/* ============================================================================
 *  1) ADMIN — Chargement de la médiathèque sur la fiche produit
 * ========================================================================== */
add_action( 'admin_enqueue_scripts', function () {
	$screen = function_exists( 'get_current_screen' ) ? get_current_screen() : null;
	if ( $screen && 'product' === $screen->post_type ) {
		wp_enqueue_media();
		wp_enqueue_script( 'jquery-ui-sortable' ); // glisser-déposer des photos
	}
} );

/* ============================================================================
 *  2) ADMIN — Metabox sur la fiche produit
 * ========================================================================== */
add_action( 'add_meta_boxes', function () {
	add_meta_box(
		'edr_gallery_metabox',
		'📸 Galerie mosaïque EDR',
		'edr_gallery_metabox_render',
		'product',
		'normal',
		'default'
	);
} );

function edr_gallery_metabox_render( $post ) {

	// Lecture des données stockées (tableau de {id, rotation})
	$stored = json_decode( get_post_meta( $post->ID, '_edr_gallery_data', true ), true );
	if ( ! is_array( $stored ) ) {
		$stored = array();
	}

	// On reconstruit un tableau avec l'URL miniature fraîche pour l'aperçu admin
	$init = array();
	foreach ( $stored as $it ) {
		$id    = isset( $it['id'] ) ? absint( $it['id'] ) : 0;
		$thumb = $id ? wp_get_attachment_image_url( $id, 'thumbnail' ) : '';
		if ( ! $thumb ) {
			continue; // image supprimée de la médiathèque
		}
		$init[] = array(
			'id'       => $id,
			'rotation' => isset( $it['rotation'] ) ? intval( $it['rotation'] ) : 0,
			'thumb'    => $thumb,
		);
	}

	wp_nonce_field( 'edr_gallery_save', 'edr_gallery_nonce' );
	?>
	<div id="edr-gallery-wrap">
		<input type="hidden" id="edr_gallery_data" name="edr_gallery_data" value="">

		<div id="edr-gallery-items" class="edr-admin-grid"></div>

		<p style="margin-top:12px;">
			<button type="button" class="button button-primary button-large" id="edr-gallery-add">
				+ Ajouter des photos
			</button>
			<span class="description" style="margin-left:10px;">
				✋ glisser-déposer pour réordonner · ↻ pivoter · ◀ ▶ déplacer · ✕ retirer
			</span>
		</p>
	</div>

	<style>
		.edr-admin-grid{ display:grid; grid-template-columns:repeat(auto-fill,minmax(120px,1fr)); gap:12px; margin-top:8px; }
		.edr-admin-grid:empty::before{ content:"Aucune photo pour le moment."; color:#777; font-style:italic; }
		.edr-item{ position:relative; border:1px solid #dcdcde; border-radius:6px; overflow:hidden; background:#f6f7f7; }
		.edr-item .edr-thumb{ width:100%; aspect-ratio:1/1; object-fit:cover; display:block; transition:transform .2s ease; cursor:move; }
		.edr-item .edr-actions{ display:flex; gap:2px; padding:4px; background:#fff; border-top:1px solid #eee; }
		.edr-item .edr-actions .button{ flex:1; min-height:24px; padding:0 4px; font-size:11px; line-height:22px; }
		.edr-item .edr-rot-badge{ position:absolute; top:4px; right:4px; background:rgba(0,0,0,.7); color:#fff; font-size:10px; padding:1px 5px; border-radius:3px; }
		/* Glisser-déposer */
		.edr-item.ui-sortable-helper{ box-shadow:0 6px 18px rgba(0,0,0,.25); opacity:.95; }
		.edr-item-placeholder{ border:2px dashed #2271b1; border-radius:6px; background:#f0f6fc; visibility:visible !important; }
	</style>

	<script>
	( function ( $ ) {
		var edrInit = <?php echo wp_json_encode( $init ); ?>;
		var data    = Array.isArray( edrInit ) ? edrInit.slice() : [];

		function sync() {
			// On ne conserve que id + rotation à l'enregistrement
			var out = data.map( function ( it ) {
				return { id: it.id, rotation: it.rotation };
			} );
			$( '#edr_gallery_data' ).val( JSON.stringify( out ) );
		}

		function render() {
			var $c = $( '#edr-gallery-items' ).empty();
			data.forEach( function ( it, idx ) {
				var $item = $(
					'<div class="edr-item" data-idx="' + idx + '">' +
						'<span class="edr-rot-badge">' + it.rotation + '°</span>' +
						'<img class="edr-thumb" src="' + it.thumb + '" style="transform:rotate(' + it.rotation + 'deg);">' +
						'<div class="edr-actions">' +
							'<button type="button" class="button edr-rot"  title="Pivoter">↻</button>' +
							'<button type="button" class="button edr-left" title="Déplacer à gauche">◀</button>' +
							'<button type="button" class="button edr-right" title="Déplacer à droite">▶</button>' +
							'<button type="button" class="button edr-del"  title="Retirer">✕</button>' +
						'</div>' +
					'</div>'
				);
				$c.append( $item );
			} );
			sync();
			initSortable();
		}

		// Glisser-déposer pour réordonner les photos
		function initSortable() {
			if ( ! $.fn.sortable ) { return; } // sécurité si jQuery UI absent
			var $c = $( '#edr-gallery-items' );
			if ( $c.hasClass( 'ui-sortable' ) ) {
				$c.sortable( 'destroy' );
			}
			$c.sortable( {
				items: '> .edr-item',
				cancel: '.edr-actions',        // les boutons ne déclenchent pas de drag
				placeholder: 'edr-item-placeholder',
				forcePlaceholderSize: true,
				tolerance: 'pointer',
				cursor: 'move',
				opacity: 0.9,
				update: function () {
					// Nouvel ordre lu dans le DOM (avant re-render)
					var order = $c.children( '.edr-item' ).map( function () {
						return $( this ).data( 'idx' );
					} ).get();
					var reordered = order.map( function ( i ) { return data[ i ]; } );
					// On applique et on redessine au tick suivant (évite les conflits jQuery UI)
					setTimeout( function () { data = reordered; render(); }, 0 );
				}
			} );
		}

		// Ajout via la médiathèque WordPress (sélection multiple)
		$( '#edr-gallery-add' ).on( 'click', function ( e ) {
			e.preventDefault();
			var frame = wp.media( {
				title: 'Sélectionner des photos pour la galerie',
				button: { text: 'Ajouter à la galerie' },
				library: { type: 'image' },
				multiple: true
			} );
			frame.on( 'select', function () {
				frame.state().get( 'selection' ).map( function ( att ) {
					att = att.toJSON();
					var thumb = ( att.sizes && att.sizes.thumbnail )
						? att.sizes.thumbnail.url
						: att.url;
					data.push( { id: att.id, rotation: 0, thumb: thumb } );
				} );
				render();
			} );
			frame.open();
		} );

		// Actions par photo (délégation d'événements)
		$( '#edr-gallery-items' )
			.on( 'click', '.edr-rot', function () {
				var i = $( this ).closest( '.edr-item' ).data( 'idx' );
				data[ i ].rotation = ( data[ i ].rotation + 90 ) % 360;
				render();
			} )
			.on( 'click', '.edr-del', function () {
				var i = $( this ).closest( '.edr-item' ).data( 'idx' );
				data.splice( i, 1 );
				render();
			} )
			.on( 'click', '.edr-left', function () {
				var i = $( this ).closest( '.edr-item' ).data( 'idx' );
				if ( i > 0 ) { var t = data[ i - 1 ]; data[ i - 1 ] = data[ i ]; data[ i ] = t; render(); }
			} )
			.on( 'click', '.edr-right', function () {
				var i = $( this ).closest( '.edr-item' ).data( 'idx' );
				if ( i < data.length - 1 ) { var t = data[ i + 1 ]; data[ i + 1 ] = data[ i ]; data[ i ] = t; render(); }
			} );

		render();
	} )( jQuery );
	</script>
	<?php
}

/* ============================================================================
 *  3) ADMIN — Enregistrement
 * ========================================================================== */
add_action( 'save_post_product', function ( $post_id ) {

	if ( ! isset( $_POST['edr_gallery_nonce'] ) ||
		 ! wp_verify_nonce( $_POST['edr_gallery_nonce'], 'edr_gallery_save' ) ) {
		return;
	}
	if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
		return;
	}
	if ( ! current_user_can( 'edit_post', $post_id ) ) {
		return;
	}

	$raw   = isset( $_POST['edr_gallery_data'] ) ? wp_unslash( $_POST['edr_gallery_data'] ) : '[]';
	$items = json_decode( $raw, true );
	$clean = array();

	if ( is_array( $items ) ) {
		foreach ( $items as $it ) {
			$id = isset( $it['id'] ) ? absint( $it['id'] ) : 0;
			if ( ! $id ) {
				continue;
			}
			$rot = isset( $it['rotation'] ) ? intval( $it['rotation'] ) : 0;
			if ( ! in_array( $rot, array( 0, 90, 180, 270 ), true ) ) {
				$rot = 0;
			}
			$clean[] = array( 'id' => $id, 'rotation' => $rot );
		}
	}

	update_post_meta( $post_id, '_edr_gallery_data', wp_json_encode( $clean ) );
} );

/* ============================================================================
 *  4) FRONT — Assets (CSS + JS lightbox), imprimés une seule fois
 * ========================================================================== */
function edr_gallery_print_assets() {
	static $done = false;
	if ( $done ) {
		return;
	}
	$done = true;

	// Le JS de la lightbox est différé dans le footer
	add_action( 'wp_footer', 'edr_gallery_footer_js', 99 );
	?>
	<style id="edr-gallery-css">
		.edr-gallery{
			display:grid;
			grid-template-columns:repeat( var(--edr-cols,6), 1fr );
			gap:var(--edr-gap,6px);
			width:100%;
		}
		.edr-gallery .edr-cell{
			position:relative; padding:0; margin:0; border:0;
			background:#111; cursor:pointer; overflow:hidden;
			aspect-ratio:var(--edr-ratio,75/25); border-radius:6px;
			box-shadow:0 4px 12px rgba(0,0,0,.18);
			transition:box-shadow .25s ease, transform .25s ease;
			-webkit-appearance:none; appearance:none;
		}
		.edr-gallery .edr-cell:hover{
			box-shadow:0 9px 24px rgba(0,0,0,.30);
			transform:translateY(-3px);
		}
		.edr-gallery .edr-cell img{
			width:100%; height:100%; object-fit:cover; display:block;
			transform:rotate( var(--rot,0deg) );
			transition:transform .3s ease;
		}
		.edr-gallery .edr-cell:hover img{
			transform:rotate( var(--rot,0deg) ) scale(1.07);
		}
		/* Photo pivotée à 90/270° : on la zoome pour remplir la vignette rectangulaire */
		.edr-gallery .edr-cell.edr-rot-side img{
			transform:rotate( var(--rot,0deg) ) scale( var(--edr-cover,1) );
		}
		.edr-gallery .edr-cell.edr-rot-side:hover img{
			transform:rotate( var(--rot,0deg) ) scale( calc( var(--edr-cover,1) * 1.07 ) );
		}
		/* Calque filigrane vignettes (motif SVG répété) */
		.edr-gallery .edr-wm-layer{
			position:absolute; inset:0; pointer-events:none;
			background-image:var(--edr-wm);
			background-repeat:repeat;
		}
		/* Survol : voile grisé + loupe qui apparaît */
		.edr-gallery .edr-cell::after{
			content:""; position:absolute; inset:0; pointer-events:none;
			background-color:rgba(35,35,38,0);
			background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cline x1='16.5' y1='16.5' x2='21' y2='21'/%3E%3C/svg%3E");
			background-repeat:no-repeat; background-position:center; background-size:0px;
			transition:background-color .25s ease, background-size .25s ease;
		}
		.edr-gallery .edr-cell:hover::after{
			background-color:rgba(35,35,38,.42);
			background-size:44px;
		}
		/* Calque filigrane vue zoomée : un seul texte centré */
		.edr-lb .edr-lb-wm{
			position:absolute; inset:0; pointer-events:none;
			background-image:var(--edr-wm-single);
			background-repeat:no-repeat;
			background-position:center;
		}

		/* ---- Pagination ---- */
		.edr-gallery .edr-cell.edr-hidden{ display:none !important; }
		.edr-pager{
			display:flex; align-items:center; justify-content:center;
			gap:6px; flex-wrap:wrap; margin-top:16px;
		}
		.edr-pager .edr-pg-nums{ display:flex; gap:6px; flex-wrap:wrap; }
		.edr-pager button{
			min-width:36px; height:36px; padding:0 10px;
			border:1px solid #dcdcde; background:#fff; color:#333;
			border-radius:8px; cursor:pointer; font-size:14px; line-height:1;
			transition:all .15s ease;
		}
		.edr-pager button:hover:not(:disabled){ border-color:#111; }
		.edr-pager button:disabled{ opacity:.4; cursor:default; }
		.edr-pager .edr-pg-num.active{ background:#111; color:#fff; border-color:#111; font-weight:700; }
		.edr-pager .edr-pg-count{ font-size:13px; color:#666; margin:0 8px; white-space:nowrap; }

		/* ---- Responsive mobile : moitié moins de colonnes ---- */
		@media (max-width:768px){
			.edr-gallery{ --edr-cols:3 !important; }
		}

		/* ---- Lightbox plein écran ---- */
		.edr-lb{
			position:fixed; inset:0; z-index:99999;
			display:none; align-items:center; justify-content:center;
			background:rgba(0,0,0,.92);
		}
		.edr-lb.open{ display:flex; }
		.edr-lb .edr-lb-stage{
			position:relative; display:flex; align-items:center; justify-content:center;
			max-width:100vw; max-height:100vh;
		}
		.edr-lb img{
			max-width:90vw; max-height:88vh; object-fit:contain;
			transition:transform .25s ease; user-select:none;
		}
		.edr-lb img.rot90, .edr-lb img.rot270{
			max-width:86vh; max-height:90vw; /* on inverse les contraintes pour le portrait pivoté */
		}
		.edr-lb button{
			position:absolute; z-index:2; cursor:pointer;
			background:rgba(255,255,255,.12); color:#fff; border:0;
			border-radius:50%; width:52px; height:52px; font-size:26px; line-height:1;
			transition:background .2s ease;
		}
		.edr-lb button:hover{ background:rgba(255,255,255,.28); }
		.edr-lb .edr-lb-close{ top:20px; right:20px; }
		.edr-lb .edr-lb-prev{ left:20px; top:50%; transform:translateY(-50%); }
		.edr-lb .edr-lb-next{ right:20px; top:50%; transform:translateY(-50%); }
		@media(max-width:600px){
			.edr-lb .edr-lb-prev{ left:8px; } .edr-lb .edr-lb-next{ right:8px; }
			.edr-lb button{ width:44px; height:44px; font-size:22px; }
		}
	</style>
	<?php
}

function edr_gallery_footer_js() {
	?>
	<script id="edr-gallery-js">
	( function () {
		var lb, lbImg;

		function ensure() {
			if ( lb ) { return; }
			lb = document.createElement( 'div' );
			lb.className = 'edr-lb';
			lb.innerHTML =
				'<button class="edr-lb-close" aria-label="Fermer">✕</button>' +
				'<button class="edr-lb-prev"  aria-label="Précédent">‹</button>' +
				'<div class="edr-lb-stage"><img alt=""><span class="edr-lb-wm" aria-hidden="true"></span></div>' +
				'<button class="edr-lb-next"  aria-label="Suivant">›</button>';
			document.body.appendChild( lb );
			lbImg = lb.querySelector( 'img' );

			lb.querySelector( '.edr-lb-close' ).addEventListener( 'click', close );
			lb.querySelector( '.edr-lb-prev'  ).addEventListener( 'click', function ( e ) { e.stopPropagation(); nav( -1 ); } );
			lb.querySelector( '.edr-lb-next'  ).addEventListener( 'click', function ( e ) { e.stopPropagation(); nav(  1 ); } );
			lb.addEventListener( 'click', function ( e ) { if ( e.target === lb ) { close(); } } );

			document.addEventListener( 'keydown', function ( e ) {
				if ( ! lb.classList.contains( 'open' ) ) { return; }
				if ( e.key === 'Escape'     ) { close(); }
				if ( e.key === 'ArrowLeft'  ) { nav( -1 ); }
				if ( e.key === 'ArrowRight' ) { nav(  1 ); }
			} );
		}

		var current = [], idx = 0;

		function show() {
			var it = current[ idx ];
			lbImg.className = '';
			lbImg.style.transform = 'rotate(' + it.rot + 'deg)';
			if ( it.rot === 90  ) { lbImg.classList.add( 'rot90'  ); }
			if ( it.rot === 270 ) { lbImg.classList.add( 'rot270' ); }
			lbImg.src = it.full;
			lb.style.setProperty( '--edr-wm-single', it.wm );
		}
		function open( cells, i ) {
			ensure(); current = cells; idx = i;
			lb.classList.add( 'open' ); document.body.style.overflow = 'hidden';
			show();
		}
		function close() {
			if ( ! lb ) { return; }
			lb.classList.remove( 'open' ); document.body.style.overflow = '';
			lbImg.src = '';
		}
		function nav( d ) {
			idx = ( idx + d + current.length ) % current.length;
			show();
		}

		document.addEventListener( 'click', function ( e ) {
			var cell = e.target.closest( '.edr-cell' );
			if ( ! cell ) { return; }
			var gallery = cell.closest( '.edr-gallery' );
			if ( ! gallery ) { return; }
			e.preventDefault();

			var wm    = getComputedStyle( gallery ).getPropertyValue( '--edr-wm-single' );
			var nodes = Array.prototype.slice.call( gallery.querySelectorAll( '.edr-cell' ) );
			var cells = nodes.map( function ( c ) {
				return {
					full: c.getAttribute( 'data-full' ),
					rot:  parseInt( c.getAttribute( 'data-rot' ), 10 ) || 0,
					wm:   wm
				};
			} );
			open( cells, nodes.indexOf( cell ) );
		} );

		/* -------- Pagination des vignettes (responsive) -------- */
		var EDR_MOBILE = window.matchMedia( '(max-width:768px)' );

		function setupGallery( g ) {
			if ( g._edrPaged ) { return; }
			g._edrPaged = true;

			var baseRows = parseInt( g.getAttribute( 'data-rows' ), 10 ) || 10;
			var cells    = Array.prototype.slice.call( g.querySelectorAll( '.edr-cell' ) );
			if ( cells.length === 0 ) { return; }

			var pager = null, cur = 1, lastPer = 0;

			// Nombre réel de colonnes rendues (le CSS peut l'avoir divisé sur mobile)
			function realCols() {
				var t = getComputedStyle( g ).gridTemplateColumns;
				var n = t.split( ' ' ).filter( function ( s ) { return s.trim() !== ''; } ).length;
				return n || 1;
			}
			// Lignes divisées par 2 sur mobile
			function curRows() {
				return EDR_MOBILE.matches ? Math.max( 1, Math.ceil( baseRows / 2 ) ) : baseRows;
			}
			function perPage() {
				return realCols() * curRows();
			}

			function buildPager() {
				pager = document.createElement( 'div' );
				pager.className = 'edr-pager';
				pager.innerHTML =
					'<button type="button" class="edr-pg-prev" aria-label="Page précédente">‹</button>' +
					'<span class="edr-pg-nums"></span>' +
					'<span class="edr-pg-count"></span>' +
					'<button type="button" class="edr-pg-next" aria-label="Page suivante">›</button>';
				g.parentNode.insertBefore( pager, g.nextSibling );
				pager.querySelector( '.edr-pg-prev' ).addEventListener( 'click', function () { go( cur - 1 ); } );
				pager.querySelector( '.edr-pg-next' ).addEventListener( 'click', function () { go( cur + 1 ); } );
				pager.querySelector( '.edr-pg-nums' ).addEventListener( 'click', function ( e ) {
					var b = e.target.closest( '.edr-pg-num' );
					if ( b ) { go( parseInt( b.getAttribute( 'data-p' ), 10 ) ); }
				} );
			}
			function removePager() {
				if ( pager ) { pager.parentNode.removeChild( pager ); pager = null; }
			}

			function render() {
				var per   = perPage();
				var pages = Math.ceil( cells.length / per );
				if ( cur > pages ) { cur = pages; }
				if ( cur < 1 )     { cur = 1; }

				if ( pages <= 1 ) {
					cells.forEach( function ( c ) { c.classList.remove( 'edr-hidden' ); } );
					removePager();
					lastPer = per;
					return;
				}
				if ( ! pager ) { buildPager(); }

				var nums = pager.querySelector( '.edr-pg-nums' );
				if ( nums.children.length !== pages ) {
					nums.innerHTML = '';
					for ( var p = 1; p <= pages; p++ ) {
						var b = document.createElement( 'button' );
						b.type = 'button';
						b.className = 'edr-pg-num';
						b.textContent = p;
						b.setAttribute( 'data-p', p );
						nums.appendChild( b );
					}
				}
				cells.forEach( function ( c, i ) {
					c.classList.toggle( 'edr-hidden', ( Math.floor( i / per ) + 1 ) !== cur );
				} );
				Array.prototype.forEach.call( nums.children, function ( b ) {
					b.classList.toggle( 'active', parseInt( b.getAttribute( 'data-p' ), 10 ) === cur );
				} );
				pager.querySelector( '.edr-pg-count' ).textContent = cur + ' / ' + pages;
				pager.querySelector( '.edr-pg-prev' ).disabled = ( cur === 1 );
				pager.querySelector( '.edr-pg-next' ).disabled = ( cur === pages );
				lastPer = per;
			}

			function go( p ) {
				var pages = Math.ceil( cells.length / perPage() );
				cur = Math.max( 1, Math.min( pages, p ) );
				render();
				g.scrollIntoView( { behavior: 'smooth', block: 'start' } );
			}

			g._edrRender = render;
			render();
		}

		function initPagers() {
			Array.prototype.forEach.call( document.querySelectorAll( '.edr-gallery' ), setupGallery );
		}
		initPagers();

		// Recalcul au redimensionnement / rotation de l'écran (anti-rebond)
		var edrRT;
		window.addEventListener( 'resize', function () {
			clearTimeout( edrRT );
			edrRT = setTimeout( function () {
				Array.prototype.forEach.call( document.querySelectorAll( '.edr-gallery' ), function ( g ) {
					if ( g._edrRender ) { g._edrRender(); }
				} );
			}, 160 );
		} );
	} )();
	</script>
	<?php
}

/* ============================================================================
 *  5) FRONT — Shortcode [edr_gallery]
 * ========================================================================== */
add_shortcode( 'edr_gallery', function ( $atts ) {

	$atts = shortcode_atts( array(
		'id'        => 0,             // ID produit (0 = produit courant)
		'cols'      => 6,            // nombre de colonnes
		'gap'       => 6,           // espacement (px)
		'ratio'     => '60/40',     // rapport largeur/hauteur des miniatures
		'rows'      => 10,          // nb de lignes max avant pagination (desktop)
		'watermark' => 'EDRAUTO.FR', // texte du filigrane
		'opacity'   => 0.4,         // opacité du filigrane (0 à 1)
	), $atts, 'edr_gallery' );

	$product_id = absint( $atts['id'] );
	if ( ! $product_id ) {
		$product_id = get_the_ID();
	}
	if ( ! $product_id ) {
		return '';
	}

	$stored = json_decode( get_post_meta( $product_id, '_edr_gallery_data', true ), true );
	if ( ! is_array( $stored ) || empty( $stored ) ) {
		return '';
	}

	$cols     = max( 1, min( 12, absint( $atts['cols'] ) ) );
	$gap      = absint( $atts['gap'] );
	$wm_text  = sanitize_text_field( $atts['watermark'] );
	$op       = max( 0, min( 1, floatval( $atts['opacity'] ) ) );
	$rows     = max( 1, absint( $atts['rows'] ) ); // lignes desktop

	// Rapport largeur/hauteur des miniatures (ex : "75/25")
	$rp     = array_map( 'floatval', explode( '/', $atts['ratio'] . '/1' ) );
	$rw     = ( isset( $rp[0] ) && $rp[0] > 0 ) ? $rp[0] : 75;
	$rh     = ( isset( $rp[1] ) && $rp[1] > 0 ) ? $rp[1] : 25;
	// Facteur de zoom pour qu'une photo pivotée à 90/270° remplisse bien la vignette
	$cover  = max( $rw / $rh, $rh / $rw );

	// Filigrane 1 : motif diagonal répété (vignettes)
	$svg = "<svg xmlns='http://www.w3.org/2000/svg' width='240' height='150'>"
		 . "<text x='14' y='82' fill='#ffffff' fill-opacity='" . esc_attr( $op ) . "' "
		 . "font-family='Arial, Helvetica, sans-serif' font-size='20' font-weight='700' "
		 . "transform='rotate(-30 120 76)'>" . esc_html( $wm_text ) . "</text></svg>";
	$wm = 'data:image/svg+xml,' . rawurlencode( $svg );

	// Filigrane 2 : un seul texte centré (vue zoomée)
	$svg_single = "<svg xmlns='http://www.w3.org/2000/svg' width='540' height='200'>"
		 . "<text x='270' y='108' text-anchor='middle' fill='#ffffff' fill-opacity='" . esc_attr( min( 1, $op + 0.05 ) ) . "' "
		 . "font-family='Arial, Helvetica, sans-serif' font-size='46' font-weight='700' "
		 . "transform='rotate(-25 270 100)'>" . esc_html( $wm_text ) . "</text></svg>";
	$wm_single = 'data:image/svg+xml,' . rawurlencode( $svg_single );

	edr_gallery_print_assets();

	ob_start();
	printf(
		'<div class="edr-gallery" data-cols="%d" data-rows="%d" style="--edr-cols:%d;--edr-gap:%dpx;--edr-ratio:%s/%s;--edr-cover:%s;--edr-wm:url(\'%s\');--edr-wm-single:url(\'%s\');">',
		$cols, $rows,
		$cols, $gap,
		esc_attr( $rw ), esc_attr( $rh ),
		esc_attr( $cover ),
		$wm, $wm_single
	);

	foreach ( $stored as $it ) {
		$id  = isset( $it['id'] ) ? absint( $it['id'] ) : 0;
		$rot = isset( $it['rotation'] ) ? intval( $it['rotation'] ) : 0;
		if ( ! in_array( $rot, array( 0, 90, 180, 270 ), true ) ) {
			$rot = 0;
		}
		$thumb = $id ? wp_get_attachment_image_url( $id, 'large' ) : '';
		$full  = $id ? wp_get_attachment_image_url( $id, 'full' )  : '';
		if ( ! $thumb ) {
			continue;
		}
		$side = ( 90 === $rot || 270 === $rot ) ? ' edr-rot-side' : '';
		printf(
			'<button type="button" class="edr-cell%s" style="--rot:%ddeg" data-full="%s" data-rot="%d" aria-label="Agrandir la photo">'
			. '<img src="%s" loading="lazy" alt="">'
			. '<span class="edr-wm-layer" aria-hidden="true"></span>'
			. '</button>',
			$side,
			$rot,
			esc_url( $full ),
			$rot,
			esc_url( $thumb )
		);
	}

	echo '</div>';
	return ob_get_clean();
} );

/* ============================================================================
 *  6) (OPTIONNEL) Insertion automatique sous le résumé produit
 *     Décommenter pour afficher la galerie sans shortcode.
 * ========================================================================== */
/*
add_action( 'woocommerce_after_single_product_summary', function () {
	echo do_shortcode( '[edr_gallery]' );
}, 15 );
*/

 

 

Comparaison Avant / Après

[bafg id= »8241″]

Spécifications techniques

Car actéristiques
Nom du modèle ELITE 10-2CH
Canal 2CH
Points forts 4K UHD HDR + 4K UHD, Wi-Fi 2,4-5 GHz, Cloud (données non incluses), Mode parking à économie d’énergie
Dimensions et poids du produit Avant : Longueur 129,7 mm (5,12 po) x Largeur 40 mm (1,58 po) x Hauteur 55,3 mm (2,18 po), 195 g (0,43 lb) Arrière : Longueur 67 mm (2,64 po) x Largeur 29 mm (1,14 po) x Hauteur 39,1 mm (1,54 po), 40 g (0,09 lb)
Connexion caméra arrière câble coaxial
Support de mémoire Carte microSD jusqu’à 1 To
Enregistrement intelligent d’événements Impact en conduite, impact en stationnement, excès de vitesse, forte accélération, freinage brusque, virage serré (y compris une marge de sécurité de 10 secondes avant l’événement)
Mode stationnement Économie d’énergie (< 1 mA) Détection de mouvement en accéléré (module complémentaire Mode parking requis)
Notifications vocales d’événements en mode stationnement OUI
Systèmes de protection Coupure automatique : 1 à 48 h Coupure basse tension : Véhicule de tourisme 11,8 à 12,5 V ou véhicule lourd 22,8 à 24 V Coupure haute température (75 °C)
Capteur d’imagerie Avant et arrière : Capteur CMOS STARVIS 2 (IMX678)
Angle de vision Avant et arrière : diagonale 146°, horizontale 125°, verticale 68°
Fréquence d’images en résolution Avant et arrière : 4K UHD à 30 images/s (double 4K) * La fréquence d’images peut varier pendant la diffusion Wi-Fi.
Codec vidéo H.265 (HEVC), H.264 (AVC)
Qualité d’image et débit binaire avant/arrière Extrême (H.265) : 60 + 30 Mbit/s ; Extrême (H.264) : 40 + 30 Mbit/s ; Élevé (par défaut) : 30 + 30 Mbit/s ; Moyen : 20 + 20 Mbit/s ; Faible : 10 + 10 Mbit/s
Format libre Format adaptatif sans restriction (US 10,922,270 B2)
Protection contre l’écrasement des fichiers d’événements Il est possible de protéger jusqu’à 50 fichiers d’événements contre l’écrasement.
Alerte de défaillance de la carte SD OUI
Redémarrage programmé OUI
Extension de fichier vidéo MP4
Wi-Fi Intégré (802.11ac – 2,4-5 GHz)
Compatible avec le cloud OUI
GPS Intégré (double bande : GPS, GLONASS)
Microphone Intégré
Conférencier Intégré
Capteur d’impact Capteur d’accélération à 3 axes
Indicateurs LED Face avant : État d’enregistrement, connectivité GPS, connectivité secteur (application/cloud) Face arrière : Voyant d’alimentation
Bouton Bouton marche/arrêt : Appui court pour allumer / Appui long pour éteindre. Capteur tactile : Appuyer sur le capteur tactile déclenche l’enregistrement manuel selon les paramètres du micrologiciel. Bouton de télécommande Bluetooth (en option) : Enregistrement manuel
Température de fonctionnement -20 °C − 65 °C (-4 °F − 149 °F)
Température de stockage -20 °C − 80 °C (-4 °F − 176 °F)
Coupure haute température Environ 75 °C (167 °F)
Batterie de secours Supercondensateur intégré
Puissance d’entrée Alimentation CC 12V-24V (Fiche CC (Ø3,5 x Ø1,1)) vers fils (Noir : GND / Jaune : B+ / Rouge : ACC)
Consommation d’énergie Mode normal (GPS activé/2 canaux) : 510 mA ; Mode parking (GPS désactivé/2 canaux) : 380 mA ; Mode économie d’énergie : moins de 12 mW (0,012 W) (moyenne < 1 mA / 12 V) * La consommation électrique réelle peut varier en fonction des conditions d’utilisation et de l’environnement.
Certifications Face avant : Telec, IC(ISED), CE, FCC, RCM, RoHS, DEEE Face arrière : FCC, IC(ISED), CE, RoHS, DEEE
Logiciel Visionneuse BlackVue * Windows 7 ou supérieur, Mac OS X Sierra (10.12) ou supérieur Visionneuse Web FLEETA * Chrome 71 ou supérieur, Safari 13.0 ou supérieur
Application Application BlackVue, application FLEETA * Android 10.0 ou supérieur, iOS 15.0 ou supérieur
Autres Système de gestion de fichiers adaptatif sans formatage
Bluetooth Intégré (V2.1+EDR/5.3)
LTE Externe (avec module LTE en option)
Garantie 2 ans

Informations complémentaires

Poids 0,9 kg
Dimensions 20 × 15 × 10 cm
Carte mémoire Go

64, 128, 256, 512

Avis

Il n’y a pas encore d’avis.

Soyez le premier à laisser votre avis sur “ELITE 10 2CH”

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *