387 lines
14 KiB
PHP
387 lines
14 KiB
PHP
<!doctype html>
|
||
<html lang="it">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
<title>Calibrazione etichetta DYMO</title>
|
||
|
||
@php
|
||
$w = ($format === '99014') ? 101 : 57;
|
||
$h = ($format === '99014') ? 54 : 32;
|
||
|
||
$dymoFix = isset($dymoFix) ? (bool) $dymoFix : false;
|
||
$rot = isset($rot) ? (int) $rot : 0;
|
||
$dx = isset($dx) ? (float) $dx : 0.0;
|
||
$dy = isset($dy) ? (float) $dy : 0.0;
|
||
$autoPrint = request()->has('autoprint') && filter_var(request()->query('autoprint'), FILTER_VALIDATE_BOOL);
|
||
|
||
// Quando il driver DYMO ruota/ritaglia in modo diverso, alcuni transform finiscono fuori pagina.
|
||
// dymo_mode permette di provare preset alternativi senza cambiare codice.
|
||
$dymoMode = strtoupper(trim((string) request()->query('dymo_mode', 'A')));
|
||
if (! in_array($dymoMode, ['A', 'B'], true)) {
|
||
$dymoMode = 'A';
|
||
}
|
||
|
||
$base = url()->current();
|
||
$qsBase = [
|
||
'format' => $format,
|
||
];
|
||
$presetA = $base . '?' . http_build_query(array_merge($qsBase, ['dymo_fix' => 0, 'rot' => 0, 'dx' => $dx, 'dy' => $dy]));
|
||
$presetB = $base . '?' . http_build_query(array_merge($qsBase, ['dymo_fix' => 0, 'rot' => 90, 'dx' => $dx, 'dy' => $dy]));
|
||
$presetC = $base . '?' . http_build_query(array_merge($qsBase, ['dymo_fix' => 1, 'rot' => -90, 'dx' => $dx, 'dy' => $dy]));
|
||
$presetD = $base . '?' . http_build_query(array_merge($qsBase, ['dymo_fix' => 1, 'rot' => 90, 'dx' => $dx, 'dy' => $dy]));
|
||
$presetC2 = $base . '?' . http_build_query(array_merge($qsBase, ['dymo_fix' => 1, 'dymo_mode' => 'B', 'rot' => -90, 'dx' => $dx, 'dy' => $dy]));
|
||
$presetD2 = $base . '?' . http_build_query(array_merge($qsBase, ['dymo_fix' => 1, 'dymo_mode' => 'B', 'rot' => 90, 'dx' => $dx, 'dy' => $dy]));
|
||
|
||
$qsCurrent = [
|
||
'format' => $format,
|
||
'dymo_fix' => $dymoFix ? 1 : 0,
|
||
'dymo_mode' => $dymoMode,
|
||
'rot' => $rot,
|
||
];
|
||
|
||
$urlDxDy = function (float $newDx, float $newDy) use ($base, $qsCurrent): string {
|
||
return $base . '?' . http_build_query(array_merge($qsCurrent, [
|
||
'dx' => number_format($newDx, 2, '.', ''),
|
||
'dy' => number_format($newDy, 2, '.', ''),
|
||
]));
|
||
};
|
||
|
||
$dxPlus05 = $urlDxDy($dx + 0.5, $dy);
|
||
$dxMinus05 = $urlDxDy($dx - 0.5, $dy);
|
||
$dyPlus05 = $urlDxDy($dx, $dy + 0.5);
|
||
$dyMinus05 = $urlDxDy($dx, $dy - 0.5);
|
||
$dxPlus1 = $urlDxDy($dx + 1.0, $dy);
|
||
$dxMinus1 = $urlDxDy($dx - 1.0, $dy);
|
||
$dyPlus1 = $urlDxDy($dx, $dy + 1.0);
|
||
$dyMinus1 = $urlDxDy($dx, $dy - 1.0);
|
||
@endphp
|
||
|
||
<style>
|
||
:root {
|
||
--w: {{ $w }}mm;
|
||
--h: {{ $h }}mm;
|
||
}
|
||
|
||
@page {
|
||
size: var(--w) var(--h);
|
||
margin: 0;
|
||
}
|
||
|
||
html, body {
|
||
margin: 0;
|
||
padding: 0;
|
||
width: var(--w);
|
||
height: var(--h);
|
||
background: #fff;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.sheet {
|
||
position: relative;
|
||
width: var(--w);
|
||
height: var(--h);
|
||
overflow: hidden;
|
||
-webkit-print-color-adjust: exact;
|
||
print-color-adjust: exact;
|
||
break-inside: avoid;
|
||
break-after: avoid-page;
|
||
page-break-inside: avoid;
|
||
page-break-after: avoid;
|
||
}
|
||
|
||
.calib {
|
||
position: absolute;
|
||
inset: 0;
|
||
transform-origin: 0 0;
|
||
}
|
||
|
||
@media print {
|
||
/* Default: offset + rot su pagina (utile per 99014 e per 11354 se il driver non ruota) */
|
||
@if(!($format === '11354' && $dymoFix))
|
||
.calib {
|
||
transform: translate({{ number_format($dx, 2, '.', '') }}mm, {{ number_format($dy, 2, '.', '') }}mm) rotate({{ (int) $rot }}deg);
|
||
}
|
||
@endif
|
||
|
||
/* Evita "seconda pagina" dovuta a arrotondamenti mm->px in alcuni browser */
|
||
html, body { width: 100%; height: 100%; overflow: hidden; }
|
||
.sheet { position: fixed; left: 0; top: 0; }
|
||
|
||
/*
|
||
* DYMO 11354 workaround:
|
||
* alcuni driver stampano la 57x32 ruotata. In quel caso impostiamo la pagina a 32x57
|
||
* e ruotiamo il contenuto interno 57x32.
|
||
*/
|
||
@if($format === '11354' && $dymoFix)
|
||
@page { size: 32mm 57mm; }
|
||
html, body { width: 32mm; height: 57mm; }
|
||
.sheet { width: 32mm; height: 57mm; }
|
||
.calib {
|
||
width: 57mm;
|
||
height: 32mm;
|
||
@php($r = (int) $rot)
|
||
@if($dymoMode === 'B')
|
||
/* Mode B: alternative origin/translation (useful when C/D are blank) */
|
||
@if($r === 90)
|
||
transform: translate({{ number_format($dx, 2, '.', '') }}mm, {{ number_format($dy, 2, '.', '') }}mm) translateX(57mm) rotate(90deg);
|
||
@else
|
||
transform: translate({{ number_format($dx, 2, '.', '') }}mm, {{ number_format($dy, 2, '.', '') }}mm) translateY(32mm) rotate(-90deg);
|
||
@endif
|
||
@else
|
||
/* Mode A: default */
|
||
@if($r === 90)
|
||
transform: translate({{ number_format($dx, 2, '.', '') }}mm, {{ number_format($dy, 2, '.', '') }}mm) translateX(32mm) rotate(90deg);
|
||
@else
|
||
transform: translate({{ number_format($dx, 2, '.', '') }}mm, {{ number_format($dy, 2, '.', '') }}mm) translateY(57mm) rotate(-90deg);
|
||
@endif
|
||
@endif
|
||
}
|
||
@endif
|
||
}
|
||
|
||
/* Grid: 1mm light + 5mm stronger */
|
||
.grid {
|
||
position: absolute;
|
||
inset: 0;
|
||
background-image:
|
||
repeating-linear-gradient(0deg, rgba(0,0,0,0.08), rgba(0,0,0,0.08) 0.2mm, transparent 0.2mm, transparent 1mm),
|
||
repeating-linear-gradient(90deg, rgba(0,0,0,0.08), rgba(0,0,0,0.08) 0.2mm, transparent 0.2mm, transparent 1mm),
|
||
repeating-linear-gradient(0deg, rgba(0,0,0,0.20), rgba(0,0,0,0.20) 0.35mm, transparent 0.35mm, transparent 5mm),
|
||
repeating-linear-gradient(90deg, rgba(0,0,0,0.20), rgba(0,0,0,0.20) 0.35mm, transparent 0.35mm, transparent 5mm);
|
||
}
|
||
|
||
.border {
|
||
position: absolute;
|
||
inset: 0;
|
||
border: 0.4mm solid #000;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.center {
|
||
position: absolute;
|
||
left: 50%;
|
||
top: 50%;
|
||
width: 12mm;
|
||
height: 12mm;
|
||
margin-left: -6mm;
|
||
margin-top: -6mm;
|
||
border: 0.5mm solid #000;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.cross {
|
||
position: absolute;
|
||
left: 50%;
|
||
top: 50%;
|
||
width: 0;
|
||
height: 0;
|
||
}
|
||
.cross::before,
|
||
.cross::after {
|
||
content: '';
|
||
position: absolute;
|
||
background: #000;
|
||
}
|
||
.cross::before {
|
||
width: 18mm;
|
||
height: 0.6mm;
|
||
left: -9mm;
|
||
top: -0.3mm;
|
||
}
|
||
.cross::after {
|
||
width: 0.6mm;
|
||
height: 18mm;
|
||
left: -0.3mm;
|
||
top: -9mm;
|
||
}
|
||
|
||
.label {
|
||
position: absolute;
|
||
left: 1.5mm;
|
||
top: 1.2mm;
|
||
font: 2.8mm/1.2 sans-serif;
|
||
color: #000;
|
||
background: rgba(255,255,255,0.85);
|
||
padding: 0.6mm 0.8mm;
|
||
border: 0.2mm solid rgba(0,0,0,0.4);
|
||
}
|
||
|
||
.help {
|
||
position: absolute;
|
||
left: 1.5mm;
|
||
bottom: 1.2mm;
|
||
font: 2.6mm/1.25 sans-serif;
|
||
color: #000;
|
||
background: rgba(255,255,255,0.85);
|
||
padding: 0.6mm 0.8mm;
|
||
border: 0.2mm solid rgba(0,0,0,0.35);
|
||
max-width: calc(100% - 3mm);
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.orient {
|
||
position: absolute;
|
||
inset: 0;
|
||
pointer-events: none;
|
||
}
|
||
.orient .top {
|
||
position: absolute;
|
||
left: 50%;
|
||
top: 1.2mm;
|
||
transform: translateX(-50%);
|
||
font: 3mm/1 sans-serif;
|
||
font-weight: 800;
|
||
letter-spacing: .6px;
|
||
background: rgba(255,255,255,0.85);
|
||
padding: 0.4mm 0.6mm;
|
||
border: 0.2mm solid rgba(0,0,0,0.35);
|
||
}
|
||
.orient .left {
|
||
position: absolute;
|
||
left: 1.2mm;
|
||
top: 50%;
|
||
transform: translateY(-50%) rotate(-90deg);
|
||
transform-origin: left top;
|
||
font: 3mm/1 sans-serif;
|
||
font-weight: 800;
|
||
letter-spacing: .6px;
|
||
background: rgba(255,255,255,0.85);
|
||
padding: 0.4mm 0.6mm;
|
||
border: 0.2mm solid rgba(0,0,0,0.35);
|
||
}
|
||
|
||
.corner {
|
||
position: absolute;
|
||
width: 6mm;
|
||
height: 6mm;
|
||
box-sizing: border-box;
|
||
border: 0.6mm solid #000;
|
||
}
|
||
.corner.tl { left: 0; top: 0; border-right: 0; border-bottom: 0; }
|
||
.corner.tr { right: 0; top: 0; border-left: 0; border-bottom: 0; }
|
||
.corner.bl { left: 0; bottom: 0; border-right: 0; border-top: 0; }
|
||
.corner.br { right: 0; bottom: 0; border-left: 0; border-top: 0; }
|
||
|
||
@media screen {
|
||
body {
|
||
padding: 12px;
|
||
background: #f3f4f6;
|
||
}
|
||
.sheet {
|
||
box-shadow: 0 0 0 1px rgba(0,0,0,0.15);
|
||
}
|
||
.toolbar {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 8px;
|
||
align-items: center;
|
||
margin: 0 0 10px 0;
|
||
}
|
||
.toolbar .hint {
|
||
font: 13px/1.2 sans-serif;
|
||
color: #111827;
|
||
}
|
||
.toolbar button {
|
||
appearance: none;
|
||
border: 1px solid rgba(0,0,0,0.25);
|
||
background: #fff;
|
||
padding: 6px 10px;
|
||
border-radius: 6px;
|
||
cursor: pointer;
|
||
font: 13px/1.2 sans-serif;
|
||
}
|
||
|
||
.toolbar a.btn {
|
||
display: inline-block;
|
||
border: 1px solid rgba(0,0,0,0.25);
|
||
background: #fff;
|
||
padding: 6px 10px;
|
||
border-radius: 6px;
|
||
cursor: pointer;
|
||
font: 13px/1.2 sans-serif;
|
||
color: #111827;
|
||
text-decoration: none;
|
||
}
|
||
|
||
.toolbar .group {
|
||
display: inline-flex;
|
||
gap: 6px;
|
||
align-items: center;
|
||
padding: 4px 6px;
|
||
border: 1px dashed rgba(0,0,0,0.18);
|
||
border-radius: 8px;
|
||
background: rgba(255,255,255,0.65);
|
||
}
|
||
}
|
||
|
||
@media print {
|
||
.no-print { display: none !important; }
|
||
}
|
||
</style>
|
||
|
||
@if($autoPrint)
|
||
<script>
|
||
window.addEventListener('load', () => {
|
||
// Alcuni browser bloccano print() senza gesto utente: se succede, usa il bottone “Stampa”.
|
||
setTimeout(() => {
|
||
try { window.print(); } catch (e) {}
|
||
}, 120);
|
||
});
|
||
</script>
|
||
@endif
|
||
</head>
|
||
<body>
|
||
<div class="toolbar no-print">
|
||
<button type="button" onclick="window.print()">Stampa</button>
|
||
<a href="{{ $presetA }}" class="btn">Preset A (fix=0 rot=0)</a>
|
||
<a href="{{ $presetB }}" class="btn">Preset B (fix=0 rot=90)</a>
|
||
<a href="{{ $presetC }}" class="btn">Preset C (fix=1 rot=-90)</a>
|
||
<a href="{{ $presetD }}" class="btn">Preset D (fix=1 rot=90)</a>
|
||
<a href="{{ $presetC2 }}" class="btn">Preset C2 (fix=1 mode=B rot=-90)</a>
|
||
<a href="{{ $presetD2 }}" class="btn">Preset D2 (fix=1 mode=B rot=90)</a>
|
||
|
||
<span class="group">
|
||
<span class="hint">dx</span>
|
||
<a href="{{ $dxMinus1 }}" class="btn">−1</a>
|
||
<a href="{{ $dxMinus05 }}" class="btn">−0.5</a>
|
||
<a href="{{ $dxPlus05 }}" class="btn">+0.5</a>
|
||
<a href="{{ $dxPlus1 }}" class="btn">+1</a>
|
||
</span>
|
||
<span class="group">
|
||
<span class="hint">dy</span>
|
||
<a href="{{ $dyMinus1 }}" class="btn">−1</a>
|
||
<a href="{{ $dyMinus05 }}" class="btn">−0.5</a>
|
||
<a href="{{ $dyPlus05 }}" class="btn">+0.5</a>
|
||
<a href="{{ $dyPlus1 }}" class="btn">+1</a>
|
||
</span>
|
||
|
||
<div class="hint" style="flex-basis: 100%;">
|
||
Nota: se A/B risultano “vuoti” o stampano spostati, usa C/D (fix=1). Se C/D stampano ma risultano troppo a sinistra/destra, correggi con dx/dy.
|
||
</div>
|
||
</div>
|
||
<div class="sheet">
|
||
<div class="calib">
|
||
<div class="grid"></div>
|
||
<div class="border"></div>
|
||
<div class="corner tl"></div>
|
||
<div class="corner tr"></div>
|
||
<div class="corner bl"></div>
|
||
<div class="corner br"></div>
|
||
<div class="center"></div>
|
||
<div class="cross"></div>
|
||
<div class="orient">
|
||
<div class="top">TOP</div>
|
||
<div class="left">LEFT</div>
|
||
</div>
|
||
<div class="label">
|
||
DYMO {{ $format }} ({{ $w }}×{{ $h }}mm) · fix={{ $dymoFix ? '1' : '0' }} · mode={{ $dymoMode }} · dx={{ number_format($dx, 2, '.', '') }}mm · dy={{ number_format($dy, 2, '.', '') }}mm · rot={{ (int) $rot }}°
|
||
</div>
|
||
<div class="help">
|
||
Prova rapida 11354: aggiungi <strong>?format=11354&dymo_fix=1</strong> (se ruotata), poi regola <strong>dx/dy</strong> in mm.
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</body>
|
||
</html>
|