h5页面全局悬浮按钮可点击、拖动、自动贴边

实际样式,可以实现悬浮贴边,同时可以拖动,自动贴边

图片下方带文字,可以根据自己的需求更改样式。可以全局任意页面存在

可以全局实现一个悬浮按钮,同时按钮可以点开,再次排列图标提供点击操作事件

代码内容


import  from '@/static/image/'
//上面的内容为引入的图片等内容
//下面部分为设置的默认样式,可以在main.js文件内传入相关内容,下面的参数根据需要删改
const defaultOptions = {
    url: '',
    isStickySide: false,
    isUni: true,
    stickyLeft: false,
    stickyRight: false,
    vertical: true,
    horizontal: true,
    style: {
        width: '140rpx',
        height: '80rpx',
        top: '1160rpx',
        right: '0',
        zIndex: 998,
    },
};
//为了便于维护,做了一个列表来方路径和图标,其他参数看着加
const listData = [{HttpPath:true,url:'网络连接地址',imageSrc:'更换图片',text:'文字',id:0},{HttpPath:true,url:'',imageSrc:'',text:'',id:1},{HttpPath:false,page:'这是页面内的代码路径',imageSrc:'',text:'',id:2},]
//使用的方法,外面就使用这个名称,下面就是不断的对样式做修改
export class Buttons {
    constructor(options = defaultOptions) {
        this.options = options;
        this.touchStartX = 0;
        this.touchStartY = 0;
        this.offsetX = 0;
        this.offsetY = 0;
        this.isDragging = false;
        this.vertical = false;
        this.horizontal = false;
        const { isUni, style = {}, isStickySide, stickyLeft = false, stickyRight = false, vertical = true, horizontal = true } = options;
        let { width = '48px', height = '48px', background = `white`, top = '1160rpx', right = '6px', zIndex = 998 } = style;
        // if (!isUni) {
            // width = `${rpx2px(width)}px`;
            // height = `${rpx2px(height)}px`;
            // top = `${rpx2px(top)}px`;
        // }
        this.el = document.createElement('div');
        this.el.classList.add('global-float-btn');
        this.el.id = 'globalFloatBtn';
        this.el.style.position = 'fixed';
        this.el.style.top = top;
        this.el.style.right = right;
        this.el.style.zIndex = `${zIndex}`;
        this.el.style.width = width;
        this.el.style.height = height;
        this.el.style.borderRadius = '50%'
        this.el.style.display = 'flex';
        this.el.style.flexDirection = 'column';
        this.el.style.justifyContent = 'center';
        this.el.style.alignItems = 'center';
        this.el.style.background = background;
        this.el.style.backgroundSize = `${width} ${height}`;
        this.vertical = vertical;
        this.horizontal = horizontal;
        if (isStickySide || stickyLeft || stickyRight) {
            this.vertical = true;
            this.horizontal = true;
        }
        this.el.addEventListener('touchstart', this.touchstart.bind(this));
        this.el.addEventListener('touchmove', this.touchmove.bind(this));
        this.el.addEventListener('touchend', this.touchend.bind(this));
        document.body.appendChild(this.el);
       let imgElement = document.createElement('img');
       imgElement.src = chevronRight
       imgElement.id = 'chevronRight';
       imgElement.style.width = '30px'
       imgElement.style.height = '30px'
        this.el.appendChild(imgElement);
    }
    //点击的时候的执行事件,由于是一个悬浮按钮,点击后弹出其他的悬浮按钮,所以做了点击判断
    btnClick(e) {
        if(e.target.id && e.target.id === 'chevronRight'){
            let listDiv = document.querySelector('#globalFloatList');
            if(listDiv !== null) {
                listDiv.remove();
            } else {
                let listDiv = document.createElement('div');
            
                listDiv.classList.add('global-float-list');
                listDiv.id = 'globalFloatList';
            
                listDiv.style.position = 'absolute';
                listDiv.style.top =  `-63px`; 
                listDiv.style.right = `60px` ; 
                listDiv.style.zIndex = 999;
                listDiv.style.width = '48px'; 
                listDiv.style.height = 'auto'; 
                listDiv.style.background = 'transparent'; 
                listDiv.style.display = 'flex';
                listDiv.style.flexDirection = 'column';
                listDiv.style.justifyContent = 'center';
                listDiv.style.alignItems = 'center';
                this.el.appendChild(listDiv);
                for (let i = 0; i < listData.length; i++) {
                    let div = document.createElement('div');
                    div.style.display = 'flex';
                    div.style.flexDirection = 'column';
                    div.style.justifyContent = 'center';
                    div.style.alignItems = 'center';
                    let imgElement = document.createElement('img');
                    imgElement.src = listData[i].imageSrc
                    imgElement.id = listData[i].id;
                imgElement.style.width = '40px'
                imgElement.style.height = '40px'
                imgElement.style.marginBottom = '3px'
                div.style.marginBottom = '15px'
                div.appendChild(imgElement);
                let divElement = document.createElement('div');
                divElement.style.height = '12px'
                divElement.style.fontSize = '12px'
                divElement.textContent = listData[i].text
                
                div.appendChild(divElement);
                listDiv.appendChild(div);
                }
                
            }

        }else{
            if(e.target.id && listData[e.target.id]){
                 if(listData[e.target.id].HttpPath){

                    if (eh.env.platform !== 'notInEhApp') {
                        eh.biz.util.openLink({ url: listData[e.target.id].url });
                    }
                    else if (env.platform !== 'notInDingTalk') {
                        biz.util.openLink({ url: listData[e.target.id].url });
                    }
                    else {
                        window.open(listData[e.target.id].url, '_blank');
                    }
                    
                 }else{
                    uni.navigateTo({
                        url: `${listData[e.target.id].page}`,
                      })
                 }
                 let listDiv = document.querySelector('#globalFloatList');
                 listDiv.remove();
            }

        }

    
    }
    touchstart(event) {
        // 阻止默认事件(防止页面滚动)
        event.preventDefault();
        // 计算偏移量
        const touch = event.touches[0];
        const touchStartX = touch.clientX;
        const touchStartY = touch.clientY;
        this.touchStartX = touchStartX;
        this.touchStartY = touchStartY;
        this.offsetX = touchStartX - this.el.offsetLeft;
        this.offsetY = touchStartY - this.el.offsetTop;
        // 标记正在拖动
        this.isDragging = false;
    }
    touchmove(event) {
        // 阻止默认事件(防止页面滚动)
        event.preventDefault();
        // 计算元素的新位置
        const touch = event.touches[0];
        const curTouchStartX = touch.clientX;
        const curTouchStartY = touch.clientY;
        const distanceX = curTouchStartX - this.touchStartX;
        const distanceY = curTouchStartY - this.touchStartY;
        // 大于10像素就算他拖动吧
        if (Math.abs(distanceX) > 10 || Math.abs(distanceY) > 10) {
            this.isDragging = true;
        }
        let left = this.horizontal ? touch.clientX - this.offsetX : this.el.offsetLeft;
        let top = this.vertical ? touch.clientY - this.offsetY : this.el.offsetTop;
        // 对元素位置进行范围限制
        if (left < 0) {
            left = 0;
        }
        else if (left > window.innerWidth - this.el.offsetWidth) {
            left = window.innerWidth - this.el.offsetWidth;
        }
        if (top < 0) {
            top = 0;
        }
        else if (top > window.innerHeight - this.el.offsetHeight) {
            top = window.innerHeight - this.el.offsetHeight;
        }
        // 设置元素新的位置
        this.el.style.left = `${left}px`;
        this.el.style.top = `${top}px`;
    }
    touchend(event) {
        event.preventDefault();
        event.stopPropagation();
        // 是拖动再做拖动该做的事情,否则做点击做的事情
        if (this.isDragging) {
            if (this.options.isStickySide) {
                if (this.el.offsetLeft > window.innerWidth / 2 - this.el.offsetWidth) {
                    this.el.style.left = (window.innerWidth - this.el.offsetWidth) + "px";
                }
                else {
                    this.el.style.left = "0px";
                }
            }
            if (this.options.stickyLeft) {
                this.el.style.left = "0px";
            }
            if (this.options.stickyRight) {
                this.el.style.left = (window.innerWidth - this.el.offsetWidth) - 6 + "px";
            }
        }
        else {
            this.btnClick(event);
        }
    }
    destroy() {
        this.el.removeEventListener('touchstart', this.touchstart.bind(this));
        this.el.removeEventListener('touchmove', this.touchmove.bind(this));
        this.el.removeEventListener('touchend', this.touchend.bind(this));
        document.body.removeChild(this.el);
        this.el = null;
    }
}

