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