Taro项目 实现一个在页面内自由拖拽的滑块,仿苹果手机的辅助按钮
效果:自由拖拽,松手会自动吸附到边上
组件代码:
import { EventProps, ITouchEvent, View } from '@tarojs/components'
import { getSystemInfoSync } from '@tarojs/taro'
import { clamp } from 'lodash'
import React, { CSSProperties, FC, useEffect, useState } from 'react'let start: EventProps['onTouchStart']
let move: EventProps['onTouchMove']
let end: EventProps['onTouchEnd']/** 来自父组件的主动cancel,因为本组件无法百分比捕捉到touchEnd事件 */
export const cancelDrag = (e: any) => {end && end(e)
}interface DraggableProps {width: stringheight: string/** 初始left值 */defaultLeft?: number/** 初始top值 */defaultTop?: number/** 上面收紧多少 */marginTop?: number/** 右边收紧多少 */marginRight?: number/** 下边收紧多少 */marginBottom?: number/** 左边收紧多少 */marginLeft?: number/** 只能垂直移动 */vertical?: boolean/** 只能水平移动 */horizontal?: boolean/** 默认左边 */left?: boolean/** 默认右边 */right?: boolean/** 默认上边 */top?: boolean/** 默认下边 */bottom?: boolean/** 默认中间 */center?: boolean/** 开始移动 */onBegin?: (e: ITouchEvent<any>) => void/** 结束移动 */onEnd?: (e: ITouchEvent<any>) => void/** 自动贴边 */autoCling?: boolean
}const Draggable: FC<DraggableProps> = ({defaultLeft = 0,defaultTop = 0,marginLeft = 0,marginRight = 0,marginBottom = 0,marginTop = 0,vertical = false,horizontal = false,left = false,right = false,top = false,bottom = false,center = false,onBegin,onEnd,width,height,autoCling,children,
}) => {const w = parseInt(width)const h = parseInt(height)const sys = getSystemInfoSync()const [state, setState] = useState({moving: false,left: defaultLeft,top: defaultTop,width: width,height: height,screenW: sys.screenWidth,screenH: sys.screenHeight,transition: '',})const setPosition = (left: number, top: number, direction = false) => {let newLeft: numberlet newTop: numberif (!direction && vertical) {newLeft = state.left} else {newLeft = clamp(left, 0 + marginLeft, state.screenW - w - marginRight)}if (!direction && horizontal) {newTop = state.top} else {newTop = clamp(top, 0 + marginTop, state.screenH - h - marginBottom)}setState((state) => {return {...state,left: newLeft,top: newTop,}})}useEffect(() => {let x = state.leftlet y = state.topif (left) {x = -1if (center) {y = state.screenH / 2 - h / 2}}if (top) {y = -1if (center) {x = state.screenW / 2 - w / 2}}if (right) {x = 99999if (center) {x = 99999y = state.screenH / 2 - h / 2}}if (bottom) {y = 99999if (center) {x = state.screenW / 2 - w / 2}}setPosition(x, y, true)}, [])start = (e: ITouchEvent<any>) => {e.stopPropagation()setState((state) => ({ ...state, moving: true }))onBegin && onBegin(e)}move = (e: ITouchEvent<any>) => {e.stopPropagation()const { pageX: x, pageY: y } = e.touches[0]setPosition(x - w / 2, y - h / 2)}end = (e: ITouchEvent<any>) => {setState((state) => ({ ...state, moving: false }))onEnd && onEnd(e)if (autoCling) {const duration = 300const x = state.left + parseInt(state.width) / 2if (!state.transition) {setState((state) => ({...state,transition: `all ${duration / 1000}s`,}))}if (x < state.screenW / 2) {setPosition(-1, state.top)} else {setPosition(99999, state.top)}setTimeout(() => {setState((state) => ({ ...state, transition: '' }))}, duration)}}const style: CSSProperties = {position: 'fixed',left: state.left,top: state.top,width,height,overflow: 'visible',transition: state.transition,display: 'flex',alignItems: 'center',justifyContent: 'center',}return (<ViewclassName='draggable'style={style}catchMoveonTouchStart={start}onTouchMove={move}onTouchEnd={end}onTouchCancel={end}>{children}</View>)
}export default Draggable
使用:
引入
import Draggable, { cancelDrag } from '@/common/components/Draggable'
父元素使用 cancelDrag方法,在外面包一层即可
<View onTouchEnd={cancelDrag}><DraggabledefaultTop={cartHeight}marginLeft={10}marginRight={10}marginTop={100}marginBottom={140}leftwidth='60px'height='60px'autoClingonBegin={() => setMoving(true)}onEnd={() => setMoving(false)}><FlexclassName='b-add-purchase m-padding-5 b-elevation-2 m-bg-primary m-text-white m-text-16'// autocolumnjustifyCenteralignCenterwidth='60px'height='60px'style={{zIndex: 1000,borderRadius: 70,}}onClick={handleCreatePurchase}><Flex justifyStart alignCenter><ViewclassName='b-font-edit-pen'style={{ fontSize: '24px !important' }}/>{/* <Flex column><View className='m-text-14'>{t('新建')}</View><View className='m-text-14'>{t('采购')}</View></Flex> */}</Flex></Flex></Draggable>
<View/>
Taro项目 实现一个在页面内自由拖拽的滑块,仿苹果手机的辅助按钮相关推荐
- vue实现指定区域自由拖拽、打印功能
先看下效果图,实现指定区域内内容自由拖拽,不超出.动态设置字体颜色及字号:设置完成实现打印指定区域内容,样式不丢失. 1.运行命令npm i vue-draggable-resizable -S, 安 ...
- 使用TARO框架实现一个登录页面
使用 TARO 框架实现一个登录页面,你需要做以下几件事: 创建一个新的 TARO 项目,在项目根目录下运行 taro init 命令. 在项目的 src 目录下创建一个新的组件,作为登录页面. 在组 ...
- Qt5.14_MinGW/MSVC下实现VS2019面板自由拖拽组合功能
文章目录 前言 一.src源码获取 二.lib_MinGW/lib_MSVC获取 三.库的添加 四.代码测试 总结 前言 最近在项目中需要实现几个窗口可以自由拖拽等需求,一开始使用Qt原生控件QDoc ...
- Vue 实现弹框自由拖拽(不出可视范围、解决快速拖动问题)
Vue 实现弹框自由拖拽(不出可视范围.解决快速拖动问题) 由于页面中弹框很多,往往会挡住想要查看的内容.从而,有了自由移动拖拽弹框的需求:但在使用的过程中发现,一开始编写的drag.js文件会移出可 ...
- winform窗体自由拖拽控件
源码地址:https://download.csdn.net/download/horseroll/10906640 以上链接是用积分下载的,如果没有积分,可以用以下链接付费下载:https://do ...
- html列表拖拽排序插件,可对列表自由拖拽排序的jQuery插件
dragslot.js是一款可以对列表自由拖拽排序的jQuery插件.该插件主要的功能是实现了列表项可以在各个列表中相互拖拽. 对于像todo list, 分配任务列表都可以应用这个效果. 使用方法 ...
- WPF实现窗体在屏幕内移动拖拽,不超过屏幕边界
WPF实现窗体在屏幕内移动拖拽,不超过屏幕边界 最近在项目中遇到WPF弹出窗体只能在屏幕内移动的需求,使用WndProc截获系统消息.ClipCursor API函数控制鼠标可用区域解决了问题,特意记 ...
- element ui 图片控件 排序_vuedraggable+element ui实现页面控件拖拽排序效果
项目要实现一些控件的拖拽排序.从而找到了这款vuedraggable控件,供大家参考,具体内容如下 如上图要实现这些控件的拖拽排序 这是拖拽后 由于公司网络的原因,项目没有使用npm,都是使用的引入的 ...
- 拖拽牛逼,轻松实现一个自由拖拽的组件
如何使元素支持拖动 实现组件的自由拖动的核心就是 html5 中新添加的全局属性 draggable 属性,该属性规定了元素是否可进行拖动.属性值如下所示: true:规定元素的可拖动的 false: ...
最新文章
- 如何保留5个有效数字输出c不4舍5入_10 个C语言课设小项目拿走不谢~
- 统计分组的原则是要体现什么_统计学简答题
- python常用的日期时间模块
- .net core读取配置文件
- Software Engineering 265
- Ajax.net实现的动态输入项
- 有关struts2中用到 js 总结
- 计算日期时间间隔,可计算情侣计算在一起的。精确到,天,时,分,秒(输入的日期距离现在有:819天19670小时1180221分钟70813262秒)
- python计算程序运行时间
- bzoj 1151: [CTSC2007]动物园zoo
- Airflow 中文文档:写日志
- 机器学习1/100天-数据预处理
- 《Cacti实战》——2.2 安装与配置相关组件和服务
- path和classpath的区别
- android mysql客户端_一款基于Android手机的MySQL客户端的设计与实现
- PyQt5 实现类似海康的设备搜索工具
- Dorado7 DataGrid变颜色 自定义渲染
- inception-v3模型神经网络图片识别系统搭建详细流程(1)
- pe下找不到ssd硬盘_进入pe后找不到固态硬盘怎么解决
- java从入门到精通----mysql05