mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-18 16:27:34 +01:00
[ion/simulator/web] Use a shared layout.json file
This commit is contained in:
61
ion/src/simulator/shared/layout.json
Normal file
61
ion/src/simulator/shared/layout.json
Normal file
@@ -0,0 +1,61 @@
|
||||
{
|
||||
"background": [0, 0, 1160, 2220],
|
||||
"screen": [192, 191, 776, 582],
|
||||
"keys": {
|
||||
"0": [133, 983, 140, 87],
|
||||
"1": [231, 886, 87, 140],
|
||||
"2": [231, 1026, 87, 140],
|
||||
"3": [275, 983, 140, 87],
|
||||
|
||||
"4": [745, 963, 129, 129],
|
||||
"5": [898, 963, 129, 129],
|
||||
|
||||
"6": [502, 908, 156, 101],
|
||||
"7": [502, 1044, 156, 101],
|
||||
|
||||
"12": [133, 1210, 129, 87],
|
||||
"13": [286, 1210, 129, 87],
|
||||
"14": [439, 1210, 129, 87],
|
||||
"15": [592, 1210, 129, 87],
|
||||
"16": [745, 1210, 129, 87],
|
||||
"17": [898, 1210, 129, 87],
|
||||
|
||||
"18": [133, 1332, 129, 87],
|
||||
"19": [286, 1332, 129, 87],
|
||||
"20": [439, 1332, 129, 87],
|
||||
"21": [592, 1332, 129, 87],
|
||||
"22": [745, 1332, 129, 87],
|
||||
"23": [898, 1332, 129, 87],
|
||||
|
||||
"24": [133, 1455, 129, 87],
|
||||
"25": [286, 1455, 129, 87],
|
||||
"26": [439, 1455, 129, 87],
|
||||
"27": [592, 1455, 129, 87],
|
||||
"28": [745, 1455, 129, 87],
|
||||
"29": [898, 1455, 129, 87],
|
||||
|
||||
"30": [133, 1578, 156, 101],
|
||||
"31": [317, 1578, 156, 101],
|
||||
"32": [502, 1578, 156, 101],
|
||||
"33": [686, 1578, 156, 101],
|
||||
"34": [871, 1578, 156, 101],
|
||||
|
||||
"36": [133, 1715, 156, 101],
|
||||
"37": [317, 1715, 156, 101],
|
||||
"38": [502, 1715, 156, 101],
|
||||
"39": [686, 1715, 156, 101],
|
||||
"40": [871, 1715, 156, 101],
|
||||
|
||||
"42": [133, 1851, 156, 101],
|
||||
"43": [317, 1851, 156, 101],
|
||||
"44": [502, 1851, 156, 101],
|
||||
"45": [686, 1851, 156, 101],
|
||||
"46": [871, 1851, 156, 101],
|
||||
|
||||
"48": [133, 1988, 156, 101],
|
||||
"49": [317, 1988, 156, 101],
|
||||
"50": [502, 1988, 156, 101],
|
||||
"51": [686, 1988, 156, 101],
|
||||
"52": [871, 1988, 156, 101]
|
||||
}
|
||||
}
|
||||
@@ -36,6 +36,12 @@ endif
|
||||
|
||||
DEFAULT = epsilon.zip
|
||||
|
||||
$(addprefix $(BUILD_DIR)/ion/src/simulator/web/,calculator.html calculator.css): ion/src/simulator/shared/layout.json
|
||||
$(call rule_label,LAYOUT)
|
||||
$(Q) $(PYTHON) ion/src/simulator/web/layout.py --html $(BUILD_DIR)/ion/src/simulator/web/calculator.html --css $(BUILD_DIR)/ion/src/simulator/web/calculator.css $<
|
||||
|
||||
$(BUILD_DIR)/ion/src/simulator/web/simulator.html: $(addprefix $(BUILD_DIR)/ion/src/simulator/web/,calculator.html calculator.css)
|
||||
|
||||
$(BUILD_DIR)/epsilon%zip: $(BUILD_DIR)/epsilon%js $(BUILD_DIR)/ion/src/simulator/web/simulator.html
|
||||
@rm -rf $(basename $@)
|
||||
@mkdir -p $(basename $@)
|
||||
|
||||
98
ion/src/simulator/web/layout.py
Normal file
98
ion/src/simulator/web/layout.py
Normal file
@@ -0,0 +1,98 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import argparse
|
||||
import json
|
||||
|
||||
def css_rule(selector, *declarations):
|
||||
css = ''
|
||||
css += selector + ' {\n'
|
||||
for decl in declarations:
|
||||
css += decl
|
||||
css += '}\n\n'
|
||||
return css
|
||||
|
||||
def css_declaration(prop, value):
|
||||
return " %s: %s;\n" % (prop, value)
|
||||
|
||||
def css_percentage_declaration(prop, ratio):
|
||||
return css_declaration(prop, "%.2f%%" % (100*ratio))
|
||||
|
||||
def css_rect_declarations(rect, ref):
|
||||
css = ''
|
||||
css += css_percentage_declaration("left", rect[0]/ref[2])
|
||||
css += css_percentage_declaration("top", rect[1]/ref[3])
|
||||
css += css_percentage_declaration("width", rect[2]/ref[2])
|
||||
css += css_percentage_declaration("height", rect[3]/ref[3])
|
||||
return css
|
||||
|
||||
def css(layout):
|
||||
background = layout["background"]
|
||||
css = ''
|
||||
css += css_rule(
|
||||
'.calculator',
|
||||
css_declaration('position', 'relative'),
|
||||
)
|
||||
css += css_rule(
|
||||
'.calculator-aspect-ratio',
|
||||
css_percentage_declaration('padding-bottom', background[3]/background[2])
|
||||
)
|
||||
css += css_rule(
|
||||
'.calculator canvas',
|
||||
css_declaration('position', 'absolute'),
|
||||
css_rect_declarations(layout['screen'], background)
|
||||
)
|
||||
css += css_rule(
|
||||
'.calculator span',
|
||||
css_declaration('position', 'absolute'),
|
||||
css_declaration('display', 'block'),
|
||||
css_declaration('border-radius', '999px'),
|
||||
css_declaration('cursor', 'pointer'),
|
||||
)
|
||||
css += css_rule(
|
||||
'.calculator span:hover',
|
||||
css_declaration('background-color', 'rgba(0, 0, 0, 0.1)')
|
||||
)
|
||||
css += css_rule(
|
||||
'.calculator span:active',
|
||||
css_declaration('background-color', 'rgba(0, 0, 0, 0.2)')
|
||||
)
|
||||
for key,rect in layout["keys"].items():
|
||||
css += css_rule(
|
||||
'.calculator span[data-key="%s"]' % key,
|
||||
css_rect_declarations(rect, background)
|
||||
)
|
||||
css += css_rule(
|
||||
'.calculator-mirror canvas',
|
||||
css_declaration('image-rendering', '-moz-crisp-edges'),
|
||||
css_declaration('image-rendering', 'pixelated'),
|
||||
css_declaration('-ms-interpolation-mode', 'nearest-neighbor')
|
||||
)
|
||||
return css
|
||||
|
||||
def html(layout):
|
||||
screen = layout["screen"]
|
||||
background = layout["background"]
|
||||
html = ''
|
||||
html += '<div class="calculator">\n'
|
||||
html += ' <canvas tabindex="1"></canvas>\n'
|
||||
for key in layout["keys"]:
|
||||
html += ' <span data-key="%s"></span>\n' % key
|
||||
html += '</div>'
|
||||
return html
|
||||
|
||||
# Argument parsing
|
||||
|
||||
parser = argparse.ArgumentParser(description='Generate HTML and CSS files from JSON layout')
|
||||
parser.add_argument('file', type=str, help='a JSON layout file')
|
||||
parser.add_argument('--css', type=str, help='an output HTML file')
|
||||
parser.add_argument('--html', type=str, help='an output CSS file')
|
||||
args = parser.parse_args()
|
||||
|
||||
with open(args.file) as f:
|
||||
layout = json.load(f)
|
||||
if args.css:
|
||||
with open(args.css, 'w') as o:
|
||||
o.write(css(layout))
|
||||
if args.html:
|
||||
with open(args.html, 'w') as o:
|
||||
o.write(html(layout))
|
||||
@@ -1,54 +0,0 @@
|
||||
<div id="keyboard">
|
||||
<div class="nav">
|
||||
<span class="left" data-key="0"></span>
|
||||
<span class="top" data-key="1"></span>
|
||||
<span class="bottom" data-key="2"></span>
|
||||
<span class="right" data-key="3"></span>
|
||||
<span class="ok" data-key="4"></span>
|
||||
<span class="back" data-key="5"></span>
|
||||
<span class="home" data-key="6"></span>
|
||||
<span class="power" data-key="7"></span>
|
||||
</div>
|
||||
<div class="functions">
|
||||
<span data-key="12"></span>
|
||||
<span data-key="13"></span>
|
||||
<span data-key="14"></span>
|
||||
<span data-key="15"></span>
|
||||
<span data-key="16"></span>
|
||||
<span data-key="17"></span>
|
||||
<span data-key="18"></span>
|
||||
<span data-key="19"></span>
|
||||
<span data-key="20"></span>
|
||||
<span data-key="21"></span>
|
||||
<span data-key="22"></span>
|
||||
<span data-key="23"></span>
|
||||
<span data-key="24"></span>
|
||||
<span data-key="25"></span>
|
||||
<span data-key="26"></span>
|
||||
<span data-key="27"></span>
|
||||
<span data-key="28"></span>
|
||||
<span data-key="29"></span>
|
||||
</div>
|
||||
<div class="digits">
|
||||
<span data-key="30"></span>
|
||||
<span data-key="31"></span>
|
||||
<span data-key="32"></span>
|
||||
<span data-key="33"></span>
|
||||
<span data-key="34"></span>
|
||||
<span data-key="36"></span>
|
||||
<span data-key="37"></span>
|
||||
<span data-key="38"></span>
|
||||
<span data-key="39"></span>
|
||||
<span data-key="40"></span>
|
||||
<span data-key="42"></span>
|
||||
<span data-key="43"></span>
|
||||
<span data-key="44"></span>
|
||||
<span data-key="45"></span>
|
||||
<span data-key="46"></span>
|
||||
<span data-key="48"></span>
|
||||
<span data-key="49"></span>
|
||||
<span data-key="50"></span>
|
||||
<span data-key="51"></span>
|
||||
<span data-key="52"></span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,43 +1,75 @@
|
||||
/* To use this file you should adhere to the following conventions:
|
||||
* - Main canvas has id #canvas
|
||||
* - Secondary canvas (fullscreen on the side) has id #secondary-canvas
|
||||
* - Calculator keyboard has id #keyboard */
|
||||
function EpsilonSetup(emModule) {
|
||||
/* emModule is an optional parameter.
|
||||
* In addition to the ones supported by Emscripten, here are the values that
|
||||
* this object can have:
|
||||
* - calculator: a DOM element containing a copy of 'calculator.html' as
|
||||
* generated by 'layout.py'
|
||||
* - mirrorCanvas: a DOM element where the main canvas will be mirrored
|
||||
*/
|
||||
|
||||
var Module;
|
||||
|
||||
(function () {
|
||||
var mainCanvas = document.getElementById('canvas');
|
||||
var secondaryCanvasContext = document.getElementById('secondary-canvas').getContext('2d');
|
||||
var epsilonLanguage = document.documentElement.lang || window.navigator.language.split('-')[0];
|
||||
Module = {
|
||||
// Configure emModule
|
||||
var emModule = (typeof emModule === 'undefined') ? {} : emModule;
|
||||
var calculator = emModule.calculator || document.querySelector('.calculator');
|
||||
var mainCanvas = calculator.querySelector("canvas");
|
||||
if (typeof emModule.mirrorCanvas === 'undefined') {
|
||||
/* If emModule.mirrorCanvas is defined as null, don't do anything */
|
||||
emModule.mirrorCanvas = document.querySelector('.calculator-mirror canvas');
|
||||
}
|
||||
var mirrorCanvasContext = emModule.mirrorCanvas ? emModule.mirrorCanvas.getContext('2d') : null;
|
||||
var defaultModule = {
|
||||
canvas: mainCanvas,
|
||||
arguments: ['--language', epsilonLanguage],
|
||||
onDisplayRefresh: function() {
|
||||
secondaryCanvasContext.drawImage(mainCanvas, 0, 0);
|
||||
arguments: [
|
||||
'--language',
|
||||
document.documentElement.lang || window.navigator.language.split('-')[0]
|
||||
],
|
||||
downloadScreenshot: function() {
|
||||
// toDataURL needs the canvas to be refreshed
|
||||
this._IonDisplayForceRefresh();
|
||||
var link = document.createElement('a');
|
||||
link.download = 'screenshot.png';
|
||||
link.href = mainCanvas.toDataURL('image/png').replace('image/png', 'image/octet-stream');
|
||||
link.click();
|
||||
}
|
||||
};
|
||||
if (mirrorCanvasContext) {
|
||||
defaultModule.onDisplayRefresh = function() {
|
||||
mirrorCanvasContext.drawImage(mainCanvas, 0, 0);
|
||||
}
|
||||
}
|
||||
for (var attrname in defaultModule) {
|
||||
if (!emModule.hasOwnProperty(attrname)) {
|
||||
emModule[attrname] = defaultModule[attrname];
|
||||
}
|
||||
}
|
||||
|
||||
Epsilon(Module);
|
||||
// Load and run Epsilon
|
||||
Epsilon(emModule);
|
||||
|
||||
document.querySelectorAll('#keyboard span').forEach(function(span){
|
||||
function eventHandler(keyHandler) {
|
||||
return function(ev) {
|
||||
var key = this.getAttribute('data-key');
|
||||
keyHandler(key);
|
||||
/* Always prevent default action of event.
|
||||
* First, this will prevent the browser from delaying that event. Indeed
|
||||
* the browser would otherwise try to see if that event could have any
|
||||
* other meaning (e.g. a click) and might delay it as a result.
|
||||
* Second, this prevents touch events to be handled twice. Indeed, for
|
||||
* backward compatibility reasons, mobile browsers usually create a fake
|
||||
* mouse event after each real touch event. This allows desktop websites
|
||||
* to work unmodified on mobile devices. But here we are explicitly
|
||||
* handling both touch and mouse events. We therefore need to disable
|
||||
* the default action of touch events, otherwise the handler would get
|
||||
* called twice. */
|
||||
ev.preventDefault();
|
||||
};
|
||||
}
|
||||
/* Install event handlers
|
||||
* This needs to be done after loading Epsilon, otherwise the _IonSimulator*
|
||||
* functions haven't been defined just yet. */
|
||||
function eventHandler(keyHandler) {
|
||||
return function(ev) {
|
||||
var key = this.getAttribute('data-key');
|
||||
keyHandler(key);
|
||||
/* Always prevent default action of event.
|
||||
* First, this will prevent the browser from delaying that event. Indeed
|
||||
* the browser would otherwise try to see if that event could have any
|
||||
* other meaning (e.g. a click) and might delay it as a result.
|
||||
* Second, this prevents touch events to be handled twice. Indeed, for
|
||||
* backward compatibility reasons, mobile browsers usually create a fake
|
||||
* mouse event after each real touch event. This allows desktop websites
|
||||
* to work unmodified on mobile devices. But here we are explicitly
|
||||
* handling both touch and mouse events. We therefore need to disable
|
||||
* the default action of touch events, otherwise the handler would get
|
||||
* called twice. */
|
||||
ev.preventDefault();
|
||||
};
|
||||
}
|
||||
var downHandler = eventHandler(emModule._IonSimulatorKeyboardKeyDown);
|
||||
var upHandler = eventHandler(emModule._IonSimulatorKeyboardKeyUp);
|
||||
|
||||
calculator.querySelectorAll('span').forEach(function(span){
|
||||
/* We decide to hook both to touch and mouse events
|
||||
* On most mobile browsers, mouse events are generated if addition to touch
|
||||
* events, so this could seem pointless. But those mouse events are not
|
||||
@@ -45,21 +77,14 @@ var Module;
|
||||
* in a very rapid sequence. This prevents Epsilon from generating an event
|
||||
* since this quick sequence will trigger the debouncer. */
|
||||
['touchstart', 'mousedown'].forEach(function(type){
|
||||
span.addEventListener(type, eventHandler(Module._IonSimulatorKeyboardKeyDown));
|
||||
span.addEventListener(type, downHandler);
|
||||
});
|
||||
['touchend', 'mouseup'].forEach(function(type){
|
||||
span.addEventListener(type, eventHandler(Module._IonSimulatorKeyboardKeyUp));
|
||||
span.addEventListener(type, upHandler);
|
||||
});
|
||||
});
|
||||
}());
|
||||
|
||||
function screenshot() {
|
||||
// toDataURL needs the canvas to be refreshed
|
||||
Module._IonDisplayForceRefresh();
|
||||
|
||||
var canvas = document.getElementById('canvas');
|
||||
var link = document.createElement('a');
|
||||
link.download = 'screenshot.png';
|
||||
link.href = canvas.toDataURL('image/png').replace('image/png', 'image/octet-stream');
|
||||
link.click();
|
||||
}
|
||||
|
||||
if (typeof exports === 'object' && typeof module === 'object') {
|
||||
module.exports = EpsilonSetup;
|
||||
}
|
||||
|
||||
80
ion/src/simulator/web/simulator.css
Normal file
80
ion/src/simulator/web/simulator.css
Normal file
@@ -0,0 +1,80 @@
|
||||
body {
|
||||
background: #C2C2C2;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.col-fullscreen {
|
||||
display: none;
|
||||
width: 60%;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.col-fullscreen canvas {
|
||||
margin-top: 7%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
body.fullscreen .col-fullscreen {
|
||||
display: block;
|
||||
}
|
||||
|
||||
body.fullscreen .col-calculator {
|
||||
width: 35%;
|
||||
float: left;
|
||||
}
|
||||
|
||||
a.action {
|
||||
display: block;
|
||||
width: 4%;
|
||||
padding: 1.5% 3%;
|
||||
border: 1px solid black;
|
||||
border-radius: 100px;
|
||||
cursor: pointer;
|
||||
opacity: 0.65;
|
||||
}
|
||||
|
||||
a.action:hover {
|
||||
opacity: 1.0;
|
||||
background-color: rgba(0,0,0,0.125);
|
||||
}
|
||||
|
||||
a.action svg {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.calculator-container {
|
||||
margin: 0 auto;
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
text-align: left;
|
||||
}
|
||||
.calculator-container > img {
|
||||
/* Rely on the img content to set the dimensions */
|
||||
max-height: 92.0vh;
|
||||
max-width: 100%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.calculator {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.calculator-container .actions {
|
||||
position: absolute;
|
||||
top: 94.0vh;
|
||||
text-align: center;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin-left: 20px; /* Center the buttons - compensate the 10px margin below */
|
||||
}
|
||||
|
||||
.calculator-container .actions a {
|
||||
display: inline-block;
|
||||
margin-right: 10px;
|
||||
}
|
||||
@@ -1,5 +1,3 @@
|
||||
#define KEYBOARD #keyboard
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
@@ -7,178 +5,17 @@
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>NumWorks graphing calculator</title>
|
||||
<style>
|
||||
body {
|
||||
background: #C2C2C2;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.col-fullscreen {
|
||||
display: none;
|
||||
width: 60%;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.col-fullscreen canvas {
|
||||
margin-top: 7%;
|
||||
width: 100%;
|
||||
image-rendering: -moz-crisp-edges;
|
||||
image-rendering: pixelated;
|
||||
-ms-interpolation-mode: nearest-neighbor;
|
||||
}
|
||||
|
||||
body.fullscreen .col-fullscreen {
|
||||
display: block;
|
||||
}
|
||||
|
||||
body.fullscreen .col-calculator {
|
||||
width: 35%;
|
||||
float: left;
|
||||
}
|
||||
|
||||
a.action {
|
||||
display: block;
|
||||
width: 4%;
|
||||
padding: 1.5% 3%;
|
||||
border: 1px solid black;
|
||||
border-radius: 100px;
|
||||
cursor: pointer;
|
||||
opacity: 0.65;
|
||||
}
|
||||
|
||||
a.action:hover {
|
||||
opacity: 1.0;
|
||||
background-color: rgba(0,0,0,0.125);
|
||||
}
|
||||
|
||||
a.action svg {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.calculator {
|
||||
margin: 0 auto;
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
text-align: left; }
|
||||
.calculator > img {
|
||||
/* Rely on the img content to set the dimensions */
|
||||
max-height: 92.0vh;
|
||||
max-width: 100%;
|
||||
display: block; }
|
||||
.calculator #canvas {
|
||||
position: absolute;
|
||||
top: 8.5%;
|
||||
left: 16.25%;
|
||||
width: 67.5%;
|
||||
height: 26.3%;
|
||||
border: 0 none; }
|
||||
.calculator .actions {
|
||||
position: absolute;
|
||||
top: 94.0vh;
|
||||
text-align: center;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin-left: 20px; /* Center the buttons - compensate the 10px margin below */
|
||||
}
|
||||
.calculator .actions a {
|
||||
display: inline-block;
|
||||
margin-right: 10px;
|
||||
}
|
||||
KEYBOARD {
|
||||
position: absolute;
|
||||
top: 38.5%;
|
||||
left: 10%;
|
||||
width: 81%;
|
||||
bottom: 5%; }
|
||||
KEYBOARD span {
|
||||
cursor: pointer;
|
||||
border-radius: 40%;
|
||||
display: block;
|
||||
float: left; }
|
||||
KEYBOARD span:hover {
|
||||
background-color: rgba(0, 0, 0, 0.1); }
|
||||
KEYBOARD span:active {
|
||||
background-color: rgba(0, 0, 0, 0.2); }
|
||||
KEYBOARD .nav {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
height: 27%;
|
||||
width: 100%; }
|
||||
KEYBOARD .nav span {
|
||||
position: absolute; }
|
||||
KEYBOARD .nav .left {
|
||||
top: 37%;
|
||||
left: 2%;
|
||||
width: 15%;
|
||||
height: 28%; }
|
||||
KEYBOARD .nav .right {
|
||||
top: 37%;
|
||||
left: 17%;
|
||||
width: 15%;
|
||||
height: 28%; }
|
||||
KEYBOARD .nav .top {
|
||||
top: 9%;
|
||||
left: 12%;
|
||||
width: 10%;
|
||||
height: 40%; }
|
||||
KEYBOARD .nav .bottom {
|
||||
top: 53%;
|
||||
left: 12%;
|
||||
width: 10%;
|
||||
height: 40%; }
|
||||
KEYBOARD .nav .home {
|
||||
top: 15%;
|
||||
left: 41%;
|
||||
width: 16.5%;
|
||||
height: 31%; }
|
||||
KEYBOARD .nav .power {
|
||||
top: 55.4%;
|
||||
left: 41%;
|
||||
width: 16.5%;
|
||||
height: 31%; }
|
||||
KEYBOARD .nav .ok {
|
||||
top: 31%;
|
||||
left: 67%;
|
||||
width: 13.5%;
|
||||
height: 38%;
|
||||
border-radius: 48%; }
|
||||
KEYBOARD .nav .back {
|
||||
top: 31%;
|
||||
left: 83.3%;
|
||||
width: 13.5%;
|
||||
height: 38%;
|
||||
border-radius: 48%; }
|
||||
KEYBOARD .functions {
|
||||
position: absolute;
|
||||
top: 26.75%;
|
||||
left: 0.5%;
|
||||
width: 98%; }
|
||||
KEYBOARD .functions span {
|
||||
margin: 1.7% 1%;
|
||||
width: 14.65%;
|
||||
height: 0;
|
||||
padding-top: 10%; }
|
||||
KEYBOARD .digits {
|
||||
position: absolute;
|
||||
top: 56.5%;
|
||||
left: 0.5%;
|
||||
width: 98%; }
|
||||
KEYBOARD .digits span {
|
||||
margin: 1.8% 2%;
|
||||
width: 16%;
|
||||
height: 0;
|
||||
padding-top: 11.3%; }
|
||||
</style>
|
||||
<style>
|
||||
#include "calculator.css"
|
||||
#include "simulator.css"
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="row">
|
||||
<div class="col-calculator">
|
||||
<div class="calculator">
|
||||
<div class="calculator-container">
|
||||
<img src="background.jpg" alt="NumWorks Calculator">
|
||||
<canvas id="canvas" oncontextmenu="event.preventDefault()"></canvas>
|
||||
#include "simulator-keyboard.html"
|
||||
#include "calculator.html"
|
||||
<div class="actions">
|
||||
<a id="action-fullscreen" class="action">
|
||||
<svg viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"><g fill="#434343"><path d="M5.075,6.95 L6.918,5.088 L3.938,2.062 L5.955,0.018 L0.052,0.018 L0.052,6.004 L2.098,3.928 L5.075,6.95 Z" class="si-glyph-fill"></path><path d="M16.0034788,9.916 L13.832,12.013 L10.799,8.96 L8.918,10.841 L11.957,13.897 L9.961,15.9813842 L16.0034788,15.9813842 L16.0034788,9.916 Z"></path></g></g></svg>
|
||||
@@ -189,13 +26,15 @@ a.action svg {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-fullscreen">
|
||||
<canvas id="secondary-canvas" width="320" height="240"></canvas>
|
||||
<div class="col-fullscreen calculator-mirror">
|
||||
<canvas width="320" height="240"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
<script src="epsilon.js"></script>
|
||||
<script>
|
||||
#include "simulator-setup.js"
|
||||
var Module = {};
|
||||
EpsilonSetup(Module);
|
||||
</script>
|
||||
<script>
|
||||
document.getElementById("action-fullscreen").addEventListener("click", function(e){
|
||||
@@ -207,7 +46,7 @@ document.getElementById("action-fullscreen").addEventListener("click", function(
|
||||
});
|
||||
|
||||
document.getElementById("action-screenshot").addEventListener("click", function(e) {
|
||||
screenshot();
|
||||
Module.downloadScreenshot();
|
||||
});
|
||||
</script>
|
||||
<script async src="https://www.numworks.com/simulator/update.js"></script>
|
||||
|
||||
Reference in New Issue
Block a user