国产成人精品无码青草_亚洲国产美女精品久久久久∴_欧美人与鲁交大毛片免费_国产果冻豆传媒麻婆精东

15158846557 在線咨詢 在線咨詢
15158846557 在線咨詢
所在位置: 首頁 > 營銷資訊 > 網(wǎng)站運(yùn)營 > 思源筆記折騰記錄-整一個(gè)全景圖瀏覽器-簡單的全景圖渲染

思源筆記折騰記錄-整一個(gè)全景圖瀏覽器-簡單的全景圖渲染

時(shí)間:2023-07-19 23:36:02 | 來源:網(wǎng)站運(yùn)營

時(shí)間:2023-07-19 23:36:02 來源:網(wǎng)站運(yùn)營

思源筆記折騰記錄-整一個(gè)全景圖瀏覽器-簡單的全景圖渲染:

一、前情提要

其實(shí)我的本行是設(shè)計(jì)師嘛,所以總是經(jīng)常需要瀏覽一下全景圖什么的,但是網(wǎng)上的全景圖網(wǎng)站總是有點(diǎn)限制,而且把圖片全都交給在線服務(wù)總有種失控的感覺,所以這回我們來搞一個(gè)本地的全景圖瀏覽器。

之前弄了一個(gè)noob-service-vite??,用來通過vite伺服文件夾方便寫點(diǎn)小功能。

思源筆記折騰記錄 - 做一個(gè)白板 - 最最最基礎(chǔ)的卡片顯示 - 鏈滴 (ld246.com)

但是它只寫死了伺服一個(gè)文件夾(也就是那個(gè)白板),為了方便鼓搗,我們來嘗試弄一個(gè)新活。

二、準(zhǔn)備工作

1、自動伺服新掛件

我們對之前的noob-service-vite做一點(diǎn)改造。

首先是讓他能夠自動識別data/viteWidgets?中的文件夾:

?noob-service-vite/util/file.js?

