1
0
mirror of https://github.com/MultiMote/niimblue synced 2026-01-19 19:37:11 +03:00

Add object position controls (#88)

This commit is contained in:
MultiMote
2025-06-22 22:54:25 +03:00
parent 4f2fe44e69
commit 3482b50cb2
4 changed files with 85 additions and 0 deletions

View File

@@ -3,6 +3,7 @@
import { tr } from "../../utils/i18n";
import MdIcon from "../basic/MdIcon.svelte";
import { appConfig } from "../../stores";
import ObjectPositionControls from "./ObjectPositionControls.svelte";
export let selectedObject: fabric.FabricObject;
export let valueUpdated: () => void;
@@ -67,6 +68,8 @@
<MdIcon icon="horizontal_distribute" />
</button>
<ObjectPositionControls {selectedObject} />
<div class="dropdown">
<button
class="btn btn-sm btn-secondary dropdown-toggle"

View File

@@ -0,0 +1,80 @@
<script lang="ts">
import MdIcon from "../basic/MdIcon.svelte";
import { tr } from "../../utils/i18n";
import * as fabric from "fabric";
import { onDestroy } from "svelte";
import QRCode from "../../fabric-object/qrcode";
import Barcode from "../../fabric-object/barcode";
export let selectedObject: fabric.FabricObject;
let prevObject: fabric.FabricObject | undefined;
let x: number;
let y: number;
let width: number;
let height: number;
const objectDimensionsChanged = () => {
const pos = selectedObject.getPointByOrigin("left", "top");
x = pos.x;
y = pos.y;
width = selectedObject.width;
height = selectedObject.height;
};
const objectChanged = (newObject: fabric.FabricObject) => {
if (prevObject !== undefined) {
prevObject.off("modified", objectDimensionsChanged);
}
newObject.on("modified", objectDimensionsChanged);
objectDimensionsChanged();
prevObject = newObject;
};
const updateObject = () => {
const newPos = new fabric.Point(Math.round(Math.max(x, 1)), Math.round(Math.max(y, 1)));
selectedObject.setPositionByOrigin(newPos, "left", "top");
selectedObject.set({
width: Math.round(Math.max(width, 1)),
height: Math.round(Math.max(height, 1)),
});
selectedObject.setCoords();
selectedObject.canvas?.requestRenderAll();
};
onDestroy(() => selectedObject.off("modified", objectDimensionsChanged));
$: objectChanged(selectedObject);
</script>
<div class="dropdown">
<button
class="btn btn-sm btn-secondary dropdown-toggle"
type="button"
data-bs-toggle="dropdown"
title={$tr("params.generic.position")}>
<MdIcon icon="control_camera" />
</button>
<div class="dropdown-menu arrangement p-2">
<div class="input-group flex-nowrap input-group-sm mb-2">
<span class="input-group-text">x</span>
<input class="form-control" type="number" min="1" bind:value={x} on:change={updateObject} />
</div>
<div class="input-group flex-nowrap input-group-sm mb-2">
<span class="input-group-text">y</span>
<input class="form-control" type="number" min="1" bind:value={y} on:change={updateObject} />
</div>
{#if !(selectedObject instanceof fabric.FabricText || selectedObject instanceof fabric.FabricImage || selectedObject instanceof QRCode || selectedObject instanceof Barcode)}
<div class="input-group flex-nowrap input-group-sm mb-2">
<input class="form-control" type="number" min="1" bind:value={width} on:change={updateObject} />
<span class="input-group-text">x</span>
<input class="form-control" type="number" min="1" bind:value={height} on:change={updateObject} />
</div>
{/if}
</div>
</div>

View File

@@ -49,6 +49,7 @@
"params.generic.fit.mode.stretch": "Stretch",
"params.generic.fit.mode.ratio_min": "Fit",
"params.generic.fit.mode.ratio_max": "Fill",
"params.generic.position": "Position",
"params.label.apply": "Apply",
"params.label.current": "Current parameters:",
"params.label.direction.left": "Left",

View File

@@ -49,6 +49,7 @@
"params.generic.fit.mode.stretch": "Растянуть",
"params.generic.fit.mode.ratio_min": "Подогнать",
"params.generic.fit.mode.ratio_max": "Заполнить",
"params.generic.position": "Расположение",
"params.label.apply": "Применить",
"params.label.current": "Текущие параметры:",
"params.label.direction.left": "Слева",