5139 sujets

Le Bar du forum

Salut,

J'ai une question concernant du SVG; je veux faire la chose suivante :
1) dessiner un ensemble de formes avec des fill des strokes & co
2) dessiner une autre forme par dessus cet ensemble qui "creuse un trou" à travers le dessin précédent

Donc, si je commence par dessiner tout un ensemble de formes avec un remplissage rouge, puis que je dessine un cercle par-dessus, et que j'utilise ce svg sur une page web avec un fond gris, je devrais voir un ensemble de formes rouges, contenant un trou "un disque en l’occurrence" laissant transparaître le gris de la page web en arrière-plan.

Faisable ?

D'avance merci
Mhhh je ne suis pas sûr que ce soit faisable ainsi : il me faut exclure une zone circulaire en plein milieu de l'ensemble, donc il faudrait que je définisse un clipping sous forme d'anneau. Et ça peut s'avérer difficile, à moins qu'on puisse exclure de l'exclusion.
J'explique plus précisément :
- j'ai un svg qui représente quelques engrenages
- je ne suis pas satisfait de celui-ci : c'est très lourd parce que c'est défini comme plusieurs paths, ce que je trouve inefficace. Pour moi, un engrenage est essentiellement une composition de formes géométriques simples, et de répétitions avec rotation, le tout complété par un joli trou en son centre
- je veux donc le refaire "à la main" en svg, mais je suis assez peu expérimenté là-dedans

Ma première hypothèse était donc de "creuser un trou" dans l'ensemble.
Si ce n'est pas possible, ma seconde hypothèse serait donc de faire un clipping sous forme d'anneau, mais je ne vois pas comment. Ou si, peut-être : un disque de la taille de mon trou, sans remplissage et avec un stroke de la largeur de l'anneau à dessiner. Ça marcherait un truc tordu comme ça ?
Modérateur
Salut,

Je pense que tu veux parler type pochoire. Si je dis pas de bétises et suivant ta description, il faut que ce soit le même <path>

Je t'invite à regarder ce bout de code :

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->

<svg
   xmlns:dc="http://purl.org/dc/elements/1.1/"
   xmlns:cc="http://creativecommons.org/ns#"
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:svg="http://www.w3.org/2000/svg"
   xmlns="http://www.w3.org/2000/svg"
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
   width="210mm"
   height="297mm"
   viewBox="0 0 744.09448819 1052.3622047"
   id="svg2"
   version="1.1">
  <g id="layer1">
    <path
       style="fill:#000000;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1"
       d="M 339.56641 39.453125 C 311.61665 39.618155 281.431 54.819667 253.68164 83.306641 C 369.61549 148.24863 481.95929 271.45332 425.71484 115.21875 C 407.03181 63.321428 375.10877 39.243264 339.56641 39.453125 z M 253.68164 83.306641 C 210.6048 59.176539 167.03243 43.073146 131.42773 52.361328 C 48.695291 73.943705 93.902364 238.16414 154.43359 364.74219 C 156.00814 326.64299 160.70668 291.41702 167.82812 259.32031 C 121.7059 205.60537 91.613151 134.02161 154.28516 126.64844 C 173.69983 131.73323 190.85731 140.57049 205.73633 151.73047 C 220.01305 124.02329 236.37104 101.07738 253.68164 83.306641 z M 205.73633 151.73047 C 190.10297 182.0705 176.97101 218.11288 167.82812 259.32031 C 193.19627 288.8646 223.41017 313.00693 245.71484 318.07617 C 298.40239 330.05061 282.82291 209.54911 205.73633 151.73047 z M 154.43359 364.74219 C 151.05985 446.37655 162.02668 541.18804 194.28516 646.64844 C 194.28516 646.64844 317.14231 543.78991 254.28516 512.36133 C 230.99571 500.7166 190.06214 439.24574 154.43359 364.74219 z " id="path4136" />
  </g>
</svg>


Pour le faire facilement, utilise Inkscape ou Illustrator
Si j'utilise un path, je gâche tout le bénéfice que je veux gagner de l'usage de formes géométriques simples. Je viens de réussir à obtenir le résultat souhaité:
Le principe est d'utiliser un masque sur l'ensemble du groupe, en utilisant fill none pour faire disparaître la partie centrale, et stroke pour faire un anneau blanc sur la zone qu'on souhaite visible.
<svg xmlns="http://www.w3.org/2000/svg" width="800" height="800" viewBox="0 0 800 800" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
	<symbol id="cog" viewBox="0 0 1000 1000">
		<mask id="cog_mask" x="0" y="0" width="1000" height="1000" >
			<circle cx="500" cy="500" r="500" stroke="#fff" stroke-width="676" fill="none"/>
		</mask>
		<g mask="url(#cog_mask)">
			<circle cx="500" cy="500" r="377"/>
			<rect id="barre2" x="0" y="450" width="1000" height="100" rx="20" ry="20"/>
			<use xlink:href="#barre2" x="0" y="0" transform="rotate(45 500 500)"/>
			<use xlink:href="#barre2" x="0" y="0" transform="rotate(90 500 500)"/>
			<use xlink:href="#barre2" x="0" y="0" transform="rotate(135 500 500)"/>
		</g>
	</symbol>