let fs = require('fs')let path = require('path')export let vite掛件目錄 = window.siyuan.config.system.workspaceDir +'/data/viteWidgets'export function 讀取掛件列表(){ let 掛件列表 =[] let 路徑列表= require('fs').readdirSync(vite掛件目錄) 路徑列表.forEach( 路徑名=>{ //如果目錄下有vite.config.js if(fs.existsSync(path.join(vite掛件目錄,路徑名,'vite.config.js'))){ 掛件列表.push({ name:路徑名, path:path.join(vite掛件目錄,路徑名) }) } } ) return 掛件列表}

2、自動伺服

這樣之后,就可以改造最開始的noob-service-vite??了

?noob-service-vite/index.js?

import noobApi from '../noobApi/index.js'import { 讀取掛件列表 } from './util/file.js'import { 獲取可用端口號 } from './util/port.js'if (window.require) { const path = require('path') const vite = require('vite') let vite服務(wù)注冊表 = {} 讀取掛件列表().forEach( 掛件屬性 => { 創(chuàng)建vite服務(wù)(掛件屬性.path) } ) function 創(chuàng)建vite服務(wù)(文件夾路徑) { return new Promise(async (resolve, reject) => { let vite配置文件路徑 = path.join(文件夾路徑, 'vite.config.js') if (!vite服務(wù)注冊表.文件夾路徑) { let server = await vite.createServer({ configFile: vite配置文件路徑, root: 文件夾路徑, }) !vite服務(wù)注冊表[文件夾路徑]?vite服務(wù)注冊表[文件夾路徑]={}:null vite服務(wù)注冊表[文件夾路徑]['server'] = server let port if (server.config.server.port) { port = await 獲取可用端口號(server.config.server.port) } else { port =await 獲取可用端口號(6806) } await server.listen(port,'127.0.0.1').then( s => { console.log(文件夾路徑,'的開發(fā)服務(wù)在:',port,'上啟用') vite服務(wù)注冊表[文件夾路徑]['port'] = port } ) resolve(server) } }) }}獲取可用端口號的實(shí)現(xiàn)其實(shí)就是嘗試能不能監(jiān)聽這個(gè)端口,如果不能就試個(gè)新的:

export async function 獲取可用端口號(端口號){ return new Promise((resolve, reject) => { let http = require('http') let 測試服務(wù) = http.createServer() let 可用端口號 = 端口號||3000 測試服務(wù).on( 'listening',()=>{ console.log(端口號) 測試服務(wù).close(()=>{ resolve(可用端口號) }) } ) 測試服務(wù).on( 'error',async(error)=>{ console.log(error) if(error.code==='EADDRINUSE'){ resolve(await 獲取可用端口號(可用端口號+1)) } else{ reject(error) } } ) 測試服務(wù).listen(端口號) }) }

二、實(shí)現(xiàn)簡單的全景圖瀏覽

1、安裝photo sphere viewer

這個(gè)很簡單啦:

npm i photo sphere viewer --registry=https://registry.npmmirror.com

2、最簡單的球面全景圖查看器

欸,我就是不寫index.html?的內(nèi)容,你們試著自己弄一下。

要實(shí)現(xiàn)一個(gè)最簡單的全景圖i瀏覽只需要幾行代碼啦:

import { Viewer } from 'photo-sphere-viewer';//這里是引入了css,vite里面你這么干跟在html里面引入差不多import 'photo-sphere-viewer/dist/photo-sphere-viewer.css'const viewer = new Viewer({ container: document.querySelector('#viewer'), //這個(gè)是我之前上傳到工作空間里的一張全景圖 panorama: 'assets/11111D5_全景圖 1_20221211_061304-20221211182953-7i0dt0q.jpg',});就像這樣:

?

?

這張全景的原圖長這樣:

?

?

第一個(gè)全景圖就渲染出來了~~

3、 加上畫廊

photo sphere viewer有很多插件,其中有一個(gè)PhotoSphereViewer.GalleryPlugin?是用來生成一連串的全景圖的。

PhotoSphereViewer.GalleryPlugin這里我們約定文件名為:全景圖-<項(xiàng)目名>-<空間名>-<id>.jpg的附件文件就是某一個(gè)系列的全景圖。

所以這里可以搞一個(gè)sql:

select * from assetswhere name like '全景圖-${項(xiàng)目名}-%'然后我們來實(shí)驗(yàn)一下:

?sphereViewer/src/index.js?

import { Viewer } from 'photo-sphere-viewer';import {GalleryPlugin} from 'photo-sphere-viewer/dist/plugins/gallery.js'import 核心api from 'http://127.0.0.1:6806/snippets/noobApi/util/kernelApi.js'import 'photo-sphere-viewer/dist/photo-sphere-viewer.css'import 'photo-sphere-viewer/dist/plugins/gallery.css'import { 獲取地址參數(shù) } from '../../whiteBoard/src/data';let {project} =獲取地址參數(shù)()console.log(project)let sql =`select * from assets where name like '全景圖-${project}-%'`let 全景圖列表 = await 核心api.sql({stmt:sql})console.log(全景圖列表)全景圖列表.forEach( item=>{ item.panorama=item.path item.thumbnail =item.path let 空間名 = item.name.split('-')[2] item.options ={ caption: 空間名, } })console.log(Viewer,GalleryPlugin)const viewer = new Viewer({ container: document.querySelector('#viewer'), panorama: 全景圖列表[0].path, plugins: [ [GalleryPlugin, { visibleOnLoad: true, }], ],});const gallery = viewer.getPlugin(GalleryPlugin);gallery.setItems(全景圖列表)?

?

嗯,好像渲染成功了~~~。

4、更方便的項(xiàng)目創(chuàng)建

啊,我們現(xiàn)在有一個(gè)全景圖瀏覽器了,但是一張張圖上傳到思源的assets里面好像太麻煩了點(diǎn),有沒有更方便的辦法咧?

首先來設(shè)想一個(gè)簡單的全景圖項(xiàng)目文件夾結(jié)構(gòu)







全部通過assets?來管理好像有點(diǎn)麻煩,而且它的嵌套結(jié)構(gòu)也不適合放到assets里面一起管理,全景圖的數(shù)據(jù)也不大可能會被用到別的地方。

所以,我們來起一個(gè)后端吧,專門用來給這個(gè)網(wǎng)頁提供服務(wù)(什么叫BFF啊~~)。

之前在noob-service-vite中,我們直接讓vite來創(chuàng)建和監(jiān)聽服務(wù)器,這回改一下,使用中間件模式。

function 創(chuàng)建vite服務(wù)(文件夾路徑) { return new Promise(async (resolve, reject) => { let vite配置文件路徑 = path.join(文件夾路徑, 'vite.config.js') if (!vite服務(wù)注冊表.文件夾路徑) { let vite中間件 = await vite.createServer({ configFile: vite配置文件路徑, root: 文件夾路徑, server: { middlewareMode: "html" } }) const app = express() !vite服務(wù)注冊表[文件夾路徑] ? vite服務(wù)注冊表[文件夾路徑] = {} : null vite服務(wù)注冊表[文件夾路徑]['server'] = app let port = vite中間件.config.server.port || 6807 port = await 獲取可用端口號(port) let server = await app.listen(port, '127.0.0.1', async () => { vite服務(wù)注冊表[文件夾路徑]['port'] = port vite服務(wù)注冊表[文件夾路徑]['server'] = server vite服務(wù)注冊表[文件夾路徑]['app'] = app vite服務(wù)注冊表[文件夾路徑]['vite'] = vite中間件 console.log(文件夾路徑, '的開發(fā)服務(wù)在:', 'http://127.0.0.1:' + port, '上啟用') if (require('fs').existsSync(文件夾路徑 + '/backend/index.js')) { //因?yàn)槟承┑疤鄣脑?,這里只能用require let router = require(文件夾路徑 +'/backend/index.js') //主意router不要妨礙vite的工作,也就是別占了vite的坑 app.use(router) app.use(vite中間件.middlewares) } })/*.then( s => { let {address,port} = server.httpServer.address() console.log(文件夾路徑,'的開發(fā)服務(wù)在:','http://'+address+':'+port,'上啟用') vite服務(wù)注冊表[文件夾路徑]['port'] = port console.log(server) } )*/ resolve(server) } }) }這樣之后,隨便試一下,就把文件存在data/widgetsData?里面吧。

按照上面約定的后端文件入口,先弄兩個(gè)接口吧:

const express = require('express')let router = express.Router()const fs = require('fs')const path = require('path')let 數(shù)據(jù)路徑 = path.join(window.siyuan.config.system.workspaceDir,'data','widgetsData','sphereViewer')if(fs.existsSync(數(shù)據(jù)路徑)){ //為了避免跟思源的接口重合,掛件后端的接口全都加上widget前綴好了 router.use('/widgetData',express.static(數(shù)據(jù)路徑)) router.use('/widgetApi/projects/getAll',(req,res)=>{ res.json(fs.readdirSync(數(shù)據(jù)路徑) })}//上面已經(jīng)做了自動導(dǎo)入,回自動把這個(gè)接口混入vite的開發(fā)服務(wù)器當(dāng)中module.exports=router這樣之后,往這個(gè)文件夾里面放一點(diǎn)文件:

?

?

這個(gè)時(shí)候訪問一下127.0.0.1:6809/widgetApi/projects/listAllProjects?(這個(gè)端口是在vite.config.js里設(shè)置的)。

?

?

可以看到我們剛剛寫的后端已經(jīng)返回了項(xiàng)目列表。

我們之前是從思源的sql獲取數(shù)據(jù)的,所以上面的查看器的獲取方式也要改一下。

但是因?yàn)橹罂赡苓€需要其他來源的全景圖數(shù)據(jù)的渲染,所以這里也使用一個(gè)跟之前做簡單白板的時(shí)候類似的適配器。

?sphereViewer/src/adapters/sql.js?

import { 核心api } from "../../../whiteBoard/src/data"export class sql全景圖適配器{ 獲取項(xiàng)目列表(){ } async 獲取全景圖列表(項(xiàng)目名){ let sql =`select * from assets where name like '全景圖-${項(xiàng)目名}-%'` let 全景圖列表 = await 核心api.sql({stmt:sql}) 全景圖列表.forEach( item=>{ item.panorama=item.path item.thumbnail =item.path let 空間名 = item.name.split('-')[2] item.options ={ caption: 空間名, } } ) return 全景圖列表 }}import { Viewer } from 'photo-sphere-viewer';import {GalleryPlugin} from 'photo-sphere-viewer/dist/plugins/gallery.js'import 'photo-sphere-viewer/dist/photo-sphere-viewer.css'import 'photo-sphere-viewer/dist/plugins/gallery.css'import { 獲取地址參數(shù) } from '../../whiteBoard/src/data';import {sql全景圖適配器} from "./adapters/sql.js"let {project} =獲取地址參數(shù)()console.log(project)let 當(dāng)前適配器 = new sql全景圖適配器()let 全景圖列表= await 當(dāng)前適配器.獲取全景圖列表(project) const viewer = new Viewer({ container: document.querySelector('#viewer'), panorama: 全景圖列表[0].path, plugins: [ [GalleryPlugin, { visibleOnLoad: true, }], ],});const gallery = viewer.getPlugin(GalleryPlugin);gallery.setItems(全景圖列表)這個(gè)時(shí)候訪問127.0.0.1:6809/?project=云park,應(yīng)該可以看到跟之前一樣的結(jié)果。

然后來試一下寫一個(gè)后端適配器:

export class sql全景圖適配器{ 獲取項(xiàng)目列表(){ } async 獲取全景圖列表(項(xiàng)目名){ let res = await fetch('widgetApi/projects/getScenesByName',{ method:"POST", body:{ name:項(xiàng)目名 } }) let 全景圖列表 = await res.json() return 全景圖列表 }}?

啊,是不是跟從思源獲取數(shù)據(jù)挺像的,這個(gè)時(shí)候getScenesByName?這個(gè)接口還不在,所以我們需要實(shí)現(xiàn)一下它。

router.post('widgetApi/projects/getScenesByName',(req,res)=>{ let {name} = req.body let 場景列表 = [] let 項(xiàng)目文件列表 = fs.readdirSync(path.join(數(shù)據(jù)路徑,name)) 項(xiàng)目文件列表.forEach( 路徑名=>{ let 縮略圖路徑 if( fs.existsSync(path.join(數(shù)據(jù)路徑,name,路徑名,'thumbnail.jpg'))){ 縮略圖路徑 = path.join('/widgetData',name,路徑名,'thumbnail.jpg').replace(////g,'/') }else if( fs.existsSync(path.join(數(shù)據(jù)路徑,name,路徑名,'_f.jpg')) ){ 縮略圖路徑=path.join('/widgetData',name,路徑名,'_f.jpg').replace(////g,'/') }else if( fs.existsSync(path.join(數(shù)據(jù)路徑,name,路徑名,'sphere.jpg')) ){ 縮略圖路徑=path.join('/widgetData',name,路徑名,'sphere.jpg').replace(////g,'/') } if(fs.existsSync(path.join(數(shù)據(jù)路徑,name,路徑名,'_b.jpg'))){ 場景列表.push( { id:路徑名, panorama:{ left: path.join('/widgetData',name,路徑名,'_r.jpg').replace(////g,'/'), front: path.join('/widgetData',name,路徑名,'_b.jpg').replace(////g,'/'), right: path.join('/widgetData',name,路徑名,'_l.jpg').replace(////g,'/'), back: path.join('/widgetData',name,路徑名,'_f.jpg').replace(////g,'/'), top: path.join('/widgetData',name,路徑名,'_u.jpg').replace(////g,'/'), bottom: path.join('/widgetData',name,路徑名,'_d.jpg').replace(////g,'/'), }, thumbnail:縮略圖路徑, options:{ caption:name, } } ) } else if(fs.existsSync(path.join(數(shù)據(jù)路徑,name,路徑名,'sphere.jpg'))){ 場景列表.push( { id:路徑名, panorama:path.join('/widgetData',name,路徑名,'sphere.jpg').replace(////g,'/'), options:{ caption:name, }, thumbnail:縮略圖路徑, } ) } } ) res.json(場景列表) })看起來應(yīng)該跟上面的這個(gè)差不多對吧,就是識別文件夾里的文件,然后匹配下路徑然后返回。

不過這里有個(gè)地方需要注意:

panorama:{ left: path.join('/widgetData',name,路徑名,'_r.jpg').replace(////g,'/'), front: path.join('/widgetData',name,路徑名,'_b.jpg').replace(////g,'/'), right: path.join('/widgetData',name,路徑名,'_l.jpg').replace(////g,'/'), back: path.join('/widgetData',name,路徑名,'_f.jpg').replace(////g,'/'), top: path.join('/widgetData',name,路徑名,'_u.jpg').replace(////g,'/'), bottom: path.join('/widgetData',name,路徑名,'_d.jpg').replace(////g,'/'),},因?yàn)殇秩酒鹘o出的六面全景圖一般是按照“人在方盒子里面”來適配六個(gè)面的,而PhotoSphereViewer?是按照“人在方盒子外面”來讀取的,所以讀取文件的時(shí)候,除了上下不用反之外,其他前后左右都要反一下~~~

我們試著使用一下這個(gè)適配器:

import {后端適配器} from './adapters/internal.js'let {project} =獲取地址參數(shù)()console.log(project)let 當(dāng)前適配器 = new 后端適配器()let 全景圖列表= await 當(dāng)前適配器.獲取全景圖列表(project) const viewer = new Viewer({ container: document.querySelector('#viewer'), panorama: 全景圖列表[0].path, plugins: [ [GalleryPlugin, { visibleOnLoad: true, }], ],});const gallery = viewer.getPlugin(GalleryPlugin);gallery.setItems(全景圖列表)然后它就報(bào)錯(cuò)了:

?

?

因?yàn)槲覀兪褂玫膃xpress?后端并沒有自帶解析post?請求的body?的能力,這個(gè)時(shí)候需要一個(gè)body-parser?

一樣的,首先需要安裝它:

?npm i --registry=https://registry.npmmirror.com body-parser?

然后引入并使用:

const bodyParser = require('body-parser')router.post('/widgetApi/projects/getScenesByName', (req,res,next)=>{ //強(qiáng)制按json解析,這樣前端就不用設(shè)置content-type了 req.headers['content-type']='application/json' //記得調(diào)用next() next() }, bodyParser.json(), let {name} = req.body let 場景列表 = [] let 項(xiàng)目文件列表 = fs.readdirSync(path.join(數(shù)據(jù)路徑,name)) 項(xiàng)目文件列表.forEach( 路徑名=>{ let 縮略圖路徑 if( fs.existsSync(path.join(數(shù)據(jù)路徑,name,路徑名,'thumbnail.jpg'))){ 縮略圖路徑 = path.join('/widgetData',name,路徑名,'thumbnail.jpg').replace(////g,'/') }else if( fs.existsSync(path.join(數(shù)據(jù)路徑,name,路徑名,'_f.jpg')) ){ 縮略圖路徑=path.join('/widgetData',name,路徑名,'_f.jpg').replace(////g,'/') }else if( fs.existsSync(path.join(數(shù)據(jù)路徑,name,路徑名,'sphere.jpg')) ){ 縮略圖路徑=path.join('/widgetData',name,路徑名,'sphere.jpg').replace(////g,'/') } if(fs.existsSync(path.join(數(shù)據(jù)路徑,name,路徑名,'_b.jpg'))){ 場景列表.push( { id:路徑名, panorama:{ left: path.join('/widgetData',name,路徑名,'_r.jpg').replace(////g,'/'), front: path.join('/widgetData',name,路徑名,'_b.jpg').replace(////g,'/'), right: path.join('/widgetData',name,路徑名,'_l.jpg').replace(////g,'/'), back: path.join('/widgetData',name,路徑名,'_f.jpg').replace(////g,'/'), top: path.join('/widgetData',name,路徑名,'_u.jpg').replace(////g,'/'), bottom: path.join('/widgetData',name,路徑名,'_d.jpg').replace(////g,'/'), }, thumbnail:縮略圖路徑, options:{ caption:name, } } ) } else if(fs.existsSync(path.join(數(shù)據(jù)路徑,name,路徑名,'sphere.jpg'))){ 場景列表.push( { id:路徑名, panorama:path.join('/widgetData',name,路徑名,'sphere.jpg').replace(////g,'/'), options:{ caption:name, }, thumbnail:縮略圖路徑, } ) } } ) res.json(場景列表)}然后再看一下127.0.0.1:6809/?project=云park48

這個(gè)時(shí)候它顯示:

?

?

這是因?yàn)镻hotoSphereViewer?默認(rèn)使用的是球面圖適配器,而我們優(yōu)先返回的是六面圖,有關(guān)它的適配器可以參考文檔:

Adapters | Photo Sphere Viewer (photo-sphere-viewer.js.org)

先不糾結(jié),按照文檔使用六面圖適配器看看:

?sphereViewer/src/index.js?

let 全景圖選項(xiàng) = { container: document.querySelector('#viewer'), panorama: 全景圖列表[0].panorama, plugins: [ [GalleryPlugin, { visibleOnLoad: true, }], ],}//如果有六面圖文件,就使用六面圖適配器if(全景圖列表[0].panorama.left){ 全景圖選項(xiàng).adapter = CubemapAdapter}let viewer= new Viewer(全景圖選項(xiàng))這回顯示對了,效果就像這樣:




?

這回好像終于干了點(diǎn)跟設(shè)計(jì)師沾邊的活兒了~~~


目前的代碼片段的地址位于:

leolee9086/snippets (github.com)

viteWidgets的地址位于

leolee9086/viteWidgets (github.com)

啊 全景圖文件我就不提供了,自己試試吧。

關(guān)鍵詞:瀏覽,簡單,渲染,筆記,折騰,記錄

74
73
25
news

版權(quán)所有? 億企邦 1997-2025 保留一切法律許可權(quán)利。

為了最佳展示效果,本站不支持IE9及以下版本的瀏覽器,建議您使用谷歌Chrome瀏覽器。 點(diǎn)擊下載Chrome瀏覽器
關(guān)閉