其他
so easy...自制代码截图工具
代码文本,通过pre或code标签插入 codepen.io 或gist 等工具 代码截图
演示
现行工具的问题
Carbon | Create and share beautiful images of your source code Codeimg.io text2image Instacode CodeKeep.io – Save & Organize code snippets Create beautiful images of your code Polacode – Visual Studio Marketplace CodeSnap – Visual Studio Marketplace
名字记不住
丢失编辑器代码样式
功能不全
配置复杂且配置不持久
适用性不强
定制代码截图工具
原理
在网页中放置(富)文本编辑器(如textarea) 粘贴入代码 将页面渲染成图片下载
(富)文本编辑器
Content Editable – Web 开发者指南 | MDN
contentEditable也是大家最为喜闻乐见的富文本编辑器实现方案,部分基础功能由浏览器实现。
html2canvas
实现代码
完整代码
import { useState } from 'react';
import CodeImg from './CodeImg';
import './App.css';
function App() {
const [fontsize, setFontsize] = useState(1);
const [name, setName] = useState("代码截图");
const [watermark, setWatermark] = useState("码中人 http://www.mzh.ren/");
const nameHandle = (e) => setName(e.target.value);
const watermarkHandle = (e) => setWatermark(e.target.value);
const clearCode = () => document.getElementById('editor-content').innerHTML = "";
return (
<div className="App">
<h1>简单代码截图</h1>
<div className="controls">
<button onClick={() => { if (fontsize < 4) { setFontsize(fontsize + 1) } }}>字体放大</button>
<button onClick={() => { if (fontsize > 1) { setFontsize(fontsize - 1) } }}>字体缩小</button>
<button onClick={ clearCode }>清空</button>
<button onClick={() => CodeImg('#editor', name)}>下载</button>
</div>
<div className="editor-wrapper" id="editor">
<div className="editor-header">
<input type="text" value={name} onChange={nameHandle} className="name" />
<div class="editor-window--actions">
<span class="editor-window--action exit"></span>
<span class="editor-window--action minimize"></span>
<span class="editor-window--action maximize"></span>
</div>
</div>
<div contentEditable="true" className={"x" + fontsize} id="editor-content">
</div>
<div className="editor-footer">
<input type="text" className="watermark" value={watermark} onChange={watermarkHandle} />
</div>
</div>
</div>
);
}
export default App;
body {
padding: 0 1em;
}
button {
margin-right: 10px;
}
button:last-child {
color: red;
}
.editor-wrapper {
position: relative;
padding: 1em;
margin-top: 1em;
background-color: rgba(0, 0, 0, 0.2);
width: fit-content;
}
/* ----editor header----- */
.editor-header {
position: absolute;
top: 1.4em;
width: 100%;
}
.editor-window--actions {
position: absolute;
top: 0;
left: 1em;
width: 80px;
}
.editor-window--action {
display: inline-block;
width: 12px;
height: 12px;
border-radius: 50%;
margin-right: 6px;
}
.editor-window--action.exit {
background-color: #ff5f56;
-webkit-box-shadow: 0 0 1px #e0443e;
box-shadow: 0 0 1px #e0443e;
}
.editor-window--action.minimize {
background-color: #ffbd2e;
-webkit-box-shadow: 0 0 1px #dea123;
box-shadow: 0 0 1px #dea123;
}
.editor-window--action.maximize {
background-color: #27c93f;
-webkit-box-shadow: 0 0 1px #1aab29;
box-shadow: 0 0 1px #1aab29;
}
.watermark,
.name {
background: transparent;
border: 0 none;
color: #fff;
width: 100%;
text-align: center;
}
.watermark {
text-align: right;
color: cornsilk;
}
/* ----- editor content ----- */
#editor-content {
min-width: 20em;
min-height: 10em;
outline: 1px dashed gray;
}
#editor-content>div {
padding: 1em;
padding-top: 3em;
color: #fff;
background-color: transparent;
border-radius: 1em;
}
.x2,
.x2>div {
font-size: 1.2rem;
line-height: 2rem;
}
.x3,
.x3>div {
font-size: 1.5rem;
line-height: 2rem;
}
.x4,
.x4>div {
font-size: 2rem;
line-height: 2.4rem;
}
/* --- editor content --- */
.editor-footer {
position: absolute;
bottom: 1.2em;
right: 1.4em;
width: 100%;
}
import html2canvas from 'html2canvas';
export default function exportImg(selector,name="代码截图"){
html2canvas(document.querySelector(selector), { // 转换为图片
useCORS: true // 解决资源跨域问题
}).then(canvas => {
let imgUrl = canvas.toDataURL('image/png');
downloadIamge(imgUrl, name + ".png")
})
}
function downloadIamge(imgsrc, name) {
let image = new Image();
image.setAttribute("crossOrigin", "anonymous");
image.onload = function () {
let canvas = document.createElement("canvas");
canvas.width = image.width;
canvas.height = image.height;
let context = canvas.getContext("2d");
context.drawImage(image, 0, 0, image.width, image.height);
let url = canvas.toDataURL("image/png"); //得到图片的base64编码数据
let a = document.createElement("a"); // 生成一个a元素
let event = new MouseEvent("click"); // 创建一个单击事件
a.download = name || "photo"; // 设置图片名称
a.href = url; // 将生成的URL设置为a.href属性
a.dispatchEvent(event); // 触发a的单击事件
};
image.src = imgsrc;
}
往期推荐