关于在微信小程序使用WebglCanvas和ThreeJs开发的二三事(一)
发布于 5 年前 作者 min49 4632 次浏览 来自 分享
最近应公司项目需求要在微信小程序上进行3D模型渲染,还要调用微信摄像头所以不能直接上webview只能使用微信的WebglCanvas来做。过程中踩了一些坑,现在功能基本达到所以打算记录下遇到的问题与解决办法思路,希望对自己和也在微信WebglCanvas上踩坑的小伙伴所有帮助,也希望官方可以及时填坑。

在开发中遇到的问题大致如下:

  1. 动态调整画布的大小,位置。
  2. ThreeJs的引入与使用。
  3. 透明混合的问题

问题描述与解决方案

  1. 所谓工欲善其事必先利其器,在使用ThreeJs进行3D渲染之前我们需要向ThreeJs提供Webgl的绘制上下文。在原生H5中我们可以轻松用的dom操作获取,而在小程序我们只能使用SelectorQuery的方法来获得
<canvas type="webgl" id="webgl" ></canvas>
// 先声明一个canvas并将其类型设为webgl
 wx.createSelectorQuery()
      .select('#webgl')
      .node()
      .exec(res=> {
        let canvas = res[0].node;
        let ctx = canvas.getContext("webgl");
        ctx.clearColor(1, 0, 0, 1);
        ctx.clear(ctx.COLOR_BUFFER_BIT);
      })
// 通过SelectorQuery获取canvas组件,获取绘制上下文,简单将画布渲染为红色

通过上面的代码我们获得一个这样的画面

这时如果你想设置画布的大小可以通过wxss或者style属性来设定,这里我们通过style来设定

<canvas type="webgl" id="webgl" 
style=" position:fixed;width:{{cavansWidth}}px;height:{{cavansHeight}}px;top:{{canvasTop}}px;left:{{canvasLeft}}px;"
></canvas>
Page({
  data: {
    cavansWidth: 150,
    cavansHeight: 150,
    canvasTop: 0,
    canvasLeft: 0,
  },
})

如果要动态修改画布大小比如改成300*300的尺寸, 一般会直接用setData来做,但这样并不能在开发者工具中正确的修改canvas尺寸。

从上图可以发现canvas的样式其实已经修改成功了但是绘制区域并没有修改成功,这是一个很奇怪的问题,这个问题也困扰我很久。万事不决用console。打印了ctx(绘制上下文)后,发现ctx中canvas属性的css样式并没有修改

抱着试一试的心态我手动修改了其属性的值。

 ctx.canvas.style.left = 20 + 'px';
 ctx.canvas.style.top = 20 + 'px';
 ctx.canvas.style.width = 300 + 'px';
 ctx.canvas.style.height = 300 + 'px';

居然就得到想要的画布,但你以为这样就结束了吗,并没有。让我们掏出我们的手机来试试预览吧。如果你是安卓机,恭喜你你获得了一个报错,如果你是苹果机你会发现修改不生效。

至于什么会这样只能问官方了。那么如何在手机上正常的修改,其实也很简单就使用setData修改,不使用style属性修改就可以了。为了方便起见,在修改前判定下是否为开发工具即可。

//index.js
//获取应用实例
const app = getApp()
Page({
  data: {
    cavansWidth: 150,
    cavansHeight: 150,
    canvasTop: 0,
    canvasLeft: 0,
  },
  onReady: function () {
    this.setData({
      cavansWidth: 300,
      cavansHeight: 300,
      canvasTop: 20,
      canvasLeft: 20,
    })
    wx.createSelectorQuery()
      .select('#webgl')
      .node()
      .exec(res => {
        let canvas = res[0].node;
        let ctx = canvas.getContext("webgl");
        wx.getSystemInfo({
          success: function (res) {
            if (res.platform == 'devtools') {
              ctx.canvas.style.left = 20 + 'px';
              ctx.canvas.style.top = 20 + 'px';
              ctx.canvas.style.width = 300 + 'px';
              ctx.canvas.style.height = 300 + 'px';
            }
          }
        })
        console.log(ctx);;
        ctx.clearColor(1, 0, 0, 1);
        ctx.clear(ctx.COLOR_BUFFER_BIT);
      })
  },
})

总结起来就一句话移动端用setData修改,开发工具用ctx.canvas.style属性修改。

另外在设置画布初始大小的时候最好设置大一点,如果你修改的尺寸比原始大小大太多会造成渲染模糊的问题,其中具体原因就要问官方了。。。。。。。

好了,第一部分就到这了,有什么问题可以私信或者发表评论,我保证尽量都看都回。

回到顶部