contenteditable实现简单画布 增加撤销功能
有勇气的牛排
361
前端
2024-11-26 22:05:16
js
基于上篇文章,js部分参考如下,在绘制过程中,将每步进行记录。
function draw(e) {
console.log(e)
logEvent('Keydown 事件', `${e}`);
const brush = document.createElement('div');
brush.classList.add('brush');
brush.style.left = `${e.offsetX - 2}px`;
brush.style.top = `${e.offsetY - 2}px`;
canvas.appendChild(brush);
undoStack.push({element: brush, action: 'draw'});
redoStack = [];
}
let undoStack = [];
let redoStack = [];
undoBtn.addEventListener('click', () => {
if (undoStack.length > 0) {
const lastAction = undoStack.pop();
if (lastAction.action === 'draw') {
canvas.removeChild(lastAction.element);
redoStack.push(lastAction);
}
}
});
redoBtn.addEventListener('click', () => {
if (redoStack.length > 0) {
const lastUndo = redoStack.pop();
if (lastUndo.action === 'draw') {
canvas.appendChild(lastUndo.element);
undoStack.push(lastUndo);
}
}
});
html
<div>
<button id="undoBtn">撤销</button>
<button id="redoBtn">回退</button>
</div>
<h2><a id="js_0"></a>js</h2>
<p>基于上篇文章,js部分参考如下,在绘制过程中,将每步进行记录。</p>
<pre><div class="hljs"><code class="lang-javascript"><span class="hljs-comment">/**
* 绘制函数:用于在画布上创建一个小圆点作为画笔
* */</span>
<span class="hljs-keyword">function</span> <span class="hljs-title function_">draw</span>(<span class="hljs-params">e</span>) {
<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(e)
<span class="hljs-title function_">logEvent</span>(<span class="hljs-string">'Keydown 事件'</span>, <span class="hljs-string">`<span class="hljs-subst">${e}</span>`</span>);
<span class="hljs-comment">// 创建一个新的div元素,用于表示画笔</span>
<span class="hljs-keyword">const</span> brush = <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">createElement</span>(<span class="hljs-string">'div'</span>);
brush.<span class="hljs-property">classList</span>.<span class="hljs-title function_">add</span>(<span class="hljs-string">'brush'</span>);
<span class="hljs-comment">// 设置画笔的位置,基于鼠标的当前位置,并且让画笔的中心与鼠标位置对齐</span>
brush.<span class="hljs-property">style</span>.<span class="hljs-property">left</span> = <span class="hljs-string">`<span class="hljs-subst">${e.offsetX - <span class="hljs-number">2</span>}</span>px`</span>; <span class="hljs-comment">// 横坐标位置,减去2px使画笔居中</span>
brush.<span class="hljs-property">style</span>.<span class="hljs-property">top</span> = <span class="hljs-string">`<span class="hljs-subst">${e.offsetY - <span class="hljs-number">2</span>}</span>px`</span>; <span class="hljs-comment">// 纵坐标位置,减去2px使画笔居中</span>
<span class="hljs-comment">// 将创建的画笔元素添加到画布中</span>
canvas.<span class="hljs-title function_">appendChild</span>(brush);
<span class="hljs-comment">// 保存绘制动作到撤销栈</span>
undoStack.<span class="hljs-title function_">push</span>({<span class="hljs-attr">element</span>: brush, <span class="hljs-attr">action</span>: <span class="hljs-string">'draw'</span>});
<span class="hljs-comment">// 清空回退栈,因为新的绘制操作会破坏回退操作</span>
redoStack = [];
}
<span class="hljs-keyword">let</span> undoStack = []; <span class="hljs-comment">// 用于保存历史记录</span>
<span class="hljs-keyword">let</span> redoStack = []; <span class="hljs-comment">// 用于保存已撤销的操作</span>
<span class="hljs-comment">// 撤销功能:从撤销栈中取出最后一个操作并移除</span>
undoBtn.<span class="hljs-title function_">addEventListener</span>(<span class="hljs-string">'click'</span>, <span class="hljs-function">() =></span> {
<span class="hljs-keyword">if</span> (undoStack.<span class="hljs-property">length</span> > <span class="hljs-number">0</span>) {
<span class="hljs-keyword">const</span> lastAction = undoStack.<span class="hljs-title function_">pop</span>();
<span class="hljs-keyword">if</span> (lastAction.<span class="hljs-property">action</span> === <span class="hljs-string">'draw'</span>) {
<span class="hljs-comment">// 移除画布上的最后一个元素</span>
canvas.<span class="hljs-title function_">removeChild</span>(lastAction.<span class="hljs-property">element</span>);
redoStack.<span class="hljs-title function_">push</span>(lastAction); <span class="hljs-comment">// 将移除的元素保存到回退栈中</span>
}
}
});
<span class="hljs-comment">// 回退功能:将最后一个撤销的操作重新添加到画布</span>
redoBtn.<span class="hljs-title function_">addEventListener</span>(<span class="hljs-string">'click'</span>, <span class="hljs-function">() =></span> {
<span class="hljs-keyword">if</span> (redoStack.<span class="hljs-property">length</span> > <span class="hljs-number">0</span>) {
<span class="hljs-keyword">const</span> lastUndo = redoStack.<span class="hljs-title function_">pop</span>();
<span class="hljs-keyword">if</span> (lastUndo.<span class="hljs-property">action</span> === <span class="hljs-string">'draw'</span>) {
<span class="hljs-comment">// 将撤销的元素重新添加回画布</span>
canvas.<span class="hljs-title function_">appendChild</span>(lastUndo.<span class="hljs-property">element</span>);
undoStack.<span class="hljs-title function_">push</span>(lastUndo); <span class="hljs-comment">// 将回退的操作重新保存到撤销栈中</span>
}
}
});
</code></div></pre>
<h2><a id="html_60"></a>html</h2>
<pre><div class="hljs"><code class="lang-html"><span class="hljs-tag"><<span class="hljs-name">div</span>></span>
<span class="hljs-tag"><<span class="hljs-name">button</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"undoBtn"</span>></span>撤销<span class="hljs-tag"></<span class="hljs-name">button</span>></span>
<span class="hljs-tag"><<span class="hljs-name">button</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"redoBtn"</span>></span>回退<span class="hljs-tag"></<span class="hljs-name">button</span>></span>
<span class="hljs-tag"></<span class="hljs-name">div</span>></span>
</code></div></pre>
留言