generated from Klectr/KTemplate
Add minimap so user can tell where they are on page
This commit is contained in:
parent
d14b240333
commit
665e82ca43
@ -1,32 +1,31 @@
|
||||
import { useState, useRef, useEffect } from "kaioken"
|
||||
import { useRef, useEffect } from "kaioken"
|
||||
import { CardSelector } from "./CardSelector"
|
||||
import { NotesSigal } from "../signals"
|
||||
import { NotesSigal, canvasDimentsion } from "../signals"
|
||||
import { NoteCard } from "./NoteCard"
|
||||
import notes from "../signals/notes"
|
||||
import { MiniMap } from "./MiniMap"
|
||||
|
||||
export default function InfiniteCanvas() {
|
||||
const [dimensions, setDimensions] = useState({ width: 3000, height: 3000 })
|
||||
const containerRef = useRef<HTMLDivElement>(null)
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
window.scrollTo({
|
||||
left: (dimensions.width / 2) - (window.innerWidth / 2),
|
||||
top: (dimensions.height / 2) - (window.innerHeight / 2)
|
||||
left: (canvasDimentsion.value.width / 2) - (window.innerWidth / 2),
|
||||
top: (canvasDimentsion.value.height / 2) - (window.innerHeight / 2)
|
||||
})
|
||||
|
||||
const updateDimensions = () => {
|
||||
setDimensions((prevDimensions) => ({
|
||||
width: Math.max(prevDimensions.width, window.innerWidth),
|
||||
height: Math.max(prevDimensions.height, window.innerHeight),
|
||||
}))
|
||||
canvasDimentsion.value = {
|
||||
width: Math.max(canvasDimentsion.value.width, window.innerWidth),
|
||||
height: Math.max(canvasDimentsion.value.height, window.innerHeight),
|
||||
}
|
||||
}
|
||||
|
||||
updateDimensions()
|
||||
window.addEventListener("resize", updateDimensions)
|
||||
notes.loadLocalStorage()
|
||||
|
||||
|
||||
return () => {
|
||||
window.removeEventListener("resize", updateDimensions)
|
||||
}
|
||||
@ -35,6 +34,7 @@ export default function InfiniteCanvas() {
|
||||
return (
|
||||
<>
|
||||
<CardSelector />
|
||||
<MiniMap />
|
||||
|
||||
<div
|
||||
className="h-screen w-full absolute top-0 left-0"
|
||||
@ -43,8 +43,8 @@ export default function InfiniteCanvas() {
|
||||
className="absolute top-0 left-0"
|
||||
ref={containerRef}
|
||||
style={{
|
||||
width: `${dimensions.width.toString()}px`,
|
||||
height: `${dimensions.width.toString()}px`,
|
||||
width: `${canvasDimentsion.value.width}px`,
|
||||
height: `${canvasDimentsion.value.width}px`,
|
||||
backgroundSize: "30px 30px",
|
||||
backgroundImage: "radial-gradient(circle, rgba(255, 255, 255, 0.2) 1px, transparent 1px)",
|
||||
}}>
|
||||
|
78
src/components/MiniMap.tsx
Normal file
78
src/components/MiniMap.tsx
Normal file
@ -0,0 +1,78 @@
|
||||
import { signal, useEffect, useRef } from "kaioken"
|
||||
import notes from "../signals/notes"
|
||||
import { Card } from "../types/Card"
|
||||
import { canvasDimentsion } from "../signals"
|
||||
import { LayerEnum } from "../utils/enums"
|
||||
|
||||
const _MAP_OFFSET = 20
|
||||
const _MAP_SCALE_FACTOR = 10
|
||||
const _defaults = { width: 0, height: 0 }
|
||||
|
||||
export function MiniMap() {
|
||||
const el = useRef<HTMLDivElement>(null)
|
||||
const scrollX = signal(0)
|
||||
const scrollY = signal(0)
|
||||
|
||||
const elMeta = el.current?.getBoundingClientRect() ?? _defaults
|
||||
const viewportWidth = window.innerWidth
|
||||
const viewportHeight = window.innerHeight
|
||||
const xPos = viewportWidth - elMeta?.width - _MAP_OFFSET
|
||||
const yPos = viewportHeight - elMeta.height - _MAP_OFFSET
|
||||
const width = canvasDimentsion.value.width / _MAP_SCALE_FACTOR
|
||||
const height = canvasDimentsion.value.height / _MAP_SCALE_FACTOR
|
||||
|
||||
useEffect(() => {
|
||||
function _handleScroll(_e: Event) {
|
||||
scrollX.value = window.scrollX
|
||||
scrollY.value = window.scrollY
|
||||
}
|
||||
window.addEventListener('scroll', _handleScroll)
|
||||
|
||||
return () => window.removeEventListener('scroll', _handleScroll)
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div ref={el} style={{
|
||||
position: 'fixed',
|
||||
backgroundColor: '#ffffff11',
|
||||
width: `${width}px`,
|
||||
height: `${height}px`,
|
||||
translate: `${xPos}px ${yPos}px`,
|
||||
zIndex: `${LayerEnum.MINIMAP}`,
|
||||
borderRadius: '4px'
|
||||
}}>
|
||||
|
||||
|
||||
{Object.keys(notes.notes.value).map((noteKey: Card['id']) => {
|
||||
const note = notes.notes.value[noteKey]
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
position: 'absolute',
|
||||
width: `${note.dimensions.w / _MAP_SCALE_FACTOR}px`,
|
||||
height: `${note.dimensions.h / _MAP_SCALE_FACTOR}px`,
|
||||
top: `${(note.position.y / _MAP_SCALE_FACTOR)}px`,
|
||||
left: `${(note.position.x / _MAP_SCALE_FACTOR)}px`,
|
||||
backgroundColor: "#666",
|
||||
border: '1px solid #222',
|
||||
borderRadius: '2px'
|
||||
}}
|
||||
></div>
|
||||
)
|
||||
})}
|
||||
|
||||
<div style={{
|
||||
position: 'absolute',
|
||||
width: `${viewportWidth / _MAP_SCALE_FACTOR}px`,
|
||||
height: `${viewportHeight / _MAP_SCALE_FACTOR}px`,
|
||||
top: `${scrollY.value / _MAP_SCALE_FACTOR}px`,
|
||||
left: `${scrollX.value / _MAP_SCALE_FACTOR}px`,
|
||||
border: '1px solid #777',
|
||||
zIndex: `${LayerEnum.MINIMAP}`,
|
||||
backgroundColor: '#fff1',
|
||||
borderRadius: '2px'
|
||||
}}></div>
|
||||
</div >
|
||||
)
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ import { NotesSigal, focusedItem } from "../signals"
|
||||
import { Card } from "../types"
|
||||
import { useDebounce } from "../utils/useDebounce"
|
||||
import notes from "../signals/notes"
|
||||
import { save } from "@tauri-apps/api/dialog"
|
||||
import { LayerEnum } from "../utils/enums"
|
||||
|
||||
namespace NoteCard {
|
||||
export interface NoteCardProps {
|
||||
@ -56,14 +56,12 @@ export function NoteCard({ key: itemKey, data: item }: NoteCard.NoteCardProps) {
|
||||
window.addEventListener('mouseup', _handleMouseUp)
|
||||
}
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<div
|
||||
onmousedown={() => focusedItem.value = itemKey}
|
||||
className="select-none transition flex flex-col justify-stretch shadow-lg rounded border border-[#3c3c3c] absolute"
|
||||
style={{
|
||||
zIndex: focusedItem.value == itemKey ? '999' : '0',
|
||||
zIndex: `${focusedItem.value == itemKey ? LayerEnum.CARD_ELEVATED : LayerEnum.CARD}`,
|
||||
width: `${item.dimensions.w}px`,
|
||||
height: `${item.dimensions.h}px`,
|
||||
top: `${item.position.y}px`,
|
||||
|
@ -2,5 +2,6 @@ import { signal } from "kaioken"
|
||||
|
||||
/** this should be an ID of some card/item */
|
||||
export const focusedItem = signal<string | null>(null)
|
||||
export const canvasDimentsion = signal({ width: 3000, height: 3000 })
|
||||
|
||||
export * as NotesSigal from "./notes"
|
||||
|
@ -8,6 +8,10 @@
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
*::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
html {
|
||||
overflow: scroll;
|
||||
}
|
||||
|
6
src/utils/enums.ts
Normal file
6
src/utils/enums.ts
Normal file
@ -0,0 +1,6 @@
|
||||
export enum LayerEnum {
|
||||
BACKGROUND,
|
||||
CARD,
|
||||
CARD_ELEVATED,
|
||||
MINIMAP,
|
||||
}
|
Loading…
Reference in New Issue
Block a user