refactor: dialogue caret
This commit is contained in:
parent
9f0c3f3c07
commit
aacfd6271f
103
app/react/components/dom/dialogue-caret.jsx
Normal file
103
app/react/components/dom/dialogue-caret.jsx
Normal file
|
@ -0,0 +1,103 @@
|
|||
import {RESOLUTION} from '@/util/constants.js';
|
||||
|
||||
import styles from './dialogue-caret.module.css';
|
||||
|
||||
const CARET_SIZE = 18;
|
||||
|
||||
export default function DialogueCaret({
|
||||
camera,
|
||||
dialogue,
|
||||
dimensions,
|
||||
scale,
|
||||
}) {
|
||||
const origin = 'function' === typeof dialogue.origin
|
||||
? dialogue.origin()
|
||||
: dialogue.origin || {x: 0, y: 0};
|
||||
let position = 'function' === typeof dialogue.position
|
||||
? dialogue.position()
|
||||
: dialogue.position || {x: 0, y: 0};
|
||||
position = {
|
||||
x: position.x + dialogue.offset.x,
|
||||
y: position.y + dialogue.offset.y,
|
||||
};
|
||||
const bounds = {
|
||||
x: dimensions.w / (2 * scale),
|
||||
y: dimensions.h / (2 * scale),
|
||||
};
|
||||
const left = Math.max(
|
||||
Math.min(
|
||||
position.x * scale - camera.x,
|
||||
RESOLUTION.x - bounds.x * scale - 16,
|
||||
),
|
||||
bounds.x * scale + 16,
|
||||
);
|
||||
const top = Math.max(
|
||||
Math.min(
|
||||
position.y * scale - camera.y,
|
||||
RESOLUTION.y - bounds.y * scale - 16,
|
||||
),
|
||||
bounds.y * scale + 88,
|
||||
);
|
||||
const offsetPosition = {
|
||||
x: ((position.x * scale - camera.x) - left) / scale,
|
||||
y: ((position.y * scale - camera.y) - top) / scale,
|
||||
};
|
||||
const difference = {
|
||||
x: origin.x - position.x + offsetPosition.x,
|
||||
y: origin.y - position.y + offsetPosition.y,
|
||||
};
|
||||
const within = {
|
||||
x: Math.abs(difference.x) < bounds.x,
|
||||
y: Math.abs(difference.y) < bounds.y,
|
||||
};
|
||||
const caretPosition = {
|
||||
x: Math.max(-bounds.x, Math.min(origin.x - position.x + offsetPosition.x, bounds.x)),
|
||||
y: Math.max(-bounds.y, Math.min(origin.y - position.y + offsetPosition.y, bounds.y)),
|
||||
};
|
||||
let caretRotation = Math.atan2(
|
||||
difference.y - caretPosition.y,
|
||||
difference.x - caretPosition.x,
|
||||
);
|
||||
caretRotation += Math.PI * 1.5;
|
||||
if (within.x) {
|
||||
caretPosition.y = bounds.y * Math.sign(difference.y);
|
||||
if (within.y) {
|
||||
if (Math.sign(difference.y) > 0) {
|
||||
caretRotation = Math.PI;
|
||||
}
|
||||
else {
|
||||
caretRotation = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (within.y) {
|
||||
caretPosition.x = bounds.x * Math.sign(difference.x);
|
||||
}
|
||||
// const corner = {
|
||||
// x: (bounds.x - Math.abs(caretPosition.x)) * Math.sign(caretPosition.x),
|
||||
// y: (bounds.y - Math.abs(caretPosition.y)) * Math.sign(caretPosition.y),
|
||||
// };
|
||||
caretPosition.x *= scale;
|
||||
caretPosition.y *= scale;
|
||||
caretPosition.x += -Math.sin(caretRotation) * (CARET_SIZE / 2);
|
||||
caretPosition.y += Math.cos(caretRotation) * (CARET_SIZE / 2);
|
||||
return (
|
||||
<svg
|
||||
className={styles.caret}
|
||||
viewBox="0 0 24 24"
|
||||
width={CARET_SIZE}
|
||||
height={CARET_SIZE}
|
||||
style={{
|
||||
transform: `
|
||||
translate(
|
||||
calc(-50% + ${caretPosition.x}px),
|
||||
calc(-50% + ${caretPosition.y}px)
|
||||
)
|
||||
rotate(${caretRotation}rad)
|
||||
`,
|
||||
}}
|
||||
>
|
||||
<polygon points="12 0, 18 10, 12 23, 23 10, 20 0" />
|
||||
</svg>
|
||||
);
|
||||
}
|
8
app/react/components/dom/dialogue-caret.module.css
Normal file
8
app/react/components/dom/dialogue-caret.module.css
Normal file
|
@ -0,0 +1,8 @@
|
|||
.caret {
|
||||
position: absolute;
|
||||
fill: #ffffff;
|
||||
stroke: #00000044;
|
||||
stroke-width: 2px;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
}
|
|
@ -5,10 +5,9 @@ import {useRadians} from '@/react/context/radians.js';
|
|||
import {RESOLUTION} from '@/util/constants.js';
|
||||
import {render} from '@/util/dialogue.js';
|
||||
|
||||
import DialogueCaret from './dialogue-caret.jsx';
|
||||
import styles from './dialogue.module.css';
|
||||
|
||||
const CARET_SIZE = 18;
|
||||
|
||||
export default function Dialogue({
|
||||
camera,
|
||||
dialogue,
|
||||
|
@ -75,9 +74,6 @@ export default function Dialogue({
|
|||
() => render(dialogue.letters, styles.letter),
|
||||
[dialogue.letters],
|
||||
);
|
||||
const origin = 'function' === typeof dialogue.origin
|
||||
? dialogue.origin()
|
||||
: dialogue.origin || {x: 0, y: 0};
|
||||
let position = 'function' === typeof dialogue.position
|
||||
? dialogue.position()
|
||||
: dialogue.position || {x: 0, y: 0};
|
||||
|
@ -103,45 +99,6 @@ export default function Dialogue({
|
|||
),
|
||||
bounds.y * scale + 88,
|
||||
);
|
||||
const offsetPosition = {
|
||||
x: ((position.x * scale - camera.x) - left) / scale,
|
||||
y: ((position.y * scale - camera.y) - top) / scale,
|
||||
};
|
||||
const difference = {
|
||||
x: origin.x - position.x + offsetPosition.x,
|
||||
y: origin.y - position.y + offsetPosition.y,
|
||||
};
|
||||
const within = {
|
||||
x: Math.abs(difference.x) < bounds.x,
|
||||
y: Math.abs(difference.y) < bounds.y,
|
||||
};
|
||||
const caretPosition = {
|
||||
x: Math.max(-bounds.x, Math.min(origin.x - position.x + offsetPosition.x, bounds.x)),
|
||||
y: Math.max(-bounds.y, Math.min(origin.y - position.y + offsetPosition.y, bounds.y)),
|
||||
};
|
||||
let caretRotation = Math.atan2(
|
||||
difference.y - caretPosition.y,
|
||||
difference.x - caretPosition.x,
|
||||
);
|
||||
caretRotation += Math.PI * 1.5;
|
||||
if (within.x) {
|
||||
caretPosition.y = bounds.y * Math.sign(difference.y);
|
||||
if (within.y) {
|
||||
if (Math.sign(difference.y) > 0) {
|
||||
caretRotation = Math.PI;
|
||||
}
|
||||
else {
|
||||
caretRotation = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (within.y) {
|
||||
caretPosition.x = bounds.x * Math.sign(difference.x);
|
||||
}
|
||||
caretPosition.x *= scale;
|
||||
caretPosition.y *= scale;
|
||||
caretPosition.x += -Math.sin(caretRotation) * (CARET_SIZE / 2);
|
||||
caretPosition.y += Math.cos(caretRotation) * (CARET_SIZE / 2);
|
||||
return (
|
||||
<div
|
||||
className={styles.dialogue}
|
||||
|
@ -151,23 +108,13 @@ export default function Dialogue({
|
|||
top: `${top}px`,
|
||||
}}
|
||||
>
|
||||
<svg
|
||||
className={styles.caret}
|
||||
viewBox="0 0 24 24"
|
||||
width={CARET_SIZE}
|
||||
height={CARET_SIZE}
|
||||
style={{
|
||||
transform: `
|
||||
translate(
|
||||
calc(-50% + ${caretPosition.x}px),
|
||||
calc(-50% + ${caretPosition.y}px)
|
||||
)
|
||||
rotate(${caretRotation}rad)
|
||||
`,
|
||||
}}
|
||||
>
|
||||
<polygon points="12 0, 18 10, 12 23, 23 10, 20 0" />
|
||||
</svg>
|
||||
<DialogueCaret
|
||||
camera={camera}
|
||||
dialogue={dialogue}
|
||||
dimensions={dimensions}
|
||||
scale={scale}
|
||||
|
||||
/>
|
||||
<p className={styles.letters}>
|
||||
{localRender(caret, radians)}
|
||||
</p>
|
||||
|
|
|
@ -1,12 +1,3 @@
|
|||
.caret {
|
||||
position: absolute;
|
||||
fill: #ffffff;
|
||||
stroke: #00000044;
|
||||
stroke-width: 2px;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
}
|
||||
|
||||
.dialogue {
|
||||
background-color: #02023999;
|
||||
border: solid 3px white;
|
||||
|
|
Loading…
Reference in New Issue
Block a user