在main.js使用

//直接引入,注意路径和名称
import { Buttons } from '';

// New一个后,页面就可以使用了,只是初始化了页面为位置
new Buttons({stickyRight:true,style:{
  top:'60vh',
}})

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
WPF仿QQ贴边自动隐藏功能主要是通过设置窗口的动画效果来实现的。首先,需要监听窗口的位置变化事件,当窗口靠近屏幕边缘时,触发隐藏动画效果。其次,可以使用WPF自带的动画库,如DoubleAnimation、Storyboard等,来定义窗口隐藏时的动画效果。在动画完成后,将窗口的Visibility属性设置为Collapsed来实现窗口的隐藏。 下面是实现这一功能的一段简单源码示例: ```csharp private void Window_LocationChanged(object sender, EventArgs e) { double screenWidth = SystemParameters.PrimaryScreenWidth; double screenHeight = SystemParameters.PrimaryScreenHeight; double pixelsFromTop = this.Top; double pixelsFromBottom = screenHeight - this.Top - this.ActualHeight; double pixelsFromLeft = this.Left; double pixelsFromRight = screenWidth - this.Left - this.ActualWidth; double boundary = 10; // 靠边触发隐藏的距离阈值 if (pixelsFromTop < boundary || pixelsFromBottom < boundary || pixelsFromLeft < boundary || pixelsFromRight < boundary) { // 如果靠近边缘,执行隐藏动画 DoubleAnimation animation = new DoubleAnimation(1, 0, new Duration(TimeSpan.FromSeconds(0.5))); this.BeginAnimation(UIElement.OpacityProperty, animation); } else { // 如果不靠近边缘,取消隐藏动画 DoubleAnimation animation = new DoubleAnimation(0, 1, new Duration(TimeSpan.FromSeconds(0.5))); this.BeginAnimation(UIElement.OpacityProperty, animation); } } ``` 这段代码中,通过监听窗口的LocationChanged事件,计算窗口与屏幕边缘的距离,并根据一定的阈值来触发隐藏动画效果。当窗口靠近边缘时,执行隐藏动画,动画完成后将窗口的Opacity属性设置为0,实现窗口的隐藏。当窗口远离边缘时,取消隐藏动画,并将窗口的Opacity属性设置为1,使窗口重新显示出来。通过这种方式,就可以实现仿QQ贴边自动隐藏的效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值