commit all archived files
This commit is contained in:
parent
7c2aecb834
commit
c57b2e3261
12
README.md
Normal file
12
README.md
Normal file
@ -0,0 +1,12 @@
|
||||
# monitortoy
|
||||
|
||||
![](https://img.shields.io/badge/written%20in-Javascript%20%28canvas%29-blue)
|
||||
|
||||
A utility to help measure and layout a multimonitor setup.
|
||||
|
||||
Features: Add monitors from a given diagonal and aspect ratio, swivel monitors, snap to edges, and measure between any two vertices.
|
||||
|
||||
|
||||
## Download
|
||||
|
||||
- [⬇️ monitortoy.htm](dist-archive/monitortoy.htm) *(7.56 KiB)*
|
312
dist-archive/monitortoy.htm
Normal file
312
dist-archive/monitortoy.htm
Normal file
@ -0,0 +1,312 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title></title>
|
||||
<style type="text/css">
|
||||
body { text-align:center; }
|
||||
#c {
|
||||
border:1px solid darkgrey;
|
||||
margin:2px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
Monitor:
|
||||
<input type="number" id="diag" value="24" min="7" max="70">
|
||||
", ratio
|
||||
<input type="number" id="ratioL" value="16" min="1" max="100">
|
||||
<a href="javascript:;" id="swap">:</a>
|
||||
<input type="number" id="ratioR" value="9" min="1" max="100">
|
||||
|
||||
<input type="button" id="add" value="Add »">
|
||||
|
|
||||
<input type="button" id="del" value="Delete »">
|
||||
|
|
||||
<input type="button" id="swivel" value="Swivel »">
|
||||
|
|
||||
<input type="button" id="measure" value="Measure »">
|
||||
<br>
|
||||
<canvas id="c">old browser</canvas>
|
||||
|
||||
<script type="text/javascript">
|
||||
var SCALE = 6,
|
||||
BOARDW = 512,
|
||||
BOARDH = 512,
|
||||
SNAPEDGE = 5,
|
||||
PTSIZE = 5,
|
||||
TEXTFADETIME = 2000;
|
||||
|
||||
var SEL_NONE = 0, SEL_DELETE = 1, SEL_SWIVEL = 2, SEL_MEASURE1 = 3, SEL_MEASURE2 = 4;;
|
||||
|
||||
function id(s) { return document.getElementById(s); };
|
||||
|
||||
var c, ctx, boxes=[], selidx=-1, dragoffset={}, selmode=SEL_NONE, measurept=[];
|
||||
var txt="", txttimeout;
|
||||
|
||||
function onDraw() {
|
||||
ctx.clearRect(0, 0, this.c.width, this.c.height);
|
||||
ctx.fillStyle = "#FF0000";
|
||||
|
||||
if (txt.length) {
|
||||
ctx.fillText(txt, 10, 15);
|
||||
}
|
||||
|
||||
for (var i in boxes) {
|
||||
if (selmode) {
|
||||
ctx.strokeStyle="#FF0000";
|
||||
} else if (selidx == i) {
|
||||
ctx.strokeStyle="#0000FF";
|
||||
} else {
|
||||
ctx.strokeStyle="#000000";
|
||||
};
|
||||
|
||||
ctx.strokeRect(boxes[i].x, boxes[i].y, boxes[i].w, boxes[i].h);
|
||||
if (selmode && boxes[i].highlight) {
|
||||
ctx.fillRect(boxes[i].x, boxes[i].y, boxes[i].w, boxes[i].h);
|
||||
} else {
|
||||
}
|
||||
}
|
||||
|
||||
if (measurept.length) {
|
||||
ctx.fillStyle = "#00FF00";
|
||||
for (var i in measurept) {
|
||||
if (measurept[i] === false) continue;
|
||||
|
||||
ctx.fillRect(
|
||||
measurept[i][0] - PTSIZE,
|
||||
measurept[i][1] - PTSIZE,
|
||||
PTSIZE * 2,
|
||||
PTSIZE * 2
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
function roundfmt(val, decimals) {
|
||||
if (decimals <= 0) return Math.round(val);
|
||||
return Math.round(val * Math.pow(10, decimals)) / Math.pow(10, decimals);
|
||||
|
||||
};
|
||||
|
||||
function findBox(x, y) {
|
||||
for (var i in boxes) {
|
||||
if (
|
||||
x > boxes[i].x && x < (boxes[i].x + boxes[i].w) &&
|
||||
y > boxes[i].y && y < (boxes[i].y + boxes[i].h)
|
||||
) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
function findCorner(x, y) {
|
||||
for (var i in boxes) {
|
||||
if (Math.abs(x - boxes[i].x) < SNAPEDGE &&
|
||||
Math.abs(y - boxes[i].y) < SNAPEDGE
|
||||
) {
|
||||
return [boxes[i].x, boxes[i].y];
|
||||
}
|
||||
|
||||
if (Math.abs(x - boxes[i].x - boxes[i].w) < SNAPEDGE &&
|
||||
Math.abs(y - boxes[i].y) < SNAPEDGE
|
||||
) {
|
||||
return [boxes[i].x + boxes[i].w, boxes[i].y];
|
||||
}
|
||||
|
||||
if (Math.abs(x - boxes[i].x) < SNAPEDGE &&
|
||||
Math.abs(y - boxes[i].y - boxes[i].h) < SNAPEDGE
|
||||
) {
|
||||
return [boxes[i].x, boxes[i].y + boxes[i].h];
|
||||
}
|
||||
|
||||
if (Math.abs(x - boxes[i].x - boxes[i].w) < SNAPEDGE &&
|
||||
Math.abs(y - boxes[i].y - boxes[i].h) < SNAPEDGE
|
||||
) {
|
||||
return [boxes[i].x + boxes[i].w, boxes[i].y + boxes[i].h];
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function onDown(x, y) {
|
||||
if (selmode == SEL_MEASURE1 || selmode == SEL_MEASURE2) {
|
||||
var c = findCorner(x, y);
|
||||
if (c === false) {
|
||||
// clicked out - cancel
|
||||
selmode = SEL_NONE;
|
||||
measurept = [];
|
||||
return;
|
||||
}
|
||||
if (selmode == SEL_MEASURE1) {
|
||||
selmode = SEL_MEASURE2;
|
||||
return;
|
||||
|
||||
} else {
|
||||
// measure
|
||||
var dx = (measurept[SEL_MEASURE1][0] - measurept[SEL_MEASURE2][0]) / SCALE,
|
||||
dy = (measurept[SEL_MEASURE1][1] - measurept[SEL_MEASURE2][1]) / SCALE;
|
||||
txt = "Measurement: "+roundfmt(Math.sqrt( dx*dx + dy*dy ), 2)+'"';
|
||||
clearTimeout(txttimeout);
|
||||
txttimeout = setTimeout(function() {
|
||||
txt = "";
|
||||
}, TEXTFADETIME);
|
||||
|
||||
// clear
|
||||
measurept = [];
|
||||
}
|
||||
}
|
||||
|
||||
var i = findBox(x, y);
|
||||
if (i != -1) {
|
||||
// found
|
||||
if (selmode == SEL_DELETE) {
|
||||
selmode = SEL_NONE;
|
||||
selidx = -1;
|
||||
delete boxes[i];
|
||||
|
||||
} else if (selmode == SEL_SWIVEL) {
|
||||
selmode = SEL_NONE;
|
||||
selidx = -1;
|
||||
var tmp = boxes[i].w; boxes[i].w = boxes[i].h; boxes[i].h = tmp;
|
||||
boxes[i].highlight = false; // clear highlight
|
||||
|
||||
} else {
|
||||
selmode = SEL_NONE;
|
||||
selidx = i;
|
||||
dragoffset = {'x':x - boxes[i].x,'y':y - boxes[i].y};
|
||||
}
|
||||
|
||||
} else {
|
||||
// not found
|
||||
selmode = SEL_NONE;
|
||||
selidx = -1;
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
function onMove(x, y) {
|
||||
if (selidx != -1) {
|
||||
boxes[selidx].x = x - dragoffset.x;
|
||||
boxes[selidx].y = y - dragoffset.y;
|
||||
|
||||
// snap to edges
|
||||
for (var i in boxes) {
|
||||
if (selidx == i) continue;
|
||||
|
||||
// horizontal snap
|
||||
|
||||
if (Math.abs(boxes[selidx].x - boxes[i].x) < SNAPEDGE) {
|
||||
boxes[selidx].x = boxes[i].x;
|
||||
} else if (Math.abs(boxes[selidx].x - boxes[i].x - boxes[i].w) < SNAPEDGE) {
|
||||
boxes[selidx].x = boxes[i].x + boxes[i].w;
|
||||
} else if (Math.abs(boxes[selidx].x + boxes[selidx].w - boxes[i].x) < SNAPEDGE) {
|
||||
boxes[selidx].x = boxes[i].x - boxes[selidx].w;
|
||||
} else if (Math.abs(boxes[selidx].x + boxes[selidx].w - boxes[i].x - boxes[i].w) < SNAPEDGE) {
|
||||
boxes[selidx].x = boxes[i].x + boxes[i].w - boxes[selidx].w;
|
||||
}
|
||||
|
||||
// vertical snap
|
||||
|
||||
if (Math.abs(boxes[selidx].y - boxes[i].y) < SNAPEDGE) {
|
||||
boxes[selidx].y = boxes[i].y;
|
||||
} else if (Math.abs(boxes[selidx].y - boxes[i].y - boxes[i].h) < SNAPEDGE) {
|
||||
boxes[selidx].y = boxes[i].y + boxes[i].h;
|
||||
} else if (Math.abs(boxes[selidx].y + boxes[selidx].h - boxes[i].y) < SNAPEDGE) {
|
||||
boxes[selidx].y = boxes[i].y - boxes[selidx].h;
|
||||
} else if (Math.abs(boxes[selidx].y + boxes[selidx].h - boxes[i].y - boxes[i].h) < SNAPEDGE) {
|
||||
boxes[selidx].y = boxes[i].y + boxes[i].h - boxes[selidx].h;
|
||||
}
|
||||
};
|
||||
|
||||
} else if (selmode == SEL_MEASURE1 || selmode == SEL_MEASURE2) {
|
||||
// collision detect with corner
|
||||
measurept[selmode] = findCorner(x, y);
|
||||
|
||||
} else if (selmode) {
|
||||
// collision detect with monitor
|
||||
for (var i in boxes) {
|
||||
boxes[i].highlight = false;
|
||||
}
|
||||
var i = findBox(x, y);
|
||||
if (i != -1) boxes[i].highlight = true;
|
||||
}
|
||||
};
|
||||
|
||||
function onUp() {
|
||||
// Unselect
|
||||
selidx = -1;
|
||||
};
|
||||
|
||||
function createBox(diag, rl, rr) {
|
||||
// Convert to width/height
|
||||
var x = diag / (Math.sqrt(rl*rl + rr*rr));
|
||||
return [rl * x * SCALE, rr * x * SCALE];
|
||||
};
|
||||
|
||||
function onLoad() {
|
||||
|
||||
// Events
|
||||
id('swap').onclick = function() {
|
||||
var rl = id('ratioL').value, rr = id('ratioR').value;
|
||||
id('ratioR').value = rl;
|
||||
id('ratioL').value = rr;
|
||||
};
|
||||
id('add').onclick = function() {
|
||||
var newbox = createBox(
|
||||
parseInt(id('diag').value, 10),
|
||||
parseInt(id('ratioL').value, 10),
|
||||
parseInt(id('ratioR').value, 10)
|
||||
);
|
||||
boxes.push({
|
||||
'x': 10, 'y': 10, 'w': newbox[0], 'h': newbox[1]
|
||||
});
|
||||
};
|
||||
id('del').onclick = function() {
|
||||
selidx = -1;
|
||||
selmode = SEL_DELETE;
|
||||
};
|
||||
id('swivel').onclick = function() {
|
||||
selidx = -1;
|
||||
selmode = SEL_SWIVEL;
|
||||
};
|
||||
id('measure').onclick = function() {
|
||||
selidx = -1;
|
||||
selmode = SEL_MEASURE1;
|
||||
};
|
||||
|
||||
// Initialise canvas
|
||||
|
||||
c = id('c'); ctx = c.getContext("2d");
|
||||
c.width = BOARDW;
|
||||
c.height = BOARDH;
|
||||
|
||||
c.onmousedown = function(e) { return onDown(e.offsetX, e.offsetY); };
|
||||
c.onmousemove = function(e) { return onMove(e.offsetX, e.offsetY); };
|
||||
c.onmouseup = onUp;
|
||||
|
||||
var raf =
|
||||
window.requestAnimationFrame ||
|
||||
window.webkitRequestAnimationFrame ||
|
||||
window.mozRequestAnimationFrame ||
|
||||
window.oRequestAnimationFrame ||
|
||||
window.msRequestAnimationFrame ||
|
||||
function(callback, ev) {
|
||||
window.setTimeout(callback, 1000 / 60);
|
||||
};
|
||||
var callFrame = function() {
|
||||
raf(function() {
|
||||
if (onDraw() !== false) callFrame();
|
||||
});
|
||||
}
|
||||
callFrame();
|
||||
};
|
||||
|
||||
onLoad();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
BIN
doc/monitortoy.png
Normal file
BIN
doc/monitortoy.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.1 KiB |
Reference in New Issue
Block a user