I’m trying to make an SVG element render within another given SVG element using path and clipPath attributes.
Specifically, I’m trying to the character’s pupil to render within the player’s eyes and no overlap onto the player’s face.
(The eyelash layering is negligible in this case.
I made a basic html that renders the character along with a JS script that animates the character.)
Here’s what the element for the left eye currently looks:
<svg>
<defs>
<clipPath id="playerEye">
<use href="head_eye_left_eye.svg" x="1.375" y="-3.75"/>
</clipPath>
</defs>
<g clip-path="url(#playerEye)">
<image href="head_base_eye_pupil.svg" x="2.75" y="-3.15"/>
</g>
</svg>
Here’s an image: Players eye with a missing pupil. Pupil should render only within the players eye.
Is there a mistake? Or is it even possible to go about using svg attributes to achieve this effect?
(I specifically also reference other parts of the character using href (referencing only .svg files).)
Any help is appreciated!
EDIT #1: The code for the file "head_eye_left_eye.svg"
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="2.3606" height="2.3835" viewBox="0,0,2.3606,2.3835"><g transform="translate(-238.8197,-178.80825)"><g data-paper-data="{"isPaintingLayer":true}" fill="#ffffff" fill-rule="nonzero" stroke="none" stroke-width="0.17188" stroke-linecap="butt" stroke-linejoin="miter" stroke-miterlimit="10" stroke-dasharray="" stroke-dashoffset="0" style="mix-blend-mode: normal"><path d="M240.63876,179.37458c0.09738,0.11448 0.50537,0.83662 0.54154,1.66652c-0.14569,0.05271 -0.65951,0.14623 -1.04444,0.15053c-0.38492,0.0043 -1.02062,-0.10631 -1.02062,-0.10631c0,0 -0.28086,-0.28131 -0.29503,-0.93228c-0.01262,-0.58006 0.20675,-1.32053 0.72654,-1.34332c0.37115,-0.01629 0.69565,0.09897 1.09199,0.56486z" data-paper-data="{"index":null}"/></g></g></svg><!--rotationCenter:1.1803017583988549:1.1917483799131503-->
And the code for the file "head_base_eye_pupil"
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="0.95959" height="1.83311" viewBox="0,0,0.95959,1.83311"><g transform="translate(-239.5202,-179.08344)"><g data-paper-data="{"isPaintingLayer":true}" fill-rule="nonzero" stroke="none" stroke-linecap="butt" stroke-linejoin="miter" stroke-miterlimit="10" stroke-dasharray="" stroke-dashoffset="0" style="mix-blend-mode: normal"><g><path d="M239.52021,180c0,-0.50619 0.21482,-0.91655 0.47979,-0.91655c0.26498,0 0.4798,0.41035 0.4798,0.91655c0,0.50619 -0.21483,0.91656 -0.4798,0.91656c-0.26497,0 -0.47979,-0.41036 -0.47979,-0.91656z" fill="#008ae6" stroke-width="0"/><path d="M240.00132,179.43809c0.05706,-0.00482 0.11033,0.04569 0.15018,0.13118c0.03995,0.08547 0.06646,0.20592 0.07023,0.34099c0.00364,0.13513 -0.01619,0.2595 -0.05116,0.35133c-0.03506,0.09181 -0.08521,0.15109 -0.14227,0.1559c-0.05706,0.00482 -0.11034,-0.04569 -0.15018,-0.13116c-0.03995,-0.08547 -0.06647,-0.20592 -0.07013,-0.34096c-0.00375,-0.13515 0.01609,-0.2595 0.05102,-0.35133c0.03506,-0.09181 0.08528,-0.15099 0.14228,-0.1559z" fill="#000000" stroke-width="0.0278"/><path d="M240.00662,179.32694c0.03231,-0.06809 0.07784,-0.11136 0.12872,-0.11349c0.05091,-0.00213 0.09774,0.03733 0.13214,0.10263c0.03455,0.06531 0.05665,0.15651 0.05821,0.25809c0.00168,0.10173 -0.01754,0.19466 -0.04999,0.26274c-0.03231,0.0681 -0.07785,0.11138 -0.12873,0.11351c-0.05091,0.00213 -0.09773,-0.03731 -0.13213,-0.10263c-0.03455,-0.06531 -0.05665,-0.15651 -0.05821,-0.25809c-0.00168,-0.10173 0.01754,-0.19466 0.04999,-0.26274z" fill="#ffffff" stroke-width="0.01811"/></g></g></g></svg><!--rotationCenter:0.47979499999999575:0.9165549999999882-->
EDIT #2: I looked at the new comments and made some changes. I am still having an issue where the pupil does not appear in the left eye. Here is what the characterSvg file is now:
<image href="head_eye_left_eye.svg" x="1.375" y="-3.75"/>
<image href="head_base_eye_pupil.svg" x="2.75" y="-3.15" opacity=".5"/>
<svg>
<defs>
<clipPath id="clipEyeLeft">
<use href="head_eye_left_eye.svg#eyeLeft" x="1.375" y="-3.75"/>
</clipPath>
</defs>
<g clip-path="url(#clipEyeLeft)">
<image href="head_base_eye_pupil.svg" x="2.75" y="-3.15"/>
</g>
</svg>
<image href="head_eye_left_lash.svg" x="0" y="-3.75"/>
I put in more of the surrounding elements for reference. The second image element is a placeholder of where the pupil should be.
Here is the revised head_eye_left_eye.svg:
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="2.3606" height="2.3835" viewBox="0,0,2.3606,2.3835">
<defs>
<clipPath id="eyeLeft">
<path d="M 4 45 c -19 -64 44 -54 43 -2 c -14 8 -32 7 -43 2 z"/>
</clipPath>
</defs>
<g transform="translate(-238.8197,-178.80825)">
<g data-paper-data="{"isPaintingLayer":true}" fill="#ffffff" fill-rule="nonzero" stroke="none" stroke-width="0.17188" stroke-linecap="butt" stroke-linejoin="miter" stroke-miterlimit="10" stroke-dasharray="" stroke-dashoffset="0" style="mix-blend-mode: normal">
<path d="M240.63876,179.37458c0.09738,0.11448 0.50537,0.83662 0.54154,1.66652c-0.14569,0.05271 -0.65951,0.14623 -1.04444,0.15053c-0.38492,0.0043 -1.02062,-0.10631 -1.02062,-0.10631c0,0 -0.28086,-0.28131 -0.29503,-0.93228c-0.01262,-0.58006 0.20675,-1.32053 0.72654,-1.34332c0.37115,-0.01629 0.69565,0.09897 1.09199,0.56486z" data-paper-data="{"index":null}"/>
</g>
</g>
</svg>
Thank you for your comments. They are greatly appreciated.
2
Answers
I was able to achieve the effect by changing up the code and instead of referencing an .svg file, I grabbed the path from the eye file and inserted it into the dynamic .svg code with a clipPath->path. Then called the pupil .svg to use the #eyeLeft clipPath. It was also important to preserve the transformation(translate(x,y)) attribute from the eye.svg file.
I understand that you would like to separate (and maybe also reuse) the different elements of your character.
My suggestion would be to do something like this, where the skin, the eye, the pupil etc. are separated in different files (like you already have) (the skin is just a rectangle here, but it could also be a file). To clip the pupil I use a clip path defined in the eye.svg file. It is the same clip path that is used inside the eye.svg to create the eye. It would look something like this:
Here, I use data URI’s to show that it works. I changed the pupil SVG a bit, by removing the width and the height attributes on the SVG element. An aside: Maybe it is a good idea just to define a viewBox for each file and let the "parent" document decide the size of the referenced SVG.
The eye.svg is defined like this: