Skip to content

Instantly share code, notes, and snippets.

@denilsonsa
Last active May 23, 2023 21:56
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save denilsonsa/a518a7825e727e55b6fb to your computer and use it in GitHub Desktop.
Save denilsonsa/a518a7825e727e55b6fb to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Live demo of Nosy Facetype by Rory Harnden</title>
<link href='http://fonts.googleapis.com/css?family=Ubuntu+Mono:400,400italic' rel='stylesheet' type='text/css'>
<style type="text/css">
@font-face {
font-family: "Nosy";
src: url(NOSY_Facetype_by_Rory_Harnden.otf) format("opentype");
}
html {
background: white;
color: black;
font-family: "Ubuntu Mono", "Courier New", Courier, monospace;
}
h1 {
margin: 0 0 0.5em 0;
}
p {
margin: 1ex 0;
}
a {
text-decoration: none;
color:#f2047b;
}
a:visited {
color:#3bceba
}
section {
display: flex;
flex-direction: row;
margin-top: 1em;
}
@media (max-width: 700px) {
section {
flex-wrap: wrap;
}
}
.formcontrol:hover {
background: #EEE;
}
.formcontrol,
.formcontrol label,
.formcontrol input {
vertical-align: middle;
}
.formcontrol * {
margin-top: 0;
margin-bottom: 0;
}
.formcontrol label {
width: 8em;
}
.formcontrol label, .formcontrol input {
display: inline-block;
height: 1.5em;
}
.formcontrol .draghandle {
display: inline-block;
width: 1.5em;
text-align: left;
text-indent: 0.33em;
cursor: move;
color: black;
text-shadow:
black 0 -0.25em 0,
black 0 -0.50em 0,
black 0.25em 0 0,
black 0.25em -0.25em 0,
black 0.25em -0.50em 0;
}
.drag-moving {
opacity: 0.25;
}
.drag-over {
background: #FFC;
}
.column:first-child {
flex-grow: 0;
flex-shrink: 0;
margin-right:25px;
}
.column:last-child {
flex-grow: 1;
flex-shrink: 1;
}
/*
http://dev.w3.org/csswg/css-fonts/#propdef-font-feature-settings
http://dev.w3.org/csswg/css-fonts/#propdef-font-variant-ligatures
https://developer.mozilla.org/en-US/docs/Web/CSS/font-feature-settings
https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant-ligatures
*/
#text {
font-family: "Nosy";
word-wrap: break-word;
overflow-wrap: break-word;
-o-font-feature-settings: "liga" off;
-o-font-variant-ligatures: none;
-moz-font-feature-settings: "liga" off;
-moz-font-variant-ligatures: none;
-webkit-font-feature-settings: "liga" off;
-webkit-font-variant-ligatures: none;
font-feature-settings: "liga" off;
font-variant-ligatures: none;
}
#output {
font-family: "Nosy";
font-size: 50vh;
line-height: 1.75em;
letter-spacing: 0;
margin-left: 0.5ex;
-o-font-feature-settings: "liga" on;
-o-font-variant-ligatures: common-ligatures;
-moz-font-feature-settings: "liga" on;
-moz-font-variant-ligatures: common-ligatures;
-webkit-font-feature-settings: "liga" on;
-webkit-font-variant-ligatures: common-ligatures;
font-feature-settings: "liga" on;
font-variant-ligatures: common-ligatures;
}
</style>
</head>
<body>
<h1><a href="http://rrry.me/nosy/">NOSY Facetype by Rory Harnden</a></h1>
<p>All the faces you're seeing on this page are being created live by the NOSY <s>typeface</s> facetype and some slightly sneaky OpenType ligatures.</p>
<p>Find out more and download free at <a href="http://rrry.me/nosy/" >rrry.me/nosy</a> (<a href="http://www.reddit.com/r/gamedev/comments/2f9p7k/nosy_free_typeface_that_creates_characters_just/" >thread on reddit.com/r/gamedev</a>). Font by <a href="http://rrry.me/">Rory Harnden</a>, demo by <a href="http://denilson.sa.nom.br/">Denilson S&aacute;</a> (also on <a href="https://gist.github.com/denilsonsa/a518a7825e727e55b6fb">GitHub Gist</a>).</p>
<section>
<div class="column">
<form id="form_with_controls">
<div class="column">
</div>
</form>
</div>
<div class="column">
<div>
<input type="button" id="randomize_button" value="Randomize!">
<input type="button" id="disable_all_button" value="Remove all!">
</div>
<div id="text"></div>
<div id="output"></div>
</div>
</section>
<script>
var parts = [
// name, min, max, color, probability of being enabled.
['face' , 1, 1, '#f1dabf', 1.0],
['ears' , 1, 9, '#f1dabf', 0.5],
['mask' , 1, 9, '#f40e3f', 0.2],
['glassesalt', 1, 5, '#e6db94', 0.2],
['eyes' , 1, 9, '#392d2f', 1.0],
['mouth' , 1, 9, '#39d59b', 0.9],
['mouthalt' , 1, 9, '#00c9ef', 0.5],
['cheeks' , 1, 9, '#ef3527', 0.3],
['eyebrows' , 1, 9, '#422f28', 0.4],
['glasses' , 1, 5, '#b31e43', 0.2],
['hair' , 1, 9, '#422f28', 0.4],
['hat' , 1, 9, '#b31e43', 0.1],
['skin' , 1, 5, '#302238', 0.3],
['beard' , 1, 5, '#00c9ef', 0.3],
['moustache' , 1, 5, '#4ec500', 0.4],
['nose' , 1, 9, '#25b68f', 0.4]
];
function createFormControl(name, value, min, max, color) {
var container = document.createElement('div');
container.setAttribute('class', 'formcontrol feature');
container.dataset.name = name;
container.innerHTML = '<span class="draghandle" draggable="true">.</span><label><input type="checkbox" name="' + name + '_enabled" checked>' + name + '</label><input type="range" name="' + name + '_number" value="' + value + '" min="' + min + '" max="' + max + '" step="1"><input type="color" name="' + name + '_color" value="' + color + '"></div>';
return container;
}
function createAllControls() {
var form = document.getElementById('form_with_controls');
form.addEventListener('submit', function(ev) { ev.preventDefault(); });
form.addEventListener('input', update_face);
form.addEventListener('change', update_face);
var randomize_button = document.getElementById('randomize_button');
randomize_button.addEventListener('click', randomize);
var disable_all_button = document.getElementById('disable_all_button');
disable_all_button.addEventListener('click', disable_all);
parts.forEach(function(currentValue, index, arr) {
var control = createFormControl(currentValue[0], 1, currentValue[1], currentValue[2], currentValue[3]);
form.appendChild(control);
new Dragster(control);
control.addEventListener('dragover', handle_drag_over);
control.addEventListener('dragster:enter', handle_dragster_enter);
control.addEventListener('dragster:leave', handle_dragster_leave);
control.addEventListener('dragend', handle_drag_end);
control.addEventListener('drop', handle_drop);
var draghandle = control.querySelector('.draghandle');
draghandle.addEventListener('dragstart', handle_drag_start);
});
}
function randomize() {
var form = document.getElementById('form_with_controls');
parts.forEach(function(currentValue, index, arr) {
var name = currentValue[0];
form[name + '_enabled'].checked = Math.random() < currentValue[4] ? true : false;
form[name + '_number'].value = Math.floor(Math.random() * currentValue[2]) + 1;
});
update_face();
}
function disable_all() {
var form = document.getElementById('form_with_controls');
parts.forEach(function(currentValue, index, arr) {
var name = currentValue[0];
if (name == 'face') {
form[name + '_enabled'].checked = true;
} else {
form[name + '_enabled'].checked = false;
}
});
update_face();
}
function update_face() {
var form = document.getElementById('form_with_controls');
var output = document.getElementById('output');
var text = document.getElementById('text');
var controls = form.querySelectorAll('.feature');
var features = [];
[].forEach.call(controls, function(elem, index, arr) {
features.push(elem.dataset.name);
});
var output_html = '';
features.forEach(function(name, index, arr) {
if (form[name + '_enabled'].checked) {
output_html += '<span style="color: ' + form[name + '_color'].value + '">' + name.toUpperCase() + form[name + '_number'].value + '</span>';
}
});
text.innerHTML = output_html;
output.innerHTML = output_html;
}
// https://bensmithett.github.io/dragster/
// https://github.com/bensmithett/dragster
(function() {
var Dragster,
__bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
Dragster = (function() {
function Dragster(el) {
this.el = el;
this.dragleave = __bind(this.dragleave, this);
this.dragenter = __bind(this.dragenter, this);
if (this.supportsEventConstructors()) {
this.first = false;
this.second = false;
this.el.addEventListener("dragenter", this.dragenter, false);
this.el.addEventListener("dragleave", this.dragleave, false);
}
}
Dragster.prototype.dragenter = function(event) {
if (this.first) {
return this.second = true;
} else {
this.first = true;
return this.el.dispatchEvent(new CustomEvent('dragster:enter', {
bubbles: true,
cancelable: true,
detail: {
dataTransfer: event.dataTransfer
}
}));
}
};
Dragster.prototype.dragleave = function(event) {
if (this.second) {
this.second = false;
} else if (this.first) {
this.first = false;
}
if (!this.first && !this.second) {
return this.el.dispatchEvent(new CustomEvent('dragster:leave', {
bubbles: true,
cancelable: true,
detail: {
dataTransfer: event.dataTransfer
}
}));
}
};
Dragster.prototype.removeListeners = function() {
this.el.removeEventListener("dragenter", this.dragenter, false);
return this.el.removeEventListener("dragleave", this.dragleave, false);
};
Dragster.prototype.supportsEventConstructors = function() {
try {
new CustomEvent("z");
} catch (_error) {
return false;
}
return true;
};
Dragster.prototype.reset = function() {
this.first = false;
return this.second = false;
};
return Dragster;
})();
window.Dragster = Dragster;
}).call(this);
// Based on: http://jsfiddle.net/james2doyle/UEx7U/
// See also: http://www.html5rocks.com/en/tutorials/dnd/basics/
// See also: https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Drag_operations
function handle_drag_start(ev) {
var formcontrol = ev.currentTarget;
while (formcontrol && formcontrol.classList && !formcontrol.classList.contains('formcontrol')) {
formcontrol = formcontrol.parentNode;
}
if (!formcontrol.classList || !formcontrol.classList.contains('formcontrol')) {
return;
}
formcontrol.classList.add('drag-moving');
ev.dataTransfer.effectAllowed = 'move';
ev.dataTransfer.setData('text/plain', 'moving:' + formcontrol.dataset.name);
}
function handle_drag_over(ev) {
var formcontrol = ev.currentTarget;
if (!formcontrol.classList.contains('formcontrol')) {
return;
}
ev.preventDefault();
}
function handle_dragster_enter(ev) {
var formcontrol = this;
if (!formcontrol.classList.contains('formcontrol')) {
return;
}
var data = ev.detail.dataTransfer.getData('text/plain');
if (data.substr(0, 7) != 'moving:') {
return;
}
formcontrol.classList.add('drag-over');
ev.preventDefault();
}
function handle_dragster_leave(ev) {
var formcontrol = this;
if (!formcontrol.classList.contains('formcontrol')) {
return;
}
var data = ev.detail.dataTransfer.getData('text/plain');
if (data.substr(0, 7) != 'moving:') {
return;
}
formcontrol.classList.remove('drag-over');
ev.preventDefault();
}
function handle_drag_end(ev) {
var formcontrol = ev.currentTarget.classList.remove('drag-moving');
var elements = document.getElementsByClassName('drag-over');
[].forEach.call(elements, function(elem, index, arr) {
elem.classList.remove('drag-over');
});
}
function handle_drop(ev) {
var formcontrol = ev.currentTarget;
if (!formcontrol.classList.contains('formcontrol')) {
return;
}
var data = ev.dataTransfer.getData('text/plain');
if (data.substr(0, 7) != 'moving:') {
return;
}
var form = document.getElementById('form_with_controls');
var from_element = form.getElementsByClassName('drag-moving')[0];
var to_element = formcontrol;
if (from_element == to_element) {
ev.preventDefault();
return;
}
var from_index = [].indexOf.call(form.childNodes, from_element);
var to_index = [].indexOf.call(form.childNodes, to_element);
var before_this = to_element;
if (from_index < to_index) {
before_this = to_element.nextSibling;
}
form.insertBefore(from_element, before_this);
ev.preventDefault();
update_face();
}
createAllControls();
randomize();
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment