feat(settings/user/color): implement basic color picker without animations
This commit is contained in:
100
app/components/Settings/BottomScreen/Menus/User/Color.vue
Normal file
100
app/components/Settings/BottomScreen/Menus/User/Color.vue
Normal file
@@ -0,0 +1,100 @@
|
||||
<script setup lang="ts">
|
||||
const GRID_SIZE = 4;
|
||||
const GRID_START_X = 32;
|
||||
const GRID_START_Y = 40;
|
||||
const CELL_SIZE = 16;
|
||||
const SPACING = 16;
|
||||
const ANIMATION_SPEED = 475;
|
||||
|
||||
const app = useAppStore();
|
||||
const { assets } = useAssets();
|
||||
|
||||
let selectedCol = app.color.col;
|
||||
let selectedRow = app.color.row;
|
||||
let selectorX = GRID_START_X + selectedCol * (CELL_SIZE + SPACING) - 4;
|
||||
let selectorY = GRID_START_Y + selectedRow * (CELL_SIZE + SPACING) - 4;
|
||||
|
||||
const select = (col: number, row: number) => {
|
||||
selectedCol = col;
|
||||
selectedRow = row;
|
||||
app.setColor(col, row);
|
||||
};
|
||||
|
||||
useKeyDown((key) => {
|
||||
switch (key) {
|
||||
case "NDS_UP":
|
||||
if (selectedRow > 0) select(selectedCol, selectedRow - 1);
|
||||
break;
|
||||
case "NDS_RIGHT":
|
||||
if (selectedCol < GRID_SIZE - 1) select(selectedCol + 1, selectedRow);
|
||||
break;
|
||||
case "NDS_DOWN":
|
||||
if (selectedRow < GRID_SIZE - 1) select(selectedCol, selectedRow + 1);
|
||||
break;
|
||||
case "NDS_LEFT":
|
||||
if (selectedCol > 0) select(selectedCol - 1, selectedRow);
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
useScreenClick((x, y) => {
|
||||
const relativeX = x - GRID_START_X;
|
||||
const relativeY = y - GRID_START_Y;
|
||||
|
||||
const col = Math.floor(relativeX / (CELL_SIZE + SPACING));
|
||||
const row = Math.floor(relativeY / (CELL_SIZE + SPACING));
|
||||
|
||||
const cellLocalX = relativeX % (CELL_SIZE + SPACING);
|
||||
const cellLocalY = relativeY % (CELL_SIZE + SPACING);
|
||||
|
||||
if (
|
||||
rectContains([0, 0, GRID_SIZE, GRID_SIZE], [col, row]) &&
|
||||
rectContains([0, 0, CELL_SIZE + 1, CELL_SIZE + 1], [cellLocalX, cellLocalY])
|
||||
) {
|
||||
select(col, row);
|
||||
}
|
||||
});
|
||||
|
||||
useRender((ctx, deltaTime) => {
|
||||
ctx.drawImage(assets.settings.bottomScreen.user.colorPalette, 16, 32);
|
||||
|
||||
// animate
|
||||
const finalSelectorX = GRID_START_X + selectedCol * (CELL_SIZE + SPACING) - 4;
|
||||
const finalSelectorY = GRID_START_Y + selectedRow * (CELL_SIZE + SPACING) - 4;
|
||||
|
||||
const dx = finalSelectorX - selectorX;
|
||||
const dy = finalSelectorY - selectorY;
|
||||
|
||||
if (dx > 0) {
|
||||
selectorX += ANIMATION_SPEED * (deltaTime / 1000);
|
||||
if (selectorX > finalSelectorX) selectorX = finalSelectorX;
|
||||
} else if (dx < 0) {
|
||||
selectorX -= ANIMATION_SPEED * (deltaTime / 1000);
|
||||
if (selectorX < finalSelectorX) selectorX = finalSelectorX;
|
||||
} else if (dy > 0) {
|
||||
selectorY += ANIMATION_SPEED * (deltaTime / 1000);
|
||||
if (selectorY > finalSelectorY) selectorY = finalSelectorY;
|
||||
} else if (dy < 0) {
|
||||
selectorY -= ANIMATION_SPEED * (deltaTime / 1000);
|
||||
if (selectorY < finalSelectorY) selectorY = finalSelectorY;
|
||||
}
|
||||
|
||||
// selector
|
||||
ctx.fillStyle = APP_COLORS[selectedRow]![selectedCol]!;
|
||||
|
||||
const offsets = [0, 3, 7, 11, 15, 19, 22];
|
||||
for (const offset of offsets) {
|
||||
ctx.fillRect(selectorX + offset, selectorY + 0, 2, 1);
|
||||
ctx.fillRect(selectorX + offset, selectorY + 23, 2, 1);
|
||||
ctx.fillRect(selectorX + 0, selectorY + offset, 1, 2);
|
||||
ctx.fillRect(selectorX + 23, selectorY + offset, 1, 2);
|
||||
}
|
||||
|
||||
// preview
|
||||
ctx.fillRect(192, 96, 32, 32);
|
||||
});
|
||||
|
||||
defineOptions({
|
||||
render: () => null,
|
||||
});
|
||||
</script>
|
||||
Reference in New Issue
Block a user