技术经验谈 技术经验谈
首页
  • 最佳实践

    • 抓包
    • 数据库操作
  • ui

    • 《JavaScript教程》
    • 《JavaScript高级程序设计》
    • 《ES6 教程》
    • 《Vue》
    • 《React》
    • 《TypeScript 从零实现 axios》
    • 《Git》
    • TypeScript
    • JS设计模式总结
  • 总纲
  • 整体开发框架
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

hss01248

一号线程序员
首页
  • 最佳实践

    • 抓包
    • 数据库操作
  • ui

    • 《JavaScript教程》
    • 《JavaScript高级程序设计》
    • 《ES6 教程》
    • 《Vue》
    • 《React》
    • 《TypeScript 从零实现 axios》
    • 《Git》
    • TypeScript
    • JS设计模式总结
  • 总纲
  • 整体开发框架
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • apps

  • app

    • 图片压缩

      • 360全景图的展示
        • html代码:
        • webview加载本地文件的方法
      • 360全景图的压缩
      • motion photo的压缩
    • 天下(anyTimeAnyWhere)
  • 作品
  • app
  • 图片压缩
hss01248
2025-10-10
目录

360全景图的展示

# Android上360全景图的展示

# 终极解决方案: 基于web

Android的Googe vr sdk无法通过手势放大缩小,且视野宽度较小,交互体验很差,基本不具备可用性,相关sdk谷歌也已经停更多年.

api 'com.google.vr:sdk-panowidget:1.180.0'

因此,我们使用Pannellum.js库,用webview加载:

# html代码:

<!DOCTYPE HTML>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>A simple example</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/pannellum@2.5.6/build/pannellum.css"/>
    <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/pannellum@2.5.6/build/pannellum.js"></script>
    <style>
    html, body {
        width: 100%;
        height: 100%;
        margin: 0;
        padding: 0;
        overflow: hidden; 
    }
    #panorama {
        width: 100%;
        height: 100%;
    }
    </style>
</head>
<body>

<div id="panorama"></div>
<script>

// 手动解析URL参数
function getUrlParam(name) {
  // 去除URL中的"?",并按"&"分割成参数数组
  const params = window.location.search.substr(1).split('&');
  
  for (let i = 0; i < params.length; i++) {
    // 分割键值对(如 "page=1" → ["page", "1"])
    const pair = params[i].split('=');
    // 解码参数名和值(处理空格、中文等编码后的字符)
    const key = decodeURIComponent(pair[0]);
    const value = decodeURIComponent(pair[1] || '');
    
    if (key === name) {
      return value;
    }
  }
  // 未找到参数时返回null
  return null;
}

// 示例:假设URL是 https://example.com?name=张三&age=20
console.log("uri参数:"+getUrlParam('uri')); // 输出: "张三"
var uri0 = getUrlParam('uri')
if(uri0===null || uri0===undefined || uri0===""){
  uri0 = 'https://pannellum.org/images/alma.jpg';
}
pannellum.viewer('panorama', {
    "type": "equirectangular",
    "panorama": uri0,
    "autoLoad": true,
    "autoRotate": -2,
    "showFullscreenCtrl":false,
    "showZoomCtrl":false,
    "compass":false,
    "showControls":false,
    "minHfov": 15,               // 自定义最大缩放级别(数值越小,缩放越大,建议 15-30 之间)
    "hfov": 30,                  // 初始视角 = 最小 Hfov(直接进入最大缩放状态)
});
</script>

</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69

# webview加载本地文件的方法

文件路径path作为参数传入网页,不要加file://协议

(用这file://协议直接被webview内核拦截)

String url = "";
        if(path.startsWith("content://")){
            path = path.replace("content://","/content-providerxxy/");
        }
        url = "https://search.hss01248.tech/pannellum.html"+"?uri="+ UrlEncodeUtil.encode(path);
1
2
3
4
5

上面的代码提供了一个功能性的html页面 (opens new window),用于加载本地或远程的360全景图.

远程url,会自动下载

image-20251010100550928

页面右下角提供按钮选择文件并载入到浏览器本地

image-20251010100906285

image-20251010101225016

webview的client加上拦截处理:

 @Override
    public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
        Uri url1 = request.getUrl();
        String path = url1.getPath();
        if(TextUtils.isEmpty(path)){
            return super.shouldInterceptRequest(view, request);
        }
        if(path.startsWith("/storage/emulated/")){
            InputStream inputStream = null;
            try {
                inputStream = new FileInputStream(path);
            } catch (FileNotFoundException e) {
                LogUtils.w(e);
                return null;
            }
            String mimeType = getMimeType(path); // 获取文件MIME类型
            return new WebResourceResponse(mimeType, "UTF-8", inputStream);
        }else if(path.startsWith("/content-providerxxy/")){
            path = path.replace("/content-providerxxy/","content://");
            InputStream inputStream = null;
            Uri uri = Uri.parse(path);
            try {
                inputStream = Utils.getApp().getContentResolver().openInputStream(uri);
            } catch (FileNotFoundException e) {
                LogUtils.w(e);
                return null;
            }
            String mimeType = Utils.getApp().getContentResolver().getType(uri);
           if(TextUtils.isEmpty(mimeType)){
               mimeType = "image/jpeg";
           }
            return new WebResourceResponse(mimeType, "UTF-8", inputStream);
        }
        return super.shouldInterceptRequest(view, request);
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

为安全起见,可加上域名白名单判断,只允许指定域名下的path能如此操作.

编辑 (opens new window)
截图后的自动压缩工具
360全景图的压缩

← 截图后的自动压缩工具 360全景图的压缩→

最近更新
01
motion photo的压缩
10-10
02
360全景图的压缩
10-10
03
webview里blob的下载和保存
09-11
更多文章>
Theme by Vdoing | Copyright © 2020-2025 | 粤ICP备20041795号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式