Skip to content

Commit

Permalink
#147 add: Textツールの機能を追加
Browse files Browse the repository at this point in the history
  • Loading branch information
ienaga committed Jul 21, 2024
1 parent 9e05d71 commit 31f7a06
Show file tree
Hide file tree
Showing 22 changed files with 813 additions and 27 deletions.
5 changes: 5 additions & 0 deletions src/css/screen.scss
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@
}
}

.text-field
{
border : 1px dotted #363636;
}

.disabled
{
pointer-events : none;
Expand Down
11 changes: 10 additions & 1 deletion src/js/config/HistoryConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -563,4 +563,13 @@ export const $LIBRARY_ADD_NEW_SHAPE_COMMAND: number = 56;
* @type {number}
* @constant
*/
export const $LIBRARY_UPDATE_SHAPE_GRAPHICS_COMMAND: number = 57;
export const $LIBRARY_UPDATE_SHAPE_GRAPHICS_COMMAND: number = 57;

/**
* @description 新規Text追加操作の識別コマンド名
* Identification command name for new Text add operation
*
* @type {number}
* @constant
*/
export const $LIBRARY_ADD_NEW_TEXT_COMMAND: number = 58;
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ import {
$CHARACTER_UPDATE_X_COMMAND,
$CHARACTER_UPDATE_Y_COMMAND,
$LIBRARY_ADD_NEW_SHAPE_COMMAND,
$LIBRARY_UPDATE_SHAPE_GRAPHICS_COMMAND
$LIBRARY_UPDATE_SHAPE_GRAPHICS_COMMAND,
$LIBRARY_ADD_NEW_TEXT_COMMAND
} from "@/config/HistoryConfig";

/**
Expand Down Expand Up @@ -217,6 +218,9 @@ export const execute = (command: number): string =>
case $LIBRARY_UPDATE_SHAPE_GRAPHICS_COMMAND:
return "「%s1」のグラフィックを変更";

case $LIBRARY_ADD_NEW_TEXT_COMMAND:
return "新規Text「%s1」を追加";

default:
break;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ import { execute as bitmapCreateDisplayObjectElementUseCase } from "@/core/appli
import { execute as movieClipCreateDisplayObjectElementUseCase } from "@/core/application/MovieClip/usecase/MovieClipCreateDisplayObjectElementUseCase";
import { execute as shapeCreateDisplayObjectElementUseCase } from "@/core/application/Shape/usecase/ShapeCreateDisplayObjectElementUseCase";
import { execute as videoCreateDisplayObjectElementUseCase } from "@/core/application/Video/usecase/VideoCreateDisplayObjectElementUseCase";
import { execute as textCreateDisplayObjectElementUseCase } from "@/core/application/Text/usecase/TextCreateDisplayObjectElementUseCase";
import {
$BITMAP_TYPE,
$MOVIE_CLIP_TYPE,
$SHAPE_TYPE,
$TEXT_TYPE,
$VIDEO_TYPE
} from "@/config/InstanceConfig";

Expand Down Expand Up @@ -62,6 +64,12 @@ export const execute = async (
);
break;

case $TEXT_TYPE:
div = await textCreateDisplayObjectElementUseCase(
workSpace.id, instance, element, layer, character
);
break;

default:
break;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ let wait: boolean = false;
let timerId: NodeJS.Timeout;

/**
* @description スクリーンに設置したBitmapのDisplayObjectのマウスダウンイベント処理関数
* Mouse down event processing function of DisplayObject of Bitmap placed on the screen
* @description スクリーンに設置したMovieClipのDisplayObjectのマウスダウンイベント処理関数
* Mouse down event processing function of DisplayObject of MovieClip placed on the screen
*
* @param {PointerEvent} event
* @return {void}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { Character } from "@/core/domain/model/Character";
import { $getScreenOffsetLeft, $getScreenOffsetTop } from "@/global/GlobalUtil";
import { $getCurrentWorkSpace } from "../../CoreUtil";
import { $createTransformStyle } from "@/controller/application/TransformSetting/TransformSettingUtil";

/**
* @description 指定されたDisplayObjectのdivを生成して返却
* Generate and return the div of the specified DisplayObject
*
* @params {Character} character
* @params {number} layer_id
* @return {string}
* @method
* @public
*/
export const execute = (
character: Character,
layer_id: number
): string => {

// 変形スタイルを生成
const workSpace = $getCurrentWorkSpace();
const transform = $createTransformStyle(character);

const x = $getScreenOffsetLeft() + character.offsetX * workSpace.scale;
const y = $getScreenOffsetTop() + character.offsetY * workSpace.scale;
const alpha = character.alpha;
const depth = character.depth;

return `
<div class="display-object text-field layer-id-${layer_id}" data-depth="${depth}" data-layer-id="${layer_id}" style="left: ${x}px; top: ${y}px; opacity: ${alpha}; ${transform}"></div>
`;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import type { Character } from "@/core/domain/model/Character";
import type { Text } from "@/core/domain/model/Text";
import { $getConcatenatedMatrix } from "@/controller/application/TransformSetting/TransformSettingUtil";
import { $getCanvas } from "@/global/GlobalUtil";

/**
* @description TextからCanvasを生成
* Create a Canvas from Text
*
* @param {Text} text
* @return {Promise}
* @method
* @public
*/
export const execute = (
text: Text,
character: Character | null = null
): Promise<HTMLCanvasElement> => {

return new Promise(async (resolve) =>
{
const canvas = $getCanvas();
if (text.text === "") {
const bounds = text.getRawBounds();
canvas.style.width = `${bounds.xMax - 2}px`;
canvas.style.height = `${bounds.yMax - 2}px`;
return resolve(canvas);
}

const displayText = new next2d.display.TextField();
if (character && character.filters.length) {
// todo filter
}

const bounds = text.getRawBounds();
displayText.x = bounds.xMax / 2;
displayText.y = bounds.yMax / 2;

const sprite = new next2d.display.Sprite();
sprite.addChild(displayText);

const container = new next2d.display.Sprite();
container.addChild(sprite);

const concatMatrix = $getConcatenatedMatrix();
sprite.transform.matrix = new next2d.geom.Matrix(
concatMatrix[0], concatMatrix[1],
concatMatrix[2], concatMatrix[3],
0, 0
);

const matrix = new next2d.geom.Matrix();
matrix.translate(
container.width / 2,
container.height / 2
);
const scale = window.devicePixelRatio;
matrix.scale(scale, scale);

// Plyerのキャッシュをリセット
next2d.player.cacheStore.reset();

const bitmapData = new next2d.display.BitmapData(container.width * scale, container.height * scale);
bitmapData.draw(container, matrix, null, canvas, (canvas: HTMLCanvasElement): void =>
{
canvas.style.width = `${container.width - 2}px`;
canvas.style.height = `${container.height - 2}px`;
resolve(canvas);
});
});
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import type { Character } from "@/core/domain/model/Character";
import type { InstanceImpl } from "@/interface/InstanceImpl";
import type { Layer } from "@/core/domain/model/Layer";
import type { Text } from "@/core/domain/model/Text";
import { execute as textRegisterEventUseCase } from "./TextRegisterEventUseCase";
import { execute as textDisplayObjectComponent } from "../component/TextDisplayObjectComponent";
import { $getCacheCanvas, $setCacheCanvas } from "@/cache/CacheUtil";
import { execute as screenAreaHierarchyAdjustmentService } from "@/screen/application/ScreenArea/service/ScreenAreaHierarchyAdjustmentService";
import { execute as screenAreaReadOnlyElementService } from "@/screen/application/ScreenArea/service/ScreenAreaReadOnlyElementService";
import { execute as instanceUpdateBlendModeService } from "@/core/application/Instance/service/InstanceUpdateBlendModeService";
import { $getDeactivated, $getReDrawState } from "@/screen/application/ScreenArea/ScreenAreaUtil";
import { execute as screenDisplayObjectUpdateMaskInCanvasStyleService } from "@/screen/application/DisplayObject/service/ScreenDisplayObjectUpdateMaskInCanvasStyleService";
import { $MASK_IN_MODE } from "@/config/LayerModeConfig";
import { $getMaskMatrix } from "@/controller/application/TransformSetting/TransformSettingUtil";

/**
* @description Shapeをcanvasに描画して返却する
* Draw Shape to canvas and return
*
* @param {number} work_space_id
* @param {Shape} instance
* @param {HTMLElement} element
* @param {Layer} layer
* @param {Character} character
* @return {Promise}
* @method
* @public
*/
export const execute = async (
work_space_id: number,
instance: InstanceImpl<Text>,
element: HTMLElement,
layer: Layer,
character: Character
): Promise<HTMLDivElement> => {

const cacheKey = character.cacheKey;

let canvas = $getCacheCanvas(work_space_id, instance.id, cacheKey);
if (!canvas) {
// TODO filters check
canvas = await instance.getHTMLElement(character);

// キャッシュに保存
$setCacheCanvas(work_space_id, instance.id, cacheKey, canvas);
}

// ブレンドモードを設定
instanceUpdateBlendModeService(canvas, character.blendMode);

// ステージに追加
element.insertAdjacentHTML("beforeend",
textDisplayObjectComponent(character, layer.id)
);

const div = element.lastElementChild as HTMLDivElement;
div.appendChild(canvas);

// マスクのスタイルを更新
if (layer.mode === $MASK_IN_MODE) {
await screenDisplayObjectUpdateMaskInCanvasStyleService(
div, layer, character.x, character.y,
$getMaskMatrix(character)
);
}

// 追加するDisplayObjectのレイヤーの階層を調整
if (!$getReDrawState()) {
screenAreaHierarchyAdjustmentService(element, div, layer);
}

// イベントを登録
if (!$getDeactivated()) {
textRegisterEventUseCase(div);
} else {
screenAreaReadOnlyElementService(div);
}

return div;
};
96 changes: 96 additions & 0 deletions src/js/core/application/Text/usecase/TextMouseDownEventUseCase.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import { $getActiveTool } from "@/tool/application/ToolUtil";
import { EventType } from "@/tool/domain/event/EventType";
import { $getCurrentWorkSpace } from "../../CoreUtil";
import { $TEXT_TYPE } from "@/config/InstanceConfig";

/**
* @description ダブルタップ用の待機フラグ
* Standby flag for double-tap
*
* @type {boolean}
* @private
*/
let wait: boolean = false;

/**
* @description ダブルタップ用の待機フラグのタイマー起動ID
* Timer activation ID for standby flag for double-tap
*
* @type {boolean}
* @private
*/
let timerId: NodeJS.Timeout;

/**
* @description スクリーンに設置したTextのDisplayObjectのマウスダウンイベント処理関数
* Mouse down event processing function of DisplayObject of Text placed on the screen
*
* @param {PointerEvent} event
* @return {void}
* @method
* @public
*/
export const execute = async (event: PointerEvent): Promise<void> =>
{
if (event.button !== 0) {
return ;
}

// 親のイベントをキャンセル
event.stopPropagation();

// 移動用のwindowイベントを登録
const tool = $getActiveTool();
if (!tool) {
return ;
}

// タイマー予約をクリア
clearTimeout(timerId);

if (!wait) {
// 初回のタップであればダブルタップを待機モードに変更
wait = true;

// ダブルタップ有効期限をセット
timerId = setTimeout((): void =>
{
wait = false;
}, 300);

// タップイベントを発火
tool.dispatchEvent(EventType.DISPLAY_OBJRCY, event);

} else {

// ダブルタップを終了
wait = false;

const element = event.target as HTMLElement;
if (!element) {
return ;
}

const workSpace = $getCurrentWorkSpace();
const movieClip = workSpace.scene;

const layerId = parseInt(element.dataset.layerId as string);
const layer = movieClip.getLayerById(layerId);
if (!layer) {
return ;
}

const depth = parseInt(element.dataset.depth as string);
const character = layer.getCharacter(movieClip.currentFrame, depth);
if (!character) {
return ;
}

const text = workSpace.getLibrary(character.libraryId);
if (!text || text.type !== $TEXT_TYPE) {
return ;
}

console.log(text);
}
};
19 changes: 19 additions & 0 deletions src/js/core/application/Text/usecase/TextRegisterEventUseCase.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { EventType } from "@/tool/domain/event/EventType";
import { execute as textMouseDownEventUseCase } from "./TextMouseDownEventUseCase";

/**
* @description スクリーンに配置するTextのイベントを登録する
* Register events for Text placed on the screen
*
* @param {HTMLElement} element
* @return {void}
* @method
* @public
*/
export const execute = (element: HTMLElement): void =>
{
// マウスダウンイベントを登録
element.addEventListener(EventType.MOUSE_DOWN,
textMouseDownEventUseCase
);
};
Loading

0 comments on commit 31f7a06

Please sign in to comment.