variabletime/assets/template.html
2023-09-24 18:39:52 +02:00

529 lines
28 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!doctype html>
<html lang="en-us">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link rel="icon" type="image/x-icon" href="/web/assets/vt-favicon.png">
<title>variable time</title>
<style>
html, body {
overscroll-behavior-x: none;
}
body {
font-family: helvetica, sans-serif;
margin: 0;
padding: none;
}
.emscripten { padding-right: 0; margin-left: auto; margin-right: auto; display: block; }
div.emscripten { text-align: center; }
div.emscripten_border { border: 1px solid black; }
/* the canvas *must not* have any border or padding, or mouse coords will be wrong */
canvas.emscripten { border: 0px none; outline: none; }
#logo {
display: inline-block;
margin: 20px 0 20px 20px;
}
.spinner {
height: 30px;
width: 30px;
margin: 0;
margin-top: 20px;
margin-left: 20px;
display: inline-block;
vertical-align: top;
-webkit-animation: rotation .8s linear infinite;
-moz-animation: rotation .8s linear infinite;
-o-animation: rotation .8s linear infinite;
animation: rotation 0.8s linear infinite;
border-left: 5px solid #EE3987;
border-right: 5px solid #EE3987;
border-bottom: 5px solid #EE3987;
border-top: 5px solid #CCCCCC;
border-radius: 100%;
background-color: #EEEEEE;
}
@-webkit-keyframes rotation {
from {-webkit-transform: rotate(0deg);}
to {-webkit-transform: rotate(360deg);}
}
@-moz-keyframes rotation {
from {-moz-transform: rotate(0deg);}
to {-moz-transform: rotate(360deg);}
}
@-o-keyframes rotation {
from {-o-transform: rotate(0deg);}
to {-o-transform: rotate(360deg);}
}
@keyframes rotation {
from {transform: rotate(0deg);}
to {transform: rotate(360deg);}
}
#status {
display: inline-block;
vertical-align: top;
margin-top: 30px;
margin-left: 20px;
font-weight: bold;
color: rgb(120, 120, 120);
}
#progress {
height: 20px;
width: 30px;
}
#controls {
display: inline-block;
float: right;
vertical-align: top;
margin-top: 30px;
margin-right: 20px;
}
#output {
width: 100%;
height: 200px;
margin: 0 auto;
margin-top: 10px;
display: block;
background-color: green;
color: black;
font-family: 'Lucida Console', Monaco, monospace;
outline: none;
}
#logo, .spinner, .emscripten, #controls, .emscripten, #output {
display: none;
}
canvas.emscripten {
display: block;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
#timeline {
display: none;
}
#midi_open {
display: none;
}
</style>
<link rel="stylesheet" type="text/css" href="/web/css/demo.css" />
</head>
<body id="body">
<div id="loader">
<div class="loaderChild">
<h1>loading</h1>
<p id="loader_progress_task">task</p>
<p id="loader_progress">|----------------------------------------------------------------------------------------------------|</p>
</div>
</div>
<a id="logo" href="http://emscripten.org">
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="110px" height="58px" viewBox="0 0 110 58" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>openFrameworks Logo</title>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="#000000" fill-rule="evenodd">
<path id="Oval-1" d="M58,29 C58,13 45,0 29,0 C13,0 0,13 0,29 C0,45 13,58 29,58 C45,58 58,45 58,29 Z"></path>
<rect id="Rectangle-1" x="59" y="0" width="25" height="58"></rect>
<rect id="Rectangle-2" x="85" y="26" width="15" height="15"></rect>
<path id="Path-2" d="M85,0 L110,0 L85,25 L85,0 Z"></path>
</g>
</svg>
</a>
<div class="spinner" id='spinner'></div>
<div class="emscripten" id="status">Downloading...</div>
<span id='controls'>
<span><input type="checkbox" id="resize">Resize canvas</span>
<span><input type="checkbox" id="pointerLock">Lock/hide mouse pointer &nbsp;&nbsp;&nbsp;</span>
<span><input type="button" value="Fullscreen" onclick="Module.requestFullscreen(document.getElementById('pointerLock').checked,
document.getElementById('resize').checked)">
</span>
</span>
<div class="emscripten">
<progress value="0" max="100" id="progress" hidden=1></progress>
</div>
<canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()" tabindex="-1"></canvas>
<textarea id="output" rows="8"></textarea>
<script type='text/javascript'>
var VARIABLE_TIME_VERSION = "0.0.1";
window.setLoadingTask = (task = 'loading', percent = 0, niceText = "|") => {
document.getElementById('loader_progress_task').innerHTML = task;
let innerHTML = "|";
for (let i = 0; i < 100; i++) {
if (i < percent) {
innerHTML += niceText[i % niceText.length];
} else {
innerHTML += "-";
}
}
innerHTML += "|";
let progress = document.getElementById("loader_progress");
progress.innerHTML = innerHTML;
};
window.setLoadingDone = () => {
document.getElementById('loader').style.display = 'none';
};
var statusElement = document.getElementById('status');
var progressElement = document.getElementById('progress');
var spinnerElement = document.getElementById('spinner');
var initializedModuleEvent = new Event('initializedModule');
window.moduleInitialized = false;
window.addEventListener('initializedModule', () => {
window.moduleInitialized = true;
});
var Module = {
preRun: [],
postRun: [function() {
window.dispatchEvent(initializedModuleEvent);
// NOTE: this can be used to know when to load saved sessions
}],
print: (function() {
var element = document.getElementById('output');
if (element) element.value = ''; // clear browser cache
return function(text) {
if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
// These replacements are necessary if you render to raw HTML
//text = text.replace(/&/g, "&amp;");
//text = text.replace(/</g, "&lt;");
//text = text.replace(/>/g, "&gt;");
//text = text.replace('\n', '<br>', 'g');
console.log(text);
if (element) {
element.value += text + "\n";
element.scrollTop = element.scrollHeight; // focus on bottom
}
};
})(),
printErr: function(text) {
if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
if (0) { // XXX disabled for safety typeof dump == 'function') {
dump(text + '\n'); // fast, straight to the real console
} else {
console.error(text);
}
},
canvas: (function() {
var canvas = document.getElementById('canvas');
// As a default initial behavior, pop up an alert when webgl context is lost. To make your
// application robust, you may want to override this behavior before shipping!
// See http://www.khronos.org/registry/webgl/specs/latest/1.0/#5.15.2
canvas.addEventListener("webglcontextlost", function(e) { alert('WebGL context lost. You will need to reload the page.'); e.preventDefault(); }, false);
return canvas;
})(),
setStatus: function(text) {
if (!Module.setStatus.last) Module.setStatus.last = { time: Date.now(), text: '' };
if (text === Module.setStatus.text) return;
var m = text.match(/([^(]+)\((\d+(\.\d+)?)\/(\d+)\)/);
var now = Date.now();
if (m && now - Module.setStatus.last.time < 30) return; // if this is a progress update, skip it if too soon
if (m) {
text = m[1];
progressElement.value = parseInt(m[2])*100;
progressElement.max = parseInt(m[4])*100;
progressElement.hidden = false;
spinnerElement.hidden = false;
} else {
progressElement.value = null;
progressElement.max = null;
progressElement.hidden = true;
if (!text) spinnerElement.style.display = 'none';
}
statusElement.innerHTML = text;
},
totalDependencies: 0,
monitorRunDependencies: function(left) {
this.totalDependencies = Math.max(this.totalDependencies, left);
Module.setStatus(left ? 'Preparing... (' + (this.totalDependencies-left) + '/' + this.totalDependencies + ')' : 'All downloads complete.');
}
};
Module.setStatus('Downloading...');
window.onerror = function(event) {
// TODO: do not warn on ok events like simulating an infinite loop or exitStatus
Module.setStatus('Exception thrown, see JavaScript console');
spinnerElement.style.display = 'none';
Module.setStatus = function(text) {
if (text) Module.printErr('[post-exception status] ' + text);
};
};
let isProfiling = false;
window.toggleProfiling = () => {
if (!isProfiling) {
Module.startProfiling();
isProfiling = true;
document.getElementById('debug_profiling').innerHTML = "debug end profiling";
} else {
Module.endProfiling();
isProfiling = false;
document.getElementById('debug_profiling').innerHTML = "debug start profiling";
}
};
</script>
{{{ SCRIPT }}}
<div id="content">
</div>
<div id="layer_panel" class="panel">
<!--<div class="header">-->
<!--<div class="move">move</div>-->
<!--</div>-->
<button id="midi_open">midi</button>
<button id="exporter_open">export</button>
<button id="save_project" onclick="window.tp.downloadProject()">save project</button>
<button id="open_project" onclick="window.tp.uploadProject(true)">open project</button>
<button id="start_new_project" onclick="window.tp.startNewProject()">start new project</button>
<!--<button id="debug_profiling" onclick="window.toggleProfiling()">debug start profiling</button>-->
</div>
<!-- EXPORT BEGIN -->
<div id="exporter">
<div class="exporterChild">
<p id="exporter_close">close</p>
<!--<video id="player" controls></video>-->
<div class="exporter_options_buttons">
<div id="exporter_options">
<div class="exporter_options_child">
<div class="options_cont">
<p class="options_title">Working resolution:</p>
<div class="options">
<p class="artboard_width"></p>
<p class="artboard_height"></p>
<p class="artboard_pixelDensity"></p>
</div>
</div>
<div class="options_cont">
<p class="options_title">Render options (to be adjusted):</p>
<div class="options adjustable">
<label id="artboard_scale_label" for="artboard_scale"></label>
<input type="number" id="artboard_scale" name="artboard_scale" value="1.0" min="0.01" max="8.0" step="0.01" />
<label id="render_timescale_label" for="render_timescale"></label>
<input type="number" id="render_timescale" name="render_timescale" value="1.0" min="0.01" max="8.0" step="0.01" />
</div>
</div>
<div class="options_cont">
<p class="options_title">Render output values:</p>
<div class="options">
<p class="render_width"></p>
<p class="render_height"></p>
<p class="render_pixels"></p>
<p class="render_length"></p>
</div>
</div>
</div>
<div class="exporter_dimension_warning">
<p>
The artboard is too large to render as mp4.* You can still render into a zipfile with still frames. You can convert these into a video with ffmpeg, <a href="https://support.apple.com/guide/quicktime-player/create-a-movie-with-an-image-sequence-qtp315cce984/mac">QuickTime</a> or a Video Editor of your choice.<br><br>* To render as mp4, please scale the artboard dimensions until the render dimensions do not exceed a total of 2.073.600 (1920 * 1080) pixels.
</p>
</div>
</div>
<div class="exportButtonsCont">
<button id="exporter_button_zip" onclick="window.renderFrames('zip')">render frames</button>
<button id="exporter_button_mp4" onclick="window.renderFrames('mp4')">render mp4</button>
<!--<button onclick="window.debugProfile()">debug profile</button>-->
</div>
</div>
<div id="exporter_render_info"><p>Please keep tab open while rendering</p></div>
<p id="export_progress_task">Progress:</p>
<p id="export_progress">|----------------------------------------------------------------------------------------------------|</p>
</div>
</div>
<!-- EXPORT END -->
<div id="notice">
<div class="content">
<div class="what"><p></p></div>
<div class="details"><p></p></div>
</div>
</div>
<!-- MIDI BEGIN -->
<div id="midiController">
<div class="midiMessages"></div>
<div class="inputs"></div>
<div class="outputs"></div>
<div class="buttons">
</div>
</div>
<!-- MIDI END -->
<!-- ABOUT BEGIN -->
<div class="buttons-bottom">
<!-- <div class="links">
<a class="button-overlay" href="https://gitlab.com/pointerstudio" target="_blank">
git↗</a>
<a class="button-overlay" href="https://www.instagram.com/variablelab" target="_blank">ig↗</a>
</div> -->
<div class="button-overlay about" onclick="showAbout()">
about
</div>
</div>
<div class="overlay-text-cont hidden" id="overlay-text-cont">
<div class="overlay-text">
<div class="vt-title">
variable time*
</div>
<div class="about-text">
<!-- <p>Variable Time is a tool for working with variable text in motion and states of transition.</p>
<p>It is developed by artist duo and creative coders studio Pointer*<a class="button-overlay link-in-text first-link" href="https://pointer.click" target="_blank">web↗</a><a class="button-overlay link-in-text" href="https://instagram.com/pointer_studio" target="_blank">ig↗</a> in collaboration with type designer Céline Hurka<a class="button-overlay link-in-text first-link" href="https://celine-hurka.com" target="_blank">web↗</a><a class="button-overlay link-in-text" href="https://www.instagram.com/celinehurka" target="_blank">ig↗</a>. Variable Time is a personal project, which is a part of Variable Lab<a class="button-overlay link-in-text first-link" href="https://variablelab.pointer.click" target="_blank">web↗</a><a class="button-overlay link-in-text" href="https://www.instagram.com/variablelab" target="_blank">ig↗</a> - a series of technical, typographic, visual and theoretical exchanges between studio Pointer*, Celine Hurka and their various collaborators. The toolset of Variable Time will be growing with new experimental features alongside their ongoing research.</p> -->
<div class="textParent aboutParent">
<p>Variable Time is an open-source tool for working with typography in motion and states of transition.</p>
<p>It is developed by artist duo and creative coders studio Pointer<a class="button-overlay link-in-text first-link" href="https://pointer.click" target="_blank">WEB↗</a><a class="button-overlay link-in-text" href="https://instagram.com/pointer_studio" target="_blank">IG↗</a>in collaboration with type designer Céline Hurka<a class="button-overlay link-in-text first-link" href="https://celine-hurka.com" target="_blank">WEB↗</a><a class="button-overlay link-in-text" href="https://www.instagram.com/celinehurka" target="_blank">IG↗</a>. Variable Time is an ongoing personal exploration, driven by their fascination with variable font formats and their potential impact on the future of verbal and non-verbal communication. This tool is one of the first and foundational projects of Variable Lab<a class="button-overlay link-in-text first-link" href="https://variablelab.pointer.click" target="_blank">WEB↗</a><a class="button-overlay link-in-text" href="https://www.instagram.com/variablelab" target="_blank">IG↗</a> a series of technical, typographic, visual and theoretical exchanges between studio Pointer and Céline Hurka. The Variable Time toolkit is designed to evolve in parallel with their ongoing research, continuously expanding with new experimental controls and features.</p>
</div>
<div class="textParent toExtend">
<h4>Current Version <button class="expandText">+</button></h4>
<div class="expanded">
<p>This is the first released version of Variable Time. It is an ongoing project for which we have many future plans and improvements.</p>
<p>Due to the way we approached font rendering, a lot of seemingly standard functionalities had to be rebuild from scratch. This gives us a lot of freedom and offers new ways in which we can approach working with typography, however it also means that some things might take longer to develop.</p>
<p>The current version of the tool only supports a basic Latin character set - so A-Z, 1-9 and punctuation. Extending it with other languages and alternates is on our priority list as well and will hopefully be possible in the upcoming versions.</p>
<p>Kerning. There are multiple ways of storing and reading Kerning tables, and we currently only support one of them. Supporting more sophisticated kerning is also on our priority list.</p>
<p>Apart from that we have exciting plans for the toolkit of Variable Time. Among other things, we are already working on addons that would allow controlling parameters with sound, recording changes live and linking sequences to more types of automated inputs.</p>
</div>
</div>
<div class="instructions">
<!-- <h4>How to use - (extremely) brief intro: </h4> -->
<div class="textParent toExtend">
<h4>Layers <button class="expandText">+</button></h4>
<div class="expanded">
<p>Variable Time allows to design and export time-based typography with an unlimited amount of layers. You can create, remove, duplicate and select layers through the overview panel in the left top corner. </p>
<video muted autoplay controls=0 loop>
<source src="/web/assets/addlayer.mp4" type="video/mp4">
<p>This is fallback content to display for user agents that do not support the video tag.</p>
</video>
</div>
</div>
<div class="textParent toExtend">
<h4>Panel <button class="expandText">+</button></h4>
<div class="expanded">
<p>The panel of Variable Time consists of a number of modifiable parameters. You can adjust these parameters per layer. You can also change the settings of an artboard through the panel if artboard is selected.</p>
<video muted autoplay controls=0 loop>
<source src="/web/assets/props.mp4" type="video/mp4">
<p>This is fallback content to display for user agents that do not support the video tag.</p>
</video>
</div>
</div>
<div class="textParent toExtend">
<h4>Sequence <button class="expandText">+</button></h4>
<div class="expanded">
<p>You can create a new sequence per each modifiable parameter in the panel by clicking on the keyframe (diamond) button on its left. This will create an empty sequence. For adding a keyframe, drag the time indicator to the right place and click on the same keyframe button again.</p>
<video muted autoplay controls=0 loop>
<source src="/web/assets/sequenceprop.mp4" type="video/mp4">
<p>This is fallback content to display for user agents that do not support the video tag.</p>
</video>
<video muted autoplay controls=0 loop>
<source src="/web/assets/addkeyframes.mp4" type="video/mp4">
<p>This is fallback content to display for user agents that do not support the video tag.</p>
</video>
<p>
You can change the duration of a sequence by dragging its right edge in the sequence panel.</p>
<video muted autoplay controls=0 loop>
<source src="/web/assets/changeduration.mp4" type="video/mp4">
<p>This is fallback content to display for user agents that do not support the video tag.</p>
</video>
<p>Selecting multiple keyframes is possible by pressing and holding SHIFT key and dragging the mouse over the keyframes.</p>
<video muted autoplay controls=0 loop>
<source src="/web/assets/selectkeyframes.mp4" type="video/mp4">
<p>This is fallback content to display for user agents that do not support the video tag.</p>
</video>
<p>The easing style can be seen by clicking on the curves button next to the name of sequenced parameter. You can select different easing functions by selecting keyframes and clicking on the timeline in-between them.</p>
<video muted autoplay controls=0 loop>
<source src="/web/assets/showeasing.mp4" type="video/mp4">
<p>This is fallback content to display for user agents that do not support the video tag.</p>
</video>
<video muted autoplay controls=0 loop>
<source src="/web/assets/changeeasing.mp4" type="video/mp4">
<p>This is fallback content to display for user agents that do not support the video tag.</p>
</video>
</div>
</div>
<div class="textParent toExtend">
<h4>Letter Delays <button class="expandText">+</button></h4>
<div class="expanded">
<p>When a parameter is sequenced, a new feature appears in the panel - letter delays. This feature applies animations to each letter with a given delay time. The delay time can differ per each animated parameter.</p>
<video muted autoplay controls=0 loop>
<source src="/web/assets/letter-delays.mp4" type="video/mp4">
<p>This is fallback content to display for user agents that do not support the video tag.</p>
</video>
</div>
</div>
<div class="textParent toExtend">
<h4>Export <button class="expandText">+</button></h4>
<div class="expanded">
<p>Variable Time allows exporting video in mp4 format and static frames. At this step it is also possible to scale the output file resolution and apply time stretch - so make your output speed slower or faster proportionally.*</p>
<p class="note">* Please keep in mind that rendering in mp4 has limits in resolution, however there is (almost) no limit in rendering frames (which you can easily convert to video with the help of various external tools).</p>
</div>
</div>
</div>
<div class="textParent toExtend">
<h4>Typefaces <button class="expandText">+</button></h4>
<div class="expanded">
<p>Variable Time features experimental variable fonts designed by Céline Hurka<a class="button-overlay link-in-text first-link" href="https://celine-hurka.com" target="_blank">WEB↗</a><a class="button-overlay link-in-text" href="https://www.instagram.com/celinehurka" target="_blank">IG↗</a> and Jacob Wise<a class="button-overlay link-in-text first-link" href="https://wisetype.nl" target="_blank">WEB↗</a><a class="button-overlay link-in-text first-link" href="https://www.instagram.com/wise_type" target="_blank">IG↗</a>. These typefaces can be used freely to explore the tool or to be used for personal non-commercial projects made with the tool. If you want to use them for commercial or client work, or if you are not sure if your case applies, please reach out to Céline Hurka and/or Jacob Wise to discuss the possibilities. </p>
<p>Currently, Tonka, the Version collection and Zaft2 are included. Tonka is available on celine-hurka.com<a class="button-overlay link-in-text first-link" href="https://celine-hurka.com/tonka/" target="_blank">WEB↗</a>. Version is Céline Hurkas Type and Media graduation project and has not been published anywhere else yet. Zaft2 is a collaborative project by Céline Hurka and Jacob Wise and is available on wisetype.nl<a class="button-overlay link-in-text first-link" href="https://wisetype.nl/collections/wt-zaft-2" target="_blank">WEB↗</a> since 2021.</p>
</div>
</div>
<div class="textParent toExtend">
<h4>Used frameworks <button class="expandText">+</button></h4>
<div class="expanded">
<p>Variable Time is built up on other open source libraries, such as openFrameworks<a class="button-overlay link-in-text first-link" href="https://www.openframeworks.cc/" target="_blank">WEB↗</a>, FreeType<a class="button-overlay link-in-text first-link" href="https://www.freetype.org/" target="_blank">WEB↗</a>, Theatre.js<a class="button-overlay link-in-text first-link" href="https://www.theatrejs.com/" target="_blank">WEB↗</a>, FFmpeg<a class="button-overlay link-in-text first-link" href="https://www.ffmpeg.org/" target="_blank">WEB↗</a> and more. For a detailed list, please visit the Variable Time source code.</p>
</div>
</div>
<!-- <div class="textParent toExtend">
<h4>Donate <button class="expandText">+</button></h4>
<div class="expanded">
<p>Variable Time is completely free of charge and brings us no commercial profit. A donation of any size would help us to dedicate more time and effort to expanding its toolkit and fixing bugs. ❤️ </p>
<a class="button-overlay" href="https://www.freetype.org/" target="_blank">DONATE↗</a>
</div>
</div> -->
</div>
<div class="button-overlay button-close" onclick="hideAbout()">
close
</div>
<div class="links">
<a class="button-overlay" href="https://gitlab.com/pointerstudio" target="_blank">
git↗</a>
<a class="button-overlay" href="https://www.instagram.com/variablelab" target="_blank">ig↗</a>
<a class="button-overlay" href="mailto:variabletime@pointer.click" target="_blank">EMAIL↗</a>
</div>
<div class="logos">
<p class="contact_us">
We would be excited to see what you make with Variable Time! Feel free to share your visuals with us via <a class="button-overlay link-in-text first-link" href="mailto:variabletime@pointer.click" target="_blank">EMAIL↗</a><br>
</p>
<p>This project is made possible thanks to support from Stimuleringsfonds</p>
<img src="/web/assets/SCI_Woordbeeld_EN_3_regels_RGB.gif" />
</div>
</div>
</div>
<!-- ABOUT END -->
<div id="timeline"><div id="timeline_head"></div><div>
<!-- EXPORT BEGIN -->
<script id="ffmpeg.min.js" type="application/javascript" src="/web/ffmpeg_modules/ffmpeg.min.js"></script>
<!-- EXPORT END -->
<script type="module" src="/web/js/main.js"> </script>
</body>
</html>