-
-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(pdf-helipad): add component
pdf-helipad
- Loading branch information
Showing
7 changed files
with
358 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
<template> | ||
<div | ||
ref="root" | ||
class="pdf-helipad"> | ||
<div | ||
ref="object" | ||
class="pdf-object pdf-object--external" | ||
:style="{ width: `${width}px`, height: `${height}px` }"> | ||
<slot /> | ||
</div> | ||
<div | ||
class="pdf-helipad__shadow" | ||
:style="{ width: `${width}px`, height: `${height}px` }"> | ||
<slot /> | ||
</div> | ||
</div> | ||
</template> | ||
|
||
<script lang="ts"> | ||
import { templateRef } from '@vueuse/core' | ||
import { | ||
defineComponent, | ||
ref, | ||
toRef, | ||
watchEffect, | ||
} from 'vue-demi' | ||
import { getPosition } from '../pdf-object/utils/position' | ||
import useDrag from './utils/use-drag' | ||
export default defineComponent({ | ||
props: { | ||
scale: { | ||
type : Number, | ||
default: 1, | ||
}, | ||
width: { | ||
type : Number, | ||
default: 198, | ||
}, | ||
height: { | ||
type : Number, | ||
default: 106, | ||
}, | ||
}, | ||
emits: ['landed'], | ||
setup (props, { emit }) { | ||
const object = templateRef<HTMLDivElement>('object') | ||
const scale = toRef(props, 'scale') | ||
const isDragged = ref(false) | ||
const x = ref(0) | ||
const y = ref(0) | ||
useDrag(object, { | ||
onstart () { | ||
const { left, top } = object.value.getBoundingClientRect() | ||
isDragged.value = true | ||
x.value = left | ||
y.value = top | ||
}, | ||
onmove (event) { | ||
x.value += event.dx | ||
y.value += event.dy | ||
}, | ||
onend (event) { | ||
isDragged.value = false | ||
if (event.relatedTarget) { | ||
const reference = event.relatedTarget | ||
const container = reference.closest('.pdf__container') | ||
const result = getPosition({ | ||
reference: reference as HTMLDivElement, | ||
container: container as HTMLDivElement, | ||
object : object.value, | ||
scale : scale.value, | ||
}) | ||
emit('landed', result) | ||
} | ||
}, | ||
}) | ||
watchEffect(() => { | ||
if (object.value) { | ||
if (isDragged.value) { | ||
object.value.style.position = 'fixed' | ||
object.value.style.transform = `translate(${x.value}px, ${y.value}px) scale(${scale.value})` | ||
object.value.style.zIndex = '50' | ||
} else { | ||
object.value.style.position = 'absolute' | ||
object.value.style.transform = '' | ||
object.value.style.zIndex = '2' | ||
} | ||
} | ||
}) | ||
return {} | ||
}, | ||
}) | ||
</script> | ||
|
||
<style lang="postcss"> | ||
.pdf-helipad { | ||
@apply relative; | ||
.pdf-object { | ||
@apply top-0 left-0 border-2 border-dashed border-subtle rounded; | ||
} | ||
&__shadow { | ||
@apply opacity-25 z-1; | ||
} | ||
} | ||
</style> |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
--- | ||
title: PDF Helipad · Components | ||
description: Add object to PDF Viewer with Drag'n'Drop | ||
--- | ||
|
||
<script setup> | ||
import pPdfHelipad from './PdfHelipad.vue' | ||
import pPdfObject from '../pdf-object/PdfObject.vue' | ||
import pPdfObjectAddon from '../pdf-object/PdfObjectAddon.vue' | ||
import pPdfViewer from '../pdf-viewer/PdfViewer.vue' | ||
import pButton from '../button/Button.vue' | ||
import IconClose from '@carbon/icons-vue/lib/close/16' | ||
import FILE from '../pdf-viewer/assets/Calibrator-v3.pdf?url' | ||
import IMG_HELICOPTER from './assets/helicopter.svg' | ||
import { reactive, ref } from 'vue-demi' | ||
|
||
const objects = reactive([]) | ||
const scale = ref(1) | ||
|
||
function onLanded (item) { | ||
objects.push({ | ||
_id : Symbol('ObjectId'), | ||
page : item.page, | ||
x : item.x, | ||
y : item.y, | ||
width : 198, | ||
height: 106, | ||
}) | ||
} | ||
|
||
function remove (index) { | ||
objects.splice(index, 1) | ||
} | ||
</script> | ||
|
||
# PDF Helipad | ||
|
||
## Usage | ||
|
||
### Simple Usage | ||
|
||
(Drag this to PDF Viewer) | ||
|
||
<p-pdf-helipad :scale="scale" @landed="onLanded"> | ||
<img class="w-full h-full" :src="IMG_HELICOPTER" /> | ||
</p-pdf-helipad> | ||
|
||
<preview> | ||
<p-pdf-viewer :src="FILE" v-model:scale="scale"> | ||
<p-pdf-object | ||
v-for="(object, i) in objects" | ||
:key="object._id" | ||
v-model:page="object.page" | ||
v-model:x="object.x" | ||
v-model:y="object.y" | ||
v-model:width="object.width" | ||
v-model:height="object.height"> | ||
<img class="w-full h-full rounded" :src="IMG_HELICOPTER" /> | ||
<p-pdf-object-addon> | ||
<p-button size="sm" icon color="danger" @click="remove(i)"> | ||
<IconClose /> | ||
</p-button> | ||
</p-pdf-object-addon> | ||
</p-pdf-object> | ||
</p-pdf-viewer> | ||
</preview> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
import type { InteractEvent, Interactable } from '@interactjs/types' | ||
import { | ||
onScopeDispose, | ||
Ref, | ||
shallowRef, | ||
watch, | ||
} from 'vue-demi' | ||
|
||
export interface DragHooks { | ||
onstart?: (event: InteractEvent) => void, | ||
onmove?: (event: InteractEvent) => void, | ||
onend?: (event: InteractEvent) => void, | ||
} | ||
|
||
export default function useDrag (target: Ref<HTMLElement>, hooks?: DragHooks) { | ||
const enable = shallowRef(true) | ||
const instance = shallowRef<Interactable>() | ||
|
||
async function init () { | ||
destroy() | ||
|
||
if (target.value) { | ||
const { default: Interact } = await import('interactjs') | ||
|
||
// Interact.dynamicDrop(true) | ||
|
||
instance.value = Interact(target.value) | ||
.draggable({ | ||
inertia : true, | ||
enabled : enable.value, | ||
onstart : hooks.onstart, | ||
onmove : hooks.onmove, | ||
onend : hooks.onend, | ||
modifiers: [ | ||
Interact.modifiers.restrict({ | ||
restriction: 'body', | ||
elementRect: { | ||
top : 0, | ||
left : 0, | ||
bottom: 1, | ||
right : 1, | ||
}, | ||
}), | ||
], | ||
}) | ||
} | ||
} | ||
|
||
function destroy () { | ||
if (instance.value) | ||
instance.value.unset() | ||
} | ||
|
||
watch(target, async () => { | ||
await init() | ||
}) | ||
|
||
watch(enable, (value) => { | ||
if (instance.value) | ||
instance.value.draggable(value) | ||
}) | ||
|
||
onScopeDispose(() => { | ||
destroy() | ||
}) | ||
|
||
return enable | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters