Sfocatura dell'immagine di sfondo SVG in Chrome con sfondo ripetuto
Uno sfondo SVG appare sfocato in Chrome e altri browser basati su Blink / webkit:
Screenshot di una parte dell'SVG in Chrome:
 
                Screenshot di una parte di SVG in Firefox:
 
                Questo accade solo quando si visualizza l'SVG con "background-repeat: true" e "background-size: contain" valori CSS. Vorremmo ripetere l'altezza dello sfondo SVG tutte le volte che è necessario, poiché l'altezza della pagina è dinamica e allungare l'immagine vettoriale sembrerebbe scadente.
L'SVG viene visualizzato in linea nel CSS nella pagina di esempio di seguito, ma il problema si verifica nello stesso modo quando mi collego all'immagine SVG esterna.
Ecco una pagina di test che mostra questo comportamento: https://august-13-2020-test-canvas.bubbleapps.io/version-test/pagemaker-test-original-2 (accedi con "nome utente" e "password", ci viene richiesto di inserire questa autenticazione qui).
Una pagina di prova con un SVG correttamente visualizzato (nitido / con bordi levigati) è qui: https://august-13-2020-test-canvas.bubbleapps.io/version-test/pagemaker-test-online-1
Una versione con bordi nitidi / lisci viene visualizzata esattamente allo stesso modo: l'unica differenza è il contenuto dell'SVG.
Ecco un collegamento allo sfondo SVG per la pagina sfocata: https://dd7tel2830j4w.cloudfront.net/d44/f1588704991659x396570736162959360/background.svg
Tutti gli SVG che ho testato da questa pagina avevano bordi nitidi: https://www.svgbackgrounds.com/#flat-mountains (quello in basso a destra è quello utilizzato nel link sopra)
Nel tentativo di risolvere questo problema o di identificarne la causa all'interno del codice SVG, ho modificato l'SVG un po ', tentando quanto segue:
- Conversione di tutti i valori in punti SVG (attributi d del percorso) in numeri interi
- Aggiunta di "PreserveAspectRatio" al tag di apertura di SVG
- Rimozione dell'altezza e della larghezza dalla dichiarazione di apertura dell'SVG
- Rimuovere le "sfumature lineari" dall'SVG e sostituirle con colori statici
- Raddoppiando le dimensioni delle forme SVG per vedere se la sfocatura diminuisce con una larghezza e un'altezza iniziali maggiori
- Aggiunta della proprietà "crispEdges" ai percorsi SVG
- Ottimizzazione di SVG (utilizzando SVGomg)
Inoltre, ho tentato di modificare un po 'il CSS, ma non sono riuscito a farlo funzionare.
Alcune idee che ho per soluzioni alternative sono le seguenti:
- Utilizzo di più immagini di sfondo per ripetere la visualizzazione dell'SVG (visualizzalo 5-10 volte sullo sfondo, imitando l'effetto background-repeat: repeat-y ma includendo più immagini di sfondo)
- Utilizzando JS per disegnare l'SVG in linea sulla pagina (dove questo bug non si verifica), creando un HTML che è esattamente la stessa altezza dell'altezza dinamica del nostro gruppo (che può cambiare in qualsiasi momento senza innescare un evento JS) e ripetendo il SVG in qualche modo all'interno di quel gruppo.
- Chiedere a un designer uno sfondo SVG diverso e sperare che il problema di sfocatura non si ripeta.
Qualsiasi aiuto qui sarebbe molto apprezzato, mi sto strappando i capelli e non sono stato in grado di risolvere il problema dopo aver consultato diversi sviluppatori su CodeMentor.io.
Risposte
Blink sembra applicare un algoritmo difettoso, prima rendendo l'SVG di dimensioni sbagliate e poi ridimensionando l'immagine raster risultante. È difficile aggirare questo problema, poiché sono coinvolti due meccanismi di ridimensionamento, SVG viewBoxe CSS background-size.
Posso offrire solo una soluzione parziale, lavorando in Chrome ed Edge (entrambi i motori), ma non funzionando in Firefox.
Sposta la responsabilità del ridimensionamento e della ripetizione dalle backgroundproprietà CSS all'SVG stesso con un <pattern>elemento. Il contenuto completo dell'immagine SVG viene spostato all'interno di questo elemento, inclusa l'impostazione viewBoxdell'attributo sugli stessi valori.
Quindi, i valori di larghezza e altezza per la ripetizione del motivo vengono impostati su width="100vw" height="504vw". Questo riempie la larghezza della finestra e mantiene le proporzioni per l'altezza. (Firefox sembra non essere in grado di interpretare le vwunità in questo contesto).
Infine, un <rect>con larghezza = altezza = 100% è definito e riempito con il modello, e l' <svg>elemento radice , senza un viewBoxattributo, è similmente impostato su larghezza = altezza = 100%.
<svg width="100%" height="100%" fill="none" xmlns="http://www.w3.org/2000/svg">
  <pattern id="pt" width="100vw" height="504vw" x="0" y="0" viewBox="0 0 1440 7258" patternUnits="userSpaceOnUse" preserveAspectRatio="xMinYMin meet">
    <rect width="1440" height="7258" fill="white"/>
    <path d="M-137 1749L1546 1994.95V2870L-137 2624.64V1749Z" fill="#F7F8FF"/>
    <path d="M-137 3776L1546 4021.95V4897L-137 4651.64V3776Z" fill="url(#paint0_linear)"/>
    <path d="M-137 3969L1546 4214.95V4900L-137 4654.64V3969Z" fill="url(#paint1_linear)"/>
    <path d="M1319 2764L1545 2796.96V2870L1319 2837.12V2764Z" fill="#264CE9"/>
    <path d="M-53 2645L96 2666.68V2744L-53 2722.37V2645Z" fill="#FBE89F"/>
    <path d="M-29 2571L307 2620.13V2699L-29 2649.99V2571Z" fill="#54A5F2"/>
    <path d="M1209 2820L1545 2869.13V2948L1209 2898.99V2820Z" fill="#6AD2F6"/>
    <path d="M-147 4649L307 4715.42V4891L-147 4824.74V4649Z" fill="#6AD2F6"/>
    <path d="M-137 -233L1546 12.9461V688L-137 442.638V-233Z" fill="url(#paint2_linear)"/>
    <g style="mix-blend-mode:multiply">
      <path d="M987 -144L2119 21.4151V388L987 222.978V-144Z" fill="#6AD2F6"/>
    </g>
    <path d="M-137 27L1546 272.946V948L-137 702.638V27Z" fill="url(#paint3_linear)"/>
    <path d="M-258 455L490 564.509V794L-258 684.751V455Z" fill="url(#paint4_linear)"/>
  </pattern>
  <linearGradient id="paint0_linear" x1="43.9999" y1="3807" x2="458.5" y2="4665" gradientUnits="userSpaceOnUse">
    <stop stop-color="#264CE9" stop-opacity="0.06"/>
    <stop offset="1" stop-color="#F7F8FF" stop-opacity="0.26"/>
  </linearGradient>
  <linearGradient id="paint1_linear" x1="43.9999" y1="4000" x2="1229" y2="5099" gradientUnits="userSpaceOnUse">
    <stop stop-color="#264CE9" stop-opacity="0.06"/>
    <stop offset="1" stop-color="#F7F8FF" stop-opacity="0"/>
  </linearGradient>
  <linearGradient id="paint2_linear" x1="194" y1="87.4999" x2="1671" y2="300" gradientUnits="userSpaceOnUse">
    <stop offset="0.270833" stop-color="#264CE9"/>
    <stop offset="1" stop-color="#6AD2F6"/>
  </linearGradient>
  <linearGradient id="paint3_linear" x1="194" y1="347.5" x2="1671" y2="560" gradientUnits="userSpaceOnUse">
    <stop stop-color="#264CE9"/>
    <stop offset="1" stop-color="#6AD2F6"/>
  </linearGradient>
  <linearGradient id="paint4_linear" x1="-108" y1="550.5" x2="490" y2="638" gradientUnits="userSpaceOnUse">
    <stop stop-color="#264CE9" stop-opacity="0.43"/>
    <stop offset="1" stop-color="#264CE9"/>
  </linearGradient>
  <rect width="100%" height="100%" fill="url(#pt)" />
</svg>
Ho semplificato un po 'il markup, ma queste modifiche sono tutte cosmetiche, inclusa la rimozione del clipPath- si applica comunque agli elementi del modello.
Non ho mai trovato una soluzione a questo problema (o almeno non è riuscito a implementare la soluzione presentata da ccprog).
Abbiamo scelto di modificare i file SVG per essere più lunghi. I nostri file SVG vengono utilizzati come sfondo per le pagine Web che hanno lunghezze dinamiche e in teoria non hanno limiti di altezza.
Ripetendo 5 volte un SVG alto ~ 8000 px, si copre fino a quando una pagina web non raggiunge un'altezza di 40000 px, il che dovrebbe andare bene per il nostro caso d'uso. Ho usato inkscape per entrare e copiare il contenuto di ogni SVG e poi replicarlo più volte, rendendo gli SVG finali 5 volte più alti di quelli originali.