3.4.2_在canvas中编辑文本
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>在canvas中编辑文本</title>
<style>
body{
background: #eee;
}
#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>
<canvas id="canvas" width="1000" height="600"></canvas>
<div id="controls">
字体:
<select id="fontStyleSelect">
<option value="palatino">palatino</option>
<option value="lucida">lucida</option>
<option value="fantasy">fantasy</option>
<option value="copperplate">copperplate</option>
<option value="tahoma" selected>tahoma</option>
<option value="verdana">verdana</option>
<option value="impact">impact</option>
<option value="century">century</option>
</select>
字体大小:
<select id="fontSizeSelect">
<option value="20px" selected>20px</option>
<option value="30px">30px</option>
<option value="40px">40px</option>
<option value="50px">50px</option>
<option value="60px">60px</option>
</select>
字体填充颜色:
<select id="fillStyleSelect">
<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>
字体描边颜色:
<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>
</div>
</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>
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
var fontSelect = document.getElementById('fontStyleSelect');
var sizeSelect = document.getElementById('fontSizeSelect');
var strokeStyleSelect = document.getElementById('strokeStyleSelect');
var fillStyleSelect = document.getElementById('fillStyleSelect');
var cursor = new TextCursor();
var line;
var blinkingInterval;
var drawingSurfaceImageData;
var blink_time = 1000;
var blink_off = 300;
cursor.fillStyle = fillStyleSelect.value;
context.fillStyle = fillStyleSelect.value;
context.strokeStyle = strokeStyleSelect.value;
context.lineWidth = 2;
setFont();
drawBackground();
saveDrawingSurface();
canvas.onmousedown = function(e){
var loc = windowToCanvas(e.clientX,e.clientY);
moveCursor(loc.x,loc.y);
line = new TextLine(loc.x,loc.y);
}
document.onkeypress = function(e){
var key = String.fromCharCode(e.which);
console.log('keypress');
context.save();
line.erase(context,drawingSurfaceImageData);
line.insert(key);
moveCursor(line.left+line.getWidth(context),line.bottom);
line.draw(context);
context.restore();
}
document.onkeydown = function(e){
if(e.keyCode === 8 || e.keyCode === 13){
e.preventDefault();
}
if(e.keyCode ===8){
context.save();
console.log('keydown')
line.erase(context,drawingSurfaceImageData);
line.removeCharacterBeforeCaret();
moveCursor(line.left+line.getWidth(context),line.bottom);
line.draw(context);
context.restore();
}
}
function moveCursor(x,y){
cursor.erase(context,drawingSurfaceImageData);
saveDrawingSurface();
cursor.draw(context,x,y);
blinkCursor(x,y);
}
function blinkCursor(x,y){
clearInterval(blinkingInterval);
blinkingInterval = setInterval(function(){
cursor.erase(context,drawingSurfaceImageData);
setTimeout(function(){
if(cursor.left == x&&cursor.top+cursor.getHeight(context) == y){
cursor.draw(context,x,y);
}
},blink_off);
},blink_time);
}
fontSelect.onchange = setFont;
sizeSelect.onchange = setFont;
strokeStyleSelect.onchange = function(){
context.strokeStyle = strokeStyleSelect.value;
}
fillStyleSelect.onchange = function(){
cursor.fillStyle = fillStyleSelect.value;
context.fillStyle = fillStyleSelect.value;
}
function setFont(){
context.font = sizeSelect.value +' ' + fontSelect.value;
}
function drawBackground(){
context.save();
context.shadowColor = undefined;
context.shadowOffsetX = 0;
context.shadowOffsetY = 0;
context.shadowBlur = 0;
var stop_y = 20;
var left_margin = stop_y*3;
var top_marigin = stop_y*4;
var i = canvas.height;
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 saveDrawingSurface(){
drawingSurfaceImageData = context.getImageData(0,0,canvas.width,canvas.height);
}
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)
};
};
</script>
</html>