在微信小程序如何跨页面构建一个可拖拽的的客服组件按钮

在微信小程序如何在快速的创建一个可拖拽的按钮,我们就需要使用微信的skyline渲染模式

app-bar 默认是全局显示在页面的最上层,所有我们利用这个特效。

首先在miniprogram文件内创建app-bar文件夹【app-bar名字只能这么写】,然后再app-bar中创建名为index的组件
而且需要再app.json 配置 “appBar”: {}

{
	...
  "appBar": {}
}

在app-bar组件中的wxml文件中

index.wxml

<pan-gesture-handler worklet:ongesture="onGesture">
  <view id="consult" class="consult" bind:tap="onConsult" hidden="{{!visible}}">
    <view class="consult-box">
      <image src="{{icon}}" mode="" />     
    </view>
  </view>
</pan-gesture-handler>

index.ts

import { openServer } from "../utils/config";

const GestureState = {
  POSSIBLE: 0,
  BEGIN: 1,
  ACTIVE: 2,
  END: 3,
  CANCELLED: 4,
};

const { shared, spring } = wx.worklet;
const defaultX = 160;
//x,y起始位置
const x = shared(defaultX);
const y = shared(0);
const scale = shared(1);

//用于记录在打开底部弹出时,y的开始位置
const dy = shared(0);

//边距
const margin = 10;

//是否是首次打开
let first = false;
//记录按钮当前位置
let iconX = shared(0);
//客服icon的尺寸
let iconWidth = shared(0);
let iconHeight = shared(0);

// 获取系统信息
const systemInfo = wx.getSystemInfoSync();
const { windowWidth, windowHeight } = systemInfo;

var app = getApp();

//需要显示的页面
const visibleRoutes: string[] = [
  "pages/index/index",
  "pages/xxx/xxx",
];
let timer = 0;
Component({
  properties: {
    visible: {
      type: Boolean,
      value: false,
      observer: function (a, b) {
        if (a && this.data.currentPathVisible) {
          first = true;
          //获取 icon 按钮的尺寸
          this.createSelectorQuery()
            .select(".consult-box")
            .boundingClientRect((res) => {
              this.setData({
                iconSize: { w: res.width, h: res.height },
              });
              iconWidth.value = res.width;
              iconHeight.value = res.height;
              console.log("iconSize", res);
            })
            .exec();
          timer = setTimeout(() => {
            x.value = spring(-margin, {}, () => {});
            clearTimeout(timer);
          }, 1000);
        }
      },
    },
    themeCode: {
      value: "",
      type: String,
      observer: function (a: string, b) {
        console.log(a);
        this.setData({
          icon: app.globalData.dictMap.get("customerServiceIcon"),
        });
      },
    },
    //监听页面是否在滚动
    scrolling: {
      type: Boolean,
      value: false,
      observer: function (a, b) {
        if (!a) {
          this.setData({
            currentPathVisible: true,
          });
          //当前路由显示,判断icon 从左边出现 还是右边出现
          console.log("显示", x.value, iconX.value, iconWidth.value);
          if (x.value >= -windowWidth / 2 + iconWidth.value) {
            //从右
            x.value = spring(-margin, {}, () => {});
          } else if (x.value <= -windowWidth / 2 + iconWidth.value) {
            //从左
            x.value = spring(
              -windowWidth + iconWidth.value + margin,
              {},
              () => {}
            );
          }
        } else {
          this.setData({
            currentPathVisible: false,
          });
          clearTimeout(timer);
          //当前路由隐藏,判断icon 从左边隐藏 还是右边隐藏
          if (x.value >= -windowWidth / 2 + iconWidth.value) {
            //向右
            x.value = spring(defaultX, {}, () => {});
          } else if (x.value <= -windowWidth / 2 + iconWidth.value) {
            //向左
            x.value = spring(-windowWidth - defaultX, {}, () => {});
          }
        }
      },
    }
  },
  data: {
    icon: "",
    //客服icon的尺寸
    iconSize: {
      w: 72,
      h: 82,
    },
    currentPathVisible: true, // 用于判断,用户进入首页,刚加载完成班别数据,此时跳转到个人主页,会触发出现悬浮客服按钮
  },
  lifetimes: {
    ready() {
      wx.onAppRoute((route: any) => {
        console.log("onAppRoute", route.path);
        if (visibleRoutes.includes(route.path)) {
          this.setData({
            currentPathVisible: true,
          });
          //当前路由显示,判断icon 从左边出现 还是右边出现
          console.log("显示", x.value, iconX.value, iconWidth.value);
          if (x.value >= -windowWidth / 2 + iconWidth.value) {
            //从右
            x.value = spring(-margin, {}, () => {});
          } else if (x.value <= -windowWidth / 2 + iconWidth.value) {
            //从左
            x.value = spring(
              -windowWidth + iconWidth.value + margin,
              {},
              () => {}
            );
          }
        } else {
          this.setData({
            currentPathVisible: false,
          });
          clearTimeout(timer);
          //当前路由隐藏,判断icon 从左边隐藏 还是右边隐藏
          if (x.value >= -windowWidth / 2 + iconWidth.value) {
            //向右
            x.value = spring(defaultX, {}, () => {});
          } else if (x.value <= -windowWidth / 2 + iconWidth.value) {
            //向左
            x.value = spring(-windowWidth - defaultX, {}, () => {});
          }
        }
      });
    },
    attached() {
      this.applyAnimatedStyle(".consult-box", () => {
        "worklet";
        return {
          transform: `translate(${x.value}px, ${y.value}px) scale(${scale.value})`,
        };
      });
    },
  },
  methods: {
    //监听打开客服
    onConsult() {
      openServer();
    },
    onGesture(evt: any) {
      "worklet";
      console.log("onGesture", evt);
      if (evt.state === GestureState.BEGIN) {
        scale.value = 1.1;
      } else if (evt.state === GestureState.ACTIVE) {
        x.value += evt.deltaX;
        y.value += evt.deltaY;
      } else if (
        evt.state === GestureState.END ||
        evt.state === GestureState.CANCELLED
      ) {
        scale.value = 1;
        //x
        if (x.value > -windowWidth / 2) {
          x.value = spring(-margin, {}, () => {});
          iconX.value = -margin;
        } else if (x.value <= -windowWidth / 2) {
          x.value = spring(
            -windowWidth + iconWidth.value + margin,
            {},
            () => {}
          );
          // iconX.value = -windowWidth + iconWidth.value + margin
          console.log(iconWidth.value, margin);
        }

        if (y.value < -windowHeight / 2 + iconHeight.value) {
          y.value = spring(-windowHeight / 2 + iconHeight.value, {}, () => {});
        } else if (y.value >= windowHeight / 2 - iconHeight.value * 2) {
          y.value = spring(
            windowHeight / 2 - iconHeight.value * 2,
            {},
            () => {}
          );
        }
      }
    },
  },
});

如何控制app-bar

首先我们在app.ts中 globalData对象中新增 appBarComp:null;

在index首页onload的时候获取app-bar实例

  onLoad: function (options: any) {
	//获取appbar实例
    if (typeof this.getAppBar === "function") {
      app.globalData.appBarComp = this.getAppBar();
    }
  }

然后在别的地方控制传递的参数来控制app-bar,通过setData控制

	//设置客服icon显示
    app.globalData.appBarComp &&
    app.globalData.appBarComp.setData({
         visible: true,
    });

到处结束,相当的简单。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值