uni-app中使用renderjs在视图层创建摇杆,摇杆addEventListener监听滑动时,this.$ownerInstance.callMethod函数不起作用

发布于 1周前 作者 vueper 来自 Uni-App

uni-app中使用renderjs在视图层创建摇杆,摇杆addEventListener监听滑动时,this.$ownerInstance.callMethod函数不起作用

使用renderjs在视图层创建了一个摇杆,摇杆addEventListener监听滑动,在监听函数里面,使用this.$ownerInstance.callMethod函数不起作用,请问我该怎样才能调用逻辑层函数?

代码如下:

renderBtn() {  
    var bottom = document.getElementById(".bottom");  
    if (!bottom) {  
        bottom = document.createElement("div");  
        bottom.classList = ["bottom"];  
        document.body.appendChild(bottom);  
        var that = this;  
        window.off = function() {  
            plus.nativeUI.confirm("确定结束吗?", (e) => {  
                if (e.index == 0) {  

                }  
            });  
        };  
        bottom.innerHTML = [
            "<div class='btn'><div class='back'></div></div>",  
            "<div class='ybtn off' onclick='off()'></div>",  

        ].join('');
    }  
    var zbtn = document.querySelector(".btn");  
    console.log('zbtn:', zbtn);  
    zbtn.addEventListener('touchstart', function(e) {  
        console.log('点击左摇杆');  
        this.startX = e.touches[0].clientX;  
        this.startY = e.touches[0].clientY;  
    })  
    zbtn.addEventListener('touchmove', function(e) {  
        this.endX = e.touches[0].clientX;  
        this.endY = e.touches[0].clientY;  
        var that = this;  
        console.log('that======:' + that);  
        //获取滑动距离  
        var distanceX = this.endX - this.startX;  
        var distanceY = this.endY - this.startY;  

        //判断滑动方向  
        if (Math.abs(distanceX) > Math.abs(distanceY) && distanceX > 0) {  
            console.log('往右滑动:' + distanceX);  
            that.callMethod("doOver");  
        } else if (Math.abs(distanceX) > Math.abs(distanceY) && distanceX < 0) {  
            console.log('往左滑动:' + distanceX);  
        } else if (Math.abs(distanceX) < Math.abs(distanceY) && distanceY < 0) {  
            console.log('往上滑动');  
        } else if (Math.abs(distanceX) < Math.abs(distanceY) && distanceY > 0) {  
            console.log('往下滑动');  
        }  
    })  
    zbtn.addEventListener('touchend', function() {  
        console.log('Swipe direction: ' + direction);  
        this.startX = 0;  
        this.startY = 0;  
        this.endX = 0;  
        this.endY = 0;  

        var back = document.querySelector(".back");  
        back.style.left = 40 + 'px';  
        back.style.top = 40 + 'px';  
    })  
}
信息类型 信息
开发环境 未提及
版本号 未提及
项目创建方式 未提及

1 回复

uni-app 中使用 renderjs 创建摇杆并监听滑动事件时,如果 this.$ownerInstance.callMethod 函数不起作用,可能是由于 renderjs 环境中对 Vue 实例的访问方式有所不同。在 renderjs 中,我们不能直接使用 Vue 实例的方法,因为 renderjs 运行在一个相对独立的环境中,用于提升性能并减少 DOM 操作对主线程的影响。

下面是一个使用 renderjs 创建摇杆并监听滑动事件的示例代码,同时展示如何在 renderjs 环境中调用页面逻辑。

页面代码 (pages/index/index.vue)

<template>
  <view class="container">
    <canvas canvas-id="joystickCanvas" style="width: 100px; height: 100px;"></canvas>
  </view>
</template>

<script>
export default {
  mounted() {
    this.$nextTick(() => {
      this.initJoystick();
    });
  },
  methods: {
    handleJoystickMove(data) {
      console.log('Joystick moved:', data);
      // 在这里处理摇杆移动的逻辑
    },
    initJoystick() {
      const renderScript = `
        const canvas = uni.createCanvasContext('joystickCanvas');
        const joystick = { x: 50, y: 50 }; // 假设摇杆中心在画布中心
        const radius = 40; // 摇杆半径

        canvas.setStrokeStyle('#000');
        canvas.setLineWidth(2);
        canvas.drawCircle(50, 50, radius, false);

        function onTouchMove(e) {
          const touch = e.touches[0];
          const rect = uni.getNodeInfo(canvas).boundingClientRect;
          joystick.x = touch.x - rect.left;
          joystick.y = touch.y - rect.top;

          // 限制摇杆在画布内移动
          if (joystick.x < 0) joystick.x = 0;
          if (joystick.y < 0) joystick.y = 0;
          if (joystick.x > rect.width) joystick.x = rect.width;
          if (joystick.y > rect.height) joystick.y = rect.height;

          // 更新画布
          canvas.clearRect(0, 0, rect.width, rect.height);
          canvas.drawCircle(50, 50, radius, false);
          canvas.beginPath();
          canvas.moveTo(50, 50);
          canvas.lineTo(joystick.x, joystick.y);
          canvas.setStrokeStyle('#FF0000');
          canvas.stroke();
          canvas.draw(true);

          // 调用页面方法
          const data = { x: joystick.x, y: joystick.y };
          postMessage(data);
        }

        canvas.canvas.addEventListener('touchmove', onTouchMove);
      `;
      uni.createSelectorQuery().select('#joystickCanvas').fields({ node: true, size: true }).exec((res) => {
        const context = res[0].node.getContext('renderjs', renderScript);
      });
    }
  },
  onUnload() {
    // 页面卸载时移除事件监听器(示例中未直接实现,但应考虑)
  }
};
</script>

解释

  1. Canvas 初始化:在 mounted 生命周期钩子中初始化摇杆。
  2. RenderJS 脚本:在 renderScript 中定义了摇杆的逻辑,包括绘制和触摸移动事件处理。
  3. 事件监听:使用 canvas.canvas.addEventListener('touchmove', onTouchMove) 监听触摸移动事件。
  4. 数据传递:通过 postMessage(data) 将摇杆位置数据发送回页面逻辑。

注意:在真实项目中,你可能需要更复杂的逻辑来处理摇杆边界、灵敏度等,并且需要确保在组件卸载时移除事件监听器以避免内存泄漏。

回到顶部