guest_worker/www/index.html

317 lines
11 KiB
HTML

<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>MT Request: draw over the image</title>
<style media="screen">
#sample, svg{
position:absolute;
top: 0;
left: 0;
bottom: 0;
right:0;
width:100%;
height:100%;
font-family: sans-serif;
}
path {
fill: none;
stroke: red;
stroke-width: 2px;
}
body.submitted path{
stroke:darkgray;
}
body.submitted .buttons{
display:none;
}
/*#wrapper {
height: calc({DRAW_HEIGHT}/{HEIGHT} * 100%);
width: calc({DRAW_WIDTH}/{WIDTH} * 100%);
position: absolute;
left: calc(({WIDTH} - {DRAW_WIDTH})/2/{WIDTH} * 100%);
top: calc(({HEIGHT} - {DRAW_HEIGHT})/2/{HEIGHT} * 100%);
background:none;
cursor: url(cursor.png) 6 6, auto;
}*/
#wrapper {
position:absolute;
top:0;
right:0;
bottom:0;
left:0;
background:none;
cursor: url(cursor.png) 6 6, auto;
}
.gray{
position:absolute;
background:rgba(255,255,255,0.7);
}
#gray_top{
left:0;
right:0;
top:0;
height:calc({TOP_PADDING}/{HEIGHT} * 100%);
}
#gray_bottom{
left:0;
right:0;
bottom:0;
height:calc(({HEIGHT} - {DRAW_HEIGHT} - {TOP_PADDING})/{HEIGHT} * 100%);
}
#gray_left{
left:0;
top:calc({TOP_PADDING}/{HEIGHT} * 100%);
height: calc({DRAW_HEIGHT}/{HEIGHT} * 100%);
width: calc({LEFT_PADDING}/{WIDTH} * 100%);
}
#gray_right{
right:0;
top:calc({TOP_PADDING}/{HEIGHT} * 100%);
height: calc({DRAW_HEIGHT}/{HEIGHT} * 100%);
width: calc(({WIDTH} - {DRAW_WIDTH} - {LEFT_PADDING})/{WIDTH} * 100%);
}
html, body{
height: 100%;
width: 100%;
margin:0;
background:gray;
}
#interface{
background:white;
height: 0;
overflow: hidden;
padding-top: calc({HEIGHT}/{WIDTH} * 100%);
background: white;
position: relative;
margin: 0 auto;
background-size: 100% 100%;
}
#innerface{
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
@media (min-aspect-ratio: {WIDTH}/{HEIGHT}) {
#interface {
height: 100vh;
width: calc({WIDTH}/{HEIGHT} * 100vh);
padding-top:0;
}
}
#info{
position: absolute;
bottom: 5px;
width: 600px;
left: calc(50% - 250px);
z-index: 999;
}
.buttons{
text-align: center;
}
</style>
</head>
<body>
<div id='interface' style="background-image:url('{IMAGE_URL}')">
<div id='innerface'>
<div id='wrapper'>
<!-- <img src="{IMAGE_URL}" id='sample'>-->
<svg id="canvas" viewBox="0 0 {WIDTH}0 {HEIGHT}0" width="{WIDTH}mm" height="{HEIGHT}mm" preserveAspectRatio="none">
<path d="" id="stroke" />
</svg>
</div>
<div id='info'>
<ul>
<li>Drag the mouse to trace the <strong>clearest lines</strong> drawing above</li>
<li>Follow the lines as precise as possible</li>
<li>Press submit when you're done.</li>
<li>You'll receive a submission token, to fill in at Mechanical Turk</li>
</ul>
<div class='buttons'>
<button id='submit'>Submit</button>
<!-- <button id='reset'>Reset</button>-->
</div>
<div id='message'></div>
</div>
<div class='gray' id='gray_top'></div>
<div class='gray' id='gray_bottom'></div>
<div class='gray' id='gray_left'></div>
<div class='gray' id='gray_right'></div>
</div>
</div>
<script type="text/javascript">
let url = window.location.origin.replace('http', 'ws') +'/ws?' + window.location.search.substring(1);
let svgEl = document.getElementById("canvas");
let strokeEl = document.getElementById('stroke');
let submitEl = document.getElementById('submit');
let resetEl = document.getElementById('reset');
let messageEl = document.getElementById('message');
let innerFaceEl = document.getElementById('innerface'); // wrapper within the interface
let svgWidth = {WIDTH};
let svgHeight = {HEIGHT};
let drawWidth = {DRAW_WIDTH};
let drawHeight = {DRAW_HEIGHT};
let xPadding = {LEFT_PADDING} / svgWidth;
let yPadding = {TOP_PADDING} / svgHeight;
let drawWidthFactor = drawWidth / svgWidth;
let drawHeightFactor = drawHeight / svgHeight;
let strokes = [];
let isDrawing = false;
let hasMouseDown = false;
let currentPoint = null;
let getCoordinates = function(e) {
// convert event coordinates into relative positions on x & y axis
let box = innerFaceEl.getBoundingClientRect();
let x = (e.x - box['left']) / box['width'];
let y = (e.y - box['top']) / box['height'];
return {'x': x, 'y': y};
}
let isInsideBounds = function(pos) {
return !(pos['x'] < 0 || pos['y'] < 0 || pos['x'] > 1 || pos['y'] > 1);
}
let isInsideDrawingBounds = function(pos) {
if(pos['x'] > xPadding && pos['x'] < (xPadding+drawWidthFactor) && pos['y'] > yPadding && pos['y'] < yPadding+drawHeightFactor) {
return true;
}
return false;
}
let draw = function(e) {
let pos = getCoordinates(e);
if(!isInsideBounds(pos)) {
// outside of bounds
return;
}
if(isDrawing && !isInsideDrawingBounds(pos)){
stopDrawing(pos);
}
if(!isDrawing && hasMouseDown && isInsideDrawingBounds(pos)){
isDrawing = true;
}
if(isDrawing) {
strokes.push([pos['x'], pos['y'], 0]);
let d = strokes2D(strokes);
strokeEl.setAttribute('d', d);
}
console.log([pos['x'], pos['y']], isDrawing);
socket.send(JSON.stringify({
'action': 'move',
'direction': [pos['x'], pos['y']],
'mouse': isDrawing,
}));
};
let stopDrawing = function(pos) {
if(!isDrawing) {
return;
}
isDrawing = false;
//document.body.removeEventListener('mousemove', draw);
if(strokes.length > 0){
// mark point as last of stroke
strokes[strokes.length - 1][2] = 1;
}
socket.send(JSON.stringify({
'action': 'up',
'direction': [pos['x'], pos['y']]
}));
}
let penup = function(e) {
if(!hasMouseDown) {
return;
}
hasMouseDown = false;
let pos = getCoordinates(e);
stopDrawing(pos);
};
let strokes2D = function(strokes) {
// strokes to a d attribute for a path
let d = "";
let last_stroke = undefined;
let cmd = "";
for (let stroke of strokes) {
if(!last_stroke) {
d += `M${stroke[0]*svgWidth*10},${stroke[1]*svgHeight*10} `;
cmd = 'M';
} else {
if (last_stroke[2] == 1) {
d += " m";
cmd = 'm';
} else if (cmd != 'l') {
d+=' l ';
cmd = 'l';
}
let rel_stroke = [stroke[0] - last_stroke[0], stroke[1] - last_stroke[1]];
d += `${rel_stroke[0]*svgWidth*10},${rel_stroke[1]*svgHeight*10} `;
}
last_stroke = stroke;
}
return d;
}
let startDrawing = function(e){
hasMouseDown = true;
};
/*let reset = function() {
strokes = [];
strokeEl.setAttribute('d', "");
socket.send(JSON.stringify({
'action': 'reset',
}));
}*/
let socket = new WebSocket(url);
document.body.addEventListener('mousemove', draw);
document.body.addEventListener('mouseup', penup);
document.body.addEventListener('mousedown', startDrawing);
socket.addEventListener('message', function(e){
let msg = JSON.parse(e.data);
console.log('receive', msg);
if(msg['action'] == 'submitted') {
document.body.classList.add('submitted');
messageEl.innerHTML = msg['msg'];
svgEl.removeEventListener('mousedown', startDrawing);
}
});
//resetEl.addEventListener('click', reset);
submitEl.addEventListener('click', function(e){
if(!strokes.length){
alert('please draw before submitting');
return;
}
socket.send(JSON.stringify({
'action': 'submit'
}));
document.body.removeEventListener('mousemove', draw);
document.body.removeEventListener('mouseup', penup);
document.body.removeEventListener('mousedown', startDrawing);
});
</script>
</body>
</html>