最近在开发小程序,身心疲惫,原因是功能和app相同,我裂开了。

各种封装组件,各种写页面,不过有个好处是以前写的h5拿来改一下标签,基本上还是ok的,就剩下最后几个功能,其中就有一个VR全景功能。

移动端倒是好做,上次做了大概2天就搞定了,原理就是threejs用css3做图片的旋转,具体例子可以参照https://threejs.org/examples/css3d_panorama.html不过多描述,下面进入今天的主角:在微信小程序中使用threejs实现VR全景功能。

刚开始想到这个功能,我是拒绝的,这简直就是要了我的头发啊,没办法,谁叫我走上开发这条不归路呢,自己选的路,秃头也要走完。。

那就硬着头皮开始吧,先百度搜了一下在小程序中使用threejs,找到一篇比较干货的文章https://developers.weixin.qq.com/community/develop/article/doc/00066c4b230b085051592292f5bc13,这篇文章作者把threejs给提炼出来了一个小程序版本,

照着他的demo先把canvas给搞出来先。然后再实现全景,怎么实现也是头疼的事情,怎么,我不会写,还不会改吗?

先看看以前h5的实现方式,采用CSS3DRenderer来实现,问题来了,小程序里面不支持dom的createElement,那咋整嘛,只有换思路了,继续研究threejs的demo,第一个版本思路出来了,说了太多废话,直接来代码了:

  1. <view style="height: 100%; width: 100%;">
  2. <canvas type="webgl" id="c" style="width: 100%; height:100%;" bindtouchstart="touchStart" bindtouchmove="touchMove" bindtouchend="touchEnd" bindtouchcancel="touchCancel" bindlongtap="longTap" bindtap="tap"></canvas>
  3. </view>
  1. import * as THREE from '../../lib/threejs/three.weapp.min.js'
  2. import { OrbitControls } from '../../lib/threejs/OrbitControls'
  3.  
  4. Page({
  5. data: {},
  6. onLoad: function () {
  7. wx.createSelectorQuery()
  8. .select('#c')
  9. .node()
  10. .exec((res) => {
  11. // 创建canvas对象
  12. const canvas = THREE.global.registerCanvas(res[0].node)
  13. // 记录canvas的id,好在page销毁的时候释放canvas
  14. this.setData({ canvasId: canvas._canvasId })
  15.  
  16. const camera = new THREE.PerspectiveCamera(75, canvas.width / canvas.height, 1, 2000);
  17. camera.position.z = 500;
  18. const scene = new THREE.Scene();
  19. scene.background = new THREE.Color(0xAAAAAA);
  20. const renderer = new THREE.WebGLRenderer({ antialias: true });
  21.  
  22. const controls = new OrbitControls(camera, renderer.domElement);
  23.  
  24. camera.position.set(200, 200, 500);
  25. controls.update();
  26. const geometry = new THREE.SphereBufferGeometry( 500, 60, 40 ).toNonIndexed();
  27. geometry.scale( - 1, 1, 1 );
  28.  
  29. var texture = new THREE.TextureLoader().load( 'http://www.yanhuangxueyuan.com/threejs/examples/textures/2294472375_24a3b8ef46_o.jpg' ); // canvas中文文档作者的图,侵删
  30. texture.minFilter = THREE.LinearFilter;
  31. texture.format = THREE.RGBFormat;
  32. var material = new THREE.MeshBasicMaterial( { map: texture } );
  33. const mesh = new THREE.Mesh(geometry, material);
  34. scene.add(mesh);
  35.  
  36. function onWindowResize() {
  37. camera.aspect = window.innerWidth / window.innerHeight;
  38. camera.updateProjectionMatrix();
  39. renderer.setSize(canvas.width, canvas.height);
  40. }
  41. function render() {
  42. canvas.requestAnimationFrame(render);
  43. controls.update();
  44. renderer.render(scene, camera);
  45. }
  46.  
  47. render()
  48.  
  49. })
  50. },
  51. onUnload: function () {
  52. // 释放canvas
  53. THREE.global.unregisterCanvas(this.data.canvasId)
  54. },
  55. touchStart(e) {
  56. console.log('canvas', e)
  57. THREE.global.touchEventHandlerFactory('canvas', 'touchstart')(e)
  58. },
  59. touchMove(e) {
  60. console.log('canvas', e)
  61. THREE.global.touchEventHandlerFactory('canvas', 'touchmove')(e)
  62. },
  63. touchEnd(e) {
  64. console.log('canvas', e)
  65. THREE.global.touchEventHandlerFactory('canvas', 'touchend')(e)
  66. }
  67. })

