赞
踩
前面的文章主要基本介绍了krpano一些元素的用法,从这篇文章开始我们就进入全景开发的实战教学,从全景切图到全景编辑最后到整个全景的预览,前端使用react框架+antd组件库+krpano,后端使用koa来实现一个类似720云全景的制作网站
在之前的文章中都是通过MAKE VTOUR Droplet.exe应用程序来手动切图的,但是对于一个制作网站来说肯定是网站来帮用户实现切图,用户只需要上传全景图片,前端拿到图片再传给后端,通过后端来完成切图,所以步骤是-->
用户选择图片切图-->
客户端拿到图片后调用接口进行上传-->
服务端实现切图-->
切图完成
krpano实现切图demo
上传图片通过Upload组件上传,这里将官方文档的示例直接复制过来
<Upload {...props}>
<Button type="primary">本地导入</Button>
</Upload>
const props: UploadProps = {
name: 'panos',
action: `${BASE_URL}/upload/panos`,
headers: {
authorization: localcache.getCacha('token')
},
showUploadList: false,
multiple: true
}
后端实现切图我们通过krpanotools.exe可执行文件执行命令行来切图,在我们从官网下来的包里就包含了这个文件
cmd执行一下krpanotools
命令,可以看到这个应用程序提供好几个功能:
makepano
:制作基于模版的全景或漫游maketiles
:制作或组合切片图像。可用于转换或重置尺寸makepreview
:制作平滑的预览图spheretocube
:球形或圆柱形全景图像转换为立方体cubetosphere
:立方体全景图像转换回球形全景图像protect
:生成自定义保护设置的viewer文件encrypt
:加密文件testserver
:测试服务register
:授权码注册详细文档建议查看官方文档
我们主要通过makepano
命令来切图,这是官方的示例命令krpanotools makepano [-config=###] [OPTIONS] inputfiles …
config参数是切图所依赖的配置文件,默认是当前路径下的templates/vtour-multires.config文件,OPTIONS参数用于设置或覆盖配置文件的设定,inputfiles参数是全景图片的路径,可以是一个或者多个图片
在cmd中执行这个命令切图
切图完成后会在图片所在的文件夹下生成一个vtour文件夹
然后点击测试服务,发现可以正常预览
切图后生成的vtour文件夹里有很多东西我们都是不需要的,我们只需要保存着切好图的panos文件夹和tour.xml,所以要根据需求来修改配置文件,打开vtour-multires.config这个文件,将对应的配置设为false或者注释掉,具体的配置说明可以查看官方文档
修改完后再执行一次切图,不再生成vtour文件夹了而是生成了切好图的文件夹和xml文件
知道如何使用krpanotools.exe切图后,我们将krpanotools.exe和对应的配置文件放入项目中
然后开始设计/upload/panos
这个接口,nodejs构建的服务端中我们可以使用child_process
模块中的exec
方法来执行命令
先将图片下载到本地,然后通过exec执行方法执行切图命令,切图完后通过xml-js这个库拿到生成的xml文件中的分辨率参数multires,之后将切好图的文件夹上传到oss,上传成功之后往数据库添加一条记录,并将结果返回给客户端,最后将本地生成的图片,文件夹和xml文件等都删除掉
/** * 批量上传 * @param {*} localFolderPath // 文件路径 * @param {*} ossFolderPath // oss路径 */ async uploadFolder(localFolderPath, ossFolderPath) { const files = fs.readdirSync(localFolderPath) for (const file of files) { const filePath = path.posix.join(localFolderPath, file) const ossPath = path.posix.join(ossFolderPath, file) if (fs.statSync(filePath).isDirectory()) { // 如果是文件夹,递归上传 await this.uploadFolder(filePath, ossPath) } else { // 如果是文件,上传到 OSS try { await this.client.put(ossPath, filePath) } catch (error) { console.error('Failed to upload file ' + ossPath + ':', error) } } } } /** * 切图并上传到阿里云oss * @param {*} ctx * @param {*} next */ uploadPano = async (ctx, next) => { const files = ctx.request.files const { id } = ctx.user if (!files.length) return ctx.app.emit('error', { code: 400, message: '文件上传错误' }, ctx) try { // krpanotools.exe切图 const execPromise = new Promise((resolve, reject) => { exec( 'krpanotools makepano [-config=templates/vtour-multires.config] ' + files[0].path, (error, stdout, stderr) => { if (error) { reject('执行命令时发生错误:' + error) } else { resolve() } } ) }) await execPromise // 全景参数 const view_uuid = files[0].filename.split('.')[0] const name = files[0].originalname.split('.')[0] const xml_path = files[0].path.split('.')[0] + '.xml' const xmlData = fs.readFileSync(xml_path, { encoding: 'utf-8', }) const xmltree = JSON.parse(xmljs.xml2json(xmlData, { compact: true, spaces: 4 })) const multires = xmltree.krpano.scene.image.cube._attributes.multires // 切图上传到oss await this.uploadFolder('uploads/' + view_uuid, '/panos/' + id + '/' + view_uuid) // 预览和文件夹的路径 const path = '/panos/' + id + '/' + view_uuid const thumbUrl = '/panos/' + id + '/' + view_uuid + '/thumb.jpg' const data = { scene_id: view_uuid, path, thumbUrl, name, multires, albumid: id, } await fileService.addPanoMaterials(data) ctx.body = { code: 200, message: '上传成功', data, } // 删除本地文件夹,图片和xml文件 fs.rmSync('uploads/' + view_uuid, { recursive: true }) fs.unlinkSync(files[0].path) fs.unlinkSync(xml_path) } catch (error) { console.log(error.message) const message = error.sqlMessage ? error.sqlMessage : error.message ? error.message : 'error' return ctx.app.emit('error', { code: 500, message }, ctx) } }
以上就是我对服务端实现切图的实现,如果还有更好的方式也欢迎大家一起分享交流,学习学习
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。