網站上這個代碼排版我真的是醉了,附上github地址,直接跑起來看效果吧~vue
<template> <div class="yht-float-btn pos-r" v-show="showBtn" :style="{'width':itemWidth+'px','height':itemHeight+'px','left':left+'px','top':top-70+'px'}" ref="floatDiv"> <div class="top-icon pos-a"> <transition name="slide-fade"> <div class="float-box text-center hide-box" v-show="show" @click="handleClickItem(0)"> <!-- 問題 --> <img src="@/assets/img/yht/icon_question.png" alt=""> </div> </transition> <transition name="slide-fade"> <div class="float-box text-center hide-box" v-show="show" @click="handleClickItem(1)"> <img src="@/assets/img/yht/icon_home.png" alt=""> <!-- 首頁 --> </div> </transition> </div> <div class="float-box text-center pos-a bottom-icon" @click="handleClickMenu"> <div> <img v-if="show" src="@/assets/img/yht/icon_close.png" alt=""> <img v-else src="@/assets/img/yht/icon_shortcut.png" alt=""> </div> </div> </div></template><script>import Util from "@/utils/common";import router from "../../router";export default { name: "drag", components: {}, props: { text: { type: String, default: "默認文字" }, itemWidth: { type: Number, default: 66 }, itemHeight: { type: Number, default: 66 }, gapWidth: { type: Number, default: 10 }, coefficientHeight: { type: Number, default: 0.8 }, showBtn: { // 是否顯示此toast default: false } }, data() { return { timer: null, currentTop: 0, clientWidth: 0, clientHeight: 0, left: 0, top: 0, show: false }; }, created() { this.clientWidth = document.documentElement.clientWidth; this.clientHeight = document.documentElement.clientHeight; this.left = this.clientWidth - this.itemWidth - this.gapWidth; this.top = this.clientHeight * this.coefficientHeight; }, mounted() { window.addEventListener("scroll", this.handleScrollStart); this.$nextTick(() => { const div = this.$refs.floatDiv; div.addEventListener("touchstart", e => { div.style.transition = "none"; }); div.addEventListener("touchmove", e => { e.preventDefault(); if (e.targetTouches.length === 1) { let touch = event.targetTouches[0]; this.left = touch.clientX - this.itemWidth / 2; this.top = touch.clientY - this.itemHeight / 2; } }); div.addEventListener("touchend", e => { div.style.transition = "all 0.3s"; if (this.left > this.clientWidth / 2) { // 浮動靠右邊 this.left = this.clientWidth - this.itemWidth - this.gapWidth; console.log("這裏是右邊"); } else { // 靠左邊 this.left = this.gapWidth; console.log("這裏是左邊"); } if (this.top < 0) { // 防止滑到上方被隱藏 this.top = this.clientHeight * this.coefficientHeight; } }); }); }, beforeDestroy() { window.removeEventListener("scroll", this.handleScrollStart); }, methods: { handleScrollStart() { this.timer && clearTimeout(this.timer); this.timer = setTimeout(() => { this.handleScrollEnd(); }, 300); this.currentTop = document.documentElement.scrollTop || document.body.scrollTop; if (this.left > this.clientWidth / 2) { this.left = this.clientWidth - this.itemWidth / 2; } else { this.left = -this.itemWidth / 2; } }, handleScrollEnd() { let scrollTop = document.documentElement.scrollTop || document.body.scrollTop; if (scrollTop === this.currentTop) { if (this.left > this.clientWidth / 2) { this.left = this.clientWidth - this.itemWidth - this.gapWidth; } else { this.left = this.gapWidth; } clearTimeout(this.timer); } }, handleClickMenu() { this.show = !this.show; }, handleClickItem(type) { if (type === 0) { router.push({ path: "/question/question" }); } else { if (window.sessionStorage.getItem("isMiniEnvironment") !== "0") { Util.toMiniIndex(); // 這裏是回到小程序首頁 } else { router.replace({ path: "/yht/index" }); } } } }};</script><style lang="less" scoped>.yht-float-btn { z-index: 99999; transition: all 0.3s; position: fixed; bottom: 20vw; img { width: 66px; height: 66px; object-fit: contain; margin-bottom: 3px; } p { font-size: 7px; }}.float-box { width: 66px; height: 66px;}.slide-fade-enter-active { transition: all 1s ease;}.slide-fade-leave-active { transition: all 0.8s cubic-bezier(1, 0.5, 0.8, 1);}.slide-fade-enter, .slide-fade-leave-to/* .slide-fade-leave-active for below version 2.1.8 */ { transform: translateY(10px); opacity: 0;}.top-icon { left: 0; bottom: 66px;}.bottom-icon { bottom: 0; left: 0;}</style>複製代碼
import Float from './floatBtn.vue';let dom;const FloatBtn = {}; // 定義插件對象FloatBtn.install = function(Vue, options) { // vue的install方法,用於定義vue插件 // 若是toast還在,則再也不執行 if (document.getElementsByClassName('yht-float-btn').length) { return; } let Instance = Vue.extend(Float); const initInstance = () => { // 實例化vue實例 dom = new Instance(); dom.vm = dom.$mount(); let boxEl = dom.$mount().$el; document.body.appendChild(boxEl); }; Vue.prototype.$floatBtn = { showFloat(options) { if (!dom) { initInstance(); } dom.vm.showBtn = true; // 顯示toast }, hideFloat(options = 0) { if (!dom) { initInstance(); } dom.vm.showBtn = false; // 顯示總體 } };};export default FloatBtn;複製代碼
let count = 2; // 懸浮按鈕計數器count++;window.sessionStorage.setItem('floatCount', count);// 而後在router-view頁面裏this.floatCount = this.$storage.get('floatCount'); // 獲取懸浮按鈕計數器if (this.floatCount > 3) { this.$floatBtn.showFloat();}// 固然若是沒有特別的需求的話,這個組件就能夠在任意一個vue頁面裏面去調用 this.$floatBtn.showFloat() 這個方法。 // 還要在mainjs裏面import FloatBtn from '@/components/floatBtn/floatBtn';Vue.use(FloatBtn); // 增長 懸浮按鈕 複製代碼