嗨呀,以上代码我是看都看不懂,那咋办嘛,你挑的嘛偶像。莫有办法,只有百度查具体每个关键字的意思,这里也就不多讲了,因为我也不知道。这种方法有个问题就是,图片只支持一张的图片,而且这个图片是要用全景相机照出来的,限制比较多,怎么办嘛,肯定不能用这个方法呀,不然这个成本就没法估算了。

于是乎我开始探索第二种方法,还是采用6张图的方法,还是原来的配方,还是熟悉的味道。话不多少,上代码:

  1. import * as THREE from './three.weapp.min.js'
  2. import { OrbitControls } from './OrbitControls'
  3.  
  4. Page({
  5. data: {},
  6. onLoad: function () {
  7. wx.createSelectorQuery()
  8. .select('#c')
  9. .node()
  10. .exec((res) => {
  11. const canvas = THREE.global.registerCanvas(res[0].node)
  12.  
  13. this.setData({ canvasId: canvas._canvasId })
  14.  
  15. const camera = new THREE.PerspectiveCamera(75, canvas.width / canvas.height, 1, 2000);
  16. const scene = new THREE.Scene();
  17. const renderer = new THREE.WebGLRenderer({ antialias: true });
  18.  
  19. const controls = new OrbitControls(camera, renderer.domElement);
  20. // 控制镜头缩放,这里禁用了,因为是用正方体做的 除非能解决正方体的大小问题
  21. controls.enableZoom = false
  22. camera.position.set(-0.1, 2, -5);
  23. controls.update();
  24.  
  25. var sides = ['右.jpg', '左.jpg','上.jpg', '下.jpg','前.jpg', '后.jpg']
  26. var materials = [];
  27. for (var i = 0; i < sides.length; i++) {
  28. var side = sides[i];
  29. var texture = new THREE.TextureLoader().load(side);
  30. materials.push( new THREE.MeshBasicMaterial( { map: texture } ) );
  31. }
  32.      // 这里物体的长宽高,我始终不知道该是多少
  33. var mesh = new THREE.Mesh( new THREE.BoxBufferGeometry( canvas.height, canvas.height, canvas.height ), materials );
  34. mesh.geometry.scale( -1, 1, 1 );
  35.  
  36. scene.add(mesh);
  37.  
  38. function onWindowResize() {
  39. camera.aspect = window.innerWidth / window.innerHeight;
  40. camera.updateProjectionMatrix();
  41. renderer.setSize(canvas.width, canvas.height);
  42. }
  43. function render() {
  44. canvas.requestAnimationFrame(render);
  45. controls.update();
  46. renderer.render(scene, camera);
  47. }
  48.  
  49. render()
  50.  
  51. })
  52. },
  53. onUnload: function () {
  54. THREE.global.unregisterCanvas(this.data.canvasId)
  55. },
  56. touchStart(e) {
  57. console.log('canvas', e)
  58. THREE.global.touchEventHandlerFactory('canvas', 'touchstart')(e)
  59. },
  60. touchMove(e) {
  61. console.log('canvas', e)
  62. THREE.global.touchEventHandlerFactory('canvas', 'touchmove')(e)
  63. },
  64. touchEnd(e) {
  65. console.log('canvas', e)
  66. THREE.global.touchEventHandlerFactory('canvas', 'touchend')(e)
  67. }
  68. })

这两种方法的区别就是,第二种采用6张图片(右左上下前后),6个面表示一个正方体,然后将视角拉到正方体内,就是一个全景效果,完美。

这里的写法也是参照的https://github.com/mrdoob/three.js/blob/master/examples/webgl_panorama_cube.html,具体其中的参数,我也不太清楚,反正编程全靠试(猜)。

贴下今天的成果吧:

这是最开始完成第二种方法时的初次效果,当我看到这个效果的时候,我就知道已经差不多快ok了。

这是最终实现的效果,哈哈还不错吧(勉强符合功能需求)

距离上一次写博客,又过去了4个月,这4个月感觉过得是真的快,然而文章依然是这么水...(这也太水了吧)

感谢threejs和https://developers.weixin.qq.com/community/develop/article/doc/00066c4b230b085051592292f5bc13文章的作者

