HTML5 Canvas笔记——简单文本编辑功能
2020-06-02 本文已影响0人
没昔
编写在canvas环境中具有简单文本编辑功能的程序。
主要功能:(1)有跟随移动的闪烁的光标;(2)能输入、插入、退格键删除。
文本编辑.html
<!DOCTYPE html>
<html>
<head>
<title>简单文本编辑</title>
<style>
body {
background: #eeeeee;
}
#canvas {
background: #fff;
cursor: pointer;
margin-left: 10px;
margin-top: 10px;
box-shadow: 4px 4px 8px rgba(0,0,0,0.5);
-webkit-box-shadow: 4px 4px 8px rgba(0,0,0,0.5);
-moz-box-shadow: 4px 4px 8px rgba(0,0,0,0.5);
}
#controls {
position: absolute;
left: 25px;
top: 25px;
}
</style>
</head>
<body>
<div id='controls'>
Font: <select id='fontSelect'>
<option value='palatino' select>palatino</option>
<option value='lucida'>lucida</option>
<option value='fantasy'>fantasy</option>
<option value='Arial'>Arial</option>
<option value='Comic Sans' selected>Comic Sans</option>
<option value='Lucida Sans'>Lucida Sans</option>
<option value='Helvetica'>Helvetica</option>
<option value='century'>century</option>
<option value='tahoma'>tahoma</option>
<option value='impact'>impact</option>
<option value='copperplate'>copperplate</option>
</select>
Size: <select id='sizeSelect'>
<option value='20px' select>20px</option>
<option value='30px'>30px</option>
<option value='32px'>32 px</option>
<option value='40px'>40px</option>
<option value='48px' selected>48 px</option>
<option value='50px'>50px</option>
<option value='60px'>60px</option>
<option value='64px'>64 px</option>
<option value='70px'>70px</option>
<option value='128px'>128 px</option>
</select>
Text stroke color:<select id='strokeStyleSelect'>
<option value='red'>red</option>
<option value='green'>green</option>
<option value='blue'>blue</option>
<option value='orange'>orange</option>
<option value='cornflowerblue' selected>cornflowerblue</option>
<option value='goldenrod'>goldenrod</option>
<option value='navy'>navy</option>
<option value='purple'>purple</option>
</select>
Text fill color:<select id='fillStyleSelect'>
<option value='rgba(255,0,0,0.5)'>semi-transparent red</option>
<option value='green'>green</option>
<option value='rgba(0,0,255,0.5)'>semi-transparent blue</option>
<option value='orange'>orange</option>
<option value='rgba(100,140,230,0.5)'>semi-transparent cornflowerblue</option>
<option value='rgba(218,165,32,0.5)' selected>semi-transparent goldenrod</option>
<option value='goldenrod' selected>goldenrod</option>
<option value='navy'>navy</option>
<option value='purple'>purple</option>
</select>
</div>
<canvas id='canvas' width='950' height='550'>
Canvas not supported
</canvas>
</body>
<script>
// 光标
TextCursor = function (width,fillStyle){
this.width = width || 2;
this.fillStyle = fillStyle || 'rgba(0,0,0,0.5)';
this.left = 0;
this.top = 0;
}
TextCursor.prototype = {
getHeight:function(context){
var h = context.measureText('M').width;
return h+h/6;
},
creatPath:function(context){
context.beginPath();
context.rect(this.left,this.top,this.width,this.getHeight(context));
},
draw:function(context,left,bottom){
context.save();
this.left = left;
this.top = bottom - this.getHeight(context);
this.creatPath(context);
context.fillStyle = this.fillStyle;
context.fill();
context.restore();
},
erase:function(context,imageData){
context.putImageData(imageData,0,0,this.left,this.top,this.width,this.getHeight(context));
}
}
</script>
<script>
//插入文本行
//插入字符位置
TextLine = function(x,y){
this.left = x;
this.bottom = y;
this.text = '';
this.caret = 0;
}
TextLine.prototype = {
getHeight:function(context){
var h = context.measureText('M').width;
return h+h/6;
},
getWidth:function(context){
return context.measureText(this.text).width;
},
insert:function(text){
this.text = this.text.substr(0,this.caret) + text +this.text.substr(this.caret);
this.caret +=text.length;
},
removeCharacterBeforeCaret:function(){
if(this.caret===0){
return;
}
this.text = this.text.substr(0,this.caret-1)+this.text.substr(this.caret);
this.caret--;
},
draw:function(context){
context.save();
context.textAlign = 'start';
context.textBaseline = 'bottom';
context.strokeText(this.text,this.left,this.bottom);
context.fillText(this.text,this.left,this.bottom);
context.restore();
},
erase:function(context,imageData){
context.putImageData(imageData,0,0);
}
}
</script>
<script src='文本编辑.js'></script>
</html>
文本编辑.js
var canvas = document.getElementById('canvas'),
context = canvas.getContext('2d'),
fontSelect = document.getElementById('fontSelect'),
sizeSelect = document.getElementById('sizeSelect'),
strokeStyleSelect = document.getElementById('strokeStyleSelect'),
fillStyleSelect = document.getElementById('fillStyleSelect'),
GRID_STROKE_STYLE='lightgray',
GIRD_HORIZONTAL_SPACING=10,
GIRD_VERTICAL_SPACING=10,
cursor=new TextCursor(),
line,
blinkingInterval,
BLINK_TIME=1000,
BLINK_OFF=300;
//function........................................
function drawBackground(){
var stop_y = 20;
var left_margin = stop_y*3;
var top_marigin = stop_y*4;
var i = canvas.height;
context.save();
context.shadowColor = undefined;
context.shadowOffsetX = 0;
context.shadowOffsetY = 0;
context.shadowBlur = 0;
context.strokeStyle = 'lightgray';
context.lineWidth = 0.5;
while(i>top_marigin){
context.beginPath();
context.moveTo(left_margin,i);
context.lineTo(canvas.width,i);
context.stroke();
i-=stop_y;
}
context.beginPath();
context.moveTo(left_margin,top_marigin);
context.lineTo(left_margin,canvas.height);
context.stroke();
context.restore();
}
function windowToCanvas(x,y){
var bbox = canvas.getBoundingClientRect();
return {
x:x-bbox.left*(canvas.width/bbox.width),
y:y-bbox.top*(canvas.height/bbox.height)
};
};
//Drawing surface...................................
function saveDrawingSurface() {
drawingSurfaceImageData = context.getImageData(0, 0,
canvas.width,
canvas.height);
}
//Text................................................
function setFont(){
context.font=sizeSelect.value+' '+fontSelect.value;
}
function blinkCursor(x,y){
clearInterval(blinkingInterval);
blinkingInterval=setInterval(function(e){
cursor.erase(context,drawingSurfaceImageData);
setTimeout(function(){
if(cursor.left==x && cursor.top+cursor.getHeight(context)==y){
cursor.draw(context,x,y);
}
},300);
},1000);
}
function moveCursor(x,y){
cursor.erase(context,drawingSurfaceImageData);
saveDrawingSurface();
cursor.draw(context,x,y);
blinkCursor(x,y);
}
//Event handlers.........................................
canvas.onmousedown=function(e){
var loc=windowToCanvas(e.clientX,e.clientY);
moveCursor(loc.x,loc.y);
line=new TextLine(loc.x,loc.y);
}
strokeStyleSelect.onchange=function(e){
cursor.strokeStyle=strokeStyleSelect.value;
context.strokeStyle=strokeStyleSelect.value;
};
fillStyleSelect.onchange=function(e){
cursor.fillStyle=fillStyleSelect.value;
context.fillStyle=fillStyleSelect.value;
};
//Key event handlers......................................
document.onkeydown=function(e){
if(e.keyCode===8 || e.keyCode===13){
e.preventDefault();
}
if(e.keyCode===8){ //Backspace
context.save();
line.erase(context,drawingSurfaceImageData);
line.removeCharacterBeforeCaret();
moveCursor(line.left+line.getWidth(context),line.bottom);
line.draw(context);
context.restore();
}
}
document.onkeypress=function(e){
var key=String.fromCharCode(e.which);
e.preventDefault();
context.save();
line.erase(context,drawingSurfaceImageData);
line.insert(key);
moveCursor(line.left+line.getWidth(context),line.bottom);
context.shadowColor='rgba(0,0,0,0.5)';
context.shadowOffsetX=1;
context.shadowOffsetY=1;
context.shadowBlur=2;
line.draw(context);
context.restore();
}
//Initialization.....................................
fontSelect.onchange=setFont;
sizeSelect.onchange=setFont;
cursor.fillStyle=fillStyleSelect.value;
cursor.strokeStyle=strokeStyleSelect.value;
context.strokeStyle=strokeStyleSelect.value;
context.fillStyle=fillStyleSelect.value;
context.lineWidth=2.0;
setFont();
drawBackground();
saveDrawingSurface();