chat-app/src/uni_modules/tmui/components/tm-adsorb/tm-adsorb.vue
scout b54bfe63ad
Some checks are pending
Check / lint (push) Waiting to run
Check / typecheck (push) Waiting to run
Check / build (build, 18.x, ubuntu-latest) (push) Waiting to run
Check / build (build, 18.x, windows-latest) (push) Waiting to run
Check / build (build:app, 18.x, ubuntu-latest) (push) Waiting to run
Check / build (build:app, 18.x, windows-latest) (push) Waiting to run
Check / build (build:mp-weixin, 18.x, ubuntu-latest) (push) Waiting to run
Check / build (build:mp-weixin, 18.x, windows-latest) (push) Waiting to run
init
2024-11-11 14:46:14 +08:00

191 lines
4.4 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<!-- #ifdef MP -->
<view @touchstart="touch.startDrag" @touchmove.stop="touch.onDrag" @touchend="touch.endDrag" :data-prop="towxsShareData">
<!-- #endif -->
<!-- #ifdef H5||APP-VUE -->
<view @touchstart="touch.startDrag" @touchmove="touch.onDrag" @touchend="touch.endDrag" :data-prop="towxsShareData">
<!-- #endif -->
<!-- #ifdef APP-NVUE -->
<view >
<!-- #endif -->
<view @touchstart="touchstart" :style="{ left: _offset[0] + 'rpx', top: _offset[1] + 'rpx' }" class="div" id="adsorb" ref="adsorb">
<view
:eventPenetrationEnabled="true"
:style="{
width: props.width + 'rpx',
height: props.height + 'rpx'
}"
>
<slot></slot>
</view>
</view>
</view>
</template>
<!-- #ifndef APP-NVUE -->
<script module="touch" lang="wxs" src="touch.wxs"></script>
<!-- #endif -->
<script lang="ts" setup>
import { ref, inject, computed, unref, PropType,getCurrentInstance } from 'vue';
// #ifdef APP-NVUE
var dom = weex.requireModule("dom");
const Binding = uni.requireNativePlugin("bindingx");
const animation = uni.requireNativePlugin("animation");
const proxy = getCurrentInstance()?.proxy??null;
// #endif
const props = defineProps({
/** 是否吸附边缘,关闭可以任意托动组件,开启拖动只会吸附在两边。 */
adsorb: {
type: Boolean,
default: true
},
/** 开启吸附后吸附到边缘的动画时间单位ms */
duration: {
type: Number,
default: 600
},
width: {
type: Number,
default: 100
},
height: {
type: Number,
default: 100
},
/** 默认的位置 */
offset: {
type: Array as PropType<Array<number>>,
default: () => [0, 0]
},
/** 吸附的偏移量比如向左时是吸附侧边0还是再往左偏移多少 */
adsorbX: {
type: Number,
default: 0
}
});
const sysinfo = inject(
'tmuiSysInfo',
computed(() => {
return {
bottom: 0,
height: 750,
width: uni.upx2px(750),
top: 0,
isCustomHeader: false,
sysinfo: null
};
})
);
const _offset = computed(() => props.offset);
let bindxToken:any = null;
const towxsShareData = ref({
adsorb: props.adsorb,
sys: sysinfo.value,
adsorbX: props.adsorbX,
duration: props.duration
});
let position = {x:0,y:0};
function getEl(el: any) {
if (typeof el === "string" || typeof el === "number") return el;
if (WXEnvironment) {
return el.ref;
} else {
return el instanceof HTMLElement ? el : el.$el;
}
}
function spinNvueAniEnd(start: number,end:number, duration = props.duration) {
// #ifdef APP-NVUE
if (!proxy?.$refs?.adsorb) return;
animation.transition(
proxy?.$refs.adsorb,
{
styles: {
transform: `translate(${start}px,${end}px)`,
transformOrigin: "center center",
},
duration: duration, //ms
timingFunction: "cubicBezier(0.18, 0.89, 0.32, 1)",
delay: 0, //ms
},
() => {
}
);
// #endif
}
function touchstart(e: TouchEvent) {
// #ifdef APP-NVUE
if (!proxy?.$refs?.adsorb) return;
let icon = getEl(proxy?.$refs.adsorb);
let icon_bind = Binding.bind(
{
anchor: icon,
eventType: "pan",
props: [
{
element: icon,
property: "transform.translateX",
expression: `x+${position.x}`,
},
{
element: icon,
property: "transform.translateY",
expression: `y+${position.y}`,
},
],
},
function (res) {
if (res.state == "end") {
position.x+=res.deltaX
position.y+=res.deltaY
if(towxsShareData.value.adsorb){
dom.getComponentRect(proxy?.$refs.adsorb, function (res:UniApp.NodeInfo|UniApp.NodeField) {
if (res?.size) {
let left=0
let top=0
let rect = res.size;
let x = uni.upx2px(props.offset[0]);
let y = uni.upx2px(props.offset[1]);
if(Math.abs((rect.left+rect.width/2))<=towxsShareData.value.sys.width/2){
left = x - Math.abs(position.x)
position.x = -left+position.x - towxsShareData.value.adsorbX
}else{
left = towxsShareData.value.sys.width - rect.right;
position.x =position.x + left + towxsShareData.value.adsorbX
}
if(rect.bottom>=towxsShareData.value.sys.height){
position.y =position.y - (rect.bottom-towxsShareData.value.sys.height)
}
if(rect.top<=0){
position.y =position.y + Math.abs(rect.top)
}
spinNvueAniEnd(position.x,position.y);
}
});
}
} else if (res.state == "start") {
}
}
);
bindxToken = icon_bind.token;
// #endif
}
defineExpose({});
</script>
<style scoped>
.div {
position: fixed;
}
</style>