blob: 2365a6d12310f399575ffe2756d0970dd1309598 [file] [log] [blame] [edit]
<!DOCTYPE html>
<html>
<!--
Copyright 2022 The IREE Authors
Licensed under the Apache License v2.0 with LLVM Exceptions.
See https://llvm.org/LICENSE.txt for license information.
SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-->
<head>
<meta charset="utf-8" />
<title>IREE Static Web Sample</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="./IREE_Logo_Icon_Color.svg" type="image/svg+xml">
<script src="./easeljs.min.js"></script>
<script src="./iree_api.js"></script>
</head>
<body style="background-color: #2b2c30; color: #ABB2BF">
<h1>IREE Static Web Sample</h1>
<canvas id="drawingCanvas" width="256" height="256"
style="border:2px solid #000000; background-color: #FFFFFF;"
oncontextmenu="return false;">
</canvas>
<canvas id="rescaledCanvas" width="28" height="28"
style="border:2px solid #000000; background-color: #FFFFFF;">
</canvas>
<br>
<div style="border:2px solid #000000; background-color: #CCCCCC; padding: 8px; color: #111111; width:440px">
<button id="predictButton" disabled onclick="predictDigit()">Predict handwritten digit</button>
<button id="clearCanvasButton" onclick="clearCanvas()">Clear canvas</button>
<br>
Prediction result: <div id="predictionResult" style="display:inline"></div>
</div>
<script>
// <canvas> drawing using easeljs forked from:
// https://createjs.com/demos/easeljs/curveto
// https://github.com/CreateJS/EaselJS/blob/master/examples/CurveTo.html
const predictButtonElement = document.getElementById('predictButton');
const predictionResultElement = document.getElementById('predictionResult');
const drawingCanvasElement = document.getElementById("drawingCanvas");
const rescaledCanvasElement = document.getElementById("rescaledCanvas");
const rescaledCanvasContext = rescaledCanvasElement.getContext("2d");
let stage;
let drawingCanvasShape;
let oldPt, oldMidPt;
let titleText;
let ireeInitialized = false;
const primaryColor = "#000000";
const eraseColor = "#FFFFFF";
const stroke = 32;
function predictDigit() {
// TODO(scotttodd): debounce / rate limit this?
ireePredictDigit(getRescaledCanvasData()).then((result) => {
predictionResultElement.innerHTML = result;
}).catch((error) => {
console.error('error predicting digit:', error);
predictionResultElement.innerHTML = "<b>" + error + "</b>";
});
}
function clearCanvas() {
stage.clear();
stage.removeAllChildren();
drawingCanvasShape = new createjs.Shape();
stage.addChild(drawingCanvasShape);
stage.update();
updateRescaledCanvas();
}
function initDrawing() {
rescaledCanvasContext.imageSmoothingEnabled = false;
rescaledCanvasContext.mozImageSmoothingEnabled = false;
rescaledCanvasContext.webkitImageSmoothingEnabled = false;
rescaledCanvasContext.msImageSmoothingEnabled = false;
stage = new createjs.Stage(drawingCanvasElement);
stage.autoClear = false;
stage.enableDOMEvents(true);
createjs.Touch.enable(stage);
createjs.Ticker.framerate = 24;
stage.addEventListener("stagemousedown", handleMouseDown);
stage.addEventListener("stagemouseup", handleMouseUp);
drawingCanvasShape = new createjs.Shape();
stage.addChild(drawingCanvasShape);
// Add instruction text.
titleText = new createjs.Text("Click and Drag to draw", "18px Arial", "#000000");
titleText.x = 30;
titleText.y = 100;
stage.addChild(titleText);
stage.update();
}
function handleMouseDown(event) {
if (!event.primary && !event.secondary) { return; }
if (stage.contains(titleText)) {
stage.clear();
stage.removeChild(titleText);
}
oldPt = new createjs.Point(stage.mouseX, stage.mouseY);
oldMidPt = oldPt.clone();
stage.addEventListener("stagemousemove", handleMouseMove);
}
function handleMouseMove(event) {
if (!event.primary && !event.secondary) { return; }
const midPt = new createjs.Point(
oldPt.x + stage.mouseX >> 1, oldPt.y + stage.mouseY >> 1);
const color = event.nativeEvent.which == 1 ? primaryColor : eraseColor;
drawingCanvasShape.graphics.clear()
.setStrokeStyle(stroke, 'round', 'round')
.beginStroke(color).moveTo(midPt.x, midPt.y)
.curveTo(oldPt.x, oldPt.y, oldMidPt.x, oldMidPt.y);
oldPt.x = stage.mouseX;
oldPt.y = stage.mouseY;
oldMidPt.x = midPt.x;
oldMidPt.y = midPt.y;
stage.update();
updateRescaledCanvas();
if (ireeInitialized) {
predictDigit();
}
}
function handleMouseUp(event) {
if (!event.primary && !event.default) { return; }
stage.removeEventListener("stagemousemove", handleMouseMove);
}
function updateRescaledCanvas() {
rescaledCanvasContext.clearRect(
0, 0, rescaledCanvasElement.width, rescaledCanvasElement.height);
rescaledCanvasContext.drawImage(
drawingCanvasElement,
/*sx=*/0, /*sy=*/0,
/*sWidth=*/256, /*sHeight=*/256,
/*dx=*/0, /*dy=*/0,
/*dWidth=*/28, /*dHeight=*/28);
}
function getRescaledCanvasData() {
return rescaledCanvasContext.getImageData(0, 0, 28, 28);
}
initDrawing();
ireeInitializeWorker().then((result) => {
predictButtonElement.disabled = false;
ireeInitialized = true;
}).catch((error) => {
console.error("Failed to initialize IREE, error: '" + error + "'");
});
</script>
</body>
</html>