Upgrade to Pro — share decks privately, control downloads, hide ads and more …

SVG

François Blavoet
January 23, 2017
94

 SVG

Slides d'un talk interne deezer sur les SVG

François Blavoet

January 23, 2017
Tweet

Transcript

  1. Le vectoriel, c'est très utile, mais ça a quelques pièges

    qu'il faut connaître Déjà, c'est quoi un SVG? -> Scalable Vector Graphics
  2. SVG ? Dans la pratique, cette note de musique, c'est

    un fichier xml : <svg fill="#2233FF" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> <path d="M0 0h24v24H0z"/> <path d="M12 3v10.55c-.59-.34-1.27-.55-2-.55-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4V7h4V3h-6z"/> </svg>
  3. <svg fill="#2233FF" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> <path

    d="M0 0h24v24H0z"/> <path d="M12 3v10.55c-.59-.34-1.27-.55-2-.55-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4V7h4V3h-6z"/> </svg> → viewBox : taille de ma zone de dessin. Ici je dessine dans un carré de 24 de côté → path : liste d'instructions, qui tiennent dans la viewBox, si je dessine en 24 24 je suis en bas à droite de mon image. et 50 50 n'aurait aucun sens ici puisqu'en dehors de la viewbox
  4. <svg fill="#2233FF" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> <path

    d="M0 0h24v24H0z"/> <path d="M12 3v10.55c-.59-.34-1.27-.55-2-.55-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4V7h4V3h-6z"/> </svg> → fill : couleur de remplissage → height / width : la taille de l'image que je veux générer, en pixels. peut être totalement différent de la viewBox
  5. Path Liste d'instructions : M : move L : line

    V : vertical line A : arc (curve) C : cubic bezier curve
  6. Path La spec svg définit beaucoup d'instructions. À chaque fois

    c'est une lettre suivie d'une série de coordonnées. c'est ça que contient un path comme celui-ci : <path d="M12 3v10.55c-.59-.34-1.27-.55-2-.55-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4V7h4V3h-6z"/>
  7. Path <path d="M12 3v10.55c-.59-.34-1.27-.55-2-.55-2.21 0-4 1.79-4 4s1.79 4 4 4

    4-1.79 4-4V7h4V3h-6z"/> certaines instructions sont écrites en majuscules, d'autres en minuscules : lettre majuscule : coordonnées absolues lettre minuscule : coordonnées relatives : on part du point d'arrivée de l'insctruction précédente.
  8. Il y a d'autres choses dans la spec, par exemple

    le linecap : <svg width="160" height="140" xmlns="http://www.w3.org/2000/svg" version="1.1"> <line x1="40" x2="120" y1="20" y2="20" stroke="black" stroke-width="20" stroke-linecap="butt"/> <line x1="40" x2="120" y1="60" y2="60" stroke="black" stroke-width="20" stroke-linecap="square"/> <line x1="40" x2="120" y1="100" y2="100" stroke="black" stroke-width="20" stroke-linecap="round"/> </svg>
  9. Très souvent lors de l'export Sketch rajoute un stroke-width, stroke-color,

    etc dans le svg pour chaque path. Une fois importé dans Android Studio vous pouvez généralement le virer, c'est un bug de leur exporteur.
  10. Et ainsi de suite, la spec SVG, c'est 800 pages

    ! Nous on travaille sur Android. On n'a pas besoin de tout ça.
  11. Si je prends un svg : <svg fill="#2233FF" height="24" viewBox="0

    0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> <path d="M0 0h24v24H0z"/> <path d="M12 3v10.55c-.59-.34-1.27-.55-2-.55-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4V7h4V3h-6z"/> </svg> et l'importe dans Android Studio (drawable/new vector drawable)
  12. j'obtiens ceci : <vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp" android:height="24dp" android:viewportHeight="24.0" android:viewportWidth="24.0"> <path

    android:fillColor="#2233FF" android:pathData="M12,3v10.55c-0.59,-0.34 -1.27,-0.55 -2,-0.55 -2.21,0 -4,1.79 -4,4s1.79,4 4,4 4,-1.79 4,-4V7h4V3h-6z" /> </vector>
  13. j'ai les mêmes composants qu'un svg standard, sauf qu'ici c'est

    un drawable android. Quand j'inflate cette resource android, j'obtiens un VectorDrawable.
  14. c'est un drawable android standard, je peux utiliser des @

    : <vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="@dimension/icon_width" android:height="24dp" android:viewportHeight="24.0" android:viewportWidth="24.0"> <path android:fillColor="@color/icon" android:pathData="@string/path_icon" /> </vector>
  15. problème le plus commun : -> even-odd Rêgle qui permet

    de coder des zones pleines et vides suivant qu'elles coupent un nombre de tracés pair ou impair
  16. Sketch ne donne pas les mains aux designers là dessus.

    C'est un outil qui permet de faire du vectoriel, mais qui n'est pas pensé pour le format svg. Résultat: L'export de svg dans sketch peut vous générer des svgs non gérés par android, et les designers n'ont pas souvent la main dessus
  17. exemple de svg avec la rêgle even-odd <svg width="24" height="32"

    viewBox="0 0 24 32" xmlns="http://www.w3.org/2000/svg"> <title> F5F3925F-A5DA-443C-94DA-B08D695ADAAF </title> <g fill="none" fill-rule="evenodd"> <path d="M0 .993C0 .443.453 0 .997 0h6.006C7.553 0 8 .452 8 .993v30.014 c0 .55-.453.993-.997.993H.997C.447 32 0 31.548 0 31.007V.993zm16 0c0-.55.453-.993.997-.993h6.006 c.55 0 .997.452.997.993v30.014c0 .55-.453.993-.997.993h-6.006c-.55 0-.997-.452-.997-.993V.993z" fill="#000"/> <path d="M-4 0h32v32H-4z"/> </g> </svg>
  18. solution : cette webapp permet de nettoyer la plupart des

    svgs pour retirer ces rêgles de fill problématiques. http://a-student.github.io/SvgToVectorDrawableConverter.Web/ Il faut juste faire attention de bien cocher Specify --fix-fill-type
  19. et pour Android < 21 ? Déjà, il faut rajouter

    une ligne dans la config gradle defaultConfig { applicationId 'deezer.android.app' minSdkVersion minSdk targetSdkVersion targetSdk multiDexEnabled true vectorDrawables.useSupportLibrary = true }
  20. vectorDrawables.useSupportLibrary = true dit à la support lib de ne

    pas générer de pngs pour nos vecteurs, on va se débrouiller pour afficher des VectorDrawables, même <21
  21. Deuxième opération, dans BaseActivity : // setup the support lib

    so we can use vector Resources static { AppCompatDelegate.setCompatVectorFromResourcesEnabled(true); } demande à la support lib de hacker l'inflation de drawables quand c'est possible, pour qu'elle prenne en charge les selectors contenant des svgs (on verra ensuite pourquoi c'est très utile)
  22. C'est l'heure du hack crado ! <?xml version="1.0" encoding="utf-8"?> <selector

    xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@drawable/ic_family_48" /> </selector>
  23. c'est à ça que sert setCompatVectorFromResourcesEnabled Le hack de la

    support lib permet d'inflater des vectorDrawableCompat mais pas directement, uniquement s'ils sont wrappés dans un selector d'où ce selector qui ne contient qu'un seul élément. A utiliser à chaque fois qu'on a unCompoundDrawable` (TextView, CheckBox, ..)
  24. Deuxième problème : context.getDrawable(id); ContextCompat.getDrawable(context, vectorId); Context et même ContextCompat

    ne gèrent pas les vectorDrawables Pour les vecteurs, utilisez plutôt : AppCompatDrawableManager.getDrawable(context, vectorId);
  25. Presque sauvés ! sauf ... Glide.with(ctx) .load(url) .placeholder(R.drawable.placeholder) .into(view); dans

    Glide/GenericRequest : private Drawable getPlaceholderDrawable() { if (placeholderDrawable == null && placeholderResourceId > 0) { placeholderDrawable = context.getResources().getDrawable(placeholderResourceId); } return placeholderDrawable; }
  26. Les placeholders/error/fallbacks de Glide n'utilisent pas la support lib !

    On peut éventuellement passer directement un drawable créé via AppCompatDrawableManager à Glide
  27. Comment faire ? Pour ces cas ci, il faut souvent

    passer par des drawables raster classiques pour les vieilles versions dans chaque bucket. Et le bucket anydpi-v21 permet de les overrider tous à partir de lollipop
  28. valueFrom et valueTo doivent être compatibles : contenir les mêmes

    instructions dans le même ordre avec juste des coordonnées différentes. Pour les animations, la principale limitation c'est qu'il manque encore des outils graphiques pour modifier les paths de manière efficace.
  29. Comme solution un peu plus efficace que d'écrire tous les

    paths à la main, il y a entre autres https://romannurik.github.io/AndroidIconAnimator/ mais toujours en cours de dev