</defs>
<use xlink:href="#cog" x="0" y="0"/>
</svg>
Aaaargh non ! Ça marche pas pareil en inline et en img, et le mask marche super mal sur Firefox, et pas du tout sur IE.
C'est pô juste : j'avais réussi à diviser le poids du fichier par 11 !
Quelqu'un a une idée ?
Modérateur
Bonjour,

Celui-là semble marcher au moins sous chrome et firefox :
<svg xmlns="http://www.w3.org/2000/svg"
     width="100" height="100" viewBox="0 0 1000 1000"
     xmlns:xlink="http://www.w3.org/1999/xlink">
	<mask id="m">
		<rect fill="white" width="100%" height="100%"/>
		<circle cx="500" cy="500" r="200" fill="black" />
	</mask>
	<g fill="black" mask="url(#m)">
		<circle cx="500" cy="500" r="400"/>
		<rect id="b" x="0" y="450" width="1000" height="100" rx="20" ry="20"/>
		<use xlink:href="#b" x="0" y="0" transform="rotate(45 500 500)"/>
		<use xlink:href="#b" x="0" y="0" transform="rotate(90 500 500)"/>
		<use xlink:href="#b" x="0" y="0" transform="rotate(135 500 500)"/>
	</g>
</svg>

EDIT : marche aussi avec safari sur mac OS et iOS
EDIT 2 : et comme source d'une image

Amicalement,
Modifié par parsimonhi (27 Jan 2016 - 02:36)
Et dès qu'on le met en tant que symbole dans un gros svg pour mettre toutes les icones inline, le masque ne fonctionne plus, comme pour le mien.
Grrrr
Modérateur
Bonjour,

Et en utilisant defs+g au lieu de symbol ?

<svg xmlns="http://www.w3.org/2000/svg"
     width="200" height="200" viewBox="0 0 1000 1000"
     xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
	<g id="cog">
		<mask id="m">
			<rect fill="white" width="100%" height="100%"/>
			<circle cx="500" cy="500" r="250" fill="black"/>
		</mask>
		<g mask="url(#m)">
			<circle cx="500" cy="500" r="425"/>
			<rect id="b" x="0" y="400" width="1000" height="200" rx="20" ry="20"/>
			<use xlink:href="#b" x="0" y="0" transform="rotate(45 500 500)"/>
			<use xlink:href="#b" x="0" y="0" transform="rotate(90 500 500)"/>
			<use xlink:href="#b" x="0" y="0" transform="rotate(135 500 500)"/>
		</g>
	</g>
</defs>
<g transform="translate(50,50)" fill="green">
	<use xlink:href="#cog" x="0" y="0" transform="scale(0.4)"/>
</g>
<g transform="translate(350,350)" fill="red">
	<use xlink:href="#cog" x="0" y="0" transform="scale(0.6)"/>
</g>
</svg>
EDIT : si tu mets plusieurs svg dans ta page, mets un <div> autour de chacun d'entre eux, ça semble éviter des effets de bords sur certains navigateurs.

Amicalement,
Modifié par parsimonhi (27 Jan 2016 - 13:19)
Apparemment, le problème se situe au niveau de l'usage du masque, et je viens de résoudre ce problème.
La nécessité du masque provient des barres qui traversent l'engrenage de part en part; mais si on fait un petit morceau de barre de chaque côté, qui s'arrête sous l'anneau, plus besoin de masque, on peut tout simplement utiliser un cercle avec un stroke pour créer l'anneau, et comme on est en fill none, on voit le fond au travers.
Dans les symboles de mon "sprite", ça donne ça :
	<symbol id="cog" viewBox="0 0 1000 1000">
		<title>Engrenage</title>		
		<g id="cog_barres" class="cog_barres"><g id="cog_barre"><rect id="cog_barre_demi" x="0" y="450" width="150" height="100" rx="20" ry="20"/><use xlink:href="#cog_barre_demi" x="850" y="0"/></g><use xlink:href="#cog_barre" x="0" y="0" transform="rotate(90 500 500)"/></g>
		<use xlink:href="#cog_barres" x="0" y="0" transform="rotate(45 500 500)"/>
		<circle class="cog_anneau" cx="500" cy="500" r="269" stroke-width="215"/>
	</symbol>
	<symbol id="cogs" viewBox="0 0 90 90">
		<title>Engrenages</title>
		<use xlink:href="#cog" x="29" y="17" width="31" height="31"/>
		<use xlink:href="#cog" x="20" y="47" width="27" height="27" transform="rotate(22 33 61)"/>
		<use xlink:href="#cog" x="48" y="45" width="21" height="21"  transform="rotate(22 58 55)"/>
	</symbol>


Merci tout le monde; sans toutes vos indications, j'aurais surement galéré un bon moment. Smiley biggrin