前言
现在网上有很多这样的HTML编辑器,这种编辑器无疑给人带来了很多方便,所以自己也想尝试制作一款这样的HTML编辑器,既然要制作,那就肯定是先把UI搭起来,再慢慢完善功能
设计思路
我的思路就是将div标签设置一个属性(contenteditable="true"
),使div成为可编辑的div
并且我发现可编辑div有个特征:在内部换行会将上一个标签复制下来,所以为了防止这种问题,我决定在内部加入<p><br></p>
这样,每次换行就会自动复制<p><br></p>
标签
把这些东西弄好后,我就开始写UI,俗话说:交互也是一门技术
UI用的Icon使用了图标字体
后面使用html写好了交互的菜单以及用css做了交互效果
UI效果
交互效果
鼠标移到Icon
鼠标移到有下拉框的Icon
开启功能
完整代码
引用的css文件
/Icon字体/
Css
@font-face {
font-family: 'poppin';
src: url('../../Content/Font/poppin.ttf') format('truetype');
}
@font-face {
font-family: 'SEGUIEMJ';
src: url('../Font/SEGUIEMJ.TTF') format('truetype');
}
*::-webkit-scrollbar {
3px;
height:1px;
}
*::-webkit-scrollbar-thumb {
border-radius: 10px;
-webkit-box-shadow: inset 0 0 5px rgba(0,0,0,0.2);
background: #0094ff;
}
*::-webkit-scrollbar-track {
-webkit-box-shadow: inset 0 0 5px rgba(0,0,0,0.2);
border-radius: 10px;
background: #ccc;
}
body {
font-family: 'poppin';
margin: 0;
padding: 0px;
}
#YolxRichText {
min- 1000px;
max- 1600px;
height: 620px;
margin: 0 auto;
position: relative;
box-sizing: border-box;
padding: 0px 40px;
margin-top: 10px;
font-family: 'poppin';
}
#YolxRichText_Input {
calc(100% - 40px);
font-size: 16px;
color: rgba(0,0,0,.8);
letter-spacing: 2px;
margin: 0;
padding: 10px 20px 245px;
outline: none;
}
.YolxRichText_Input_token {
white-space: pre-wrap;
}
#YolxRichText_Ouput {
position: absolute;
top: 0px;
right: 0px;
100%;
height: 500px;
font-size: 12px;
color: #fff;
letter-spacing: 2px;
}
#YolxRichText_Ouput_Preview {
padding: 10px 20px 245px;
color: #000;
}
#YolxRichText_Ouput h1 {
text-align: center;
border-bottom: 2px dotted #ff6a00;
color: #ff6a00;
}
#YolxRichText_Input_section * {
display: inline;
}
.editor {
calc(100% - 15px);
height: 100%;
overflow: auto;
float: left;
}
.color_SkyBlue {
color: skyblue !important;
}
.YolxRichText_editor, .YolxRichText_Preview, .YolxRichText_Help {
50%;
height: 500px;
overflow: auto;
position: relative;
float: left;
border: 1px solid #ccc;
box-sizing: border-box;
}
.YolxRichText_Help {
20%;
font-size: 14px;
padding: 0px 10px;
display:none;
}
.YolxRichText_Help p {
display:block;
}
.YolxRichText_Help p span {
display: block;
}
br {
line-height: 26px;
}
.EditorMenu {
100%;
height: 36px;
position: relative;
float: left;
box-sizing: border-box;
background: #f1f1f1;
border: 1px solid #ccc;
border-bottom: none;
}
.EditorMenu ul {
margin: 0;
padding: 0px;
height: 100%;
display: flex;
text-align: center;
margin: 0px 5px;
}
.EditorMenu ul li {
display: block;
36px;
line-height: 2.3em;
position: relative;
}
.EditorMenu ul li:hover {
cursor: pointer;
}
.EditorMenu ul li:hover i {
color: #000;
}
.EditorMenu ul li:hover div {
z-index: 2;
display: block;
animation: EditorMenuAnima ease 0.5s forwards;
}
@keyframes EditorMenuAnima {
0% {
top:-100px;
}
30% {
top: 35px;
}
60% {
top: 20px;
}
100% {
top: 35px;
}
}
.EditorMenu ul li svg {
26px;
height: 34px;
}
.EditorMenu ul li div {
100px;
z-index: 1;
position: absolute;
top: 35px;
left: 0px;
background-color: #fff;
border: 1px solid #f1f1f1;
border-right-color: #ccc;
border-bottom-color: #ccc;
border-top:1px solid #ccc;
margin: 0;
display: none;
transition: all ease 0.5s;
box-sizing: border-box;
overflow: hidden;
}
.EditorMenu ul .editor_menu_face {
}
.EditorMenu ul .editor_menu_face div ul {
display: flex;
}
.EditorMenu ul .editor_menu_face .face {
display: block;
position: initial;
100%;
padding: 10px;
border: none;
max-height: 138px;
overflow-y: auto;
}
.EditorMenu ul .editor_menu_face .face span {
font-size: 24px;
padding: 0px 4px;
}
.EditorMenu ul .editor_menu_face .face span:hover {
background:#ccc;
border-radius:3px;
}
.EditorMenu ul li div p {
}
.EditorMenu_ul_li_div_p {
text-align: center;
color: #999;
line-height: 2;
border-bottom: 1px solid #f1f1f1;
font-size: 13px;
}
.EditorMenu ul li ul {
display: block;
margin: 0px;
}
.EditorMenu ul li div ul li {
color: #333;
padding: 5px 0;
100%;
float: left;
}
.EditorMenu ul li div ul li:hover {
background: #ccc;
}
.noPaddingAndMargin {
margin: 0;
padding: 0;
}
.EditorMenu ul li i {
color: #999;
}
.LinesOfCode {
height: 100%;
float: left;
background: #eee;
padding: 10px 5px 0px 5px;
}
.LinesOfCode ul {
text-align:left;
font-size:12px;
}
.LinesOfCode ul li {
margin: 20px 0px;
}
Html
<div id="YolxRichText">
<div class="EditorMenu">
<ul>
<li title="撤销"><i class="fa fa-undo"></i></li>
<li title="重做"><i class="fa fa-repeat"></i></li>
<li title="标题">
<i class="fa fa-header"></i>
<div style="transform: translateX(-35%);">
<p class="EditorMenu_ul_li_div_p noPaddingAndMargin">设置标题</p>
<ul>
<li><h1 class="noPaddingAndMargin">H1</h1></li>
<li><h2 class="noPaddingAndMargin">H2</h2></li>
<li><h3 class="noPaddingAndMargin">H3</h3></li>
<li><h4 class="noPaddingAndMargin">H4</h4></li>
<li><h5 class="noPaddingAndMargin">H5</h5></li>
<li><p class="noPaddingAndMargin">正文</p></li>
</ul>
</div>
</li>
<li title="字体">
<i class="fa fa-font"></i>
<div style="transform: translateX(-35%);">
<p class="EditorMenu_ul_li_div_p noPaddingAndMargin">设置字体</p>
<ul>
<li>poppin</li>
<li>微软雅黑</li>
<li>宋体</li>
<li>A字体</li>
<li>B字体</li>
<li>C字体</li>
</ul>
</div>
</li>
<li title="字号">
<i class="fa fa-text-height"></i>
<div style="transform: translateX(-35%);">
<p class="EditorMenu_ul_li_div_p noPaddingAndMargin">设置字号</p>
<ul>
<li>x-small</li>
<li>small</li>
<li>normal</li>
<li>large</li>
<li>x-large</li>
<li>xx-large</li>
</ul>
</div>
</li>
<li title="颜色">
<i class="fa fa-pencil"></i>
<div style=" 300px;transform: translateX(-45%);">
<p class="EditorMenu_ul_li_div_p noPaddingAndMargin">字体颜色</p>
<ul>
<li style="99px"><i class="fa fa-pencil" style="color: #000000;"></i></li>
<li style="100px"><i class="fa fa-pencil" style="color: #1c487f;"></i></li>
<li style="99px"><i class="fa fa-pencil" style="color: #4d80bf;"></i></li>
<li style="99px"><i class="fa fa-pencil" style="color: #c24f4a;"></i></li>
<li style="100px"><i class="fa fa-pencil" style="color: #8baa4a;"></i></li>
<li style="99px"><i class="fa fa-pencil" style="color: #7b5ba1;"></i></li>
<li style="99px"><i class="fa fa-pencil" style="color: #46acc8;"></i></li>
<li style="100px"><i class="fa fa-pencil" style="color: #f9963b;"></i></li>
<li style="99px"><i class="fa fa-pencil" style="color: #eeece0;"></i></li>
<li style="99px"><i class="fa fa-pencil" style="color: #ffffff;"></i></li>
<li style="99px"><i class="fa fa-magic" style="color: coral;"></i></li>
</ul>
</div>
</li>
<li title="背景色">
<i class="fa fa-paint-brush"></i>
<div style=" 300px;transform: translateX(-45%);">
<p class="EditorMenu_ul_li_div_p noPaddingAndMargin">字体颜色</p>
<ul>
<li style="99px"><i class="fa fa-paint-brush" style="color: #000000;"></i></li>
<li style="100px"><i class="fa fa-paint-brush" style="color: #1c487f;"></i></li>
<li style="99px"><i class="fa fa-paint-brush" style="color: #4d80bf;"></i></li>
<li style="99px"><i class="fa fa-paint-brush" style="color: #c24f4a;"></i></li>
<li style="100px"><i class="fa fa-paint-brush" style="color: #8baa4a;"></i></li>
<li style="99px"><i class="fa fa-paint-brush" style="color: #7b5ba1;"></i></li>
<li style="99px"><i class="fa fa-paint-brush" style="color: #46acc8;"></i></li>
<li style="100px"><i class="fa fa-paint-brush" style="color: #f9963b;"></i></li>
<li style="99px"><i class="fa fa-paint-brush" style="color: #eeece0;"></i></li>
<li style="99px"><i class="fa fa-paint-brush" style="color: #ffffff;"></i></li>
<li style="99px"><i class="fa fa-magic" style="color: coral;"></i></li>
</ul>
</div>
</li>
<li title="加粗"><i class="fa fa-bold"></i></li>
<li title="斜体"><i class="fa fa-italic"></i></li>
<li title="下划线"><i class="fa fa-underline"></i></li>
<li title="删除线"><i class="fa fa-strikethrough"></i></li>
<li title="对齐方式">
<i class="fa fa-paragraph"></i>
<div style="transform: translateX(-35%);">
<p class="EditorMenu_ul_li_div_p noPaddingAndMargin">对齐方式</p>
<ul>
<li title="靠左"><i class="fa fa-list-ol"></i></li>
<li title="居中"><i class="fa fa-list-ul"></i></li>
<li title="靠右"><i class="fa fa-list-ul"></i></li>
</ul>
</div>
</li>
<li class="editor_menu_face" title="插入表情">
<i class="fa fa-meh-o"></i>
<div style="300px;transform: translateX(-45%);">
<p class="EditorMenu_ul_li_div_p noPaddingAndMargin">插入表情</p>
<ul>
<li><span>Emoji</span></li>
<li style="1px;background:#ccc;"></li>
<li><span>更多表情</span></li>
</ul>
<div class="face">
<span>?</span>
<span>?</span>
<span>?</span>
<span>?</span>
<span>?</span>
<span>?</span>
<span>?</span>
<span>?</span>
<span>?</span>
<span>?</span>
<span>?</span>
<span>?</span>
<span>?</span>
<span>?</span>
</div>
</div>
</li>
<li title="设置列表">
<i class="fa fa-list-ul"></i>
<div style="transform: translateX(-35%);">
<p class="EditorMenu_ul_li_div_p noPaddingAndMargin">设置列表</p>
<ul>
<li><i class="fa fa-list-ol" title="有序列表"></i></li>
<li><i class="fa fa-list-ul" title="无序列表"></i></li>
</ul>
</div>
</li>
<li title="媒体">
<i class="fa fa-tv"></i>
<div style="transform: translateX(-35%);">
<p class="EditorMenu_ul_li_div_p noPaddingAndMargin">插入媒体</p>
<ul>
<li><i class="fa fa-youtube-play" title="视频"></i></li>
<li><i class="fa fa-music" title="音乐"></i></li>
</ul>
</div>
</li>
<li title="超链接"><i class="fa fa-chain"></i></li>
<li title="代码块"><i class="fa fa-terminal"></i></li>
<li title="引用"><i class="fa fa-quote-left"></i></li>
<li title="表格"><i class="fa fa-table"></i></li>
<li title="图片"><i class="fa fa-image"></i></li>
<li title="导入"><i class="fa fa-importfile"><svg t="1552977381714" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2344" xmlns:xlink="http://www.w3.org/1999/xlink" width="26" height="26" class="icon"><path d="M708.266667 460.8h-140.8V307.2H384v25.6a34.133333 34.133333 0 1 1-68.266667 0V290.133333c0-28.2752 22.9248-51.2 51.2-51.2h298.666667l110.933333 128v366.933334c0 28.2752-22.9248 51.2-51.2 51.2H366.933333c-28.2752 0-51.2-22.9248-51.2-51.2v-42.666667a34.133333 34.133333 0 1 1 68.266667 0v25.6h324.266667v-256z m0-68.266667v-0.132266l-72.533334-83.694934V392.533333h72.533334z m-352.674134 149.905067H277.282133c-16.469333 0-29.815467-14.574933-29.815466-32.554667 0-17.975467 13.3504-32.5504 29.815466-32.5504h78.3104l-27.997866-25.706666a25.924267 25.924267 0 0 1 0-38.190934 30.754133 30.754133 0 0 1 41.6 0l83.2 76.386134a25.8688 25.8688 0 0 1 8.375466 20.0704 25.8432 25.8432 0 0 1-8.375466 20.053333l-83.2 76.3904a30.754133 30.754133 0 0 1-41.6 0 25.924267 25.924267 0 0 1 0-38.190933l27.997866-25.706667z" fill="#999999" p-id="2345"></path></svg></i></li>
<li title="导出"><i class="fa fa-derivefile"><svg t="1552977587969" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2453" xmlns:xlink="http://www.w3.org/1999/xlink" width="26" height="26" class="icon"><path d="M674.133333 682.666667v51.2c0 28.2752-22.9248 51.2-51.2 51.2H264.533333c-28.2752 0-51.2-22.9248-51.2-51.2V290.133333c0-28.2752 22.9248-51.2 51.2-51.2h358.4c28.2752 0 51.2 22.9248 51.2 51.2v51.2a34.133333 34.133333 0 1 1-68.266666 0v-34.133333H281.6v409.6h324.266667v-34.133333a34.133333 34.133333 0 1 1 68.266666 0z m31.325867-140.228267h-78.3104c-16.469333 0-29.815467-14.574933-29.815467-32.554667 0-17.975467 13.3504-32.5504 29.815467-32.5504h78.3104l-27.997867-25.706666a25.924267 25.924267 0 0 1 0-38.190934 30.754133 30.754133 0 0 1 41.6 0l83.2 76.386134a25.8688 25.8688 0 0 1 8.375467 20.0704 25.8432 25.8432 0 0 1-8.375467 20.053333l-83.2 76.3904a30.754133 30.754133 0 0 1-41.6 0 25.924267 25.924267 0 0 1 0-38.190933l27.997867-25.706667zM443.733333 588.782933a31.338667 31.338667 0 0 1-22.976-8.802133L375.466667 535.9104v24.0512c0 15.927467-13.371733 28.8384-29.866667 28.8384s-29.866667-12.910933-29.866667-28.842667v-95.914666c0-15.931733 13.371733-28.842667 29.866667-28.842667l0.541867 0.004267a31.317333 31.317333 0 0 1 22.434133 8.814933L443.733333 517.149867l75.157334-73.130667a31.317333 31.317333 0 0 1 22.434133-8.814933L541.866667 435.2c16.494933 0 29.866667 12.910933 29.866666 28.842667v95.914666c0 15.931733-13.371733 28.842667-29.866666 28.842667s-29.866667-12.910933-29.866667-28.842667v-24.046933l-45.290667 44.0704a31.338667 31.338667 0 0 1-22.976 8.802133z" fill="#999999" p-id="2454"></path></svg></i></li>
<li title="新建"><i class="fa fa-newfile"><svg t="1552977627227" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2562" xmlns:xlink="http://www.w3.org/1999/xlink" width="26" height="26" class="icon"><path d="M511.278933 426.756267c-17.109333 22.741333 72.738133 14.208 68.458667 18.474666-47.061333 31.266133-88.4224 54.0032-149.751467 78.161067-41.361067 15.6288-86.997333 110.843733-104.1152 149.213867-18.538667 38.370133-21.393067 58.261333-27.093333 76.736-1.429333 5.687467-9.984 24.157867-27.101867 17.053866-17.1136-5.6832-17.1136-25.578667-14.263466-34.103466 48.494933-170.530133 126.933333-305.536 215.36-405.009067 19.968-22.741333 48.490667-39.790933 71.313066-46.8992 98.4064-28.420267 161.160533-24.157867 223.914667-24.157867-12.834133 18.474667-25.672533 35.528533-39.936 52.5824-2.850133 2.8416-115.52 17.0496-132.637867 39.790934-17.109333 22.737067 91.281067 7.104 88.426667 9.9456a723.473067 723.473067 0 0 1-49.92 45.474133c-2.850133 1.4208-105.536-1.4208-122.653867 22.741333zM605.866667 605.866667v-59.733334a34.133333 34.133333 0 1 1 68.266666 0v59.733334h59.733334a34.133333 34.133333 0 1 1 0 68.266666h-59.733334v59.733334a34.133333 34.133333 0 1 1-68.266666 0v-59.733334h-59.733334a34.133333 34.133333 0 1 1 0-68.266666h59.733334z" fill="#999999" p-id="2563"></path></svg></i></li>
<li title="保存"><i class="fa fa-save"></i></li>
<li title="预览"><i class="fa fa-eye color_SkyBlue"></i></li>
<li title="帮助"><i class="fa fa-question-circle-o"></i></li>
<li title="切换编辑器"><i class="fa fa-wrench color_SkyBlue"></i></li>
</ul>
</div>
<div class="YolxRichText_editor">
<div class="LinesOfCode">
<ul class="noPaddingAndMargin">
<li>1</li>
</ul>
</div>
<div class="editor">
<div id="YolxRichText_Input" tabindex="0" contenteditable="true"><p><br></p></div>
</div>
</div>
<div class="YolxRichText_Preview">
<div id="YolxRichText_Ouput">
<h1>预览</h1>
<div id="YolxRichText_Ouput_Preview">
</div>
</div>
</div>
<div class="YolxRichText_Help">
<h1>帮助文档</h1>
<hr />
<h3>快捷键</h3>
<p>
<span>撤销:Ctrl / Command + Z</span>
<span>重做:Ctrl / Command + Shift + Z || Ctrl / Command + Y</span>
<span>加粗:Ctrl / Command + B</span>
<span>斜体:Ctrl / Command + I</span>
<span>斜体:Ctrl / Command + I</span>
<span>标题:Ctrl / Command + Shift + H</span>
<span>无序列表:Ctrl / Command + Shift + U</span>
<span>有序列表:Ctrl / Command + Shift + O</span>
<span>检查列表:Ctrl / Command + Shift + C</span>
<span>插入代码:Ctrl / Command + Shift + K</span>
<span>插入链接:Ctrl / Command + Shift + L</span>
<span>插入图片:Ctrl / Command + Shift + G</span>
</p>
<hr />
<h3>标题 Title</h3>
<p>
<span>$[Title|1] 1级标题 <span style="color:#46acc8">示例:$[Title|1]HelloWorld</span></span>
<span>$[Title|2] 2级标题 <span style="color:#46acc8">示例:$[Title|2]HelloWorld</span></span>
<span>$[Title|3] 3级标题 <span style="color:#46acc8">示例:$[Title|3]HelloWorld</span></span>
<span>$[Title|4] 4级标题 <span style="color:#46acc8">示例:$[Title|4]HelloWorld</span></span>
<span>$[Title|5] 5级标题 <span style="color:#46acc8">示例:$[Title|5]HelloWorld</span></span>
<span>$[Title|p] 正文 <span style="color:#46acc8">示例:$[Title|p]HelloWorld</span></span>
</p>
<hr />
<h3>文本 Text</h3>
<p>
<span>$[Text|b]Value^ 加粗文本 <span style="color:#46acc8">示例:$[Text|b]HelloWorld^</span></span>
<span>$[Text|i]Value^ 斜体文本 <span style="color:#46acc8">示例:$[Text|i]HelloWorld^</span></span>
<span>$[Text|d]Value^ 删除文本 <span style="color:#46acc8">示例:$[Text|d]HelloWorld^</span></span>
<span>$[Text|u]Value^ 重点文本 <span style="color:#46acc8">示例:$[Text|u]HelloWorld^</span></span>
</p>
<hr />
<h3>代码 Code</h3>
<p>
<span>$[Code|*]^ 自识别代码 <span style="color:#46acc8">$[Code|*]HelloWorld^</span></span>
</p>
<hr />
<h3>列表 List</h3>
<p>
<span>$[List|u]^ 无序列表 <span style="color:#46acc8">$[List|u]HelloWorld^</span></span>
<span>$[List|o]^ 有序列表 <span style="color:#46acc8">$[List|o]HelloWorld^</span></span>
</p>
<hr />
<h3>表格 Table</h3>
<p>
<span>$[Table|*]^ 表格 <span style="color:#46acc8">$[Table|*]HelloWorld^</span></span>
</p>
<hr />
<h3>注释 Annotation</h3>
<p>
<span>$[Annotation|*]^ 注释 <span style="color:#46acc8">$[Annotation|*]HelloWorld^</span></span>
</p>
</div>
</div>
现在就做到这里,下一篇我们继续完善