dry-fire-target-maker/index.html

128 lines
3.0 KiB
HTML
Raw Normal View History

2023-02-14 06:21:19 +00:00
<!DOCTYPE html>
<html>
<head>
<title>Target scaler</title>
<style>
body {
max-width: 70em;
}
input {
margin-left: 1em;
}
.complex-radio {
display: inline-block;
text-align: center;
vertical-align: top;
}
.complex-radio img {
width: 10em;
}
#print {
width: 100%;
}
#print .target {
display: block;
margin-left: auto;
margin-right: auto;
}
@media screen {
#print {
display: none;
}
}
@media print {
#ui {
display: none;
}
}
</style>
</head>
<body>
<div id="ui">
<h1>Dry Fire Target Maker</h1>
<p>
2023-02-14 06:33:28 +00:00
Scale the target by setting the simulated and actual distances to the target in any unit of length,
then click <em>Print</em>.
</p>
<p>
For example, if you want the target to appear as if it is 15m away when it is actually
only 3m away, set <em>Simulated distance</em> to 15 and <em>Actual distance</em>
2023-02-14 06:21:19 +00:00
to 3.
</p>
2023-02-14 06:33:28 +00:00
<p>
The target <strong>will not</strong> fit on US letter paper if <em>Actual distance</em> is more than ~35% of <em>Simulated distance</em>.
</p>
<hr>
2023-02-14 06:21:19 +00:00
<p>
<label>Simulated distance<input id="simulated-range" type="number" value="40"></label>
</p>
<p>
<label>Actual distance<input id="actual-range" type="number" value="3"></label>
</p>
<fieldset role="radiogroup" id="target-styles">
<legend>Target style</legend>
<label><input type="radio" name="target-style" checked>
<div class="complex-radio">
<div>USPSA</div><img class="target" src="uspsa.svg">
</div>
</label>
<label><input type="radio" name="target-style">
<div class="complex-radio">
<div>IDPA</div><img class="target" src="idpa.svg">
</div>
</label>
<label><input type="radio" name="target-style">
<div class="complex-radio">
<div>IPSC</div><img class="target" src="ipsc.svg">
</div>
</label>
</fieldset>
<p>
<button id="print-button">Print</button>
</p>
</div>
<div id="print">
<img class="target">
</div>
<script>
{
let target = document.querySelector("#print .target");
let simulatedRange = document.getElementById("simulated-range");
let actualRange = document.getElementById("actual-range");
const updateScale = () => {
let scale = actualRange.value / simulatedRange.value;
target.style.width = target.naturalWidth * scale + "mm";
}
simulatedRange.addEventListener("change", updateScale);
actualRange.addEventListener("change", updateScale);
target.addEventListener("load", updateScale);
document.getElementById("print-button").addEventListener("click", print.bind(window));
const updateTargetStyle = () => {
const checked = document.querySelector("#target-styles input[type=radio]:checked");
const src = checked.labels[0].getElementsByTagName("img")[0].src;
target.src = src;
};
document.querySelectorAll("#target-styles label").forEach((label) => {
label.addEventListener("change", updateTargetStyle);
});
updateTargetStyle();
}
</script>
</body>
</html>