@sequent-org/moodboard 1.2.103 → 1.2.105

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sequent-org/moodboard",
3
- "version": "1.2.103",
3
+ "version": "1.2.105",
4
4
  "type": "module",
5
5
  "description": "Interactive moodboard",
6
6
  "main": "./src/index.js",
@@ -252,17 +252,35 @@ export class PlacementTool extends BaseTool {
252
252
  };
253
253
 
254
254
  if (isTextWithEditing) {
255
- // Для текста позиция должна совпадать с точкой клика без смещений
256
- // Диагностика: логируем позицию курсора и мировые координаты в момент клика
255
+ // Для текста позиция должна совпадать с точкой клика без смещений.
256
+ // Используем ту же систему координат, что HtmlTextLayer/HtmlHandlesLayer:
257
+ // CSS ←→ world через toGlobal/toLocal БЕЗ дополнительных поправок на resolution.
258
+ let worldForText = worldPoint;
257
259
  try {
260
+ const app = this.app;
261
+ const view = app?.view;
262
+ const worldLayer = this.world || this._getWorldLayer();
263
+ if (view && view.parentElement && worldLayer && worldLayer.toLocal) {
264
+ const containerRect = view.parentElement.getBoundingClientRect();
265
+ const viewRect = view.getBoundingClientRect();
266
+ const offsetLeft = viewRect.left - containerRect.left;
267
+ const offsetTop = viewRect.top - containerRect.top;
268
+ // event.x / event.y заданы в координатах контейнера ToolManager,
269
+ // поэтому приводим их к экранным координатам относительно view
270
+ const screenX = event.x - offsetLeft;
271
+ const screenY = event.y - offsetTop;
272
+ const globalPoint = new PIXI.Point(screenX, screenY);
273
+ const local = worldLayer.toLocal(globalPoint);
274
+ worldForText = { x: local.x, y: local.y };
275
+ }
258
276
  console.log('🧭 Text click', {
259
277
  cursor: { x: event.x, y: event.y },
260
- world: { x: Math.round(worldPoint.x), y: Math.round(worldPoint.y) }
278
+ world: { x: Math.round(worldForText.x), y: Math.round(worldForText.y) }
261
279
  });
262
280
  } catch (_) {}
263
281
  position = {
264
- x: Math.round(worldPoint.x),
265
- y: Math.round(worldPoint.y)
282
+ x: Math.round(worldForText.x),
283
+ y: Math.round(worldForText.y)
266
284
  };
267
285
  // Слушаем событие создания объекта, чтобы получить его ID
268
286
  const handleObjectCreated = (objectData) => {
@@ -2067,23 +2067,49 @@ export class SelectTool extends BaseTool {
2067
2067
  } catch (_) {}
2068
2068
 
2069
2069
  // Для новых текстов: синхронизируем мировую позицию объекта с фактической позицией wrapper,
2070
- // чтобы после закрытия редактора статичный текст встал ровно туда же без сдвига
2070
+ // чтобы после закрытия редактора статичный текст встал ровно туда же без сдвига.
2071
+ // Используем ту же систему координат, что и HtmlTextLayer/HtmlHandlesLayer:
2072
+ // CSS ←→ world через toGlobal/toLocal БЕЗ умножения/деления на resolution.
2071
2073
  try {
2072
2074
  if (create && objectId) {
2073
2075
  const worldLayerRef = this.textEditor.world || (this.app?.stage);
2074
- const viewRes = (this.app?.renderer?.resolution) || (view.width && view.clientWidth ? (view.width / view.clientWidth) : 1);
2075
- // Статичный HTML-текст не имеет верхнего внутреннего отступа (HtmlTextLayer ставит padding: 0),
2076
- // поэтому добавляем padTop к topPx при расчёте мировых координат
2077
- const yCssStaticTop = Math.round(topPx + padTop);
2078
- const globalPoint = new PIXI.Point(Math.round(leftPx * viewRes), Math.round(yCssStaticTop * viewRes));
2079
- const worldPoint = worldLayerRef && worldLayerRef.toLocal ? worldLayerRef.toLocal(globalPoint) : { x: position.x, y: position.y };
2080
- const newWorldPos = { x: Math.round(worldPoint.x), y: Math.round(worldPoint.y) };
2081
- this.eventBus.emit(Events.Object.StateChanged, {
2082
- objectId: objectId,
2083
- updates: { position: newWorldPos }
2084
- });
2085
- // Диагностика
2086
- console.log('🧭 Text position sync', { objectId, newWorldPos, leftPx, topPx, yCssStaticTop, padTop, viewRes });
2076
+ const viewEl = this.app?.view;
2077
+ if (worldLayerRef && viewEl && viewEl.parentElement) {
2078
+ const containerRect = viewEl.parentElement.getBoundingClientRect();
2079
+ const viewRect = viewEl.getBoundingClientRect();
2080
+ const offsetLeft = viewRect.left - containerRect.left;
2081
+ const offsetTop = viewRect.top - containerRect.top;
2082
+
2083
+ // Статичный HTML-текст не имеет верхнего внутреннего отступа (HtmlTextLayer ставит padding: 0),
2084
+ // поэтому добавляем padTop к topPx при расчёте мировой позиции верхнего края текста.
2085
+ const yCssStaticTop = Math.round(topPx + padTop);
2086
+ // Переводим CSS-координаты wrapper в экранные координаты относительно view
2087
+ const screenX = Math.round(leftPx - offsetLeft);
2088
+ const screenY = Math.round(yCssStaticTop - offsetTop);
2089
+ const globalPoint = new PIXI.Point(screenX, screenY);
2090
+ const worldPoint = worldLayerRef.toLocal
2091
+ ? worldLayerRef.toLocal(globalPoint)
2092
+ : { x: position.x, y: position.y };
2093
+ const newWorldPos = {
2094
+ x: Math.round(worldPoint.x),
2095
+ y: Math.round(worldPoint.y)
2096
+ };
2097
+ this.eventBus.emit(Events.Object.StateChanged, {
2098
+ objectId: objectId,
2099
+ updates: { position: newWorldPos }
2100
+ });
2101
+ // Диагностика
2102
+ console.log('🧭 Text position sync', {
2103
+ objectId,
2104
+ newWorldPos,
2105
+ leftPx,
2106
+ topPx,
2107
+ yCssStaticTop,
2108
+ padTop,
2109
+ offsetLeft,
2110
+ offsetTop
2111
+ });
2112
+ }
2087
2113
  }
2088
2114
  } catch (_) {}
2089
2115
  }