Making Faces - SVG and JavaScript
After spending some time away from the code I wrote yesterday and reading a very useful article, I was able to finish this silly prototype. I noticed I had some pretty gnarly typos in my JavaScript yesterday that I'm embarassed to point out, but I am know going to make sure I double check my namespace URIs.
View the code:
HTML and JS
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="150" height="210" x="0px" y="0px" id="logo"><symbol id="head" width="150" height="210" ><path id="skin" fill="#FFF" d="M130.098 106.531c-1.176-2.388-2.497-3.379-3.741-3.771-1.715 2.676-4.012 4.962-4.036 4.993a1 1 0 01-1.541-1.26c1.543-2.197 2.029-8.529 1.99-13.055.003-3.037-.154-5.318-.154-5.323l.043-.367c.852-2.701 1.169-6.005 1.169-9.29 0-3.602-.373-7.182-.77-9.957a1.477 1.477 0 01-.614.116c-.44-.005-.696-.138-.776-.174a.994.994 0 01-.529-1.11c.174-.796.254-1.813.254-2.917.002-2.346-.347-5.044-.678-7.068a1 1 0 01-1.601-.75c-.284-5.4-1.566-8.278-2.597-9.751-.489 1.807-1.841 2.558-1.958 2.598a1 1 0 01-1.436-.743c-.341-2.147-1.405-3.381-2.685-4.228-1.276-.834-2.788-1.194-3.777-1.332a5.717 5.717 0 00-.146-.021c-.509 2.878-2.811 4.228-2.887 4.286-.31.185-.694.189-1.009.013a1.006 1.006 0 01-.505-.871c-.042-5.015-1.94-7.039-3.311-7.896.009.176.014.348.014.516.022 4.21-2.563 5.715-2.757 5.775a.99.99 0 01-1.052-.1.996.996 0 01-.378-.989c.097-.488.143-.972.143-1.448.006-1.087-.229-2.147-.57-3.105-.264 3.641-2.414 5.043-2.593 5.115a1 1 0 01-1.495-.929c.018-.267.027-.521.027-.762.007-3.135-1.452-5.453-2.812-6.929.281 1.616.281 2.708.281 2.752-.005 1.678-.203 2.776-.621 3.586-.392.822-1.238 1.302-1.923 1.268-.973-.031-1.495-.529-1.579-.573a.996.996 0 01-.191-1.359c.331-.472.421-.824.423-1.134.131-1.076-1.809-2.573-2.926-3.091l-.066-.035-.091.076a8.593 8.593 0 00-1.229 1.306c-.897 1.186-1.793 2.956-1.797 5.456 0 .322-.153.624-.414.813a1.015 1.015 0 01-.899.138c-.141-.03-4.623-1.611-5.991-7.385a2.283 2.283 0 00-.962.504c-.573.508-1.225 1.535-1.234 3.933a.992.992 0 01-.998.999c-.281.021-1.058-.194-1.631-1.053-.493-.715-.934-1.817-1.219-3.691a4.43 4.43 0 00-.858.451c-.904.641-1.807 1.654-1.828 3.971 0 .229.01.475.033.735a1 1 0 01-1.313 1.035c-.162-.014-1.531-.593-2.554-2.4.153.773.49 1.552 1.129 2.301a1.001 1.001 0 01-1.153 1.57c-.056-.026-1.882-.806-3.757-2.411-1.218-1.041-2.486-2.471-3.221-4.29-.341 1.289-.629 3.158-.629 5.782a.999.999 0 01-1.447.895c-.105-.041-2.583-1.326-3.337-4.51-.625.691-1.213 1.675-1.218 3.114a1 1 0 01-.689.95c-.056.015-.401.138-.901.143-.293-.005-.683-.036-1.091-.323-.342-.229-.57-.652-.634-1.068a13.737 13.737 0 00-2.29 3.247 1.003 1.003 0 01-1.137.522 2.098 2.098 0 01-.878-.493 2.245 2.245 0 01-.606-.917 29.03 29.03 0 00-1.053 1.541c-1.816 2.842-3.744 6.945-4.224 11.993l-.043.211c.002.005-.619 1.927-1.251 5.27a73.863 73.863 0 00-1.262 13.559c0 2.747.157 5.686.551 8.738a1 1 0 01-1.438 1.022 1.766 1.766 0 01-.302-.199c.089 1.44.194 3.127.309 4.865.31 4.726.694 9.901.927 11.275.082.49-.213.97-.688 1.119a1.002 1.002 0 01-1.201-.527l-1.385-2.921c-1.461.069-3.078.722-4.567 3.299-1.529 2.688-2.74 7.54-2.735 15.696.058 11.895 7.057 14.75 10.624 15.688 1.183.287 1.911.311 1.913.311.535.02.963.461.963 1.002v8.998c-.015 4.172 2.157 9.346 4.378 13.395 2.213 4.061 4.416 7 4.431 7.016l13.479 18.473c5.734 7.332 13.587 8.719 18.233 8.838.147.002.084.006.113.006h.01l.007.002.01.002c.01 0 .024.002.044.006a23.046 23.046 0 00.847.077c.59.047 1.446.09 2.496.09 5.332.01 15.517-1.178 21.603-8.992l13.507-18.512c0-.008 2.208-2.943 4.421-7.004 2.223-4.049 4.395-9.223 4.381-13.395-.003-8.992-.003-8.992 0-8.998a1 1 0 01.962-1.002c0-.002.155-.006.493-.047.337-.043.827-.121 1.418-.264a13.98 13.98 0 004.331-1.842c3.115-2.049 6.27-5.869 6.293-13.846.003-7.519-1.022-12.228-2.381-15.023zM96.611 14.136c.26.297.323.716.163 1.073.317.091.636.19.952.293.156-.412.186-.876.037-1.327A2 2 0 0095.24 12.9l-.077.025a6.97 6.97 0 01-.633 1.245l1.031-.324a1 1 0 011.05.29z"/><path id="noseMouth" fill="#231F20" d="M82.277 88.014l-.049-.124c-.031-.033-1.308-2.392-3.96-2.423a.504.504 0 00-.388.184.507.507 0 00-.1.419c.002.019 1.896 8.94 3.793 19.102 1.896 10.148 3.791 21.56 3.786 26.341-.025 7.629-5.722 8.149-7.916 8.209-.475 0-.746-.032-.746-.03-12.128-.063-13.138-7.112-13.214-10.24 0-.856.097-1.375.093-1.375a.499.499 0 00-.888-.393c-1.254 1.646-1.919 3.778-1.921 6.009 0 2.989 1.202 6.175 3.836 8.605 2.636 2.432 6.685 4.086 12.31 4.084h.082c7.648 0 11.416-2.89 13.139-6.307 1.733-3.402 1.508-7.231 1.646-9.07.004-.07.006-.141.006-.211-.021-4.898-9.505-42.734-9.509-42.78zM97.108 147.807a.503.503 0 00-.537-.424.499.499 0 00-.458.506v.188c-.069 1.748-.465 15.264-20.25 15.307-10.63-.012-16.053-3.924-18.912-7.799a16.951 16.951 0 01-2.615-5.342c-.419-1.453-.469-2.393-.474-2.393a.5.5 0 00-1 .004c0 .008-.005.09-.005.232.003 1.098.166 6.07 3.172 10.824 2.996 4.756 8.89 9.221 20.03 9.221h.054c9.465.01 14.817-3.195 17.729-7.105 2.914-3.904 3.391-8.42 3.393-11.025 0-1.335-.125-2.175-.127-2.194z"/><circle fill="#82AFCF" id="rightEye" cx="53.613" cy="97.05" r="4.5"/><circle fill="#82AFCF" id="leftEye" cx="101.113" cy="97.05" r="4.5"/><path id="eyebrows" fill="#231F20" d="M60.842 84.437c-1.827-2.789-12.777 1.139-15.394 2.383-3.413 1.623-6.701 4.081-8.721 7.333-.517.833.213 1.585 1.237 1.792 3.128-2.938 6.833-5.278 10.94-6.57 2.768-.872 5.717-1.287 8.618-1.09 3.208.218 4.088-.21 3.32-3.848M92.785 82.883c-1.416-.285-1.591 2.299-1.408 3.105.563 2.476 3.512 1.249 5.221 1.249 6.447.013 12.563 2.752 17.356 6.969 1.29 1.134 2.867-.077 1.771-1.72-1.435-2.152-3.814-3.975-5.983-5.324-5.047-3.139-11.08-4.287-16.957-4.279"/><path id="outline" fill="#231F20" d="M130.455 98.042c.604-4.095 1.474-11.331 1.474-19.172 0-5.354-.403-10.989-1.593-16.115a5.016 5.016 0 001.644-3.707 5.094 5.094 0 00-.193-1.371c-.465-1.599-3.807-13-9.322-20.766a5.03 5.03 0 00-.387-2.329c-.205-.445-3.21-7.378-10.207-10.927a4.97 4.97 0 00-1.574-1.736c-1.461-.987-7.539-5.01-13.521-6.71a1.001 1.001 0 00-1.213-1.363l-1.033.324c.518-.8.96-1.828 1.074-3.092a.997.997 0 00-1.308-1.027c-.662.218-2.543.841-4.691 1.603a5.003 5.003 0 00-6.487-2.745c-.424.172-2.878 1.188-5.368 3.109-4.396-2.033-9.872-3.057-11.905-3.402a5.005 5.005 0 00-5.47 3.089c-.807-.261-1.342-.422-1.417-.445a4.998 4.998 0 00-6.375 4.011c-5.898 1.655-11.799 5.212-12.669 5.735a5.001 5.001 0 00-2.188 2.86c-6.709 3.608-9.598 10.276-9.799 10.713a4.94 4.94 0 00-.391 2.334c-5.514 7.766-8.856 19.164-9.319 20.763a4.91 4.91 0 00-.195 1.371 4.995 4.995 0 001.644 3.705c-1.191 5.129-1.596 10.763-1.598 16.117.002 7.84.872 15.077 1.479 19.173-4.264 2.582-8.035 8.99-8.023 23.508-.037 12.975 7.29 19.059 13.501 21.09v4.908c.055 10.535 8.895 22.469 9.985 23.98l13.474 18.469c.042.051.07.092.093.121 7.251 9.256 17.183 10.971 22.591 11.141.6.064 1.983.191 3.904.191 6.472-.004 18.574-1.422 26.348-11.32l.102-.133 13.483-18.479c1.086-1.504 9.923-13.436 9.977-23.971v-4.908c6.21-2.029 13.537-8.113 13.5-21.09.01-14.518-3.764-20.927-8.027-23.507zm-11.475 49.507c.014 4.172-2.158 9.346-4.381 13.395-2.213 4.061-4.421 6.996-4.421 7.004L96.671 186.46c-6.086 7.814-16.271 9.002-21.603 8.992a32.116 32.116 0 01-3.171-.149 2.422 2.422 0 00-.172-.018.244.244 0 00-.044-.006l-.01-.002-.007-.002h-.01c-.029 0 .034-.004-.113-.006-4.646-.119-12.499-1.506-18.233-8.838l-13.479-18.473c-.015-.016-2.218-2.955-4.431-7.016-2.221-4.049-4.393-9.223-4.378-13.395v-8.998c0-.541-.428-.982-.963-1.002-.002 0-.73-.023-1.913-.311-3.567-.938-10.566-3.793-10.624-15.688-.005-8.156 1.206-13.008 2.735-15.696 1.489-2.577 3.106-3.229 4.567-3.299l1.385 2.921c.212.45.726.674 1.201.527.475-.149.77-.629.688-1.119-.232-1.374-.617-6.55-.927-11.275-.114-1.738-.22-3.425-.309-4.865.132.105.235.166.302.199a1 1 0 001.438-1.022 68.344 68.344 0 01-.551-8.738c0-5.493.631-10.216 1.262-13.559.632-3.343 1.253-5.265 1.251-5.27l.043-.211c.479-5.048 2.407-9.151 4.224-11.993.359-.565.715-1.079 1.053-1.541.145.394.369.711.606.917.406.367.78.467.878.493.454.113.929-.106 1.137-.522a13.737 13.737 0 012.29-3.247c.063.416.292.839.634 1.068.408.287.798.318 1.091.323.5-.005.846-.128.901-.143a1 1 0 00.689-.95c.005-1.439.593-2.423 1.218-3.114.754 3.184 3.231 4.469 3.337 4.51a.999.999 0 001.447-.895c0-2.624.288-4.493.629-5.782.734 1.819 2.003 3.249 3.221 4.29 1.875 1.605 3.701 2.385 3.757 2.411a1 1 0 001.153-1.57 4.964 4.964 0 01-1.129-2.301c1.022 1.808 2.392 2.387 2.554 2.4a1 1 0 001.313-1.035 8.37 8.37 0 01-.033-.735c.021-2.316.924-3.33 1.828-3.971a4.46 4.46 0 01.858-.451c.285 1.874.726 2.977 1.219 3.691.573.858 1.35 1.074 1.631 1.053a.994.994 0 00.998-.999c.01-2.397.661-3.425 1.234-3.933.316-.281.665-.429.962-.504 1.368 5.773 5.851 7.354 5.991 7.385.302.099.639.048.899-.138.261-.189.414-.491.414-.813.004-2.5.899-4.271 1.797-5.456a8.542 8.542 0 011.229-1.306l.091-.076.066.035c1.117.518 3.057 2.015 2.926 3.091-.002.31-.092.662-.423 1.134a.996.996 0 00.191 1.359c.084.044.606.542 1.579.573.685.034 1.531-.445 1.923-1.268.418-.81.616-1.908.621-3.586 0-.044 0-1.136-.281-2.752 1.359 1.476 2.818 3.794 2.812 6.929 0 .241-.01.495-.027.762a1 1 0 001.495.929c.179-.072 2.329-1.475 2.593-5.115.341.958.576 2.019.57 3.105 0 .477-.046.96-.143 1.448a.996.996 0 00.378.989.995.995 0 001.052.1c.193-.061 2.779-1.565 2.757-5.775 0-.168-.005-.34-.014-.516 1.37.857 3.269 2.882 3.311 7.896 0 .36.193.691.505.871.314.177.699.172 1.009-.013.076-.059 2.378-1.408 2.887-4.286l.146.021c.989.138 2.501.498 3.777 1.332 1.279.847 2.344 2.08 2.685 4.228a1 1 0 001.436.743c.117-.04 1.469-.791 1.958-2.598 1.03 1.473 2.313 4.351 2.597 9.751a.999.999 0 001.601.75c.331 2.024.68 4.723.678 7.068 0 1.104-.08 2.121-.254 2.917a.994.994 0 00.529 1.11c.08.036.336.169.776.174.179.01.396-.028.614-.116.396 2.775.77 6.355.77 9.957 0 3.285-.317 6.589-1.169 9.29l-.043.367c0 .005.157 2.286.154 5.323.039 4.525-.447 10.857-1.99 13.055a1 1 0 001.541 1.26c.024-.031 2.321-2.317 4.036-4.993 1.244.392 2.565 1.383 3.741 3.771 1.359 2.795 2.385 7.504 2.38 15.02-.023 7.977-3.178 11.797-6.293 13.846a13.98 13.98 0 01-4.331 1.842c-.591.143-1.081.221-1.418.264-.338.041-.493.045-.493.047a1 1 0 00-.962 1.002c-.001.009-.001.009.001 9.001z"/></symbol></svg>
<section class="code-block">
<svg class="head-svg">
<use href="#head" />
</svg>
<button id="make-face-button">Add another Face</button>
</section>
<div id="headcontainer">
</div>
<aside class="note"><p>I was able to finish fixing my JavaScript for this post thanks to this handy article, <a href="https://florianbrinkmann.com/en/svg-use-element-javascript-4513/">Create SVG and USE element with JavaScript</a> by <a href="https://florianbrinkmann.com/en/">Florian Brinkmann</a>. Thanks Florian!</p></aside>
<script>
/* Variables */
const bodyElement = document.getElementsByTagName('body');
const faceBtn = document.querySelector('#make-face-button');
const faceCont = document.querySelector('#headcontainer');
/* Functions */
function randomNum(minnum, maxnum) {
min = Math.ceil(minnum);
max = Math.floor(maxnum);
return Math.floor(Math.random() * (maxnum - minnum) + minnum);
}
function faceMaker() {
let svgElem = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
let useElem = document.createElementNS('http://www.w3.org/2000/svg', 'use');
useElem.setAttributeNS('http://www.w3.org/1999/xlink', 'href', '#head');
svgElem.setAttribute('class','svg-head');
let posY = randomNum(40, 200);
let posX = randomNum(10, 100);
let rndOpacity = randomNum(1,100);
let rndRotation = randomNum(-180,180);
let rndColorOne = randomNum(0, 255);
let rndColorTwo = randomNum(0, 255);
let rndColorThree = randomNum(0, 255);
svgElem.setAttribute('width', '150');
svgElem.setAttribute('height', '210');
svgElem.setAttribute('style', `transform: rotate(${rndRotation}deg);background-color: rgb(${rndColorOne}, ${rndColorTwo}, ${rndColorThree}); opacity: calc(${rndOpacity} * .01); position: absolute; top: ${posY}%; left: calc(${posX}% - 150px); box-shadow: 5px 5px 5px 5px #00000055;`);
svgElem.appendChild(useElem);
document.body.appendChild(svgElem);
console.log(`face added at ${posY} and ${posX}`);
};
/* Events */
faceBtn.addEventListener('click', () => {
faceMaker();
});
</script>
CSS
#logo {
display: none;
}
#head:hover > #leftEye, #head:hover > #rightEye, #head:hover > #outline, #head:hover > #eyebrows, #head:hover > #noseMouth, #head:hover > #skin {
transition: fill .25s ease-out, stroke .3s ease-in;
fill: transparent;
stroke: black;
stroke-width: 1px;
stroke-opacity: .5;
}
.head-svg {
width: 150px;
height: 210px;
position: relative;
}
aside.note {
background-color: rgb(255, 225, 94);
border: solid 1px rgba(255, 169, 71, 0.733);
padding: 1rem;
margin: 1rem auto;
max-width: 60ch;
font-family: Helvetica, Arial, sans-serif;
}
#make-face-button {
min-height: 44px;
border-radius: .5rem;
border: solid 1px #bcbcbc;
position: relative;
z-index: 100;
background-color: white;
}
@supports (display: grid) {
.code-block {
display: grid;
place-items: center;
}
}