cssAudio - Activefile-genericCSS - ActiveGeneric - ActiveHTML - ActiveImage - ActiveJS - ActiveSVG - ActiveText - Activefile-genericVideo - ActiveLovehtmlicon-new-collectionicon-personicon-teamlog-outoctocatpop-outspinnerstartv

Pen Settings

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URL's added here will be added as <link>s in order, and before the CSS in the editor. If you link to another Pen, it will include the CSS from that Pen. If the preprocessor matches, it will attempt to combine them before processing.

Quick-add: + add another resource

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

Quick-add: + add another resource

Code Indentation

     

Save Automatically?

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

            
              <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>&reg;</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: $boardC - #210001;
$boardCDark2: $boardC - #420002;

$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;
		/* The button’s span should be focused instead */
	}
}
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;
		}
	}
}
/* Interface */
.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;
}
/* Typography */
.caps {
	text-transform: uppercase;
}
.cursive {
	font-family: "Aladin", cursive;
}
/* Animation */
.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%);}
}
            
          
!
            
              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,
		// canvas dimensions
		w = u * uw,
		h = u * uh,
		// scale, keep at 2 for best retina results
		s = 2;

	// set canvas dimensions with scale
	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() {
			// x bounds
			if (stylus.x < 0) {
				stylus.x = 0;
			} else if (stylus.x > w - stylus.w) {
				stylus.x = w - stylus.w;
			}
			// y bounds
			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");
			// 0 = left, 1 = up, 2 = right, 3 = down
			switch (d) {
				case 0:
					--stylus.x
					break;
				case 1:
					--stylus.y;
					break;
				case 2:
					++stylus.x;
					break;
				case 3:
					++stylus.y;
					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;
				}
				// prevent scrolling at same time
				if (e.keyCode >= 37 && e.keyCode <= 40) {
					e.preventDefault();
				}
			}
			checkPos();
			draw("#eee");
		},
		getAngle = function(ele) {
			let el = document.querySelector(ele),
				elTr = el.style.transform,
				// break down matrix value of crank transform and get angle
				matrixVal = elTr.split('(')[1].split(')')[0].split(','),
				cos1 = matrixVal[0],
				sin = matrixVal[1],
				angle = Math.round(Math.atan2(sin, cos1) * (180 / Math.PI));
			
			// convert negative angles to positive, correct -0 issue
			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 {
			// interacting with board on iOS would cause accidental panning
			document.addEventListener("touchmove", function(e) {
        		e.preventDefault();
    		});
		}
	}
	
	// erase via device shake
	if (window.DeviceMotionEvent) {
		window.addEventListener("devicemotion",function(e) {
			let az = Math.round(e.acceleration.z);
			if (az < -16) {
				erase();
			}
		});
	}
	// erase via button
	let erEvent = "ontouchend" in document.documentElement ? "touchend" : "click";
	document.querySelector("#erase").addEventListener(erEvent, function() {
		shakeBrd();
		erase();
	});
	// draw with arrow keys
	document.addEventListener("keydown", moveKbd);
}
            
          
!
999px
Loading ..................

Console