uniapp微信小程序VR看车内饰(Skybox,Cubemap)
插件市场或者github上大多是threejs或者web-view方式.但是threejs太大了,web-view不符要求,需要嵌入页面中,只能canvas+webgl实现.找到一个库GitHub - alibaba/G3D: A pure 3D render engine compatible with webgl, running both in browser and gcanvas.虽然早
插件市场或者github上大多是threejs或者web-view方式.
但是threejs太大了,web-view不符要求,需要嵌入页面中,只能canvas+webgl实现.
找到一个库 GitHub - alibaba/G3D: A pure 3D render engine compatible with webgl, running both in browser and gcanvas. 虽然早就不更新了,但是用到微信小程序的webgl1.0还是可以的.
他的源码中就有skybox的示例,整个库打包后 101k
下面是components/bui-vr-preview 目录下的文件
bui-vr-preview.vue
g3d.min.js //下载源码自己打包吧
Image360.js
<template>
<view class="bui-vr-preview" style="background-color: aliceblue;">
<canvas type="webgl" :id="id" :canvas-id="id" :style="{width: width, height:height}"
:disable-scroll="true"
@touchmove.prevent.stop="touchmove"
@touchstart.prevent.stop="touchstart"
@touchend.prevent.stop="touchend"
@error="canvasIdErrorCallback"></canvas>
</view>
</template>
<script>
// fbudlr
import Image360 from "./Image360.js";
let images = [
"https://yourhost****/dist/00/manager/buick/pano_f.jpeg?imageMogr2/auto-orient/strip/rotate/180/thumbnail/!1024x1024r/quality/70/interlace/1/gravity/center",
"https://yourhost****/dist/00/manager/buick/pano_b.jpeg?imageMogr2/auto-orient/strip/rotate/180/thumbnail/!1024x1024r/quality/70/interlace/1/gravity/center",
"https://yourhost****/dist/00/manager/buick/pano_u.jpeg?imageMogr2/auto-orient/strip/rotate/180/thumbnail/!1024x1024r/quality/70/interlace/1/gravity/center",
"https://yourhost****/dist/00/manager/buick/pano_d.jpeg?imageMogr2/auto-orient/strip/rotate/360/thumbnail/!1024x1024r/quality/70/interlace/1/gravity/center",
"https://yourhost****/dist/00/manager/buick/pano_l.jpeg?imageMogr2/auto-orient/strip/rotate/180/thumbnail/!1024x1024r/quality/70/interlace/1/gravity/center",
"https://yourhost****/dist/00/manager/buick/pano_r.jpeg?imageMogr2/auto-orient/strip/rotate/180/thumbnail/!1024x1024r/quality/70/interlace/1/gravity/center",
]
export default {
name: "bui-vr-preview",
props: {
/* canvas id, 同一页面多次引用,不可重名 */
id:{
type:String,
default: "canvas_" + Math.round(Math.random()*9999)
},
/**
* 高度 默认450rpx
*/
height: {
type: String,
default: "450rpx"
},
/**
* 宽度 默认 100%
*/
width: {
type: String,
default: "100%"
}
},
data() {
return {
imagebox:null,
inited: false,
};
},
onLoad() {
this.init()
},
methods: {
canvasIdErrorCallback: function (e) {
console.error("canvas 操作异常",e.detail.errMsg ,e)
},
init() {
let self = this;
let selector= this.$$('#'+this.id)
selector.node()
.exec((res) => {
const canvas = res[0].node
console.log(res)
this.imagebox = new Image360(canvas,images,{
textureComplete:()=>{
self.inited = true;
}
});
})
},
touchmove(e) {
let self = this;
if(!self.inited)return;
this.imagebox.touchmove(e)
},
touchstart(e){
let self = this;
this.imagebox.touchstart(e)
},
touchend(e){
let self = this;
if(!self.inited)return;
this.imagebox.touchend(e)
},
}
}
</script>
<style lang="scss" scoped>
</style>
let {
Engine,
Scene,
RotatePerspectiveCamera,
Skybox,
Geometry
} = require("./g3d.min.js")
let lx = null,
ly = null;
/**
*
* 由于 threejs 太大了...
* 先天不足: 由于 wxs不能操作, 微信小程序默认采用前后端分离,消息模式,所以性能和效率上都有损耗,可能不会太流畅
* 注意: 微信小程序不支持2048图片 见 https://github.com/deepkolos/three-platformize
*
注意 skybox 从立方体内部看纹理,是反的, 目前是用cdn把图片转了180度解决. 后面如果遇到不支持cdn的,要考虑用canvas进行镜像转换
貌似可以直接用webgl 把贴图直接镜像..... 没成功
@mail 35802713@qq.com
*/
class Image360 {
/**
* @param {Object} selector
* @param {Object} canvas
* @param {Object} images
* @param {Object} opt
*/
constructor(canvas, images, opt) {
this.canvas = canvas;
// this.gl = canvas.getContext('webgl');
this.images = images;
this.opt = opt || {
//贴图全部加载完成的回调事件
textureComplete: (image360) => {}
}
this.init();
}
/**
* 初始化
*/
init() {
let self = this;
this.engine = new Engine(self.canvas);
this.scene = new Scene(this.engine);
this.camera = new RotatePerspectiveCamera(this.scene);
//横向角度
this.camera.alpha = 0;
//纵向角度
this.camera.beta = 0;
this.camera.radius =10;// 不用改,大了看起来像镜中地球
this.camera.near = 0.001;
this.camera.far = 2000;
// console.log(this.camera,this.scene)
let cnt = 0;
// fbudlr
let imageListPOsi = [ "back","front", "top","bottom", "left", "right"];
let pos = {}
for (let i = 0; i < this.images.length; i++) {
let image = this.canvas.createImage(); //和h5区别 小程序这里没有 new Image
pos[imageListPOsi[i]] = image;
image.onload = () => {
cnt++;
if (cnt >= 6) { //pano形式最多6张,也就是正方体的6个面
let skybox = new Skybox(self.scene, pos,100,true);
console.log(skybox)
function render() {
self.scene.render();
self.requestAnimationFrame(render);
}
render();
//贴图全部加载完成后的回调,外部调用
self.opt.textureComplete && self.opt.textureComplete(self);
}
}
image.src = this.images[i];
}
}
touchmove(e) {
let self = this;
//console.log(e)
let x = e.touches[0].clientX;
let y = e.touches[0].clientY;
self.camera.alpha += (x - lx) / 5;
this.camera.beta = self.clamp(-90, 90, this.camera.beta - (y - ly) / 5);
lx = x;
ly = y;
}
touchstart(e) {
let self = this;
//console.log(e)
let x = e.touches[0].clientX;
let y = e.touches[0].clientY;
lx = x;
ly = y;
}
touchend(e) {
}
/**
* 重绘界面 就认为是动画呈现吧
* 见 https://developers.weixin.qq.com/miniprogram/dev/api/canvas/Canvas.requestAnimationFrame.html
*/
requestAnimationFrame(cb) {
this.canvas.requestAnimationFrame(cb);
}
clamp(min, max, v) {
return v < min ? min : v > max ? max : v;
}
}
export default Image360
外部调用方式:
<bui-vr-preview></bui-vr-preview>
只是第一版,没有增加外部传入图片的prop.
非H5嵌入.
遇到的问题:
由于在立方体内部向外看, 纹理贴图就是反的,现在是用七牛的翻转图片的方式达到正向的效果.
希望有熟悉webgl的达人弄出完美的
网上还看到有用css3弄出来的cubemap的例子....
更多推荐
所有评论(0)