h5实现一个吸附在键盘上的工具栏

<template>

<div class="keyboard-toolbar-container">

<!-- 聊天内容区域 -->

<div class="chat-container">

<h2 class="chat-title">聊天示例</h2>

<div class="messages" ref="messagesContainer">

<div class="message received">

<img src="https://picsum.photos/id/1005/40/40" alt="对方头像" class="avatar">

<div class="message-content">你好!这个工具栏会在你点击输入框时显示在键盘上方</div>

</div>

<div class="message sent">

<div class="message-content">看起来很不错,有哪些功能呢?</div>

<img src="https://picsum.photos/id/1012/40/40" alt="我的头像" class="avatar">

</div>

<div class="message received">

<img src="https://picsum.photos/id/1005/40/40" alt="对方头像" class="avatar">

<div class="message-content">有表情、图片、文件等常用功能,试试看吧!</div>

</div>

</div>

<!-- 输入区域 -->

<div class="input-area">

<textarea

v-model="message"

@focus="showToolbar = true"

@blur="onInputBlur"

placeholder="输入消息..."

ref="messageInput"

></textarea>

<button @click="sendMessage" class="send-btn">发送</button>

</div>

</div>

<!-- 吸附在键盘上的工具栏 -->

<div

class="toolbar"

:class="{ 'toolbar-visible': showToolbar, 'toolbar-hidden': !showToolbar }"

>

<button class="toolbar-btn" @click="handleToolClick('emoji')">

<i class="fa fa-smile-o"></i>

<span>表情</span>

</button>

<button class="toolbar-btn" @click="handleToolClick('image')">

<i class="fa fa-picture-o"></i>

<span>图片</span>

</button>

<button class="toolbar-btn" @click="handleToolClick('file')">

<i class="fa fa-file-o"></i>

<span>文件</span>

</button>

<button class="toolbar-btn" @click="handleToolClick('mic')">

<i class="fa fa-microphone"></i>

<span>语音</span>

</button>

<button class="toolbar-btn" @click="handleToolClick('location')">

<i class="fa fa-map-marker"></i>

<span>位置</span>

</button>

<button class="toolbar-btn" @click="handleToolClick('more')">

<i class="fa fa-ellipsis-h"></i>

<span>更多</span>

</button>

</div>

</div>

</template>

<script>

export default {

name: 'KeyboardToolbar',

data() {

return {

message: '',

showToolbar: false,

// 用于追踪是否点击了工具栏按钮

toolbarClicked: false

};

},

methods: {

// 处理输入框失焦事件

onInputBlur() {

// 延迟隐藏工具栏,防止点击工具栏按钮时立即隐藏

setTimeout(() => {

if (!this.toolbarClicked) {

this.showToolbar = false;

}

this.toolbarClicked = false;

}, 200);

},

// 处理工具栏按钮点击

handleToolClick(type) {

this.toolbarClicked = true;

console.log(`点击了${this.getToolName(type)}工具`);

// 可以根据不同类型执行不同操作

switch(type) {

case 'emoji':

// 显示表情选择器逻辑

break;

case 'image':

// 选择图片逻辑

break;

case 'file':

// 选择文件逻辑

break;

// 其他工具的处理逻辑...

}

// 点击后重新聚焦到输入框

this.$refs.messageInput.focus();

},

// 获取工具名称

getToolName(type) {

const toolNames = {

emoji: '表情',

image: '图片',

file: '文件',

mic: '语音',

location: '位置',

more: '更多'

};

return toolNames[type] || type;

},

// 发送消息

sendMessage() {

if (!this.message.trim()) return;

// 创建新消息元素

const newMessage = document.createElement('div');

newMessage.className = 'message sent';

newMessage.innerHTML = `

<div class="message-content">${this.message}</div>

<img src="https://picsum.photos/id/1012/40/40" alt="我的头像" class="avatar">

`;

// 添加到消息容器并滚动到底部

this.$refs.messagesContainer.appendChild(newMessage);

this.refs.messagesContainer.scrollTop = this.refs.messagesContainer.scrollHeight;

// 清空输入框

this.message = '';

}

},

mounted() {

// 监听窗口 resize 事件,处理键盘显示/隐藏

window.addEventListener('resize', () => {

const isInputFocused = document.activeElement === this.$refs.messageInput;

if (isInputFocused) {

this.showToolbar = true;

// 调整滚动位置,确保输入框可见

setTimeout(() => {

this.refs.messagesContainer.scrollTop = this.refs.messagesContainer.scrollHeight;

}, 300);

}

});

},

beforeDestroy() {

window.removeEventListener('resize', () => {});

}

};

