Trying new pinch to zoom mode
This commit is contained in:
parent
4b901a87d7
commit
1c9812c3a8
10
app.vue
10
app.vue
|
|
@ -6,6 +6,8 @@ function toggleLeftPanel(_: Event): void {
|
|||
</script>
|
||||
|
||||
<script setup lang="ts">
|
||||
const { path } = useRoute();
|
||||
|
||||
const { data: tags } = await useAsyncData('descriptions', queryContent('/tags').findOne);
|
||||
|
||||
provide('tags/descriptions', tags);
|
||||
|
|
@ -14,7 +16,7 @@ onMounted(() => {
|
|||
icon = document.querySelector('.site-nav-bar .clickable-icon');
|
||||
icon?.removeEventListener('click', toggleLeftPanel);
|
||||
icon?.addEventListener('click', toggleLeftPanel);
|
||||
})
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
@ -29,9 +31,9 @@ onMounted(() => {
|
|||
</svg>
|
||||
</div>
|
||||
<div class="gap-3">
|
||||
<NuxtLink class="site-nav-bar-text" aria-label="Accueil" :href="'/'">Accueil</NuxtLink>
|
||||
<NuxtLink class="site-nav-bar-text" aria-label="Systeme" :href="'/explorer'">Systeme</NuxtLink>
|
||||
<NuxtLink class="site-nav-bar-text" aria-label="Outils" :href="'/tools'">Outils</NuxtLink>
|
||||
<NuxtLink class="site-nav-bar-text" aria-label="Accueil" :href="'/'" ><img src="" /></NuxtLink>
|
||||
<NuxtLink class="site-nav-bar-text" aria-label="Systeme" :href="'/explorer'" :class="{'mod-active': path.startsWith('/explorer')}">Systeme</NuxtLink>
|
||||
<NuxtLink class="site-nav-bar-text" aria-label="Outils" :href="'/tools'" :class="{'mod-active': path.startsWith('/tools')}">Outils</NuxtLink>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
|
|
|
|||
|
|
@ -51,24 +51,24 @@
|
|||
|
||||
.gap-1 > *
|
||||
{
|
||||
padding-left: .4em;
|
||||
padding-right: .4em;
|
||||
margin-left: .4em;
|
||||
margin-right: .4em;
|
||||
}
|
||||
.gap-1 > *:first-child, .gap-2 > *:first-child, .gap-3 > *:first-child
|
||||
{
|
||||
padding-left: 0;
|
||||
margin-left: 0;
|
||||
}
|
||||
.gap-1 > *:last-child, .gap-2 > *:last-child, .gap-3 > *:last-child
|
||||
{
|
||||
padding-right: 0;
|
||||
margin-right: 0;
|
||||
}
|
||||
.gap-2 > *
|
||||
{
|
||||
padding-left: .8em;
|
||||
padding-right: .8em;
|
||||
margin-left: .8em;
|
||||
margin-right: .8em;
|
||||
}
|
||||
.gap-3 > *
|
||||
{
|
||||
padding-left: 1.2em;
|
||||
padding-right: 1.2em;
|
||||
margin-left: 1.2em;
|
||||
margin-right: 1.2em;
|
||||
}
|
||||
|
|
@ -45,7 +45,7 @@
|
|||
--site-name-color-hover: var(--text-muted);
|
||||
--site-name-font: inherit;
|
||||
--site-name-size: 18px;
|
||||
--site-name-weight: var(--font-medium);
|
||||
--site-name-weight: var(--font-normal);
|
||||
--site-menu-icon-color: var(--text-faint);
|
||||
--site-menu-icon-color-hover: var(--text-normal);
|
||||
--site-menu-icon-size: 24px;
|
||||
|
|
@ -4982,4 +4982,9 @@ body {
|
|||
|
||||
.site-nav-bar > div:last-child {
|
||||
justify-content: end;
|
||||
}
|
||||
|
||||
.site-nav-bar-text.mod-active {
|
||||
padding-bottom: .5em;
|
||||
border-bottom: 3px solid var(--nav-item-border-color-active);
|
||||
}
|
||||
|
|
@ -31,10 +31,12 @@ const results = computed(() => {
|
|||
</div>
|
||||
<Teleport to="body" v-if="input !== ''">
|
||||
<div class="search-results" :style="{top: (pos.bottom + 4) + 'px', left: pos.left + 'px', width: pos.width + 'px'}">
|
||||
<div class="suggestion-item" v-if="results.length > 0" v-for="result of results" :key="result._path" @mouseenter="(e) => (e.target as HTMLElement).classList.add('is-selected')" @mouseleave="(e) => (e.target as HTMLElement).classList.remove('is-selected')" @mousedown="navigateTo('/explorer' + result._path); input = ''">
|
||||
<div class="suggestion-item" v-if="results.length > 0" v-for="result of results" :key="result._path" @mouseenter="(e) => (e.target as HTMLElement).classList.add('is-selected')" @mouseleave="(e) => (e.target as HTMLElement).classList.remove('is-selected')" @mousedown.prevent="navigateTo('/explorer' + result._path); input = ''">
|
||||
<div class="suggestion-content">
|
||||
<div class="suggestion-title">
|
||||
{{ result.title.substring(0, clear(result.title).indexOf(clear(input))) }}<span class="suggestion-highlight">{{ result.title.substring(clear(result.title).indexOf(clear(input)), clear(result.title).indexOf(clear(input)) + clear(input).length + 1) }}</span>{{ result.title.substring(clear(result.title).indexOf(clear(input)) + clear(input).length + 1) }}
|
||||
<ProseA :href="result._path">
|
||||
{{ result.title.substring(0, clear(result.title).indexOf(clear(input))) }}<span class="suggestion-highlight">{{ result.title.substring(clear(result.title).indexOf(clear(input)), clear(result.title).indexOf(clear(input)) + clear(input).length + 1) }}</span>{{ result.title.substring(clear(result.title).indexOf(clear(input)) + clear(input).length + 1) }}
|
||||
</ProseA>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ function darken(rgb: string): boolean
|
|||
|
||||
const props = defineProps<Props>();
|
||||
|
||||
const classes: any = { 'canvas-node-group': props.node.type === 'group', 'is-themed': props.node.color !== undefined, 'mod-canvas-color-custom': (props.node?.color?.startsWith('#') ?? false) };
|
||||
const classes: Record<string, boolean> = { 'canvas-node-group': props.node.type === 'group', 'is-themed': props.node.color !== undefined, 'mod-canvas-color-custom': (props.node?.color?.startsWith('#') ?? false) };
|
||||
const size = Math.max(props.node.width, props.node.height);
|
||||
|
||||
if(props.node.color !== undefined)
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ let centerX = ref(0), centerY = ref(0), canvas = ref<HTMLDivElement>();
|
|||
let minX = ref(+Infinity), minY = ref(+Infinity), maxX = ref(-Infinity), maxY = ref(-Infinity);
|
||||
let bbox = ref<DOMRect>();
|
||||
|
||||
let lastPinchLength = 0;
|
||||
|
||||
let _minX = +Infinity, _minY = +Infinity, _maxX = -Infinity, _maxY = -Infinity;
|
||||
|
||||
onMounted(async () => {
|
||||
|
|
@ -66,7 +68,7 @@ const onPointerDown = (event: PointerEvent) => {
|
|||
}
|
||||
|
||||
const onPointerMove = (event: PointerEvent) => {
|
||||
if (event.isPrimary === false) return;
|
||||
if (event.isPrimary === false || dragging === false) return;
|
||||
dispX.value -= (posX - event.clientX) / zoom.value;
|
||||
dispY.value -= (posY - event.clientY) / zoom.value;
|
||||
|
||||
|
|
@ -79,11 +81,39 @@ const onPointerUp = (event: PointerEvent) => {
|
|||
dragging = false;
|
||||
document.removeEventListener('pointermove', onPointerMove);
|
||||
document.removeEventListener('pointerup', onPointerUp);
|
||||
document.removeEventListener('pointercancel', onPointerUp);
|
||||
}
|
||||
|
||||
const onWheel = (event: WheelEvent) => {
|
||||
zoom.value = clamp(zoom.value * 1 + (event.deltaY * -0.001), minZoom.value, 3);
|
||||
zoom.value = clamp(zoom.value + (event.deltaY * -0.001), minZoom.value, 3);
|
||||
}
|
||||
|
||||
const onTouchStart = (event: TouchEvent) => {
|
||||
if(event.touches?.length === 2)
|
||||
{
|
||||
dragging = false;
|
||||
lastPinchLength = length(event.touches[0].clientX, event.touches[0].clientY, event.touches[1].clientX, event.touches[1].clientY);
|
||||
|
||||
document.addEventListener('touchmove', onTouchMove);
|
||||
document.addEventListener('touchend', onTouchEnd);
|
||||
}
|
||||
}
|
||||
|
||||
const onTouchEnd = (event: TouchEvent) => {
|
||||
if(event.touches?.length !== 2)
|
||||
dragging = true;
|
||||
|
||||
document.removeEventListener('touchmove', onTouchMove);
|
||||
document.removeEventListener('touchend', onTouchEnd);
|
||||
}
|
||||
|
||||
const onTouchMove = (event: TouchEvent) => {
|
||||
if(event.touches?.length === 2)
|
||||
{
|
||||
const l = length(event.touches[0].clientX, event.touches[0].clientY, event.touches[1].clientX, event.touches[1].clientY);
|
||||
zoom.value = clamp(zoom.value + ((lastPinchLength - l) * -0.01), minZoom.value, 3);
|
||||
|
||||
lastPinchLength = l;
|
||||
}
|
||||
}
|
||||
|
||||
const reset = (_: MouseEvent) => {
|
||||
|
|
@ -98,6 +128,9 @@ function clamp(x: number, min: number, max: number): number {
|
|||
return min;
|
||||
return x;
|
||||
}
|
||||
function length(x1: number, y1: number, x2: number, y2: number): number {
|
||||
return Math.sqrt((x2 - x1)^2 + (y2 - y1)^2);
|
||||
}
|
||||
function edgePos(side: 'bottom' | 'top' | 'left' | 'right', pos: { x: number, y: number }, n: number): { x: number, y: number } {
|
||||
switch (side) {
|
||||
case "left":
|
||||
|
|
@ -180,7 +213,7 @@ function getCenter(n: { x: number, y: number }, i: { x: number, y: number }, r:
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<div ref="canvas" @pointerdown="onPointerDown" @wheel.passive="onWheel" @touchstart.prevent="" @dragstart.prevent=""
|
||||
<div ref="canvas" @pointerdown="onPointerDown" @wheel.passive="onWheel" @touchstart.prevent="onTouchStart" @dragstart.prevent=""
|
||||
class="canvas-wrapper node-insert-event mod-zoomed-out"
|
||||
:style="{ '--zoom-multiplier': (1 / Math.pow(zoom, 0.7)) }">
|
||||
<div class="canvas-controls" style="z-index: 999;">
|
||||
|
|
|
|||
|
|
@ -11,6 +11,12 @@ export default defineNuxtConfig({
|
|||
},
|
||||
],
|
||||
|
||||
router: {
|
||||
options: {
|
||||
scrollBehaviorType: 'smooth'
|
||||
}
|
||||
},
|
||||
|
||||
css: ['~/assets/common.css', '~/assets/global.css'],
|
||||
|
||||
content: {
|
||||
|
|
|
|||
Loading…
Reference in New Issue