@bebranded/bb-contents 1.0.112 → 1.0.114

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/bb-contents.js +105 -31
  2. package/package.json +1 -1
package/bb-contents.js CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * BeBranded Contents
3
3
  * Contenus additionnels français pour Webflow
4
- * @version 1.0.112
4
+ * @version 1.0.114
5
5
  * @author BeBranded
6
6
  * @license MIT
7
7
  * @website https://www.bebranded.xyz
@@ -32,11 +32,11 @@
32
32
  window._bbContentsInitialized = true;
33
33
 
34
34
  // Log de démarrage simple (une seule fois)
35
- console.log('bb-contents | v1.0.112');
35
+ console.log('bb-contents | v1.0.114');
36
36
 
37
37
  // Configuration
38
38
  const config = {
39
- version: '1.0.112',
39
+ version: '1.0.114',
40
40
  debug: false, // Debug désactivé pour rendu propre
41
41
  prefix: 'bb-', // utilisé pour générer les sélecteurs (data-bb-*)
42
42
  youtubeEndpoint: null, // URL du worker YouTube (à définir par l'utilisateur)
@@ -409,28 +409,52 @@
409
409
  const originalHeight = img.style.height;
410
410
 
411
411
  img.onload = () => {
412
- // SOLUTION MOBILE SAFARI : Pour les SVG sur mobile, appliquer les styles AVANT le clonage
413
- if (isSVG && isMobile) {
414
- // Utiliser contain pour éviter le débordement
412
+ // SOLUTION MOBILE SAFARI : Pour les SVG sur mobile Safari, utiliser contain avec optimisations
413
+ if (isSVG && isMobile && isSafari) {
414
+ // SUR SAFARI MOBILE : Utiliser contain MAIS avec des optimisations pour éviter le flou
415
415
  img.style.objectFit = 'contain';
416
416
  img.style.objectPosition = 'center';
417
417
 
418
- // Ajouter des contraintes pour empêcher le débordement et forcer la taille
419
- img.style.maxWidth = '100%';
420
- img.style.maxHeight = '100%';
418
+ // Dimensions avec contraintes pour forcer contain
421
419
  img.style.width = '100%';
422
420
  img.style.height = '100%';
421
+ img.style.maxWidth = '100%';
422
+ img.style.maxHeight = '100%';
423
423
  img.style.boxSizing = 'border-box';
424
424
 
425
- // Forcer le GPU rendering
426
- img.style.webkitTransform = 'translate3d(0, 0, 0)';
427
- img.style.transform = 'translate3d(0, 0, 0)';
425
+ // Optimisations pour améliorer le rendu des SVG avec contain
426
+ // Utiliser auto au lieu de crisp-edges pour contain
427
+ img.style.imageRendering = 'auto';
428
+ img.style.webkitBackfaceVisibility = 'hidden';
429
+ img.style.backfaceVisibility = 'hidden';
430
+
431
+ // Forcer le GPU rendering AVANT d'appliquer contain
432
+ img.style.webkitTransform = 'translateZ(0)';
433
+ img.style.transform = 'translateZ(0)';
428
434
 
429
- // Améliorer le rendu des SVG
430
- img.style.imageRendering = 'crisp-edges';
435
+ // Conteneur parent pour contraindre et centrer
436
+ const parent = img.parentElement;
437
+ if (parent) {
438
+ parent.style.display = 'flex';
439
+ parent.style.alignItems = 'center';
440
+ parent.style.justifyContent = 'center';
441
+ parent.style.overflow = 'hidden';
442
+ parent.style.boxSizing = 'border-box';
443
+
444
+ // S'assurer que le parent a des dimensions
445
+ if (!parent.style.width) parent.style.width = '100%';
446
+ if (!parent.style.height) parent.style.height = '100%';
447
+ }
448
+ } else if (isSVG && isMobile) {
449
+ // Pour Chrome mobile, utiliser contain normalement
450
+ img.style.objectFit = 'contain';
451
+ img.style.objectPosition = 'center';
452
+ img.style.maxWidth = '100%';
453
+ img.style.maxHeight = '100%';
454
+ img.style.width = '100%';
455
+ img.style.height = '100%';
456
+ img.style.boxSizing = 'border-box';
431
457
 
432
- // S'assurer que le conteneur parent permet au SVG de s'afficher correctement
433
- // et empêche le débordement avec overflow hidden
434
458
  const parent = img.parentElement;
435
459
  if (parent) {
436
460
  parent.style.display = 'flex';
@@ -466,6 +490,8 @@
466
490
 
467
491
  // SOLUTION SAFARI MOBILE SIMPLE : Attendre plus longtemps
468
492
  const isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
493
+ // Détecter spécifiquement Safari (pas Chrome mobile)
494
+ const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent) || /iPhone|iPad|iPod/.test(navigator.userAgent);
469
495
 
470
496
  // Timeout plus long sur mobile pour laisser le temps aux images de se charger
471
497
  const maxWaitTime = isMobile ? 5000 : 3000; // 5 secondes sur mobile
@@ -474,17 +500,39 @@
474
500
  const waitForImages = () => {
475
501
  waitTimeout += 100;
476
502
 
477
- // Attendre que TOUTES les images soient chargées (ou s'il n'y a pas d'images, attendre un minimum)
503
+ // SAFARI MOBILE : Attendre ABSOLUMENT que TOUTES les images soient chargées
478
504
  if (totalImages === 0) {
479
505
  // Pas d'images, démarrer après un court délai
480
506
  const renderDelay = isMobile ? 500 : 100;
481
507
  setTimeout(() => {
482
508
  startSafariAnimation();
483
509
  }, renderDelay);
484
- } else if (imagesLoaded >= totalImages || waitTimeout >= maxWaitTime) {
485
- // Toutes les images sont chargées OU timeout atteint
486
- // Attendre plus longtemps sur mobile pour le rendu visuel
487
- const renderDelay = isMobile ? 1000 : 200;
510
+ } else if (imagesLoaded >= totalImages) {
511
+ // SAFARI MOBILE : Vérifier que les images ont vraiment leurs dimensions
512
+ let imagesReady = true;
513
+ if (isSafari && isMobile) {
514
+ images.forEach(img => {
515
+ if (!img.complete || img.naturalWidth === 0 || img.naturalHeight === 0) {
516
+ imagesReady = false;
517
+ }
518
+ });
519
+ }
520
+
521
+ if (imagesReady) {
522
+ // Toutes les images sont chargées ET ont leurs dimensions
523
+ // Attendre plus longtemps sur mobile Safari pour le rendu visuel
524
+ const renderDelay = isSafari && isMobile ? 1500 : (isMobile ? 1000 : 200);
525
+ setTimeout(() => {
526
+ startSafariAnimation();
527
+ }, renderDelay);
528
+ } else {
529
+ // Continuer à attendre que les dimensions soient disponibles
530
+ setTimeout(waitForImages, 100);
531
+ }
532
+ } else if (waitTimeout >= maxWaitTime) {
533
+ // Timeout atteint : forcer le démarrage mais c'est un fallback
534
+ console.warn('[MARQUEE] Timeout atteint, certaines images peuvent ne pas être chargées');
535
+ const renderDelay = isSafari && isMobile ? 1500 : (isMobile ? 1000 : 200);
488
536
  setTimeout(() => {
489
537
  startSafariAnimation();
490
538
  }, renderDelay);
@@ -541,6 +589,13 @@
541
589
  const step = (parseFloat(speed) * (isVertical ? 1.5 : 0.8)) / 60;
542
590
  let isPaused = false;
543
591
 
592
+ // OPTIMISATION SAFARI MOBILE : Ajouter will-change pour améliorer la fluidité
593
+ if (isSafari && isMobile) {
594
+ scrollContainer.style.willChange = 'transform';
595
+ scrollContainer.style.webkitBackfaceVisibility = 'hidden';
596
+ scrollContainer.style.backfaceVisibility = 'hidden';
597
+ }
598
+
544
599
  // Ajuster la taille du conteneur
545
600
  if (isVertical && !useAutoHeight) {
546
601
  scrollContainer.style.height = totalSize + 'px';
@@ -561,27 +616,35 @@
561
616
  ? `translate3d(0, ${currentPosition}px, 0)`
562
617
  : `translate3d(${currentPosition}px, 0, 0)`;
563
618
  scrollContainer.style.transform = initialTransform;
619
+
620
+ // OPTIMISATION SAFARI MOBILE : Forcer un reflow avant de démarrer l'animation
621
+ if (isSafari && isMobile) {
622
+ void scrollContainer.offsetHeight;
623
+ }
564
624
 
565
- // Fonction d'animation Safari avec debug des resets
625
+ // Fonction d'animation Safari optimisée
566
626
  let frameCount = 0;
567
- const animate = () => {
627
+ let lastTime = performance.now();
628
+ const animate = (currentTime) => {
568
629
  if (!isPaused) {
569
630
  frameCount++;
570
631
 
632
+ // OPTIMISATION SAFARI MOBILE : Utiliser le temps réel pour une animation plus fluide
633
+ const deltaTime = isSafari && isMobile ? (currentTime - lastTime) / 16.67 : 1;
634
+ lastTime = currentTime;
635
+
571
636
  if (direction === (isVertical ? 'bottom' : 'right')) {
572
- currentPosition += step;
637
+ currentPosition += step * deltaTime;
573
638
  if (currentPosition >= 0) {
574
639
  currentPosition = -(finalContentSize + gapSize);
575
640
  }
576
641
  } else {
577
- currentPosition -= step;
642
+ currentPosition -= step * deltaTime;
578
643
  if (currentPosition <= -(2 * (finalContentSize + gapSize))) {
579
644
  currentPosition = -(finalContentSize + gapSize);
580
645
  }
581
646
  }
582
647
 
583
- // Animation continue
584
-
585
648
  // ARRONDI pour éviter les erreurs de précision JavaScript
586
649
  currentPosition = Math.round(currentPosition * 100) / 100;
587
650
 
@@ -594,10 +657,21 @@
594
657
  requestAnimationFrame(animate);
595
658
  };
596
659
 
597
- // Démarrer l'animation avec un petit délai pour Safari
598
- setTimeout(() => {
599
- animate();
600
- }, 50);
660
+ // Démarrer l'animation avec un délai adapté pour Safari
661
+ if (isSafari && isMobile) {
662
+ // Safari mobile : attendre un peu plus pour que tout soit prêt
663
+ requestAnimationFrame(() => {
664
+ requestAnimationFrame(() => {
665
+ lastTime = performance.now();
666
+ animate(lastTime);
667
+ });
668
+ });
669
+ } else {
670
+ setTimeout(() => {
671
+ lastTime = performance.now();
672
+ animate(lastTime);
673
+ }, 50);
674
+ }
601
675
 
602
676
  // Pause au survol pour Safari
603
677
  if (element.getAttribute('bb-marquee-pause') === 'true') {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bebranded/bb-contents",
3
- "version": "1.0.112",
3
+ "version": "1.0.114",
4
4
  "description": "Contenus additionnels français pour Webflow",
5
5
  "main": "bb-contents.js",
6
6
  "scripts": {