<div class="wrapper clearfix">
<div class="controls column">
<fieldset>
<legend>viewBox</legend>
<div class="input">
<label for="#min-x"><min-x></label> <input type="number" id="min-x" class="viewbox-option" value="0" step="1">
</div>
<div class="input">
<label for="#min-y"><min-y></label> <input type="number" id="min-y" class="viewbox-option" value="0" step="1">
</div>
<label for="#viewBox-width"><width></label>
<input type="range" id="viewbox-width" class="viewbox-option" min="100" value="800" max="1600" step="10"><output for="viewbox-width">800</output>
<label for="#viewbox-height"><height></label>
<input type="range" id="viewbox-height" class="viewbox-option" min="100" value="600" max="1200" step="10" data-current-value="300"><output for="viewbox-height">600</output>
</fieldset>
<fieldset>
<legend>preserveAspectRatio</legend>
<label for="alignment"><align></label>
<select class="preserveAspectRatio-options" id="alignment">
<option value="none">None</option>
<option value="xMinYMin">xMinYMin</option>
<option value="xMinYMid">xMinYMid</option>
<option value="xMinYMax">xMinYMax</option>
<option value="xMidYMin">xMidYMin</option>
<option value="xMidYMid" selected>xMidYMid</option>
<option value="xMidYMax">xMidYMax</option>
<option value="xMaxYMin">xMaxYMin</option>
<option value="xMaxYMid">xMaxYMid</option>
<option value="xMaxYMax">xMaxYMax</option>
</select>
<div class="radios">
<input type="radio" value="meet" name="meetOrSlice" id="meet" checked="checked"><label for="meet" style="margin-right: 1em;">meet</label>
<input type="radio" value="slice" name="meetOrSlice" id="slice"><label for="slice">slice</label>
</div>
</fieldset>
<input type="checkbox" id="guidelines-visibility"><label for="guidelines-visibility" style="display:inline-block; margin-left: .5em;">Show x & y Guidelines</label>
</div>
<div class="svg-container column">
<svg class="outer" width="800" height="600" viewBox="0 0 800 600">
<g class="guidelines">
<path id="midlines" class="separator guideline" stroke-dasharray="2" />
</g>
<path class="separator ruler" />
<svg class="inner" width="800" height="600" viewBox="0 0 800 600" preserveAspectRatio="xMidYMid meet">
<g id="parrot">
<path fill="#68A284" d="M98.595 272.797c-41.144 0-77.262-28.608-97.898-71.725 3.832 44.6 25.214 98.16 98.218 98.16 72.024 0 94.49-54.748 98.282-99.631C176.686 243.541 140.206 272.797 98.595 272.797z" />
<path fill="#5EEA99" d="M196.082 161.237c-20.703 42.64-56.618 70.872-97.487 70.872 -40.322 0-75.837-27.467-96.662-69.153C0.61 170.116 0 177.521 0 185.006c0 5.137 0.222 10.535 0.697 16.066 20.636 43.116 56.754 71.725 97.898 71.725 41.611 0 78.091-29.256 98.603-73.195 0.422-5.018 0.625-9.916 0.625-14.596C197.822 176.919 197.318 168.93 196.082 161.237z" />
<path fill="#B6382F" d="M98.915 94.931c-63.562 0-90.091 30.654-96.982 68.025 20.824 41.687 56.339 69.153 96.662 69.153 40.869 0 76.784-28.232 97.487-70.872C190.195 124.653 167.334 94.931 98.915 94.931z" />
<path fill="#B6382F" d="M118.635 0c0.559 3.308-0.557 11.669-8.582 20.761 -3.538 4.004-3.218 3.191-4.57 5.207 -1.356 2.023-3.029 3.832-5.068 5.396 -2.076 1.537-2.77 2.442-6.062 3.158 -0.569-3.316-0.999-3.953-1.232-8.067 -0.139-2.562 0.43-6.148 1.79-8.161 1.368-2.012 2.879-4.152 6.157-6.386C103.149 10.369 115.682 5.588 118.635 0z" />
<path fill="none" d="M95.193 185.62h-0.008c0.705 0.101 1.417 0.174 2.151 0.194C96.602 185.794 95.893 185.721 95.193 185.62z" />
<path fill="#B6382F" d="M42.493 82.895l-0.026-0.034c0 0 0.004 0.166 0.004 0.422 -0.117 1.52-0.226 3.046-0.226 4.599 0 0.471 0.045 0.934 0.057 1.407 -0.32 5.711-1.168 14.632-3.651 24.038 -1.752 6.597-4.295 13.434-8.063 19.572 -2.735 4.472-4.901 9.551-6.639 14.786 -6.816 20.509-6.842 43.583-6.842 43.583 1.07 44.281 37.275 109.358 81.81 109.358V185.713v-44.488V31.21C69.3 31.21 45.021 53.936 42.493 82.895zM95.185 185.62h0.008c0.7 0.101 1.409 0.174 2.144 0.194C96.602 185.794 95.89 185.721 95.185 185.62z" />
<path fill="#EA575B" d="M174.207 148.585c-1.775-5.548-4.021-10.947-6.907-15.687 -3.439-5.646-5.878-11.878-7.604-17.967 -2.954-10.397-3.847-20.393-4.137-26.365 0-0.23 0.026-0.458 0.026-0.686 0-1.032-0.102-2.044-0.155-3.063 -0.022-1.22-0.003-1.957-0.003-1.957l-0.087 0.128c-2.49-29.01-26.777-51.778-56.426-51.778v110.015 44.488 114.913c44.572 0 80.796-65.137 81.806-109.459C180.721 191.167 180.698 168.835 174.207 148.585z" />
<path fill="#CABA9F" d="M80.822 78.55c-2.656 4.653-5.429 12.289-2.901 16.539l16.07 26.983c1.266 2.134 2.935 3.199 4.604 3.199V60.084C93.127 60.084 82.571 75.489 80.822 78.55z" />
<path fill="#DDD2C0" d="M103.195 122.072l16.069-26.983c2.535-4.25 0.279-10.875-2.9-16.539 -1.323-2.356-13.207-18.466-17.77-18.466v65.186C100.26 125.271 101.933 124.206 103.195 122.072z" />
<path fill="#07171B" d="M56.912 70.246c0 5.746 2.878 10.404 6.436 10.404 3.553 0 6.431-4.659 6.431-10.404 0-5.748-2.878-10.403-6.431-10.403C59.791 59.843 56.912 64.499 56.912 70.246z" />
<path fill="#FFFFFF" d="M63.807 66.213c0 1.541-1.255 2.794-2.795 2.794 -1.545 0-2.796-1.253-2.796-2.794 0-1.544 1.251-2.794 2.796-2.794C62.552 63.419 63.807 64.668 63.807 66.213z" />
<ellipse fill="#07171B" cx="134.481" cy="70.246" rx="6.433" ry="10.404" />
<circle fill="#FFFFFF" cx="132.145" cy="66.213" r="2.794" />
<path fill="#CABA9F" d="M66.542 294.861c0 3.184-2.581 5.765-5.765 5.765l0 0c-3.188 0-5.769-2.581-5.769-5.765v-10.41c0-3.184 2.581-5.764 5.769-5.764l0 0c3.184 0 5.765 2.58 5.765 5.764V294.861z" />
<path fill="#CABA9F" d="M78.083 294.861c0 3.184-2.584 5.765-5.769 5.765l0 0c-3.187 0-5.772-2.581-5.772-5.765v-10.41c0-3.184 2.585-5.764 5.772-5.764l0 0c3.184 0 5.769 2.58 5.769 5.764V294.861z" />
<path fill="#CABA9F" d="M89.62 294.861c0 3.184-2.581 5.765-5.769 5.765l0 0c-3.188 0-5.769-2.581-5.769-5.765v-10.41c0-3.184 2.581-5.764 5.769-5.764l0 0c3.188 0 5.769 2.58 5.769 5.764V294.861z" />
<path fill="#DDD2C0" d="M119.743 294.861c0 3.184-2.581 5.765-5.769 5.765l0 0c-3.188 0-5.769-2.581-5.769-5.765v-10.41c0-3.184 2.581-5.764 5.769-5.764l0 0c3.188 0 5.769 2.58 5.769 5.764V294.861z" />
<path fill="#DDD2C0" d="M131.28 294.861c0 3.184-2.581 5.765-5.765 5.765l0 0c-3.191 0-5.772-2.581-5.772-5.765v-10.41c0-3.184 2.581-5.764 5.772-5.764l0 0c3.184 0 5.765 2.58 5.765 5.764V294.861z" />
<path fill="#DDD2C0" d="M142.821 294.861c0 3.184-2.585 5.765-5.773 5.765l0 0c-3.183 0-5.768-2.581-5.768-5.765v-10.41c0-3.184 2.585-5.764 5.768-5.764l0 0c3.188 0 5.773 2.58 5.773 5.764V294.861z" />
<path fill="#EA575B" d="M125.907 10.497c0.565 3.304-3.541 15.808-7.905 20.605 -1.729 1.899-10.165 10.726-18.8 12.396 -0.569-3.319-1.255-8.693-0.607-11.196 0.682-2.471 2.551-6.471 9.201-9.417C117.434 18.62 121.515 16.084 125.907 10.497z" />
</g>
<g class="guidelines">
<path id="minx" stroke="orange" stroke-width="5" class="guideline" />
<path id="midmaxx" stroke="orange" stroke-dasharray="1" stroke-width="2" class="guideline" />
<path id="miny" stroke="#9b59b6" stroke-width="5" class="guideline" />
<path id="midmaxy" stroke="#9b59b6" stroke-dasharray="1" stroke-width="2" class="guideline" />
</g>
<path class="separator ruler" />
</svg>
</svg>
</div>
</div>
<footer>
Copyright © <a href="http://sarasoueidan.com/" style="color:deepPink">Sara Soueidan</a>. Thank you <a style="color: deepPink" href="https://twitter.com/DmitryBaranovsk">Dmitry Baranovsky</a> for refactoring the demo's code.
</footer>
@import url(
https://fonts.googleapis.com/css?family=Open + Sans:400italic,
600italic,
700italic,
800italic,
400,
600,
700,
800
);
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html {
background-color: #eee;
}
body {
width: 100vw;
min-height: 100vh;
font-family: "Open Sans", sans-serif;
line-height: 1.5;
display: flex;
flex-direction: column;
align-items: center;
}
p {
margin: 0.75em 0;
}
.wrapper {
background-color: #3b3f45;
flex: 1;
display: flex;
width: 100vw;
min-height: 680px;
}
.svg-container {
position: relative;
width: 800px;
height: 600px;
margin: 1.8em 0;
}
.controls,
.sidebar {
padding: 1em;
color: #fff;
width: 250px;
}
h2 {
text-align: center;
color: #ea575b;
margin-bottom: 1em;
font-size: 2.5em;
}
h3 {
margin-bottom: 1em;
}
label {
display: block;
margin-top: 1.5em;
color: #ddd;
}
.radios label {
display: inline-block;
margin-left: 0.25em;
}
select {
border: 1px solid transparent;
background-color: #eee;
color: #1b1f25;
border-radius: 3px;
padding: 0.5em;
margin: 0.5em 0;
width: 100%;
cursor: pointer;
font-family: "Open Sans", sans-serif;
font-weight: 500;
}
select option:nth-of-type(even) {
background-color: #fff;
}
.input {
width: 48.5%;
display: inline-block;
}
.input input {
max-width: 50px;
font-size: 1.05em;
font-weight: 400;
}
.outer {
overflow: scroll;
}
input {
background-color: #eee;
padding: 0.1em;
border: 2px solid transparent;
color: #1b1f25;
border-radius: 3px;
max-width: 100%;
margin-top: 0.5em;
display: inline-block;
font-family: "Open Sans", sans-serif;
font-weight: 600;
}
input[type="text"]:required {
border: 2px solid #ff3e5a;
}
output {
width: 40px;
color: #2cb2ba;
}
input[type="range"] {
display: inline-block;
margin-bottom: 1em;
margin-right: 0.2em;
width: 135px;
background: none !important;
-webkit-appearance: none;
-moz-appearance: none;
}
input:focus {
border: 2px solid #2cb2ba;
outline: none;
}
input[type="range"]::-webkit-slider-runnable-track {
width: 135px;
height: 5px;
background-color: #eee;
border: none;
border-radius: 3px;
}
input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
border: none;
height: 20px;
width: 20px;
border-radius: 50%;
background: #2cb2ba;
margin-top: -8px;
}
input[type="range"]::-moz-range-track {
width: 135px;
height: 5px;
background-color: #eee;
border: none;
border-radius: 3px;
}
input[type="range"]::-moz-range-thumb {
border: none;
height: 20px;
width: 20px;
border-radius: 50%;
background: #2cb2ba;
}
input[type="range"]::-ms-track {
width: 135px;
height: 20px;
background-color: #eee;
border: none;
border-radius: 10px;
color: transparent;
}
input[type="range"]::-ms-thumb {
border: none;
height: 20px;
width: 20px;
border-radius: 50%;
background: #2cb2ba;
}
fieldset {
padding: 0 1em 1em;
margin-bottom: 1em;
border-radius: 3px;
}
legend {
color: #fff;
}
svg {
position: absolute;
}
svg.outer {
background-color: white;
border: 1px solid #ddd;
}
.inner .separator {
stroke: #4cd2da;
stroke-width: 2;
}
.outer > .separator {
stroke: #aaa;
stroke-width: 1;
}
.inner .labels {
fill: #4cd2da;
stroke: #2cb2ba;
stroke-width: 1;
}
.outer > .labels {
fill: #ccc;
}
.cheatsheet {
background-color: white;
padding: 1em;
margin: 1em auto;
width: 1300px;
}
.plain {
margin-top: 1em;
color: #0077aa;
font-size: 0.9em;
}
dl {
margin: 1em 0;
}
dt {
font-weight: bolder;
margin: 0.5em 0;
}
dd {
padding-left: 1em;
}
.guide-trigger {
background-color: #2cb2ba;
color: white;
padding: 0.5em 1em;
border-radius: 5px;
border: none;
font-size: 1.5em;
color: #eee;
font-family: "Open Sans", sans-serif;
text-align: center;
display: block;
width: 100%;
cursor: pointer;
margin-bottom: 14em;
-webkit-transition: background-color 0.2s linear;
transition: background-color 0.2s linear;
}
.guide-trigger:hover {
background-color: transparent;
}
button {
border: 2px solid transparent;
}
button:active,
button:focus {
border: 2px solid #2cb2ba;
outline: none;
}
footer {
text-align: center;
}
header {
width: 1300px;
background-color: white;
padding: 0.5em 1em;
margin: 0 auto 1em;
}
header a {
color: #bb4347;
font-weight: bold;
}
.ad-wrapper {
background-color: #f5f5f5;
border: 1px solid #eee;
padding-bottom: 0.5em;
margin-bottom: 2em;
}
.ad-wrapper a {
border-bottom: none !important;
margin: 0 auto;
}
.ad-wrapper a:hover {
border-bottom: none !important;
}
.one .bsa_it_ad {
font-family: inherit;
padding: 0.5em 0.5em 0 0.5em;
background: transparent;
margin: 0;
border: none !important;
text-align: center;
width: 100%;
color: #333;
}
.one .bsa_it_p {
display: none !important;
clear: both;
}
.one .bsa_it_ad .bsa_it_i {
padding: 0;
margin: 5px auto !important;
display: inline-block;
float: none !important;
}
.one .bsa_it_ad .bsa_it_i img {
padding: 0;
border: none;
}
.one .bsa_it_ad .bsa_it_t {
padding: 6px 0;
margin-top: 10px;
}
.one .bsa_it_ad .bsa_it_d {
padding: 0;
font-size: 11px;
color: #333;
}
.one .bsa_it_p {
display: none;
}
#bsap_aplink,
#bsap_aplink:hover {
display: block;
font-size: 10px;
margin: 0 1em 0;
text-align: center;
text-transform: uppercase;
letter-spacing: 1px;
color: grey;
border-bottom: none;
}
footer {
padding: 1em;
background-color: rgba(0, 0, 0, 0.8);
color: #fff;
width: 100vw;
}
var outerSVG = document.querySelector(".outer");
var innerSVG = document.querySelector(".inner");
var svgns = "http://www.w3.org/2000/svg";
function makeRulers(svgElement, distance, units) {
var vb = svgElement.getAttribute("viewBox").split(" "),
svgWidth = vb[2],
nbOfWSeparators = svgWidth / distance,
nbOfWUnits = svgWidth / units,
svgHeight = vb[3],
nbOfHSeparators = svgHeight / distance,
nbOfHUnits = svgHeight / units,
pathstring = "",
path = svgElement.querySelectorAll(".ruler"),
i,
g = document.createElementNS(svgns, "g");
for (i = 0; i < path.length; i++) {
if (path[i].parentNode == svgElement) {
path = path[i];
break;
}
}
for (i = 0; i <= nbOfWUnits; i++) {
pathstring += "M" + i * units + ",0v15";
}
for (i = 0; i <= nbOfWSeparators; i++) {
pathstring += "M" + i * distance + ",0v30";
var value = document.createElementNS(svgns, "text");
value.setAttribute("x", i * distance - 15);
value.setAttribute("y", 43);
value.textContent = i * distance;
g.appendChild(value);
}
for (i = 0; i <= nbOfHUnits; i++) {
pathstring += "M0," + i * units + "h15";
}
for (i = 0; i <= nbOfHSeparators; i++) {
pathstring += "M0," + i * distance + "h30";
var value = document.createElementNS(svgns, "text");
value.setAttribute("x", 30);
value.setAttribute("y", i * distance + 5);
value.textContent = i * distance;
g.appendChild(value);
}
g.setAttribute("class", "labels");
g.setAttribute("font-size", "16px");
path.setAttribute("d", pathstring);
svgElement.appendChild(g);
}
makeRulers(outerSVG, 100, 10);
makeRulers(innerSVG, 100, 10);
// preserveAspectRatio Controls
var aligmentOptions = document.querySelector(".preserveAspectRatio-options"),
meetOrSlice = "meet",
alignment = "xMidYMid",
sliceOption = document.getElementById("slice"),
meetOption = document.getElementById("meet");
sliceOption.onclick = function () {
if (this.checked) meetOrSlice = "slice";
setPreserveAspectRatio();
};
meetOption.onclick = function () {
if (this.checked) meetOrSlice = "meet";
setPreserveAspectRatio();
};
aligmentOptions.onchange = function () {
alignment = this.options[this.selectedIndex].value;
setPreserveAspectRatio();
};
function setPreserveAspectRatio() {
innerSVG.setAttribute("preserveAspectRatio", alignment + " " + meetOrSlice);
}
var vbGuidelinesVisibility = document.getElementById("guidelines-visibility");
//when the checkbox is clicked
vbGuidelinesVisibility.onclick = function () {
//get all the currently available guidelines
var guidelines = document.querySelectorAll(".guidelines");
if (this.checked) {
guidelines[0].style.display = "";
guidelines[1].style.display = "";
drawXandYLines();
} else {
guidelines[0].style.display = "none";
guidelines[1].style.display = "none";
}
};
//viewBox input Controls
var vbMinX = document.getElementById("min-x"),
vbMinY = document.getElementById("min-y"),
vbWidth = document.getElementById("viewbox-width"),
vbHeight = document.getElementById("viewbox-height");
var vbMinXvalue = vbMinX.value,
vbMinYvalue = vbMinY.value,
vbWidthValue = vbWidth.value,
vbHeightValue = vbHeight.value;
vbMinX.addEventListener("blur", resetInput, false);
vbMinY.addEventListener("blur", resetInput, false);
function resetInput() {
if (!this.value) this.value = 0;
setViewboxAttributeValue();
}
vbMinX.addEventListener("change", vbMinXHandler, false);
vbMinX.addEventListener("input", vbMinXHandler, false);
function vbMinXHandler() {
setViewboxAttributeValue();
updateRulers();
vbMinXvalue = this.value;
if (vbGuidelinesVisibility.checked) drawXandYLines();
}
vbMinY.addEventListener("change", vbMinYHandler, false);
vbMinY.addEventListener("input", vbMinYHandler, false);
function vbMinYHandler() {
setViewboxAttributeValue();
updateRulers();
vbMinYvalue = this.value;
if (vbGuidelinesVisibility.checked) drawXandYLines();
}
vbWidth.addEventListener("change", vbWidthHandler, false);
vbWidth.addEventListener("input", vbWidthHandler, false);
function vbWidthHandler() {
updateRangeOutput(this);
setViewboxAttributeValue();
updateRulers();
vbWidthValue = this.value;
if (vbGuidelinesVisibility.checked) drawXandYLines();
}
vbHeight.addEventListener("change", vbHeightHandler, false);
vbHeight.addEventListener("input", vbHeightHandler, false);
function vbHeightHandler() {
updateRangeOutput(this);
setViewboxAttributeValue();
updateRulers();
vbHeightValue = this.value;
if (vbGuidelinesVisibility.checked) drawXandYLines();
}
var midlines = document.getElementById("midlines"),
minx = document.getElementById("minx"),
midmaxx = document.getElementById("midmaxx"),
miny = document.getElementById("miny"),
midmaxy = document.getElementById("midmaxy");
function drawXandYLines() {
var vb = outerSVG.getAttribute("viewBox").split(" "),
svgWidth = vb[2],
svgHeight = vb[3],
midx = +vbMinXvalue + vbWidthValue / 2,
maxx = +vbMinXvalue + +vbWidthValue,
midy = +vbMinYvalue + vbHeightValue / 2,
maxy = +vbMinYvalue + +vbHeightValue;
midlines.setAttribute(
"d",
"M" +
[svgWidth / 2, 0, svgWidth / 2, svgHeight] +
"M" +
[0, svgHeight / 2, svgWidth, svgHeight / 2]
);
minx.setAttribute("d", "M" + [vbMinXvalue, 0, vbMinXvalue, vbHeightValue]);
midmaxx.setAttribute(
"d",
"M" + [midx, 0, midx, vbHeightValue] + "M" + [maxx, 0, maxx, vbHeightValue]
);
miny.setAttribute("d", "M" + [0, vbMinYvalue, vbWidthValue, vbMinYvalue]);
midmaxy.setAttribute(
"d",
"M" + [0, midy, vbWidthValue, midy] + "M" + [0, maxy, vbWidthValue, maxy]
);
}
function updateRangeOutput(self) {
self.nextSibling.textContent = self.value;
}
function updateRulers() {
//remove all previously added text
var labels = innerSVG.querySelector(".labels");
labels.parentNode.removeChild(labels);
//redraw lines according to new viewBox width and height values
makeRulers(innerSVG, 100, 10);
}
function setViewboxAttributeValue() {
var viewBoxValue =
vbMinX.value +
" " +
vbMinY.value +
" " +
vbWidth.value +
" " +
vbHeight.value;
innerSVG.setAttribute("viewBox", viewBoxValue);
}
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.