</script>

<style scoped>

.keyboard-toolbar-container {

display: flex;

flex-direction: column;

height: 100vh;

overflow: hidden;

background-color: #f5f5f5;

font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;

}

.chat-container {

flex: 1;

display: flex;

flex-direction: column;

padding: 16px;

overflow: hidden;

}

.chat-title {

text-align: center;

margin: 0 0 16px 0;

color: #333;

font-weight: 600;

}

.messages {

flex: 1;

overflow-y: auto;

margin-bottom: 16px;

display: flex;

flex-direction: column;

gap: 12px;

}

.message {

display: flex;

max-width: 80%;

word-break: break-word;

}

.message.received {

align-self: flex-start;

}

.message.sent {

align-self: flex-end;

flex-direction: row-reverse;

}

.avatar {

width: 40px;

height: 40px;

border-radius: 50%;

margin: 0 8px;

}

.message-content {

padding: 10px 14px;

border-radius: 18px;

line-height: 1.4;

}

.message.received .message-content {

background-color: #ffffff;

border-top-left-radius: 4px;

box-shadow: 0 1px 2px rgba(0,0,0,0.1);

}

.message.sent .message-content {

background-color: #007aff;

color: white;

border-top-right-radius: 4px;

}

.input-area {

display: flex;

gap: 8px;

align-items: flex-end;

}

.input-area textarea {

flex: 1;

border: 1px solid #ddd;

border-radius: 20px;

padding: 12px 16px;

resize: none;

outline: none;

font-size: 16px;

min-height: 42px;

max-height: 120px;

}

.send-btn {

background-color: #007aff;

color: white;

border: none;

border-radius: 50%;

width: 44px;

height: 44px;

display: flex;

align-items: center;

justify-content: center;

cursor: pointer;

font-weight: bold;

}

/* 工具栏样式 */

.toolbar {

position: fixed;

left: 0;

right: 0;

bottom: 0;

background-color: white;

display: flex;

justify-content: space-around;

padding: 8px 0;

box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.05);

transition: all 0.3s ease;

z-index: 100;

}

.toolbar-hidden {

transform: translateY(100%);

opacity: 0;

}

.toolbar-visible {

transform: translateY(0);

opacity: 1;

}

.toolbar-btn {

display: flex;

flex-direction: column;

align-items: center;

justify-content: center;

background: none;

border: none;

color: #666;

font-size: 12px;

padding: 6px;

width: 50px;

cursor: pointer;

}

.toolbar-btn i {

font-size: 20px;

margin-bottom: 4px;

}

.toolbar-btn:active {

background-color: #f0f0f0;

border-radius: 8px;

}

</style>

相关推荐
知识分享小能手3 小时前
微信小程序入门学习教程,从入门到精通,微信小程序页面制作(2)
前端·javascript·学习·微信小程序·小程序·前端框架·notepad++
jason_yang3 小时前
JavaScript 风格指南 精选版
前端·javascript·代码规范
小高0074 小时前
🔍ECMAScript 2025 有哪些新特性?
前端·javascript
正义的大古4 小时前
OpenLayers地图交互 -- 章节十七:键盘缩放交互详解
javascript·vue.js·openlayers
Hashan4 小时前
elpis-core:基于 Koa 的轻量级 Web 应用框架
前端·javascript·node.js
前端Hardy4 小时前
轻松搞定JavaScript数组方法,面试被问直接答!
前端·javascript·面试
云枫晖4 小时前
手写Promise-catch和finally
前端·javascript
薄雾晚晴4 小时前
大屏开发实战:封装自动判断、无缝衔接的文字滚动组件,告别文本截断烦恼
前端·javascript·vue.js
Beginner x_u4 小时前
前端八股文 Vue上
前端·javascript·vue.js·八股文