Skip to content
Permalink
master
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time
<!doctype html>
<html class="no-js" lang="">
<head>
<meta charset="utf-8">
<title>Letterform crop</title>
<link rel="preload" href="https://use.typekit.net/djb2ljb.css" as="style" crossorigin>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="manifest" href="site.webmanifest">
<link rel="apple-touch-icon" href="icon.png">
<link rel="stylesheet" href="css/normalize.css">
<link rel="stylesheet" href="css/main.css">
<meta name="theme-color" content="#fafafa">
<link rel="stylesheet" href="https://use.typekit.net/djb2ljb.css">
<script src="https://kit.fontawesome.com/5e541f73d9.js" crossorigin="anonymous"></script>
<style>
main {
max-width: 115rem;
}
.wrapper {
display: grid;
grid-template-areas: "instructions canvas" "controls canvas";
grid-gap: 20px;
}
.canvas-container {
grid-area: canvas;
}
canvas,
#gallery img {
border: 3px solid #ccc;
width: 100%;
}
.controls {
grid-area: controls;
padding: 10px;
display: grid;
grid-template-columns: 1fr 1fr;
}
.controls button,
.controls select {
margin-bottom: 1rem;
}
.controls label {
display: block;
}
.info {
grid-area: instructions;
padding: 10px;
background-color: seashell;
}
#gallery {
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
grid-gap: 1em;
margin-top: 2rem;
}
#gallery a {
display: block;
transition: all 0.3s ease-in;
}
#gallery a:hover {
box-shadow: 0 20px 20px rgba(0, 0, 0, 0.1);
transform: translateY(-10px);
}
#save {
background-color: var(--tomato);
-webkit-appearance: none;
border: 0;
color: white;
padding: 1rem;
}
#clear {
margin-left: auto;
}
</style>
</head>
<body>
<main>
<span class="sr-only">Warning! This app is visually heavy as allows a user to scale a letter and examine the details of form and counterform.</span>
<a href="#accessibility-settings" class="sr-only">Jump to accessibility settings</a>
<nav class="lesson" aria-pressed="false">
<div class="nav--meta">
<i class="fas fa-bars"></i>
<h1>Examine a Letterform</h1>
</div>
<a href="index.html" id="return" style="margin-bottom: 20px">« Return to lessons</a>
</nav>
<h1>Examine a letterform</h1>
<div class="wrapper">
<section class="info">
<p><strong>Type</strong> any character to change the letterform.</p>
<p><strong>Click and drag</strong> in the canvas to position a letter.</p>
<p><strong>Scale and crop</strong> the letter until it becomes abstracted to better see details of the form and counterform.</p>
<p>Image states can be saved. <strong>Click</strong> any saved state to download it. The gallery will save in the browser if you refresh.</p>
</section>
<section class="controls">
<div>
<label for="fontsize">Font size:</label>
<input type="range" id="fontsize" name="fontsize" value="800" min="400" max="1500">
</div>
<div>
<label for="fontfamily">Font Family:</label>
<select id="fontfamily" name="fontfamily">
<optgroup label="Serif">
<option value="baskerville-urw">Baskerville</option>
<option value="bodoni-urw">Bodoni</option>
<option value="adobe-caslon-pro">Caslon</option>
<option value="garamond-premier-pro">Garamond</option>
<option value="times" selected>Times</option>
<option value="hoefler text">Hoefler Text</option>
<option value="mrs-eaves">Mrs. Eaves</option>
</optgroup>
<optgroup label="Sans Serif">
<option value="futura-pt">Futura</option>
<option value="gill-sans-nova">Gill Sans</option>
<option value="gill-sans-nova-condensed">Gill Sans Condensed</option>
<option value="gill-sans-nova-inline">Gill Sans Inline</option>
<option value="helvetica">Helvetica</option>
<option value="monaco">Monaco</option>
<option value="optima">Optima</option>
</optgroup>
</select>
</div>
<div style="grid-column: 1 / span 2;">
<button id="center">Center text</button> <button id="lock">Lock text</button>
<button id="reset">Reset everything</button>
</div>
<div style="grid-column: 1 / span 2; margin-top: 2rem; display: flex;"><button id="save">Save state</button> <button id="clear" class="hidden">Clear gallery</button></div>
</section>
<canvas id="cropMe" height="400" width="400"></canvas>
</div>
<!-- the below forces these fonts to load into the browser -->
<div class="font_preload" style="opacity: 0">
<span style="font-family: garamond-premier-pro, serif;font-weight: 400;font-style: normal;"></span>
<span style="font-family: adobe-caslon-pro, serif;font-weight: 400;font-style: normal;"></span>
<span style="font-family: mrs-eaves, serif;font-weight: 400;font-style: normal;"></span>
<span style="font-family: gill-sans-nova, sans-serif;font-weight: 400;font-style: normal;"></span>
<span style="font-family: futura-pt, sans-serif;font-weight: 400;font-style: normal;"></span>
<span style="font-family: bodoni-urw, serif;font-weight: 400;font-style: normal;"></span>
<span style="font-family: baskerville-urw, serif;font-weight: 400;font-style: normal;"></span>
<span style="font-family: gill-sans-nova-condensed, sans-serif;font-weight: 500;font-style: normal;"></span>
<span style="font-family: gill-sans-nova-inline, sans-serif;font-weight: 700;font-style: normal;"></span>
</div>
<div id="gallery">
</div>
</main>
<aside class="accessibility" id="accessibility-settings">
<div class="open-toggle" aria-label="Accessibility panel open button" role="button" aria-pressed="false" tabindex="0"><i class="fas fa-universal-access"></i></div>
<h1>Accessibility settings</h1>
<label for="font-style">Font style:</label>
<select name="font-style" id="font-style" autocomplete="off" style="margin-bottom: 1rem;">
<option value="">Default</option>
<option value="opendyslexic">OpenDyslexic</option>
<option value="lato">Lato</option>
<option value="verdana">Verdana</option>
</select>
<label for="high-contrast">High contrast:</label>
<input type="checkbox" name="high-contrast" id="high-contrast" autocomplete="off">
</aside>
<script src="js/vendor/fabric.js"></script>
<script src="js/vendor/localforage.js"></script>
<script src="js/nav.js"></script>
<script>
// Variable for the canvas
const canvas = new fabric.Canvas('cropMe');
// Variable for the text
let text = new fabric.Textbox('a', {
fill: '#333',
fontSize: 800,
editable: false,
top: -200,
left: 0
});
// create the image array for use later in the gallery
let imgSet = [];
// Add the text to the canvas
canvas.add(text).setActiveObject(text);
// Remove controls from the object
canvas.item(0).hasControls = canvas.item(0).hasBorders = false;
// Grab the font size control and add the event
document.getElementById('fontsize').addEventListener('mousemove', function () {
text.set({
fontSize: this.value
});
canvas.renderAll();
})
// Grab the font family element and add the event
document.getElementById('fontfamily').onchange = function () {
text.set({
fontFamily: this.value
});
canvas.renderAll();
};
// Center element
document.getElementById('center').addEventListener('click', function () {
text.center();
})
// Reset
document.getElementById('reset').addEventListener('click', function () {
text.set({
fontSize: 800,
text: 'a'
});
text.center();
})
// Lock event listener & function
let lockBtn = document.getElementById('lock');
let lock = false;
lockBtn.addEventListener('click', function () {
if (lock === false) {
lockBtn.innerHTML = 'Unlock text';
lock = !lock;
} else {
lockBtn.innerHTML = 'Lock text';
lock = !lock;
}
});
// Only allow one letter at a time
document.body.addEventListener('keyup', event => {
// First, check to make sure if the lock is on. If it is, don't proceed.
if (lock === true) {
return;
}
if (event.key.length === 1) {
let lastChar = event.key.charAt();
text.set({
text: lastChar
});
canvas.renderAll();
}
});
function renderGallery() {
// Render the array on the page
document.getElementById('gallery').innerHTML = '';
for (i = 0; i < imgSet.length; i++) {
document.getElementById('gallery').innerHTML += '<a href="' + imgSet[i] + '" download="' + i + '.png"><img src="' + imgSet[i] + '" alt=""></a>';
}
}
// Set the 'clear gallery' button to visible
function showClearGalleryButton() {
document.getElementById('clear').classList.remove('hidden');
}
// Save canvas as base64 data
document.getElementById('save').addEventListener('click', function () {
imgSet.unshift(canvas.toDataURL()); //set image into the array
renderGallery();
showClearGalleryButton();
//Send the array to localStorage
localforage
.setItem("savedCrops", JSON.stringify(imgSet))
.then((value) => {
console.log(value);
})
.catch((error) => {
console.error(error);
});
});
// Clear gallery button
document.getElementById('clear').addEventListener('click', function () {
document.getElementById('gallery').innerHTML = ''; //remove all images
document.getElementById('clear').classList.add('hidden'); // hide the 'clear' button
imgSet = []; // clear the array
localforage.clear(); //clear localForage
})
// Run local forage retrieval
function savedCrops() {
localforage
.getItem("savedCrops")
.then((value) => {
console.log('localForage ran');
if (value !== null) {
imgSet = JSON.parse(value);
showClearGalleryButton();
}
renderGallery();
})
.catch((error) => {
console.error(error);
});
}
window.addEventListener('load', savedCrops);
</script>
<script src="js/vendor/modernizr-3.11.2.min.js"></script>
<script src="js/main.js"></script>
</body>
</html>