+
+
{{ keyboardHeight }}
#推荐标签{{ index }}
@@ -71,10 +73,10 @@
diff --git a/ios-keyboard-accessory.html b/ios-keyboard-accessory.html
new file mode 100644
index 0000000..4a4b784
--- /dev/null
+++ b/ios-keyboard-accessory.html
@@ -0,0 +1,247 @@
+
+
+
+
+
+
iOS 适配键盘辅助栏
+
+
+
+
+
iOS 键盘辅助栏(贴合键盘)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/js/index.js b/js/index.js
index bf97312..66ddcff 100644
--- a/js/index.js
+++ b/js/index.js
@@ -30,12 +30,18 @@ createApp({
const editorRef = ref(null);
+ let isIOS = false; // 是否是 ISO 设备
onMounted(() => {
document.addEventListener("selectionchange", getFocusedNodeName);
- // 添加键盘事件监听
document.addEventListener("keydown", handleDeleteKey);
-
judgeIsEmpty();
+
+ isIOS = /iPhone|iPad|iPod/.test(navigator.userAgent); // 检测iOS设备
+ console.log("isIOS", isIOS);
+
+ // 1. 监听视觉视口变化(iOS主要依赖这个)
+ if (window.visualViewport) window.visualViewport.addEventListener("resize", getKeyboardHeight.bind(this));
+ else window.addEventListener("resize", getKeyboardHeight.bind(this));
});
onUnmounted(() => {
@@ -206,9 +212,7 @@ createApp({
let focusedNode = selection.focusNode;
// 如果是文本节点,取其父元素
- if (focusedNode.nodeType === Node.TEXT_NODE) {
- focusedNode = focusedNode.parentNode;
- }
+ if (focusedNode.nodeType === Node.TEXT_NODE) focusedNode = focusedNode.parentNode;
// 检查节点是否在.editor容器内
const isInEditor = editorRef.value.contains(focusedNode);
@@ -225,45 +229,16 @@ createApp({
let lastSelection = null;
onMounted(() => {
- setTimeout(() => {
- focusLastNode();
- }, 1000);
+ setTimeout(() => focusLastNode(), 1000);
});
const focusLastNode = () => {
- const editor = document.getElementById("editor");
- const selection = window.getSelection();
-
- // 清除现有选择范围
- selection.removeAllRanges();
-
- // 创建新的范围对象
- const range = document.createRange();
-
- // 找到最后一个有效子节点(跳过空白文本节点)
- let lastNode = editor.lastChild;
- while (lastNode) {
- // 检查是否为有效节点(非空白文本节点)
- if (!(lastNode.nodeType === 3 && lastNode.textContent.trim() === "")) {
- break;
- }
- lastNode = lastNode.previousSibling;
- }
-
- if (lastNode) {
- // 设置范围到最后一个节点的末尾
- range.setStartAfter(lastNode);
- range.setEndAfter(lastNode);
- } else {
- // 如果编辑器为空,选择整个编辑器
- range.selectNodeContents(editor);
- range.collapse(false);
- }
-
- // 将范围添加到选择对象,不设置焦点
- selection.addRange(range);
-
- editorRef.value.blur();
+ const newRange = document.createRange();
+ const textNode = document.createTextNode("");
+ editorRef.value.appendChild(textNode);
+ newRange.setStartAfter(textNode, 0);
+ newRange.setEndAfter(textNode, 0);
+ lastSelection = newRange;
};
let isEmpty = ref(true);
@@ -285,9 +260,9 @@ createApp({
let isBottomState = ref(false); // 底部按钮 显示
const onEditorFocus = () => {
isBottomState.value = true;
- setTimeout(() => getKeyboardHeight(), 500);
};
+ let fixedState = ref(false);
const onEditorBlur = () => {
isBottomState.value = false;
};
@@ -369,6 +344,7 @@ createApp({
// formData.append("type", "image");
// console.log("formData", formData);
+ const reader = new FileReader();
reader.onload = (e) => {
const imgSrc = e.target.result;
console.log("imgSrc", imgSrc);
@@ -393,9 +369,20 @@ createApp({
span.innerHTML = `
#${label} `;
lastSelection.insertNode(span);
- // 移动光标到emoji后面
- lastSelection.setStartAfter(span);
- lastSelection.setEndAfter(span);
+ // 移动光标到元素后面并确保光标位置被正确设置和获取
+ const newRange = document.createRange();
+ newRange.setStartAfter(span);
+ newRange.setEndAfter(span);
+
+ // 更新选择范围
+ const selection = window.getSelection();
+ selection.removeAllRanges();
+ selection.addRange(newRange);
+ lastSelection = newRange;
+
+ // 手动触发selectionchange事件,确保其他组件知道光标位置变化
+ const selectionChangeEvent = new Event("selectionchange", { bubbles: true });
+ document.dispatchEvent(selectionChangeEvent);
judgeIsEmpty();
};
@@ -412,9 +399,20 @@ createApp({
const textNode = document.createTextNode(emoji);
lastSelection.insertNode(textNode);
- // 移动光标到emoji后面
- lastSelection.setStartAfter(textNode);
- lastSelection.setEndAfter(textNode);
+ // 移动光标到emoji后面并确保光标位置被正确设置和获取
+ const newRange = document.createRange();
+ newRange.setStartAfter(textNode);
+ newRange.setEndAfter(textNode);
+
+ // 更新选择范围
+ const selection = window.getSelection();
+ selection.removeAllRanges();
+ // selection.addRange(newRange);
+ lastSelection = newRange;
+
+ // 手动触发selectionchange事件,确保其他组件知道光标位置变化
+ const selectionChangeEvent = new Event("selectionchange", { bubbles: true });
+ document.dispatchEvent(selectionChangeEvent);
judgeIsEmpty();
getCursorPosition("emoji");
@@ -437,9 +435,9 @@ createApp({
// 计算目标位置:中间偏上(视口高度的30%位置)
// 公式:元素顶部相对于视口的位置 + 滚动距离 - 目标位置(视口高度的30%)
// const targetPosition = window.scrollY + rect.top - viewportHeight * 0.3; // 30%位置,比正中间更靠上
- const height = type == "emoji" ? 300 : keyboardHeight;
+ const height = type == "emoji" ? 300 : keyboardHeight.value;
// console.log(height);
- const targetPosition = window.scrollY + rect.top - (originalWindowHeight - height) + 40;
+ const targetPosition = window.scrollY + rect.top - (originalWindowHeight - height) + 110;
// 平滑滚动到目标位置
if (Math.abs(targetPosition - window.scrollY) > 10) {
@@ -458,22 +456,41 @@ createApp({
const operateRef = ref(null);
onMounted(() => {
- // 初始化时记录初始窗口高度
- originalWindowHeight = window.visualViewport.height;
- keyboardHeight = originalWindowHeight / 2;
+ // 优先使用 visualViewport 高度(更准确反映视觉区域)
+ if (window.visualViewport) originalWindowHeight = window.visualViewport.height;
+ else originalWindowHeight = window.innerHeight;
+
+ keyboardHeight.value = originalWindowHeight / 2; // 默认设置屏幕一般
});
let originalWindowHeight = 0;
- let keyboardHeight = 0;
+ let keyboardHeight = ref(0);
// 获取键盘高度
const getKeyboardHeight = () => {
- const currentHeight = window.visualViewport.height;
+ console.log("getKeyboardHeight");
+ let currentHeight = "";
+ if (isIOS) currentHeight = window.visualViewport?.height || window.innerHeight;
+ else currentHeight = window.visualViewport ? window.visualViewport.height : window.innerHeight;
- // 键盘弹出时,窗口高度会减小
- if (currentHeight < originalWindowHeight) keyboardHeight = originalWindowHeight - currentHeight;
+ // 计算高度差(键盘高度 = 初始高度 - 当前高度)
+ const diff = originalWindowHeight - currentHeight;
+
+ // 判断键盘状态(高度差 > 100 认为是键盘弹出,避免误判)
+ if (diff > 100) {
+ console.log("键盘弹出");
+ keyboardHeight.value = diff;
+ fixedState.value = true;
+ } else if (diff <= 100) {
+ console.log("键盘收取");
+ setTimeout(() => (fixedState.value = false), 200);
+ // 键盘收起时重置初始高度(避免屏幕旋转等场景导致偏差)
+ originalWindowHeight = currentHeight;
+ }
+
+ console.log("keyboardHeight:", keyboardHeight.value);
};
- return { isBottomState, operateRef, onEditorBlur, onEditorFocus, cutAnonymity, isEmpty, selectEmoji, closeEmoji, openEmoji, optionEmoji, emojiState, insertLabel, editorRef, info, title, titleLength, titleTextarea, adjustTextareaHeight, isPTitle, paragraphTitle, insertImage, onEditorInput };
+ return { keyboardHeight, fixedState, isBottomState, operateRef, onEditorBlur, onEditorFocus, cutAnonymity, isEmpty, selectEmoji, closeEmoji, openEmoji, optionEmoji, emojiState, insertLabel, editorRef, info, title, titleLength, titleTextarea, adjustTextareaHeight, isPTitle, paragraphTitle, insertImage, onEditorInput };
},
}).mount("#appIndex");
diff --git a/keyboard-accessory.html b/keyboard-accessory.html
new file mode 100644
index 0000000..77191af
--- /dev/null
+++ b/keyboard-accessory.html
@@ -0,0 +1,227 @@
+
+
+
+
+
+
H5 键盘辅助栏
+
+
+
+
+
键盘辅助栏示例
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+