<button id="erase" tabindex="-1">
<span tabindex="0">Erase</span>
</button>
<div id="note" class="note hide">
<p><strong>Note</strong>: Shaking your device to erase works but not inside this iframe. <a href="javascript:window.open(location.href)">Open separately in another tab</a>, then give it a try!</p>
</div>
<div class="board">
<div class="top">
<span class="caps">Magic</span>
<span class="cursive">Etch A Sketch</span><sup>®</sup>
<span class="caps">Screen</span>
</div>
<div class="middle">
<span class="dial-label">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" width="48px" height="48px" viewBox="0 0 48 48" enable-background="new 0 0 48 48">
<g>
<polygon points="10.792,16.5 1,24.563 10.792,32.5 10.792,27.5 38.208,27.5 38.208,32.5 48,24.5 38.208,16.5 38.208,21.5
10.792,21.5"/>
</g>
<g>
<polygon fill="#fff" points="9.792,15.5 0,23.563 9.792,31.5 9.792,26.5 37.208,26.5 37.208,31.5 47,23.5 37.208,15.5 37.208,20.5 9.792,20.5"/>
</g>
</svg>
</span>
<canvas></canvas>
<span class="dial-label">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" width="48px" height="48px" viewBox="0 0 48 48" enable-background="new 0 0 48 48">
<g>
<polygon points="16,38.209 24.063,48 32,38.209 27,38.209 27,10.792 32,10.792 24,1 16,10.792 21,10.792 21,38.209 "/>
</g>
<g>
<polygon fill="#fff" points="15,37.209 23.063,47 31,37.209 26,37.209 26,9.792 31,9.792 23,0 15,9.792 20,9.792 20,37.209 "/>
</g>
</svg>
</span>
</div>
<div class="dial" id="horz"></div>
<div class="info">
<div class="dial-labels">
<span class="dial-label">Horizontal<br>Dial</span>
<span class="dial-label">Vertical<br>Dial</span>
</div>
<div class="safety">
<span class="caps">Magic screen is glass set in sturdy plastic frame<br>Use with care</span>
</div>
</div>
<div class="dial" id="vert"></div>
</div>
$boardC: #d90009;
$boardCDark1: #b80008;
$boardCDark2: #970007;
$minFontS: 16;
$maxFontS: 28;
$minScrnS: 300;
$maxScrnS: 1440;
*, *:before, *:after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
:root {
font-size: calc(#{0px + $minFontS} + (#{$maxFontS} - #{$minFontS}) * (100vw - #{0px + $minScrnS})/(#{$maxScrnS} - #{$minScrnS}));
}
body, button {
font: 1em "Fira Sans", sans-serif;
line-height: 1.5;
}
a, a:visited {
color: $boardC;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
a:active {
color: $boardCDark1;
}
button, button > span {
color: #fff;
display: inline-block;
}
button {
background-color: transparent;
border: 0;
border-radius: 0.2em;
overflow: hidden;
position: fixed;
top: 0.75em;
left: 0.75em;
transition: opacity 0.15s linear;
-webkit-appearance: none;
z-index: 1;
> span {
background-color: #333;
padding: 0.5em 1em;
transition: all 0.15s linear;
width: 100%;
height: 100%;
}
&:hover > span, > span:focus {
background-color: #1a1a1a;
}
&:active > span {
background-color: #000;
}
&:focus {
outline: 0;
}
}
canvas {
border: {
radius: 0.75em;
top: 0.4em solid $boardCDark2;
right: 0.4em solid $boardCDark1;
bottom: 0.4em solid $boardCDark1;
left: 0.4em solid $boardCDark2;
};
display: block;
width: 22.25em;
height: 16.25em;
}
p {
margin-bottom: 1.5em;
}
.top, .middle {
width: 100%;
}
.top {
color: #ffea75;
font: {
size: 1em;
weight: normal;
};
letter-spacing: 0.1em;
line-height: 2;
text-align: center;
transform: scaleY(0.9);
span {
font-style: italic;
}
.caps {
margin: 0 0.5em;
}
.cursive {
font-size: 2em;
}
}
.middle {
display: flex;
align-items: flex-end;
.dial-label {
font-size: 2em;
height: 1em;
line-height: 1;
width: (30em - 22.25)/4;
svg {
width: 0.75em;
height: 0.75em;
}
}
}
.board {
background-color: $boardC;
border-radius: 0.5em;
box-shadow:
0.4em 0.4em 0 $boardCDark1 inset,
-0.4em -0.4em 0 $boardCDark2 inset;
color: #fff;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
align-items: center;
margin: 0 auto 1.5em auto;
width: 30em;
height: 25em;
text-shadow: 1px 1px #000;
will-change: transform;
}
.note {
margin: 1.5em auto;
width: 100%;
max-width: 24em;
}
.hide {
height: 0;
margin: 0.75em auto;
visibility: hidden;
}
.info {
font-size: 0.5em;
width: calc(100% - 18em);
}
.dial {
background-image: radial-gradient(#bbb 4%,#fff 5%);
border: {
radius: 50%;
top: 0.4em solid #ddd;
right: 0.4em solid #bbb;
bottom: 0.4em solid #bbb;
left: 0.4em solid #ddd;
};
cursor: grab;
margin: 0.5em;
width: 3.5em;
height: 3.5em;
}
.dial-labels {
display: flex;
justify-content: space-between;
margin-bottom: 0.5em;
}
.dial-label, .safety {
opacity: 0.5;
}
.dial-label {
text-align: center;
}
.safety {
font-weight: bold;
letter-spacing: 0.25em;
text-align: center;
}
.caps {
text-transform: uppercase;
}
.cursive {
font-family: "Aladin", cursive;
}
.shaking {
animation: shake 0.6s ease-out;
}
@keyframes shake {
from, to {transform:translateY(0);}
12.5% {transform:translateY(-4%);}
25% {transform:translateY(4%);}
50% {transform:translateY(-1%);}
}
View Compiled
console.clear();
window.addEventListener("load",app);
function app() {
var cnv = document.querySelector("canvas"),
c = cnv.getContext("2d"),
root = document.querySelector(":root"),
rootFS = window.getComputedStyle(root).getPropertyValue("font-size"),
u = +rootFS.substr(0,rootFS.length-2),
uw = 22.25,
uh = 16.25,
w = u * uw,
h = u * uh,
s = 2;
cnv.width = w * s;
cnv.height = h * s;
cnv.style.width = uw + "em";
cnv.style.height = uh + "em";
c.scale(s,s);
var stylus = {
x: w/2,
y: h/2,
w: 3
},
draw = function(color) {
c.fillStyle = color;
c.fillRect(stylus.x,stylus.y,stylus.w,stylus.w);
},
checkPos = function() {
if (stylus.x < 0) {
stylus.x = 0;
} else if (stylus.x > w - stylus.w) {
stylus.x = w - stylus.w;
}
if (stylus.y < 0) {
stylus.y = 0;
} else if (stylus.y > h - stylus.w) {
stylus.y = h - stylus.w;
}
},
shadeBrd = function() {
c.fillStyle = "#bbb";
c.fillRect(0,0,w,h);
},
erase = function() {
let op = 0,
opInc = 0.05,
incStop = 0.5,
doIt = function() {
op += opInc;
c.globalAlpha = op;
shadeBrd();
if (op < incStop) {
setTimeout(doIt,1000/60);
} else {
op = 0;
c.globalAlpha = 1;
}
};
doIt();
},
move = function(d) {
draw("#555");
let inc = 2;
switch (d) {
case 0:
stylus.x -= inc;
break;
case 1:
stylus.y -= inc;
break;
case 2:
stylus.x += inc;
break;
case 3:
stylus.y += inc;
break;
default:
break;
}
checkPos();
draw("#eee");
},
moveKbd = function(e) {
draw("#555");
if (e && e.keyCode) {
let inc = 2;
switch (e.keyCode) {
case 37:
stylus.x -= inc;
break;
case 38:
stylus.y -= inc;
break;
case 39:
stylus.x += inc;
break;
case 40:
stylus.y += inc;
break;
default:
break;
}
if (e.keyCode >= 37 && e.keyCode <= 40) {
e.preventDefault();
}
}
checkPos();
draw("#eee");
},
getAngle = function(ele) {
let el = document.querySelector(ele),
elTr = el.style.transform,
matrixVal = elTr.split('(')[1].split(')')[0].split(','),
cos1 = matrixVal[0],
sin = matrixVal[1],
angle = Math.round(Math.atan2(sin, cos1) * (180 / Math.PI));
if (angle < 0) {
angle += 360;
if (angle == "-0") {
angle = 0;
}
}
return angle;
},
dialH = 0,
dialHFn = Draggable.create("#horz", {
type: "rotation",
throwProps: true,
onDrag: function() {
let aH = getAngle("#horz");
if (aH > dialH) {
move(2);
} else if (aH < dialH) {
move(0);
}
dialH = aH;
}
}),
dialV = 0,
dialVFn = Draggable.create("#vert", {
type: "rotation",
throwProps: true,
onDrag: function() {
let aV = getAngle("#vert");
if (aV > dialV) {
move(1);
} else if (aV < dialV) {
move(3);
}
dialV = aV;
}
}),
shakeBrd = function() {
let brd = document.querySelector(".board");
brd.className = "";
void brd.offsetWidth;
brd.className = "board shaking";
};
shadeBrd();
if ("ontouchstart" in document.documentElement) {
if (window.parent != window.self) {
document.querySelector("#note").classList.remove("hide");
} else {
document.addEventListener("touchmove", function(e) {
e.preventDefault();
});
}
}
if (window.DeviceMotionEvent) {
window.addEventListener("devicemotion",function(e) {
let az = Math.round(e.acceleration.z);
if (az < -16) {
erase();
}
});
}
let erEvent = "ontouchend" in document.documentElement ? "touchend" : "click";
document.querySelector("#erase").addEventListener(erEvent, function() {
shakeBrd();
erase();
});
document.addEventListener("keydown", moveKbd);
}