123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186 |
- <template>
- <img :src="tempPhoto" class="face-animation" v-if="tempPhoto" ref="coverRef">
- <div class="photo-layout">
- <ButtonPane class="photo-btn fun-ctrl" size="80" @click="photo">
- <ui-icon type="photo" class="icon" />
- </ButtonPane>
- <img
- :src="showCoverUrl"
- class="cover"
- :style="{opacity: showCoverUrl ? '1' : 0}"
- @click="router.push(writeRouteName.photos)"
- >
- </div>
- </template>
- <script setup lang="ts">
- import UiIcon from "@/components/base/components/icon/index.vue";
- import ButtonPane from "@/components/button-pane/index.vue";
- import {list} from '@/store/measure'
- import {fixPoints} from '@/store/fixPoint'
- import {baseLines} from '@/store/baseLine'
- import {basePoints} from '@/store/basePoint'
- import {photos} from '@/store/photos'
- import { useSDK } from '@/hook/useLaser'
- import {genUseLoading} from "@/hook";
- import {base64ToBlob, getId} from "@/utils";
- import {nextTick, ref} from "vue";
- import {api, uploadImage} from "@/store/sync";
- import {router, writeRouteName} from "@/router";
- import {Pos, Pos3D} from "@/sdk";
- const showCoverUrl = ref<string>()
- if (photos.value[photos.value.length - 1]?.url) {
- api.getFile(photos.value[photos.value.length - 1]?.url)
- .then(url => showCoverUrl.value = url)
- }
- const tempPhoto = ref<string>();
- const coverRef = ref<HTMLImageElement>()
- const getCurrentScreen = (pos: Pos3D): Pos => {
- const sdk = useSDK()
- const data = sdk.scene.getScreenByPoint(pos)
- return data.trueSide ? data.pos : null
- }
- const getCurrentScreens = (poss: Array<Pos3D>): Array<Pos> =>
- poss.map(getCurrentScreen).filter(pos => !!pos);
- const photo = genUseLoading(async () => {
- const sdk = useSDK()
- const dom = sdk.scene.el
- dom.style.pointerEvents = "none"
- const data = sdk.scene.screenshot(
- dom.offsetWidth,
- dom.offsetHeight
- )
- const {dataUrl: base64} = await data.finishPromise
- const blob = base64ToBlob(base64)
- tempPhoto.value = URL.createObjectURL(blob)
- const upload = uploadImage(blob)
- await nextTick();
- const handler = async () => {
- coverRef.value.removeEventListener("animationend", handler)
- showCoverUrl.value = tempPhoto.value
- tempPhoto.value = null
- baseLines.value.concat(list.value).forEach(item => {
- item.show = false
- })
- await nextTick()
- const url = await upload
- photos.value.push({
- id: getId(),
- url: url,
- time: new Date().getTime(),
- meterPerPixel: data.meterPerPixel,
- measures: list.value
- .map(data => {
- const pos = getCurrentScreens(data.points)
- if (pos.length) {
- return { pos, dis: sdk.carry.measureMap.get(data).getDistance().value }
- } else {
- return null
- }
- })
- .filter(poss => poss),
- baseLines: baseLines.value
- .map(data => getCurrentScreens(data.points))
- .filter(poss => poss.length),
- fixPoints: fixPoints.value.map(data => ({ text: data.text, pos: getCurrentScreen(data.pos) })),
- basePoints: getCurrentScreens(basePoints.value.map(data => data.pos))
- })
- showCoverUrl.value = await api.getFile(url)
- dom.style.pointerEvents = "all"
- baseLines.value.concat(list.value).forEach(item => {
- item.show = true
- })
- }
- coverRef.value.addEventListener("animationend", handler)
- })
- </script>
- <style scoped lang="scss">
- .photo-layout {
- position: absolute;
- z-index: 2;
- right: var(--boundMargin);
- top: 50%;
- transform: translateY(-50%);
- text-align: center;
- color: #fff;
- font-size: 20px;
- .icon {
- position: absolute;
- transform: translateX(-50%);
- }
- }
- .photo-btn {
- position: static;
- margin-bottom: 16px;
- .icon {
- font-size: 28px;
- }
- }
- .cover {
- width: 48px;
- height: 48px;
- border: 1px solid #fff;
- object-fit: cover;
- border-radius: 24px;
- overflow: hidden;
- }
- .face-animation {
- pointer-events: none;
- position: absolute;
- left: 0;
- right: 0;
- top: 0;
- bottom: 0;
- animation: 1s linear 1 both photo-face;
- }
- .face-animation.start {
- }
- @keyframes photo-face {
- from {
- left: 0;
- top: 0;
- width: 100vw;
- height: 100vh;
- margin-left: 0;
- margin-top: 0;
- border-radius: 0;
- }
- 30%,
- 40%,
- to {
- left: 50vw;
- top: 100px;
- width: 48px;
- height: 48px;
- margin-left: -24px;
- border-radius: 50%;
- z-index: 3
- }
- 70% {
- left: calc(80vw - 60px);
- top: calc(calc(50% - 48px) / 1.5);
- }
- to {
- left: calc(100vw - 63px);
- top: calc(calc(50%) + 20px);
- }
- }
- </style>
|