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();


上一篇下一篇

猜你喜欢

热点阅读