微信小程序之threejs全景的更多相关文章

  1. 微信小程序开发(3) 热门电影

    在这篇微信小程序开发教程中,我们将介绍如何使用微信小程序开发热门电影及预览功能. 本文主要分为两个部分,小程序主体部分及电影主页和详情页页面部分 一.小程序主体部分 一个小程序主体部分由三个文件组成, ...

  2. 微信小程序开发心得

    微信小程序也已出来有一段时间了,最近写了几款微信小程序项目,今天来说说感受. 首先开发一款微信小程序,最主要的就是针对于公司来运营的,因为,在申请appid(微信小程序ID号)时候,需要填写相关的公司 ...

  3. 微信小程序体验(2):驴妈妈景区门票即买即游

    驴妈妈因为出色的运营能力,被腾讯选为首批小程序内测单位.驴妈妈的技术开发团队在很短的时间内完成了开发任务,并积极参与到张小龙团队的内测问题反馈.驴妈妈认为,移动互联网时代,微信是巨大的流量入口,也是旅 ...

  4. 微信小程序(微信应用号)组件讲解

    这篇文章主要讲解微信小程序的组件. 首先,讲解新建项目.现在有句话:招聘三天以上微信小程序开发,这个估计只能去挖微信的工程师了.技术新,既然讲解,那我们就从开始建项目讲解. 打开微信web开发者工具, ...

  5. 神技!微信小程序(应用号)抢先入门教程(附最新案例DEMO-豆瓣电影)持续更新

    微信小程序 Demo(豆瓣电影) 由于时间的关系,没有办法写一个完整的说明,后续配合一些视频资料,请持续关注 官方文档:https://mp.weixin.qq.com/debug/wxadoc/de ...

  6. 通过微信小程序看前端

    前言 2016年9月22日凌晨,微信官方通过“微信公开课”公众号发布了关于微信小程序(微信应用号)的内测通知.整个朋友圈瞬间便像炸开了锅似的,各种揣测.介绍性文章在一夜里诞生.而真正收到内测邀请的公众 ...

  7. 快速了解微信小程序的使用,一个根据小程序的框架开发的todos app

    微信官方已经开放微信小程序的官方文档和开发者工具.前两天都是在看相关的新闻来了解小程序该如何开发,这两天官方的文档出来之后,赶紧翻看了几眼,重点了解了一下文档中框架与组件这两个部分,然后根据简易教程, ...

  8. 来自于微信小程序的一封简讯

    9月21晚间,微信向部分公众号发出公众平台-微信应用号(小程序)的内测邀请,向来较为低调的微信在这一晚没人再忽视它了. 来自个人博客:Damonare的个人博客 一夜之间火了的微信应用号你真的知道吗? ...

  9. 微信小程序前端源码逻辑和工作流

    看完微信小程序的前端代码真的让我热血沸腾啊,代码逻辑和设计一目了然,没有多余的东西,真的是大道至简. 废话不多说,直接分析前端代码.个人观点,难免有疏漏,仅供参考. 文件基本结构: 先看入口app.j ...

随机推荐

  1. leetcode-03-二叉树的锯齿层次遍历

    题目描述: 方法一: # Definition for a binary tree node. # class TreeNode: # def __init__(self, x): # self.va ...

  2. Python3基础笔记_字符串类型

    # 1.Python转义字符 a = "sqwerdf" # 2.Python字符串运算符 ''' + 字符串连接 a + b 输出结果: HelloPython * 重复输出字符 ...

  3. HashMap四种遍历方式

    public static void main(String[] args){ Map<String,String> map = new HashMap<String, String ...

  4. Linux的CentOS上如何安装nginx

    1. 安装nginx前,首先要装好gcc和g++环境: 2. 在centOS上装nginx,需要PCRE.zlib和ssl的支持,出ssl外其他都需要从其官网上下载好,上传至服务器: 3. 接着将上传 ...

  5. <b> <i> 标记

    <b></b> bold 加粗 <i></i> italic 斜线 : 对应Word文档的 I   斜体 <u></u>unde ...

  6. PAT甲级——A1079 Total Sales of Supply Chain

    A supply chain is a network of retailers(零售商), distributors(经销商), and suppliers(供应商)-- everyone invo ...

  7. eclipse memory analyzer对系统内存溢出堆文件解析0(转)

    前言 在平时工作过程中,有时会遇到OutOfMemoryError,我们知道遇到Error一般表明程序存在着严重问题,可能是灾难性的.所以找出是什么原因造成OutOfMemoryError非常重要.现 ...

  8. mybtais分批insert

    这里自己写了个对集合按一批的数量进行分批操作的分页bean,见PagenationUtil如下: package com.util; import java.util.List ; /** * @au ...

  9. 03_springmvc整合mybatis

    一.整合思路 springmvc+mybaits的系统架构: 第一步整合dao层:mybatis和spring整合:通过spring管理mapper接口,使用mapper的扫描器自动扫描mapper接 ...

  10. python3-常用模块之time

    import time time模块主要是处理各种类型的时间 常用方法 1.time.sleep(secs) (线程)推迟指定的时间运行,单位为秒. 2.time.time() 获取当前时间戳 时间戳 ...