简易HTML编辑器
<style>iframe { position: relative; width: 100%; height: 100%; border: none; outline: none; box-sizing: border-box; margin: 0; }
.wrap{ left:calc(50% - 81px); transform:translateX(-50%);width:1400px; height:700px; background:linear-gradient(to right,#eee 59px,#aaa 60px,#fff 0); border:1px solid gray; border-radius:4px; box-shadow:2px 2px 6px gray; z-index: 1; position:relative; margin: 30px 0; }
@media screen and (max-width: 1280px) { .wrap { width: 90vw; height: 75vh; font-size: 12px; } }
.wrap:hover{ border-color: black; }
.wrap:has(#editor:focus) { border-width:2px; }
.same{ position: absolute; top:10px; box-sizing: border-box; padding: 8px; border:none; border-radius: inherit; white-space: pre-wrap; word-break: break-all; font: normal 16px/24px Consolas,'Courier New','Andale Mono',monospace; tab-size: 4; overflow: auto; }
#editor{ right: 0; width: calc(100% - 60px); height: calc(100% - 20px); resize: none; outline: none; background: #fefefe; scroll-padding: 8px;}
#line-number{ position: absolute; width: 100%; height: calc(100% - 20px); color: gray; user-select: none; }
#line-number > span{cursor:pointer;}
#line-number > span:hover{ font-weight: bold; color: red; }
#mnbox{ min-height: 0; visibility: hidden; }
#showBox { position: fixed; top: 0; right: 0; bottom: 0; left: 0; background: #fff; display: none; padding: 0; overflow: hidden; z-index: 10000; margin: 0; }
#showBox::after { position: absolute; content: '关闭预览'; bottom: 10px; left: calc(50% - 40px); padding: 0 4px; width: 80px; height: 30px; line-height: 30px; text-align: center; border: 1px solid #efe; border-radius: 6px; background: #eee; font-size: 14px; box-shadow: 2px 2px 6px rgba(0,0,0,.25); cursor: pointer; }
#btnPrev { padding: 2px 8px; cursor: pointer; border: 1px solid #efe; border-radius: 4px; box-shadow:2px 2px 6px rgba(0,0,0,.25); font-size: 14px; }
#btnPrev:hover { color: red; }
</style>
<h2>Web代码简易编辑器</h2>
<div class="wrap">
<div id="mnbox" class="same"></div>
<div id="line-number" class="same"></div>
<textarea id="editor" class="same" placeholder="输入CSS+HTML+JS代码..."></textarea>
</div>
<p><button type="button" id="btnPrev" title="预览效果">运行代码</button></p>
<div id="showBox" title="点击关闭"></div>
<script>
let isSyncing = false;
const lnum = document.getElementById('line-number');
const editor = document.getElementById('editor');
const mnbox = document.getElementById('mnbox');
const btnPrev = document.getElementById('btnPrev');
const selectLine = (num) => {
let mpos, tstr = '';
let ar = editor.value.split('\n');
for (j = 0; j < num; j ++) {
tstr += ar + 2;
}
mpos = tstr.length;
editor.setSelectionRange(mpos, mpos + ar.length);
editor.focus();
};
const addLineNum = () => {
const lines = editor.value.split('\n');
let str = '';
lines.forEach((line, key) => {
let br = '<br>'.repeat(calcSolftLines(line) || 1);
let idx = (key + 1).toString().padStart(4,' ');
str += `<span onclick="selectLine(${key})">${idx}</span>${br}`;
});
lnum.innerHTML = str;
};
const calcSolftLines = (text) => {
const cssdata = window.getComputedStyle(editor);
mnbox.style.width = editor.offsetWidth + 'px';
mnbox.style.overflowY = editor.scrollTop > 0 ? 'scroll' : 'hidden';
mnbox.innerText = text;
const lineheight = parseFloat(cssdata.getPropertyValue('line-height'));
const padding = parseFloat(cssdata.getPropertyValue('padding'));
return Math.floor((mnbox.offsetHeight - padding * 2) / lineheight);
};
const getCurrentLineIndent = () => {
const cursorPos = editor.selectionStart;
const content = editor.value;
let lineStart = content.lastIndexOf('\n', cursorPos - 1) + 1;
const line = content.slice(lineStart, cursorPos);
return line.match(/^[\t ]*/)?. || '';
};
const insertTextAtCursor = (text) => {
const start = editor.selectionStart;
const end = editor.selectionEnd;
const content = editor.value;
editor.value = content.slice(0, start) + text + content.slice(end);
editor.selectionStart = editor.selectionEnd = start + text.length;
};
const preView = (htmlCode, targetBox) => {
if (targetBox.innerHTML) return;
console.log('Yes');
window.localStorage.setItem('ed1', htmlCode);
const iframe = document.createElement('iframe');
htmlCode = htmlCode + '\n<style>body {margin: 0; }</style>\n';
iframe.srcdoc = htmlCode;
targetBox.appendChild(iframe);
targetBox.style.display = 'block';
targetBox.onclick = () => {
targetBox.innerHTML = '';
targetBox.style.display = 'none';
}
};
btnPrev.onclick = () => preView(editor.value, showBox);
editor.onkeydown = (e) => {
if (e.key === 'Tab') {
e.preventDefault();
insertTextAtCursor('\t');
}
if (e.key === 'Enter') {
e.preventDefault();
const indent = getCurrentLineIndent();
insertTextAtCursor('\n' + indent);
addLineNum();
}
};
const bindEventLnum = () => {
removeEventEditor();
lnum.addEventListener('scroll', lnumScroll);
};
const bindEventEditor = () => {
removeEventLnum();
editor.addEventListener('scroll', editorScroll);
};
const lnumScroll = () => {
if (!isSyncing) {
isSyncing = true;
editor.scrollTop = lnum.scrollTop;
isSyncing = false;
}
};
const editorScroll = () => {
if (!isSyncing) {
isSyncing = true;
lnum.scrollTop = editor.scrollTop;
isSyncing = false;
}
};
lnum.addEventListener('mouseover', bindEventLnum);
editor.addEventListener('mouseover', bindEventEditor);
lnum.addEventListener('touchstart', bindEventLnum, { passive: false });
editor.addEventListener('touchstart', bindEventEditor, { passive: false });
const removeEventLnum = () => lnum.removeEventListener('scroll', lnumScroll);
const removeEventEditor = () => editor.removeEventListener('scroll', editorScroll);
editor.oninput = () => addLineNum();
window.onresize = () => addLineNum();
editor.onmouseenter = () => editor.focus();
editor.value = window.localStorage.getItem('ed1');
editor.setSelectionRange(0, 0);
addLineNum();
</script> 这个,可以在线测试帖子代码,css + HTML + JS 代码一般都可以预览 这个好,刚我试的代码还保存着。直接运行了。。 这个真好,把黑黑前面讲解放到其中测试,感觉很方便{:4_187:} 红影 发表于 2025-5-25 21:59
这个真好,把黑黑前面讲解放到其中测试,感觉很方便
就是得多看个浏览器标签 马黑黑 发表于 2025-5-25 21:48
这个,可以在线测试帖子代码,css + HTML + JS 代码一般都可以预览
这就是你教程里常出现的运行{:4_173:}
这个工具得上置顶,不然哪里找 花飞飞 发表于 2025-5-25 21:59
这个好,刚我试的代码还保存着。直接运行了。。
有记忆功能 花飞飞 发表于 2025-5-25 22:00
这就是你教程里常出现的运行
这个工具得上置顶,不然哪里找
你站里不是有吗 马黑黑 发表于 2025-5-25 22:00
有记忆功能
嗯哪,你的编辑程序都有这个功能。{:4_173:}
只是刚在那个贴子里,突然这个贴子里打开也能看到,就觉得跟时空穿越了一样 马黑黑 发表于 2025-5-25 22:00
你站里不是有吗
嗯哪,好几个天天换着用{:4_173:} 花飞飞 发表于 2025-5-25 22:06
嗯哪,好几个天天换着用
爱用哪个用哪个挺好 花飞飞 发表于 2025-5-25 22:04
嗯哪,你的编辑程序都有这个功能。
只是刚在那个贴子里,突然这个贴子里打开也能看到,就觉得 ...
惊喜来一个 马黑黑 发表于 2025-5-25 22:00
就是得多看个浏览器标签
有个标签也好啊,可以随时打开随时关闭,也方便呢{:4_187:} 这个编辑器好哦,测试预览方便了。 梦江南 发表于 2025-5-26 09:01
这个编辑器好哦,测试预览方便了。
{:4_190:} 红影 发表于 2025-5-25 22:51
有个标签也好啊,可以随时打开随时关闭,也方便呢
方便就行 马黑黑 发表于 2025-5-26 12:37
方便就行
嗯嗯,非常方便实用{:4_187:} 马黑黑 发表于 2025-5-25 22:27
爱用哪个用哪个挺好
大框的小框的,彩色的和不彩色的,都齐活了{:4_173:}好用 马黑黑 发表于 2025-5-25 22:28
惊喜来一个
的确,喜从天降点开就有代码 花飞飞 发表于 2025-5-26 20:38
的确,喜从天降点开就有代码
{:4_191:}