文字添加样式
思路:为每一个字添加一个span标签,然后通过js添加css,可能部分代码不需要可删除
代码:
const fontSet = (key, val) => {
//key:css样式名 val:样式值
const editableDiv = document.getElementById('editableDiv');
const range = window.getSelection().getRangeAt(0);
const selectedText = range.toString();
if (selectedText.length === 0) {
return;
}
// 创建一个文档片段来存储每个字符的新span元素
const fragment = document.createDocumentFragment();
// 遍历选中的文本中的所有文本节点
const textNodes = [];
(function getTextNodes(node) {
if (node.nodeType === Node.TEXT_NODE) {
textNodes.push(node);
} else {
for (let i = 0; i < node.childNodes.length; i++) {
getTextNodes(node.childNodes[i]);
}
}
})(range.cloneContents());
// 为选中文本中的每个字符创建新的span元素,并设置样式
for (const textNode of textNodes) {
const parentElement = textNode.parentNode;
// console.log(parentElement.style, 'parentElement');
const hasParentElement = parentElement && parentElement.nodeType === Node.ELEMENT_NODE;
const originalStyles = hasParentElement ? window.getComputedStyle(parentElement) : null;
for (const char of textNode.textContent) {
let newSpan;
// 如果当前字符已经被包含在一个单独的span元素中
if (textNode.parentNode.tagName === 'SPAN' && textNode.textContent.length === 1) {
newSpan = textNode.parentNode;
newSpan.style.removeProperty(key);
} else {
newSpan = document.createElement('span');
// 如果有父元素标签,将原始样式复制到新的span元素
newSpan.textContent = char; // 将新创建的span元素的文本内容设置为当前字符
}
// 应用新样式
newSpan.style[key] = val;
newSpan.style.display = 'inline-block';
newSpan.style.userSelect = 'text';
newSpan.textContent = char; // 将新创建的span元素的文本内容设置为当前字符
fragment.appendChild(newSpan);
}
}
// 将选中的文本替换为新的span元素
range.deleteContents();
range.insertNode(fragment);
// 更新数据和视图
function removeEmptyTags(element) {
const childNodes = element.childNodes;
for (let i = 0; i < childNodes.length; i++) {
const child = childNodes[i];
// 如果子元素是一个元素节点
if (child.nodeType === 1) {
// 检查是否为空或只包含空白字符
if (/^\s*$/.test(child.innerHTML)) {
// 删除空元素
element.removeChild(child);
// 更新循环索引
i--;
} else {
// 递归处理子元素的子元素
removeEmptyTags(child);
}
}
}
}
// 调用函数,删除 editableDiv 中的空标签
const editableDivContent = document.getElementById('editableDiv');
removeEmptyTags(editableDivContent);
window.getSelection().removeAllRanges();
};
滑选
以上是添加样式效果
文字样式回显
思路:给想回显的标签添加点击事件绑定方法,获取到插入点前一个字的style,然后给编辑传值回显
代码:
getTextBeforeCursor = (node, position) => {
// if (node.nodeType === Node.TEXT_NODE) {
// return node.nodeValue.substring(0, position);
// }
// let textBeforeCursor = '';
// for (let i = 0; i < position; i++) {
// textBeforeCursor += node.childNodes[i].textContent;
// }
// return textBeforeCursor;
if (node.nodeType === Node.TEXT_NODE) {
return position > 0 ? node.nodeValue.substring(position - 1, position) : '';
}
let textBeforeCursor = '';
for (let i = 0; i < position; i++) {
textBeforeCursor += node.childNodes[i].textContent;
}
return textBeforeCursor.slice(-1);
};
Divchange = value => {
const selection = window.getSelection();
const range = selection.getRangeAt(0);
const cursorPosition = range.startOffset;
const node = range.startContainer;
const textBeforeCursor = this.getTextBeforeCursor(node, cursorPosition);
let element = node;
while (element.nodeType !== Node.ELEMENT_NODE) {
element = element.parentNode;
}
const computedStyle = window.getComputedStyle(element);
const backgroundColor = computedStyle.getPropertyValue('background-color');
const fontSize = computedStyle.getPropertyValue('font-size');
const color = computedStyle.getPropertyValue('color');
const fontFamily = computedStyle.getPropertyValue('font-family');
const bold = computedStyle.getPropertyValue('font-weight');
const italic = computedStyle.getPropertyValue('font-style');
const textDecoration = computedStyle.getPropertyValue('text-decoration-line');
const textDecorations = computedStyle.getPropertyValue('text-decoration-line');
const verticalAlign = computedStyle.getPropertyValue('vertical-align');
sessionStorage.setItem('verticalAlign', verticalAlign == 'super' ? 'super' : '');
sessionStorage.setItem('verticalAligns', verticalAlign == 'sub' ? 'sub' : '');
sessionStorage.setItem('bold', bold == '700' ? 'bolder' : '');
sessionStorage.setItem('italic', italic == 'italic' ? 'italic' : '');
sessionStorage.setItem('textDecoration', textDecoration == 'line-through' ? 'line-through' : '');
sessionStorage.setItem('textDecorations', textDecorations == 'underline' ? 'underline' : '');
sessionStorage.setItem('fontFamily', fontFamily);
sessionStorage.setItem('backgroundColor', backgroundColor);
sessionStorage.setItem('fontSize', fontSize);
sessionStorage.setItem('color', color);
};
效果:
回显