소스 검색

feat: tag

rindy 2 년 전
부모
커밋
2bf865afbb
4개의 변경된 파일231개의 추가작업 그리고 4개의 파일을 삭제
  1. 36 1
      src/components/files/TagItem.vue
  2. 144 0
      src/components/files/TagLaserItem.vue
  3. 49 3
      src/components/files/TagManager.vue
  4. 2 0
      src/pages/Viewer.vue

+ 36 - 1
src/components/files/TagItem.vue

@@ -1,5 +1,11 @@
 <template>
+    <div v-if="props.scene == 'laser'"  :data-tag-id="props.tag.sid"  class="tag-item" ref="dom">
+        <div class="tag-icon">
+            <span>{{ props.index }}</span>
+        </div>
+    </div>
     <div
+        v-else
         @click="onClick"
         :data-tag-id="props.tag.sid"
         :style="{ lefts: `${props.tag.x}px`, tops: `${props.tag.y}px`, transform: `translate(${props.tag.x}px,${props.tag.y}px)`, display: props.tag.visible ? 'block' : 'none' }"
@@ -11,6 +17,7 @@
     </div>
 </template>
 <script setup>
+import { ref,onMounted } from 'vue'
 const props = defineProps({
     tag: {
         type: Object,
@@ -21,12 +28,40 @@ const props = defineProps({
         required: true,
     },
 })
-
 const emits = defineEmits(['action'])
 
+const dom = ref(null)
+
 const onClick = () => {
     emits('action', { event: 'focus', sid: props.tag.sid, tag: props.tag })
 }
+onMounted(() => {
+    if (window.laser) {
+        window.laser.then(sdk => {
+            const posInfo = sdk.scene.getPointByScreen({ x: e.clientX, y: e.clientY })
+            sdk.addMouseDownEvent(e => {
+                if (e.button == 2) {
+                    const posInfo = sdk.scene.getPointByScreen({ x: e.clientX, y: e.clientY })
+                    const tag = {
+                        panoId: '0',
+                        createTime: 1658223413176,
+                        icon: 'R7PTZK233714.png',
+                        x: e.clientX,
+                        y: e.clientY,
+                        position: { x: -0.7253925749728442, y: -0.12276942990074809, z: 2.3097074481849633 },
+                        media: { link: [{ src: 'https://test.4dkankan.com/#/scene' }] },
+                        type: 'link',
+                        title: '链接热点',
+                        content: '',
+                        sid: 'ctKxOW233013',
+                        visible: true,
+                    }
+                    tags.value.push(tag)
+                }
+            })
+        })
+    }
+})
 </script>
 <style lang="scss" scoped>
 .tag-item {

+ 144 - 0
src/components/files/TagLaserItem.vue

@@ -0,0 +1,144 @@
+<template>
+    <div :data-tag-id="props.tag.sid"  class="tag-item">
+        <div class="tag-icon">
+            <span>{{ props.index }}</span>
+        </div>
+    </div>
+</template>
+<script setup>
+const props = defineProps({
+    tag: {
+        type: Object,
+        required: true,
+    },
+    index: {
+        type: Number,
+        required: true,
+    },
+})
+console.log(props)
+const emits = defineEmits(['action'])
+
+const onClick = () => {
+    emits('action', { event: 'focus', sid: props.tag.sid, tag: props.tag })
+}
+
+</script>
+<style lang="scss" scoped>
+.tag-item {
+    cursor: pointer;
+    pointer-events: all;
+    display: none;
+    position: absolute;
+    width: 26px;
+    height: 26px;
+    margin-left: -13px;
+    margin-top: -13px;
+    z-index: 1;
+    &.active {
+        .tag-icon {
+            background-color: green;
+        }
+    }
+}
+
+.tag-item.focus {
+    z-index: 2;
+}
+.tag-item.focus .tag-body {
+    transform: translateY(-50%) scale(1);
+}
+.tag-item.fixed {
+    z-index: 3;
+}
+.tag-item.active {
+    z-index: 4;
+}
+
+.tag-item .tag-icon {
+    position: relative;
+    display: block;
+    width: 26px;
+    height: 26px;
+    border-radius: 0 50% 50% 50%;
+    border: 1px solid #fff;
+    transform: rotate(-135deg);
+    background-color: #0076f6;
+    span {
+        display: block;
+        transform: rotate(135deg);
+        margin-top: 3px;
+        margin-left: -1px;
+        text-align: center;
+    }
+}
+
+.tag-item .tag-icon.animate {
+    animation: tag-animate-zoom 3s -1s linear infinite;
+}
+
+.tag-item .tag-body {
+    position: fixed;
+    right: 0;
+    top: 50%;
+    margin-right: 70px;
+    width: 200px;
+    height: 200px;
+    transform: translateY(-50%) scale(1);
+    transform-origin: calc(100% + 40px) -50%;
+    background: rgba(27, 27, 28, 0.8);
+    border-radius: 4px;
+    min-width: 400px;
+    padding: 30px 20px;
+}
+
+.tag-item .tag-body::before {
+    content: '';
+    position: absolute;
+    width: 40px;
+    height: 100%;
+    top: 0;
+    right: -40px;
+}
+
+.tag-item .tag-body::after {
+    content: '';
+    position: absolute;
+    top: 50%;
+    right: -39px;
+    width: 0;
+    height: 0;
+    border-top: 15px solid transparent;
+    border-bottom: 15px solid transparent;
+    border-left: 40px solid rgba(27, 27, 28, 0.8);
+    transform: translateY(-50%);
+}
+
+@keyframes tag-animate-zoom {
+    0% {
+        transform: scale(1);
+    }
+    50% {
+        transform: scale(0.7);
+    }
+    100% {
+        transform: scale(1);
+    }
+}
+
+.tag-item .v-enter-from,
+.tag-item .v-leave-to {
+    opacity: 0;
+    transform: translateY(50%) scale(0);
+}
+.tag-item .v-enter-active,
+.tag-item .v-leave-active {
+    will-change: transform;
+    transition: all 0.25s cubic-bezier(0.35, 0.32, 0.65, 0.63);
+}
+.tag-item .v-enter-to,
+.tag-item .v-leave-from {
+    opacity: 1;
+    transform: translateY(-50%) scale(1);
+}
+</style>

+ 49 - 3
src/components/files/TagManager.vue

@@ -1,19 +1,65 @@
 <template>
     <div xui_tags_view>
-        <TagItem v-for="(tag, index) in tags" :tag="tag" :index="index + 1" @action="onAction" :class="{active: notify && notify.sid == tag.sid}" />
-        <!-- <TagView v-if="notify" :notify="notify" @action="onAction" /> -->
+        <!-- <TagItem v-for="(tag, index) in tags" :tag="tag" :index="index + 1" @action="onAction" :class="{ active: notify && notify.sid == tag.sid }" /> -->
         <TagEditor v-if="notify" :notify="notify" @action="onAction" />
     </div>
 </template>
 <script setup>
-import { ref } from 'vue'
+import { ref, watchEffect } from 'vue'
 import TagItem from './TagItem.vue'
+import TagLaserItem from './TagLaserItem.vue'
 import TagView from './TagView.vue'
 import TagEditor from './TagEditor.vue'
+
 let timer = setInterval(() => {
     if (window.kankan) {
         init(window.kankan)
         clearInterval(timer)
+    } else if (window.laser) {
+        window.laser.then(sdk => {
+            watchEffect(onClean => {
+                const cleans = tags.value.map((tag, index) => {
+                    console.error(TagLaserItem, tag.position)
+                    return sdk.sceneCarry.use({
+                        components: TagLaserItem,
+                        props: {
+                            pos: tag.position,
+                            tag,
+                            index,
+                        },
+                    })
+                })
+
+                return onClean(() => {
+                    cleans.forEach(clean => clean())
+                })
+            })
+        })
+
+        window.laser.then(sdk => {
+            sdk.addMouseDownEvent(e => {
+                if (e.button == 2) {
+                    const info = sdk.scene.getPointByScreen({ x: e.clientX, y: e.clientY })
+                    const tag = {
+                        panoId: '0',
+                        createTime: 1658223413176,
+                        icon: 'R7PTZK233714.png',
+                        x: e.clientX,
+                        y: e.clientY,
+                        position: info.position,
+                        media: { link: [{ src: 'https://test.4dkankan.com/#/scene' }] },
+                        type: 'link',
+                        title: '链接热点',
+                        content: '',
+                        sid: 'ctKxOW233013',
+                        visible: true,
+                        scene: 'laser',
+                    }
+                    tags.value.push(tag)
+                }
+            })
+        })
+        clearInterval(timer)
     }
 }, 50)
 const notify = ref(null)

+ 2 - 0
src/pages/Viewer.vue

@@ -269,6 +269,8 @@ const onLoadSource = () => {
     }
     if(source.value.type < 2) {
         window['kankan'] = sourceFrame.value.contentWindow.app
+    } else {
+        window['laser'] = sourceFrame.value.contentWindow.loaded
     }
     loadSourceScene(sourceFrame, source.value.type < 2 ? 'kankan' : 'laser', mode.value)
 }