2.12.1_拖动多边形对象

2.12.1_拖动多边形对象

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>可拖动的多边形对象</title>
        <style>
            body{
                background: #eee;
            }
            #controls{
                position: absolute;
                left: 25px;
                top: 25px;
            }
            #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);
            }
        </style>
    </head>
    <body>
        <canvas id="canvas" width="1050" height="600"></canvas>
        <div id="controls">
            描边的颜色:
            <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>
            填充的颜色:
            <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="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>

            起始角度:
            <input id="startAngleSelect" type="number" value="0" />

            填充:
            <input id="fillCheckbox" type="checkbox" checked />
            <input id="eraseAllButton" type="button" value="擦除全部线条" /><br />
            可拖动:<input id="editCheckbox" type="checkbox" />
            指示线:
            <input id="guidewireCheckbox" type="checkbox"/>
        </div>
    </body>
    <script>
        var canvas = document.getElementById('canvas'),
            context = canvas.getContext('2d'),

            strokeStyleSelect = document.getElementById('strokeStyleSelect'),
            fillStyleSelect = document.getElementById('fillStyleSelect'),
            sidesSelect = document.getElementById('sidesSelect'),

            startAngleSelect = document.getElementById('startAngleSelect'),
            fillCheckbox = document.getElementById('fillCheckbox'),
            guidewireCheckbox = document.getElementById('guidewireCheckbox'),
            eraseAllButton = document.getElementById('eraseAllButton'),
            editCheckbox = document.getElementById('editCheckbox'),

            drawingSurfaceImageData,
            mousedown ={},
            rubberbandRect = {},

            dragging = false,
            draggingOffsetX,
            draggingOffsetY,

            filled= fillCheckbox.checked,
            sidesNum = parseInt(sidesSelect.value),
            startAngle = parseInt(startAngleSelect.value)*Math.PI/180, //起始角度转弧度
            guidewires = false,
            editing = false,
            polygons = []; //用于保存绘制好的多边形对象集合

            //初始化
            context.strokeStyle = strokeStyleSelect.value;
            context.fillStyle = fillStyleSelect.value;

            context.shadowColor = 'rgba(0,0,0,0.4)';
            context.shadowOffsetX = 2;
            context.shadowOffsetY = 2;
            context.shadowBlur = 4;

            drawGrid('lightgray',10,10);

            //事件处理器
            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);
                    drawGrid('lightgray',10,10);
                    drawPolygons();
                }else{
                    if(dragging){ //处于绘制的状态
                        restoreDrawingSurface();
                        updateRubberband(loc,sidesNum,startAngle);
                        if(guidewires){
                            drawGuidewires(loc.x,loc.y);
                        }
                    }
                }
            }

            canvas.onmouseup = function(e){
                var loc = windowToCanvas(e.clientX,e.clientY);
                dragging = false;
                if(editing){

                }else{
                    restoreDrawingSurface();
                    updateRubberband(loc,sidesNum,startAngle);
                }
            }

            guidewireCheckbox.onchange = function(){
                guidewires = guidewireCheckbox.value;
            }
            fillStyleSelect.onchange = function(){
                context.fillStyle= fillStyleSelect.value;
            }
            strokeStyleSelect.onchange = function(){
                context.strokeStyle = strokeStyleSelect.value;
            }
            editCheckbox.onchange = function (){
                if(editCheckbox.checked){
                    startEditing();
                }else{
                    stopEditing();
                }
            }
            sidesSelect.onchange = function (){
                sidesNum = parseInt(sidesSelect.value);
            }
            startAngleSelect.onchange =function(){
                startAngle = parseInt(startAngleSelect.value)*Math.PI/180
            }
            fillCheckbox.onchange = function(){
                filled= fillCheckbox.checked;
            }
            eraseAllButton.onclick = function (){
                context.clearRect(0,0,canvas.width,canvas.height);
                drawGrid('lightgray',10,10);
                saveDrawingSurface();
                polygons = [];
            }
            //重绘所有的多边形
            function drawPolygons(){
                polygons.forEach(function(polygon){
                    drawPolygon(polygon);
                })
            }
            //开始编辑
            function startEditing(){
                canvas.style.cursor = 'pointer';
                editing = true;
            }
            //结束编辑
            function stopEditing(){
                canvas.style.cursor = 'crosshair';
                editing = false;
            }
            //绘制指示线
            function drawGuidewires(x,y){
                context.save();
                context.strokeStyle = 'rgba(0,0,230,0.4)';
                context.lineWidth = 0.5;
                drawVerticalLine(x);
                drawHorizontalLine(y);
                context.restore();
            }
            //绘制垂线
            function drawVerticalLine(x){
                context.beginPath();
                context.moveTo(x+0.5,0);
                context.lineTo(x+0.5,context.canvas.height);
                context.stroke();
            }
            //绘制水平线
            function drawHorizontalLine(y){
                context.beginPath();
                context.moveTo(0,y+0.5);
                context.lineTo(context.canvas.width,y+0.5);
                context.stroke();
            }
            //实时更新视图
            function updateRubberband(loc,sidesNum,startAngle){
                updateRubberRectangle(loc);
                drawRubberbandShape(loc,sidesNum,startAngle);
            }
            //维护一个四边形
            function updateRubberRectangle(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,sidesNum,startAngle){
                var polygon = new Polygon(mousedown.x,
                                          mousedown.y,
                                          rubberbandRect.width,
                                          sidesNum,
                                          startAngle,
                                          context.strokeStyle,
                                          context.fillStyle,
                                          filled

                );
                drawPolygon(polygon);
                if(!dragging){ //如果绘制多边形后监测以鼠标抬起了,也就相当于dragging为false时,把绘制好的多边形加入到
                            //保存的polygos对象中
                    polygons.push(polygon);

                }

            }
            //绘制多边形
            function drawPolygon(polygon){
                context.beginPath();
                polygon.createPath(context);
                polygon.stroke(context);
                if(polygon.filled){
                    polygon.fill(context);
                }
            }
            //多边形各个角的构造函数
            var 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.cos(angle),
                                             this.y-this.radius*Math.sin(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 startDragging(loc){
                saveDrawingSurface();
                mousedown.x =loc.x;
                mousedown.y = loc.y;
            }
            //保存绘图表面
            function saveDrawingSurface(){
                drawingSurfaceImageData = context.getImageData(0,0,canvas.width,canvas.height);
            }
            //恢复绘图表面
            function restoreDrawingSurface(){
                context.putImageData(drawingSurfaceImageData,0,0);
            }
            //重新定位canvas中的坐标
            function windowToCanvas(x,y){
                var bbox = canvas.getBoundingClientRect(); //得到canvas元素的宽高定位
                return {
                    x:x-bbox.left * (canvas.width/bbox.width),
                    y:y-bbox.top * (canvas.height/bbox.height)
                };
            }
            //绘制网格线
            function drawGrid(color,stepX,stepY){
                context.save();
                context.shadowColor = undefined;
                context.shadowBlur = 0;
                context.shadowOffsetX = 0;
                context.shadowOffsetY = 0;
                context.strokeStyle = color;
                context.lineWidth = 0.5;

                for(var i =stepX+0.5;i<context.canvas.width;i+=stepX){
                    context.beginPath();
                    context.moveTo(i,0);
                    context.lineTo(i,context.canvas.height);
                    context.stroke();
                };
                for(var i=stepY+0.5;i<context.canvas.height;i+=stepY){
                    context.beginPath();
                    context.moveTo(0,i);
                    context.lineTo(context.canvas.width,i);
                    context.stroke();
                }
                context.restore();
            }
    </script>
</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值