current position:Home>Come on, Vue move the end suspension ball assembly
Come on, Vue move the end suspension ball assembly
2022-05-15 02:14:03【Maple moving forward】
Description of each parameter
## attribute
dragableRange: Drag range .parent Parent window Visual window
dragable: Can I drag . Default true
position: initial position .[object Object] top、left、right、bottom
indent: Whether you need to indent . Default false
indentDelayTime: Delay indent . Company :ms, by 0 Do not indent
indentDistance: Indent distance . Company :px
needNearEdge: Whether trimming is required after dragging the floating ball . Default :false
nearEdgeTransition: Welt transition animation ,transition Property value . Default :'all ease 0.3s'
nearEdgeDirection: The welt direction after dragging the suspension ball . The default trimming direction is the nearest direction .
indentNearEdge: Whether the suspension ball needs to be indented after trimming ( At this time, the indent direction is the direction of the welt ). Default false
indentNearEdgeDelay: Delayed retraction after floating ball welt . Company :ms, Default 1000, by 0 Then there is no delay
## event
clickFunc: Callback event after clicking the floating ball
## slots
slotsDirection: Slot content orientation , By default, it is placed to the right of the floating ball ( If it is not set and turned on needNearEdge, Then the direction will be changed automatically according to the trimming condition )
Component implementation
<template>
<div
class="suspend_ball_wrapper"
:style="{
position: dragableRange === 'window' ? 'fixed' : 'absolute',
...position,
}"
>
<div
v-if="dragable"
class="suspend_ball"
@touchstart="touchstart"
@touchmove="touchmove"
@touchend="touchend"
>
<div class="slots" :class="[slotsDirectionData]">
<slot />
</div>
</div>
<div v-else class="suspend_ball">
<div class="slots" :class="[slotsDirectionData]">
<slot />
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
left: 0,
top: 0,
touchType: 0, // Touch type 1 Drag the levitation ball 0 Click on the levitation ball
indentTimer: null,
indentNearEdgeTimer: null,
slotsDirectionData: "right",
};
},
props: {
dragable: {
type: Boolean,
default: true,
},
dragableRange: {
type: String,
default: "parent",
},
position: {
type: Object,
default: function () {
return {
left: 0,
top: 0,
};
},
},
indent: {
type: Boolean,
default: false,
},
indentDelayTime: {
type: Number,
default: 1000,
},
indentDistance: {
type: Number,
default: 30,
},
indentNearEdge: {
type: Boolean,
default: false,
},
needNearEdge: {
type: Boolean,
default: false,
},
nearEdgeTransition: {
type: String,
default: "all ease 0.3s",
},
nearEdgeDirection: String,
indentNearEdgeDelay: {
type: Number,
default: 1000,
},
slotsDirection: {
type: String,
default: "right",
},
},
created() {
this.slotsDirection && (this.slotsDirectionData = this.slotsDirection);
},
mounted() {
if (this.indent && this.indentDelayTime) {
this.setIndent();
}
},
methods: {
touchstart(e) {
const el = this.$el;
e.preventDefault();
// Touch type 1 Drag the levitation ball 0 Click on the levitation ball
this.touchType = 0;
this.$el.style.transition = "none";
this.clearAllTimeout();
// The coordinates when the finger is pressed
const starX = e.touches[0].clientX;
const starY = e.touches[0].clientY;
this.starX = starX;
this.starY = starY;
// The position of the finger relative to the element itself
this.distanceX = starX - el.offsetLeft;
this.distanceY = starY - el.offsetTop;
},
touchmove(e) {
// The coordinates where the finger moves
const moveX = e.touches[0].clientX;
const moveY = e.touches[0].clientY;
// Finger movement distance
const moveXDistance = moveX - this.starX;
const moveYDistance = moveY - this.starY;
// Set location
let left = moveX - this.distanceX;
let top = moveY - this.distanceY;
// Handle the slight movement caused by clicking
if (Math.abs(moveXDistance) > 15 || Math.abs(moveYDistance) > 15) {
this.touchType = 1;
}
this.validMove(left, top);
},
touchend() {
if (this.touchType === 0) {
this.$emit("touchFunc");
}
// Whether you need to indent
if (this.needNearEdge) {
const {
self_offsetWidth,
self_offsetHeight,
parent_offsetWidth,
parent_offsetHeight,
} = this.getSelfAndParentOffset();
const obj = {
left: parseFloat(this.$el.style.left),
top: parseFloat(this.$el.style.top),
};
obj.right = parent_offsetWidth - obj.left - self_offsetWidth;
obj.bottom = parent_offsetHeight - obj.top - self_offsetHeight;
// Minimum value in each direction
let minKey = "";
// Calculate trim direction
if (this.nearEdgeDirection) {
minKey = this.nearEdgeDirection;
} else {
let min = Math.min();
for (const key in obj) {
const val = parseFloat(obj[key]);
if (val < min) {
min = val;
minKey = key;
}
}
}
// Set welt transition
if (this.nearEdgeTransition) {
this.$el.style.transition = this.nearEdgeTransition;
}
// Trim settings
this.$el.style[minKey] = 0;
// Set the indent after trimming
if (this.indentNearEdge) {
if (this.indentNearEdgeDelay !== 0) {
clearTimeout(this.indentNearEdgeTimer);
this.indentNearEdgeTimer = setTimeout(() => {
this.$el.style[minKey] = -this.indentDistance + "px";
this.setOtherDirectionVal(minKey, this.indentDistance);
}, this.indentNearEdgeDelay);
} else {
this.$el.style[minKey] = -this.indentDistance + "px";
}
}
this.setOtherDirectionVal(minKey);
}
},
// Move
validMove(left, top) {
const {
self_offsetWidth,
self_offsetHeight,
parent_offsetWidth,
parent_offsetHeight,
} = this.getSelfAndParentOffset();
if (left + self_offsetWidth > parent_offsetWidth) {
left = parent_offsetWidth - self_offsetWidth;
}
if (top + self_offsetHeight > parent_offsetHeight) {
top = parent_offsetHeight - self_offsetHeight;
}
if (left <= 0) {
left = 0;
}
if (top <= 0) {
top = 0;
}
this.$el.style.left = left + "px";
this.$el.style.top = top + "px";
this.left = left;
this.top = top;
this.right = "auto";
this.bottom = "auto";
},
// Set indent
setIndent(delayTime) {
clearTimeout(this.indentTimer);
this.indentTimer = setTimeout(() => {
let direction;
let el = this.$el;
const positionObj = this.getPositionComputedStyle();
for (const key in positionObj) {
if (parseFloat(positionObj[key]) === 0) {
direction = key;
}
}
el.style[direction] = el.style[direction] - this.indentDistance + "px";
}, delayTime || this.indentDelayTime);
},
// Set other directions position value
setOtherDirectionVal(minKey, indentDistance = 0) {
const {
parent_offsetWidth,
parent_offsetHeight,
self_offsetWidth,
self_offsetHeight,
} = this.getSelfAndParentOffset();
let slotsDirection = "";
switch (minKey) {
case "left":
this.$el.style["right"] =
parent_offsetWidth - self_offsetWidth + indentDistance + "px";
slotsDirection = "right";
break;
case "right":
this.$el.style["left"] =
parent_offsetWidth - self_offsetWidth + indentDistance + "px";
slotsDirection = "left";
break;
case "top":
this.$el.style["bottom"] =
parent_offsetHeight - self_offsetHeight + indentDistance + "px";
slotsDirection = "bottom";
break;
case "bottom":
this.$el.style["top"] =
parent_offsetHeight - self_offsetHeight + indentDistance + "px";
slotsDirection = "top";
break;
}
// Set the slot orientation ( Not set slotsDirection Then automatically judge )
if (!this.slotsDirection) {
this.slotsDirectionData = slotsDirection;
}
},
// Calculation offset value
getSelfAndParentOffset() {
const ifwindowRange = this.dragableRange === "window";
const parent_offsetWidth = !ifwindowRange
? this.$el.parentNode.offsetWidth
: window.innerWidth;
const parent_offsetHeight = !ifwindowRange
? this.$el.parentNode.offsetHeight
: window.innerHeight;
const self_offsetWidth = this.$el.offsetWidth;
const self_offsetHeight = this.$el.offsetHeight;
return {
parent_offsetWidth,
parent_offsetHeight,
self_offsetWidth,
self_offsetHeight,
};
},
getPositionComputedStyle() {
let el = this.$el;
let style = getComputedStyle(el);
const positionObj = {
top: style.top,
bottom: style.bottom,
left: style.left,
right: style.right,
};
return positionObj;
},
clearAllTimeout() {
clearTimeout(this.indentTimer);
clearTimeout(this.indentNearEdgeTimer);
},
},
};
</script>
<style lang="less" scoped>
.suspend_ball_wrapper {
position: absolute;
// top: 0;
// left: 0;
width: 60px;
height: 60px;
z-index: 1000;
.suspend_ball {
width: 100%;
height: 100%;
border-radius: 50%;
background-size: cover;
background-image: url("https://img0.baidu.com/it/u=272572278,3446974957&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500");
.slots {
position: absolute;
width: fit-content;
height: 100%;
&.right {
left: calc(100% + 10px);
}
&.left {
right: calc(100% + 10px);
}
&.top {
bottom: calc(100% + 10px);
}
&.bottom {
top: calc(100% + 10px);
}
}
}
}
</style>
effect
copyright notice
author[Maple moving forward],Please bring the original link to reprint, thank you.
https://en.qdmana.com/2022/132/202205120524479702.html
The sidebar is recommended
- Vue Chapter 4 Ajax in Vue: cross domain problems and slot slots
- Online nginx does not support the bug record of error reporting in delete request
- Okhttp sets the public parameters and puts the JSON object into the @ body to request the configuration of the public parameters
- Fluent ignores authentication of HTTPS and WSS certificates
- Browser loading HTML page evokes the most complete strategy of APP in mobile phone
- HTTP status code 304 and Etag details
- Using angularjs for fuzzy dynamic search drop-down box content
- Seamless connection to Macao, Hengqin Island, which is beautiful beyond the sky, is on fire again
- JQuery framework
- Vue mouse down and move event
guess what you like
A simple Vue answer demo, single choice and multiple choice
Front end interview question: if the cell in the table is red, click it to turn into white; if it is white, click it to turn into red, and what is not clicked is white
Vue packaging folding panel plus animation effect
If the front-end does real-time data acquisition?
Ant vue3 table sorted by time
Vue local refresh iframe
Vue instruction authority
Vue iframe refresh remains on the original page
Vue realizes Gaode map API mask, positioning and weather
Comparison and implementation of bidirectional data binding between react and Vue
Random recommended
- React error report record
- Analysis of react life cycle function
- react demo1 TodoList
- Summary of the differences between state and props in react
- Difference between controlled components and uncontrolled components in react
- Node. JS use get Stream download file
- How does JavaScript copy arrays instead of references
- JavaScript calculates the number of days, hours, minutes and seconds between days
- JQuery get page address parameters
- JavaScript create Download
- node. JS traversal directory
- Tips for using JavaScript string split (how to keep the delimiter)
- Common CSS notes
- JavaScript usage Get the address of the regular function
- New generation node JS web development framework koa zero foundation entry learning notes
- JavaScript notes
- asp. Net core method for modifying HTML without rerun
- Summary of compatibility processing of H5 + Vue cli project in Safari browser
- Summary of amap scheme of Gaode map used in vue3 + TS project
- Summary of filter scheme used in JS code in Vue
- Build an electron project based on Vue from scratch
- In Vue project, solve the problem of verification conflict when eslint and prettier are used at the same time
- Vue3 + vuecli4 solve chunk vendors JS file is too large. Scheme summary
- Scheme summary of eslint check before vue3 + vite configuration project operation and eslint check before git submission
- Fatal authentication failed for 'httpxxxx Git 'solution
- Vue's solution to the compatibility of hevc encoded video in each end browser
- Record the solution to the error in obtaining the picture in springboot in Vue
- [Vue] detailed analysis of the life cycle function of Vue components
- [Vue] deeper understanding of user-defined attribute props
- [Vue] front end error: cannot read properties of undefined (reading 'split')
- [Vue] asynchronous problem of component value transfer -- the sub component gets the data slowly
- [Vue] Vue data changes, but the page is not updated in real time
- [element UI] use of form verification -- detailed explanation
- [Vue] use of slots - Review
- The influence on the fixed positioning element of the inner layer when the outer element has a fixed height and overflows and rolls
- Precautions
- Change detection strategy of angular component
- Angular service and @ injectable
- JS, HTML and CSS are not compatible and do not use common knowledge
- Properties to be known in angular @ component