vue cli上简单的功能,在js上太难弄了,这个弹窗功能时常用到,生存起来备用吧
备注:deepseek这个人工智障写一堆有题目的我,还老服务器繁忙
结果图:
html代码:
- <div class="modal-mask" v-show="qrcodeShow" @click.self="closeModal">
- <div class="modal-container" ref="modal" :style="modalStyle">
- <div
- class="modal-header"
- @mousedown="startDrag"
- @touchstart.prevent="startDrag"
- @mouseup="stopDrag"
- @touchend="stopDrag"
- >
- <span>获取app</span>
- <span class="close-btn" @click="closeModal">×</span>
- </div>
- <div class="image-container">
- <img :src="qrcodeImgUrl" class="modal-image" alt="弹窗图片" />
- </div>
- </div>
- </div>
复制代码 js代码:
- data: {
- scanCodeList: [],
- qrcodeShow: false,
- qrcodeImgUrl: "**图片地址**",
- isDragging: false,
- startX: 0,
- startY: 0,
- translateX: 0,
- translateY: 0,
- modalRect: null,
- },
- created() {
- this.$nextTick(() => {
- // 使用jQuery添加动画效果
- $(".modal-container").hide();
- // 监听弹窗状态变化
- this.$watch("qrcodeShow", (newVal) => {
- if (newVal) {
- $(".modal-container").fadeIn(300);
- } else {
- $(".modal-container").fadeOut(300);
- }
- });
- });
- },
- computed: {
- modalStyle() {
- return {
- transform: `translate(${this.translateX}px, ${this.translateY}px)`,
- };
- },
- },
- methods: {
- showModal() {
- this.qrcodeShow = true;
- },
- closeModal() {
- this.qrcodeShow = false;
- },
- // 开始拖动
- startDrag(e) {
- this.isDragging = true;
- const clientX = e.touches ? e.touches[0].clientX : e.clientX;
- const clientY = e.touches ? e.touches[0].clientY : e.clientY;
- // 记录初始位置
- this.startX = clientX - this.translateX;
- this.startY = clientY - this.translateY;
- // 获取弹窗尺寸
- this.modalRect = this.$refs.modal.getBoundingClientRect();
- // 添加事件监听
- document.addEventListener("mousemove", this.onDrag);
- document.addEventListener("touchmove", this.onDrag, { passive: false });
- document.addEventListener("mouseup", this.stopDrag);
- document.addEventListener("touchend", this.stopDrag);
- // 优化拖动体验
- document.body.style.cursor = "grabbing";
- document.body.style.userSelect = "none";
- },
- // 拖动处理
- onDrag(e) {
- if (!this.isDragging) return;
- // 获取坐标
- const clientX = e.touches ? e.touches[0].clientX : e.clientX;
- const clientY = e.touches ? e.touches[0].clientY : e.clientY;
- // 计算新位置
- let newX = clientX - this.startX;
- let newY = clientY - this.startY;
- // 计算边界
- const viewportWidth = document.documentElement.clientWidth;
- const viewportHeight = document.documentElement.clientHeight;
- const modalWidth = this.modalRect.width;
- const modalHeight = this.modalRect.height;
- // 有效边界
- const minX = -(viewportWidth - modalWidth) / 2;
- const minY = -(viewportHeight - modalHeight) / 2;
- const maxX = (viewportWidth - modalWidth) / 2;
- const maxY = (viewportHeight - modalHeight) / 2;
- // 应用约束
- newX = Math.max(minX, Math.min(newX, maxX));
- newY = Math.max(minY, Math.min(newY, maxY));
- // 更新位置
- this.translateX = newX;
- this.translateY = newY;
- },
- // 停止拖动
- stopDrag() {
- this.isDragging = false;
- // 移除事件监听
- document.removeEventListener("mousemove", this.onDrag);
- document.removeEventListener("touchmove", this.onDrag);
- document.removeEventListener("mouseup", this.stopDrag);
- document.removeEventListener("touchend", this.stopDrag);
- // 恢复样式
- document.body.style.cursor = "";
- document.body.style.userSelect = "";
- },
- // 重置位置到屏幕中央
- resetPosition() {
- this.$nextTick(() => {
- const modal = this.$refs.modal;
- if (modal) {
- const rect = modal.getBoundingClientRect();
- const viewportWidth = document.documentElement.clientWidth;
- const viewportHeight = document.documentElement.clientHeight;
- this.translateX = (viewportWidth - rect.width) / 2;
- this.translateY = (viewportHeight - rect.height) / 2;
- }
- });
- },
- },
复制代码 css代码:
- /* 遮罩层样式 */
- .modal-mask {
- position: fixed;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- background: rgba(0, 0, 0, 0.5);
- z-index: 9998;
- display: flex;
- justify-content: center;
- align-items: center;
- /* 弹窗容器 */
- .modal-container {
- display: none;
- background: white;
- border-radius: 8px;
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.33);
- width: 500px;
- height: 500px;
- z-index: 9999;
- position: relative;
- /* 弹窗头部 */
- .modal-header {
- height: 50px;
- padding: 15px;
- border-bottom: 1px solid #eee;
- display: flex;
- justify-content: space-between;
- align-items: center;
- cursor: move;
- user-select: none; /* 防止文字被选中 */
- span {
- font-size: 18px;
- font-weight: bold;
- }
- /* 关闭按钮样式 */
- .close-btn {
- cursor: pointer;
- font-size: 20px;
- color: #666;
- padding: 0 5px;
- }
- }
- /* 图片容器 */
- .image-container {
- padding: 20px;
- width: 100%;
- height: calc(100% - 50px);
- overflow: auto;
- img {
- width: 100%;
- height: 100%;
- object-fit: cover;
- }
- }
- }
- }
复制代码 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |