1. 程式人生 > >4.canvas實現多邊形橡皮筋式繪圖功能

4.canvas實現多邊形橡皮筋式繪圖功能

首先是html程式碼:

<div id="control">
    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">cornflowerblue</option>
        <option value="goldenrod">goldenrod</option>
        <option value="navy">navy</option>
        <option value="purple"selected>purple</option>
    </select>
    fill color:
    <select id="fillStyleSelect">
        <option value="rgba(255,0,0,0.5)">red</option>
        <option value="rgba(0,255,0,0.5)">green</option>
        <option value="rgba(0,0,255,0.5)">blue</option>
        <option value="rgba(255,165,0,0.5)"selected>orange</option>
        <option value="rgba(100,149,237,0.5)">cornflowerblue</option>
        <option value="rgba(218,165,32,0.5)">goldenrod</option>
        <option value="rgba(0,0,128,0.5)">navy</option>
        <option value="rgba(160,32,240,0.5)">purple</option>
        <option value="rgba(0,0,0,0.5)">black</option>
    </select>
    sides:
    <select id="sidesSelect">
        <option value="3"selected>3</option>
        <option value="4">4</option>
        <option value="5">5</option>
        <option value="6">6</option>
        <option value="7">7</option>
        <option value="8">8</option>
    </select>
    start angle:
    <select id="startAngleSelect">
        <option value="0" selected>0</option>
        <option value="15">15</option>
        <option value="30">30</option>
        <option value="45">45</option>
        <option value="60">60</option>
        <option value="75">75</option>
        <option value="90">90</option>
        <option value="0">105</option>
        <option value="15">120</option>
        <option value="30">135</option>
        <option value="45">150</option>
        <option value="60">165</option>
        <option value="75">180</option>
    </select>
    Fill:
   <input id="fillCheckbox" type="checkbox" checked/>
    Edit:
    <input id="editCheckbox" type="checkbox"/>
    <input id="eraseAllButton" type="button" value="erase all"/>
</div>
<canvas id='canvas'width=1200 height=650>
    can't use canvas
</canvas>

js實現程式碼:

var canvas = document.getElementById('canvas'),
    context = canvas.getContext('2d'),
    eraseAllButton = document.getElementById('eraseAllButton'),
    strokeStyleSelect = document.getElementById('strokeStyleSelect'),
    fillStyleSelect = document.getElementById('fillStyleSelect'),
    fillcheckbox = document.getElementById('fillCheckbox'),
    editcheckbox = document.getElementById('editCheckbox'),
    drawingSurfaceImageData,
    mousedown = {},
    rubberbandRect = {},
    dragging = false,
    draggingOffsetX,
    draggingOffsetY,
    sidesSelect = document.getElementById('sidesSelect'),
    startAngleSelect = document.getElementById('startAngleSelect'),
    returnToLast = document.getElementById('returnToLast'),
    sides = 3,
    startAngle = 0,
    guidewire = true,
    editing =false,
    polygons = [],
    Point = function(x, y){
    this.x = x;
    this.y = y;
    };
var Polygon = function(centerX, centerY, radius, sides,startAngle,
                       strokeStyle, fillStyle, filled){
    this.x = centerX;
    this.y = centerY;
    this.radius = radius;
    this.sides = sides;
    this.startAngle = startAngle;
    this.strokeStyle = strokeStyle;
    this.fillStyle = fillStyle;
    this.filled = filled;
}
Polygon.prototype = {

    getPoints: function(){
        var points = [],
            angle = this.startAngle|| 0;
        for(var i = 0; i < this.sides; i++){
            points.push(new Point(this.x+ this.radius* Math.sin(angle),
                this.y- this.radius* Math.cos(angle)));
            angle+= 2* Math.PI/ this.sides;
        }
        return points;
    },
    createPath: function(context){
        var points= this.getPoints();
        context.beginPath();
        context.moveTo(points[0].x, points[0].y);
        for(var i= 1; i< this.sides; i++){
            context.lineTo(points[i].x, points[i].y);
        }
        context.closePath();
    },
    stroke: function(context){
        context.save();
        this.createPath(context);
        context.strokeStyle= this.strokeStyle;
        context.stroke();
        context.restore();
    },
    fill: function(context){
        context.save();
        this.createPath(context);
        context.fillStyle= this.fillStyle;
        context.fill();
        context.restore();
    },
    move: function(x, y){
        this.x= x;
        this.y= y;
    }
};
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)};
}
function saveDrawingSurface(){
    drawingSurfaceImageData = context.getImageData(0, 0,
        canvas.width, canvas.height);
}
function restoreDrawingface(){
    context.putImageData(drawingSurfaceImageData, 0, 0);
}
function drawPolygon(polygon){
    context.beginPath();
    polygon.createPath(context);
    polygon.stroke(context);
    if(fillcheckbox.checked){
        polygon.fill(context);
    }
}
function updateRubberbandRectangle(loc){
    rubberbandRect.width= Math.abs(loc.x- mousedown.x);
    rubberbandRect.height= Math.abs(loc.y- mousedown.y);
    if(loc.x> mousedown.x) rubberbandRect.left= mousedown.x;
    else rubberbandRect.left= loc.x;
    if(loc.y> mousedown.y) rubberbandRect.top= mousedown.y;
    else rubberbandRect.top= loc.y;
}
function drawRubberbandShape(loc, sides, startAngle){
    var polygon= new Polygon(mousedown.x, mousedown.y,
        rubberbandRect.width, parseInt(sidesSelect.value),
        (Math.PI/ 180)* parseInt(startAngleSelect.value),
        context.strokeStyle,
        context.fillStyle,
        fillcheckbox.checked);
    drawPolygon(polygon);
    if(!dragging)
        polygons.push(polygon);
}
function updateRubberband(loc, sides, startAngle){
    updateRubberbandRectangle(loc);
    drawRubberbandShape(loc, sides, startAngle);
}
function drawPolygons(){
    polygons.forEach(function(polygon){
        drawPolygon(polygon);
    });
}
function startDragging(loc){
    saveDrawingSurface();
    mousedown.x= loc.x;
    mousedown.y= loc.y;
}
function stopEditing(){
    canvas.style.cursor= 'crosshair';
    editing= false;
}
function startEditing(){
    canvas.style.cursor= 'pointer';
    editing= true;
}
canvas.onmousedown= function (e){
    var loc= windowToCanvas(e.clientX, e.clientY);
    e.preventDefault();
    if(editing){
        polygons.forEach(function(polygon){
            polygon.createPath(context);
            if(context.isPointInPath(loc.x, loc.y)){
                startDragging(loc);
                dragging= polygon;
                draggingOffsetX= loc.x- polygon.x;
                draggingOffsetY= loc.y- polygon.y;
                return;
            }
        });
    }
    else{
        startDragging(loc);
        dragging= true;
    }
};
canvas.onmousemove= function(e){
    var loc= windowToCanvas(e.clientX, e.clientY);
    e.preventDefault();
    if(editing && dragging){
        dragging.x= loc.x - draggingOffsetX;
        dragging.y= loc.y - draggingOffsetY;
        context.clearRect(0, 0, canvas.width, canvas.height);
        drawPolygons();
    }
    else{
        if(dragging){
            restoreDrawingface();
            updateRubberband(loc, sides, startAngle);
        }
    }
};
canvas.onmouseup= function(e){
    var loc= windowToCanvas(e.clientX, e.clientY);
    dragging= false;
    if(editing){

    }
    else{
        restoreDrawingface();
        updateRubberband(loc);
    }
};
eraseAllButton.onclick= function(e){
    context.clearRect(0, 0, canvas.width, canvas.height);
    polygons= [];
    saveDrawingSurface();
};
strokeStyleSelect.onchange=function(e){
    context.strokeStyle= strokeStyleSelect.value;
};
fillStyleSelect.onchange = function(e){
    context.fillStyle = fillStyleSelect.value;
};
editcheckbox.onchange = function(e){
    if(editcheckbox.checked){
        startEditing();
    }
    else
        stopEditing();
};
context.lineWidth= 20;
context.strokeStyle = strokeStyleSelect.value;
context.fillStyle = fillStyleSelect.value;