lapsha/src/components/Canvas.vue

129 lines
2.7 KiB
Vue

<script setup lang="ts">
import { onMounted, onUpdated, ref } from "vue";
import { ONE_MM } from "../const";
import { useStore } from "../store";
import { storeToRefs } from "pinia";
const store = useStore();
const {
imageBackgroundColor,
vMargin,
vRotation,
hMargin,
hMargin2,
marginEnable,
marginColor,
marginLeftMargin,
imageHeight,
imageWidth,
} = storeToRefs(store);
const ctx = ref<null | CanvasRenderingContext2D>(null);
const clearCanvas = () => {
if (ctx.value) {
ctx.value.shadowColor
ctx.value.fillStyle = imageBackgroundColor.value;
ctx.value.fillRect(0, 0, imageWidth.value * ONE_MM, imageHeight.value * ONE_MM);
ctx.value.beginPath();
}
};
const render = () => {
if (vMargin.value < 1 || hMargin.value < 1 || hMargin2.value < 1) {
return
}
if (imageWidth.value < 1 || imageHeight.value < 1) {
return
}
clearCanvas();
var hMargins = [hMargin.value, hMargin2.value];
var imageHeightPx = imageHeight.value * ONE_MM;
var imageWidthPx = imageWidth.value * ONE_MM;
var vMarginPx = vMargin.value * ONE_MM;
var rotationDelta = imageHeightPx / Math.tan(vRotation.value / 180 * Math.PI);
if (ctx.value) {
ctx.value.strokeStyle = "#000000";
ctx.value.beginPath();
ctx.value.stroke();
var x = 0;
var y = 0;
let i = 0;
while (y < imageHeightPx) {
y += hMargins[i % 2] * ONE_MM;
ctx.value.moveTo(0, y);
ctx.value.lineTo(imageWidthPx, y);
ctx.value.stroke();
i++;
}
x = 0;
y = 0;
i = 0;
while (x - rotationDelta < imageWidthPx) {
x = i * vMarginPx;
var x0 = x;
var y0 = 0;
var x1 = x - rotationDelta;
var y1 = imageHeightPx;
ctx.value.moveTo(x0, y0);
ctx.value.lineTo(x1, y1);
ctx.value.stroke();
i++;
}
x = marginLeftMargin.value * ONE_MM;
if (marginEnable.value) {
ctx.value.strokeStyle = marginColor.value;
ctx.value.lineWidth = 2;
ctx.value.beginPath();
ctx.value.moveTo(x, 0);
ctx.value.lineTo(x, imageHeightPx);
ctx.value.stroke();
}
}
};
onMounted(() => {
const canvas = document.getElementById("canvas") as HTMLCanvasElement;
if (canvas) {
ctx.value = canvas.getContext("2d");
}
render();
});
onUpdated(() => {
render();
});
</script>
<template>
<canvas id="canvas" :width="imageWidth * ONE_MM" :height="imageHeight * ONE_MM" />
<!-- Костыль, чтобы обновлялся стейт, неужели vue не может красиво это делать -->
<div style="display: none;">
{{ store }}
</div>
</template>
<style scoped>
canvas {
border: 1px solid black;
margin: 20px;
height: calc(100vh - 40px);
}
</style>