HTML5游戏开发(五)

HTML5游戏开发(五)

一、绘制仪表盘

主用于圆形刻度练习。

(一)绘制基本功能

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>线段</title>
        <style>
            body {
                background: #283c3c;
            }
            #canvas {
                background: #f0fff0;
                border: thin solid #FFFFCC;
            }
        </style>
    </head>
    <body>
        <canvas id='canvas' width='600' height='500'>
    </canvas>
        <script src="js/meter.js"></script>
    </body>
</html>

JavaScript脚本

var canvas = document.getElementById('canvas'),
    context = canvas.getContext('2d'),
    CENTROID_RADIUS = 10,                               //中心点半径
    CENTROID_STROKE_STYLE = 'rgba(0, 0, 0, 0.5)',       //中心点样式
    CENTROID_FILL_STYLE   = 'rgba(80, 190, 240, 0.6)',  //中心点填充样式

    RING_INNER_RADIUS = 35,                             //内圆环半径
    RING_OUTER_RADIUS = 55,                             //外圆环半径

    ANNOTATIONS_FILL_STYLE = 'rgba(0, 0, 230, 0.9)',    //数字标记样式
    ANNOTATIONS_TEXT_SIZE = 12,                         //数据标记字体大小

    TICK_WIDTH = 10,                                    //标记线粗细
    TICK_LONG_STROKE_STYLE = 'rgba(100, 140, 230, 0.9)',//标记线长线样式
    TICK_SHORT_STROKE_STYLE = 'rgba(100, 140, 230, 0.7)',//标记线短线样式

    TRACKING_DIAL_STROKING_STYLE = 'rgba(100, 140, 230, 0.5)',  //数字标记样式

    GUIDEWIRE_STROKE_STYLE = 'goldenrod',                       //参考线路径样式
    GUIDEWIRE_FILL_STYLE = 'rgba(250, 250, 0, 0.6)',            //参考线填充样式
    //圆的大小
    circle = { x: canvas.width/2,
               y: canvas.height/2,
               radius: 150
             };

//-----------------------1、基本功能
//绘制背景网格
function drawGrid(color, stepx, stepy) {
   context.save()

   context.shadowColor = undefined;
   context.shadowOffsetX = 0;
   context.shadowOffsetY = 0;

   context.strokeStyle = color;
   context.fillStyle = '#ffffff';
   context.lineWidth = 0.5;
   context.fillRect(0, 0, context.canvas.width,
                          context.canvas.height);

   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();
}
//绘制参考线
context.shadowOffsetX = 2;
context.shadowOffsetY = 2;
context.shadowBlur = 4;

context.textAlign = 'center';
context.textBaseline = 'middle';
drawGrid('lightgray', 10, 10);

//绘制仪表盘
(function drawDial() {
   var loc = {x: circle.x, y: circle.y};
})();
(二)绘制中心点与外圆
//绘制仪表盘
(function drawDial() {
   var loc = {x: circle.x, y: circle.y};
   //绘制中心圆点  
   drawCentroid();
   //绘制外圆环
   drawRing();
})();

//------------------------------2、绘制中心点与外圆
//绘制中心圆点    
function drawCentroid() {
   context.beginPath();
   context.save();
   context.strokeStyle = CENTROID_STROKE_STYLE;
   context.fillStyle = CENTROID_FILL_STYLE;
   context.arc(circle.x, circle.y,
               CENTROID_RADIUS, 0, Math.PI*2, false);
   context.stroke();
   context.fill();
   context.restore();
}
//绘制外圆环
function drawRingOuterCircle() {
   context.shadowColor = 'rgba(0, 0, 0, 0.7)';
   context.shadowOffsetX = 3,
   context.shadowOffsetY = 3,
   context.shadowBlur = 6,
   context.strokeStyle = TRACKING_DIAL_STROKING_STYLE;
   context.beginPath();
   context.arc(circle.x, circle.y, circle.radius +
               RING_OUTER_RADIUS, 0, Math.PI*2, true);
   context.stroke();
}
//填充外圆环颜色
function drawRing() {
   drawRingOuterCircle();

   context.strokeStyle = 'rgba(0, 0, 0, 0.1)';
   context.arc(circle.x, circle.y,
               circle.radius + RING_INNER_RADIUS,
               0, Math.PI*2, false);

   context.fillStyle = 'rgba(100, 140, 230, 0.1)';
   context.fill();
   context.stroke();
}

显示效果:
iamge

(三)绘制刻度与数字标记

重点:角度与弧度计算,公式为:==角度=180°×弧度÷π==
==弧度=角度×π÷180°==

//绘制仪表盘
(function drawDial() {
   var loc = {x: circle.x, y: circle.y};
   //绘制中心圆点  
   drawCentroid();
   //绘制外圆环
   drawRing();
   //绘制刻度
    drawTicks();
   //绘制标记数字
   drawAnnotations();
})();

//----------------------------3、绘制刻度与数字标记
//绘制刻度,标记
function drawTick(angle, radius, cnt) {
    //刻度分隔为4份,长的为短的2倍
   var tickWidth = cnt % 4 === 0 ? TICK_WIDTH : TICK_WIDTH/2;
   context.beginPath();
    //绘制起始点
   context.moveTo(circle.x + Math.cos(angle) * (radius - tickWidth),
                  circle.y + Math.sin(angle) * (radius - tickWidth));
    //绘制终点
   context.lineTo(circle.x + Math.cos(angle) * (radius),
                  circle.y + Math.sin(angle) * (radius));

   context.strokeStyle = TICK_SHORT_STROKE_STYLE;
   context.stroke();
}
//绘制所有标记
function drawTicks() {
   var radius = circle.radius + RING_INNER_RADIUS, //半径
       ANGLE_MAX = 2*Math.PI,//最大角度
       ANGLE_DELTA = Math.PI/64;//角度间隔
   context.save();
   //最大角度,按间隔进行递增
   for (var angle = 0, cnt = 0; angle < ANGLE_MAX;
                                angle += ANGLE_DELTA, cnt++) {
      //绘制标记                            
      drawTick(angle, radius, cnt++); 
   }
   context.restore();
}
//绘制数字刻度
function drawAnnotations() {
    //数字标记半径
   var radius = circle.radius + RING_INNER_RADIUS;
   context.save();
   //数字标记样式
   context.fillStyle = ANNOTATIONS_FILL_STYLE;
   //数字标记字体大小与字体样式
   context.font = ANNOTATIONS_TEXT_SIZE + 'px Helvetica'; 
   //每循环一次为8分之一 PI增量,2×PI为一个整圆  
   //数字8将一个圆可以分为16份,改变此数字,可以更变数字显示密度
   for (var angle=0; angle < 2*Math.PI; angle += Math.PI/8) {
      context.beginPath();
      //绘制文本数字 度数为:角度=180°×弧度÷π toFixed四舍五入
      context.fillText((angle * 180 / Math.PI).toFixed(0),
         circle.x + Math.cos(angle) * (radius - TICK_WIDTH*2),
         circle.y - Math.sin(angle) * (radius - TICK_WIDTH*2));
   }
   context.restore();
}

显示效果:
iamge

(四)绘制指示线与内圆

//绘制仪表盘
(function drawDial() {
   var loc = {x: circle.x, y: circle.y};
   //绘制中心圆点  
   drawCentroid();
   //绘制指示线
   drawCentroidGuidewire(loc);
   //绘制外圆环
   drawRing();
   //绘制内圆 标记线内
   drawTickInnerCircle();
   //绘制刻度
    drawTicks();
   //绘制标记数字
   drawAnnotations();
})();

//------------------------4、绘制指示线与内圆
function drawCentroidGuidewire(loc) {
   var angle = -Math.PI/4,
       radius, endpt;

  radius = circle.radius + RING_OUTER_RADIUS;

  if (loc.x >= circle.x) {
      endpt = { x: circle.x + radius * Math.cos(angle),
                y: circle.y + radius * Math.sin(angle)
      };
   }
   else {
      endpt = { x: circle.x - radius * Math.cos(angle),
                y: circle.y - radius * Math.sin(angle)
      };
   }

   context.save();

   context.strokeStyle = GUIDEWIRE_STROKE_STYLE;
   context.fillStyle = GUIDEWIRE_FILL_STYLE;

   context.beginPath();
   context.moveTo(circle.x, circle.y);
   context.lineTo(endpt.x, endpt.y);
   context.stroke();

   context.beginPath();
   context.strokeStyle = TICK_LONG_STROKE_STYLE;
   context.arc(endpt.x, endpt.y, 5, 0, Math.PI*2, false);
   context.fill();
   context.stroke();

   context.restore();
}
//绘制内圆
function drawTickInnerCircle() {
   context.save();
   context.beginPath();
   context.strokeStyle = 'rgba(0, 0, 0, 0.1)';
   context.arc(circle.x, circle.y,
               circle.radius + RING_INNER_RADIUS - TICK_WIDTH,
               0, Math.PI*2, false);
   context.stroke();
   context.restore();
}

显示效果:
iamge

二、贝塞尔曲线

  贝塞尔曲线最初是由法国物理学家与数学家Paul de Casteljau发明的。曲线的核心定义:起始点、终止点(也称锚点)、控制点。然而贝塞尔曲线的得名,却是由于 1962 年另一位就职于雷诺的法国工程师皮埃尔·贝塞尔的广泛宣传。他使用这种只需要很少的控制点就能够生成复杂平滑曲线的方法,来辅助汽车车体的工业设计。
贝塞尔曲线分为两种:平方贝塞尔曲线和立方贝赛尔曲线。

(一)二次方贝塞尔曲线

二次方贝塞尔曲线就是只向一个方向弯曲的简单曲线。

参数描述
cpx贝塞尔控制点的 x 坐标
cpy贝塞尔控制点的 y 坐标
x结束点的 x 坐标
y结束点的 y 坐标
1、简单对号
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>贝塞尔曲线</title>
        <style>
            body {
                background: #283c3c;
            }
            #canvas {
                background: #f0fff0;
                border: thin solid #FFFFCC;
            }
        </style>
    </head>
    <body>
        <canvas id='canvas' width='400' height='300'>
    </canvas>
        <script src="js/Bezier01.js"></script>
    </body>
</html>

JS脚本

var context = document.getElementById('canvas').getContext('2d');
//填充样式
context.fillStyle     = 'cornflowerblue';
//轮廓样式
context.strokeStyle   = 'yellow';
//阴影颜色
context.shadowColor   = 'rgba(50, 50, 50, 1.0)';
context.shadowOffsetX = 2;
context.shadowOffsetY = 2;
context.shadowBlur    = 4;
//线粗细
context.lineWidth = 20;
//线帽为圆
context.lineCap = 'round';

context.beginPath();
context.moveTo(120.5, 130);
//贝塞尔曲线绘制
context.quadraticCurveTo(150.8, 130, 160.6, 150.5);
context.quadraticCurveTo(190, 250.0, 210.5, 160.5);
context.quadraticCurveTo(240, 100.5, 290, 70.5);
context.stroke();

显示效果:
image

2、箭头绘制

其中,红点为控制点,蓝色点为终点。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>贝塞尔曲线</title>
        <style>
            body {
                background: #283c3c;
            }
            #canvas {
                background: #f0fff0;
                border: thin solid #FFFFCC;
            }
        </style>
    </head>
    <body>
        <canvas id='canvas' width='400' height='300'>
    </canvas>
        <script src="js/Bezier01.js"></script>
    </body>
</html>

JS脚本:

var canvas = document.getElementById('canvas'),
    context = canvas.getContext('2d'),
    ARROW_MARGIN = 30, //箭头边距
    POINT_RADIUS = 7, //圆点半径
    //所有绘制点
    points = [{
            x: canvas.width - ARROW_MARGIN,
            y: canvas.height - ARROW_MARGIN
        },

        {
            x: canvas.width - ARROW_MARGIN * 2,
            y: canvas.height - ARROW_MARGIN
        },

        {
            x: POINT_RADIUS,
            y: canvas.height / 2
        },

        {
            x: ARROW_MARGIN,
            y: canvas.height / 2 - ARROW_MARGIN
        },

        {
            x: canvas.width - ARROW_MARGIN,
            y: ARROW_MARGIN
        },

        {
            x: canvas.width - ARROW_MARGIN,
            y: ARROW_MARGIN * 2
        },
    ];

//绘制圆点
function drawPoint(x, y, strokeStyle, fillStyle) {
    context.beginPath();
    context.fillStyle = fillStyle;
    context.strokeStyle = strokeStyle;
    context.lineWidth = 0.5;
    context.arc(x, y, POINT_RADIUS, 0, Math.PI * 2, false);
    context.fill();
    context.stroke();
}
//绘制贝塞尔曲线的点
function drawBezierPoints() {
    var i,
        strokeStyle,
        fillStyle;
    //获取数组中的所有点
    for(i = 0; i < points.length; ++i) {
        //点的样式
        fillStyle = i % 2 === 0 ? 'red' : 'blue',
        strokeStyle = i % 2 === 0 ? 'red' : 'blue';
        context.font="16px Helvetica"
        context.fillText(i+1,points[i].x+8, points[i].y);
        //绘制点
        drawPoint(points[i].x, points[i].y,
            strokeStyle, fillStyle);
    }
}
//绘制箭头
function drawArrow() {
    context.strokeStyle = '#2B334A';
    context.fillStyle = 'cornflowerblue';
    //起点
    context.moveTo(canvas.width - ARROW_MARGIN,
        ARROW_MARGIN * 2);
    //绘制路径
    context.lineTo(canvas.width - ARROW_MARGIN,
        canvas.height - ARROW_MARGIN * 2);
    //第一个控制点与结束点                
    context.quadraticCurveTo(points[0].x, points[0].y,
        points[1].x, points[1].y);
    //第二个路径
    context.lineTo(ARROW_MARGIN,
        canvas.height / 2 + ARROW_MARGIN);
    //第二个控制点与结束点,起点将以第个路径的点为起点
    context.quadraticCurveTo(points[2].x, points[2].y,
        points[3].x, points[3].y);
    //第三个绘制
    context.lineTo(canvas.width - ARROW_MARGIN * 2,
        ARROW_MARGIN);

    context.quadraticCurveTo(points[4].x, points[4].y,
        points[5].x, points[5].y);
    context.fill();
    context.stroke();
}

//清空画布
context.clearRect(0, 0, canvas.width, canvas.height);
//绘制箭头
drawArrow();
drawBezierPoints();

显示效果:
image

(二)三次方贝塞尔曲线

三次方贝塞尔曲线可以向两个方向弯曲。

 <!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>贝塞尔曲线</title>
        <style>
            body {
                background: #283c3c;
            }
            #canvas {
                background: #f0fff0;
                border: thin solid #FFFFCC;
            }
        </style>
    </head>
    <body>
        <canvas id='canvas' width='400' height='300'>
    </canvas>
        <script src="js/Bezier02.js"></script>
    </body>
</html>

JS脚本

var canvas = document.getElementById('canvas'),
    context = canvas.getContext('2d'),
    //定义终点
    endPoints = [
       { x: 100, y: 70 },
       { x: 320, y: 270 },
    ],
    //定义控制点
    controlPoints = [
       { x: 100, y: 250 },
       { x: 360, y: 70 },
    ];

//贝塞尔曲线绘制
function drawBezierCurve() {
   context.strokeStyle = 'blue';
   context.fillStyle = 'yellow';

   context.beginPath();
   context.moveTo(endPoints[0].x, endPoints[0].y);
   context.bezierCurveTo(controlPoints[0].x, controlPoints[0].y,
                         controlPoints[1].x, controlPoints[1].y,
                         endPoints[1].x, endPoints[1].y);
   context.stroke();
}
//终点
function drawEndPoints() {
   context.strokeStyle = 'blue';
   context.fillStyle = 'blue';

   endPoints.forEach( function (point) {
      context.beginPath();
      context.arc(point.x, point.y, 5, 0, Math.PI*2, false);
      context.stroke();
      context.fill();
   });
}
//绘制控制点
function drawControlPoints() {
   context.strokeStyle = 'yellow';
   context.fillStyle = 'red';

   controlPoints.forEach( function (point) {
      context.beginPath();
      context.arc(point.x, point.y, 5, 0, Math.PI*2, false);
      context.stroke();
      context.fill();
   });
}
//绘制控制点
drawControlPoints();
//绘制终点
drawEndPoints();
//绘制贝塞尔曲线
drawBezierCurve();

最终显示:
image

(四)编辑贝塞尔曲线

1、基本功能
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>编辑贝塞尔曲线</title>
        <style>
            body {
                background: #eeeeee;
            }
            .floatingControls {
                position: absolute;
                left: 150px;
                top: 100px;
                width: 300px;
                padding: 20px;
                border: thin solid rgba(0, 0, 0, 0.3);
                background: rgba(0, 0, 200, 0.1);
                color: blue;
                font: 14px Arial;
                -webkit-box-shadow: rgba(0, 0, 0, 0.2) 6px 6px 8px;
                box-shadow: rgba(0, 0, 0, 0.2) 6px 6px 8px;
                display: none;
            }
            .floatingControls p {
                margin-top: 0px;
                margin-bottom: 20px;
            }
            #controls {
                position: absolute;
                left: 25px;
                top: 25px;
            }
            #canvas {
                background: #f0fff0;
                cursor: pointer;
                margin-left: 10px;
                margin-top: 10px;
                -webkit-box-shadow: 4px 4px 8px rgba(0, 0, 0, 0.5);
                box-shadow: 4px 4px 8px rgba(0, 0, 0, 0.5);
            }
        </style>
    </head>
    <body>
        <canvas id='canvas' width='605' height='400'>
     </canvas>
        <div id='controls'>
            连框颜色:
            <select id='strokeStyleSelect'>
                <option value='red'></option>
                <option value='green'>绿</option>
                <option value='blue'></option>
                <option value='orange'></option>
                <option value='cornflowerblue' selected>菊蓝</option>
                <option value='goldenrod'> 鲜黄</option>
                <option value='navy'>深蓝</option>
                <option value='purple'>紫色</option>
            </select>
            参考线: <input id='guidewireCheckbox' type='checkbox' checked/>
            <input id='eraseAllButton' type='button' value='擦除所有' />
        </div>
        <div id='instructions' class='floatingControls'>
            <p>拖拽结束点与控制点改变曲线形状.</p>
            <p>当你完成绘制后,点击外边结束绘制。</p>
            <input id='instructionsOkayButton' type='button' value='确定' autofocus/>
            <input id='instructionsNoMoreButton' type='button' value='不再显示' />
        </div>
        <script src='js/BezierEdit.js'></script>
    </body>
</html>

JS脚本:

var canvas = document.getElementById('canvas'),
    context = canvas.getContext('2d'),
    eraseAllButton = document.getElementById('eraseAllButton'),                     //擦除所有
    strokeStyleSelect = document.getElementById('strokeStyleSelect'),               //线条颜色
    guidewireCheckbox = document.getElementById('guidewireCheckbox'),               //是否显示参考线
    instructions = document.getElementById('instructions'),                         //显示提示信息层
    instructionsOkayButton = document.getElementById('instructionsOkayButton'),     //提示信息确定按钮
    instructionsNoMoreButton = document.getElementById('instructionsNoMoreButton'), //不再提示信息按钮

    showInstructions = true,//提示信息
   //网格颜色
    GRID_STROKE_STYLE = 'lightblue',
    GRID_SPACING = 10,
    //控制点参数
    CONTROL_POINT_RADIUS = 5,
    CONTROL_POINT_STROKE_STYLE = 'blue',
    CONTROL_POINT_FILL_STYLE = 'rgba(255, 255, 0, 0.5)',
    //结束点参数
    END_POINT_STROKE_STYLE = 'navy',
    END_POINT_FILL_STYLE   = 'rgba(0, 255, 0, 0.5)',
    //参考线样式
    GUIDEWIRE_STROKE_STYLE = 'rgba(0,0,230,0.4)',

    drawingImageData,      // 图像数据存储--按下鼠标事件

    mousedown = {},        // 光标位置--鼠标事件
    rubberbandRect = {},   // 鼠标移动事件的不断更新

    dragging = false,      // 如果为真,用户可以拖动鼠标标
    draggingPoint = false, // 结束点或控制点的拖动

    endPoints     = [ {}, {} ],  //结束点坐标
    controlPoints = [ {}, {} ],  //控制点坐标
    editing  = false,            //如果为真用户可以编辑曲线
    //获取参考线值
    guidewires = guidewireCheckbox.checked;

//------------------1、基本功能
//绘制网格
function drawGrid(color, stepx, stepy) {
   context.save()
   context.strokeStyle = color;
   context.lineWidth = 0.5;
   context.clearRect(0, 0, context.canvas.width, context.canvas.height);
   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();
}
//坐标转换
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)
          };
}
context.strokeStyle = strokeStyleSelect.value;
drawGrid(GRID_STROKE_STYLE, GRID_SPACING, GRID_SPACING);
2、贝塞尔曲线绘制
//--------------------------2、贝塞尔曲线绘制
//保存绘制
function saveDrawingSurface() {
   drawingImageData = context.getImageData(0, 0,
                         canvas.width, canvas.height);
}
//恢复绘制
function restoreDrawingSurface() {
   context.putImageData(drawingImageData, 0, 0);
}

//橡皮圈更新绘制
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 drawBezierCurve() {
   context.beginPath();
   context.moveTo(endPoints[0].x, endPoints[0].y);
   context.bezierCurveTo(controlPoints[0].x, controlPoints[0].y,
                         controlPoints[1].x, controlPoints[1].y,
                         endPoints[1].x, endPoints[1].y);
   context.stroke();
}
//更新结束点与控制点
function updateEndAndControlPoints() {
    //结束点坐标
   endPoints[0].x = rubberbandRect.left;
   endPoints[0].y = rubberbandRect.top;

   endPoints[1].x = rubberbandRect.left + rubberbandRect.width;
   endPoints[1].y = rubberbandRect.top  + rubberbandRect.height
   //控制点坐标
   controlPoints[0].x = rubberbandRect.left;
   controlPoints[0].y = rubberbandRect.top  + rubberbandRect.height

   controlPoints[1].x = rubberbandRect.left + rubberbandRect.width;
   controlPoints[1].y = rubberbandRect.top;
}
//绘制结束点与控制点小圆点
function drawRubberbandShape(loc) {
   updateEndAndControlPoints();
   drawBezierCurve();
}
//更新橡皮圈
function updateRubberband(loc) {
   updateRubberbandRectangle(loc);
   drawRubberbandShape(loc);
}
3、绘制结束点与控制点
//-------------------------3、绘制结束点与控制点
//绘制控制点
function drawControlPoint(index) {
   context.beginPath();
   context.arc(controlPoints[index].x, controlPoints[index].y,
               CONTROL_POINT_RADIUS, 0, Math.PI*2, false);
   context.stroke();
   context.fill();
}
//绘制控制点
function drawControlPoints() {
   context.save();
   context.strokeStyle = CONTROL_POINT_STROKE_STYLE;
   context.fillStyle   = CONTROL_POINT_FILL_STYLE;

   drawControlPoint(0);
   drawControlPoint(1);

   context.stroke();
   context.fill();
   context.restore();
}
//绘制结束点
function drawEndPoint(index) {
   context.beginPath();
   context.arc(endPoints[index].x, endPoints[index].y,
               CONTROL_POINT_RADIUS, 0, Math.PI*2, false);
   context.stroke();
   context.fill();
}
//绘制结束点
function drawEndPoints() {
   context.save();
   context.strokeStyle = END_POINT_STROKE_STYLE;
   context.fillStyle   = END_POINT_FILL_STYLE;

   drawEndPoint(0);
   drawEndPoint(1);

   context.stroke();
   context.fill();
   context.restore();
}
//绘制控制点与结束点
function drawControlAndEndPoints() {
   drawControlPoints();
   drawEndPoints();
}
//光标结束点
function cursorInEndPoint(loc) {
   var pt;
   endPoints.forEach( function(point) {
      context.beginPath();
      context.arc(point.x, point.y,
                  CONTROL_POINT_RADIUS, 0, Math.PI*2, false);

      if (context.isPointInPath(loc.x, loc.y)) {
         pt = point;
      }
   });
   return pt;
}
//光标在控制点
function cursorInControlPoint(loc) {
   var pt;
   //查找控制点
   controlPoints.forEach( function(point) {
      context.beginPath();
      context.arc(point.x, point.y, 
                  CONTROL_POINT_RADIUS, 0, Math.PI*2, false);
      //重点通过 isPointInPath 判定鼠标点击的点是否在路径中,如果
      //不在则认为编辑结束
      if (context.isPointInPath(loc.x, loc.y)) {
         pt = point;
      }
   });
   return pt;
}
//更新拖拽点
function updateDraggingPoint(loc) {
   draggingPoint.x = loc.x;
   draggingPoint.y = loc.y;
}
4、绘制参考线
//-----------------------4、绘制参考线
//绘制水平线
function drawHorizontalGuidewire (y) {
   context.beginPath();
   context.moveTo(0, y + 0.5);
   context.lineTo(context.canvas.width, y + 0.5);
   context.stroke();
}
//绘制垂直线
function drawVerticalGuidewire (x) {
   context.beginPath();
   context.moveTo(x + 0.5, 0);
   context.lineTo(x + 0.5, context.canvas.height);
   context.stroke();
}
//绘制参考线
function drawGuidewires(x, y) {
   context.save();
   context.strokeStyle = GUIDEWIRE_STROKE_STYLE;
   context.lineWidth = 0.5;
   drawVerticalGuidewire(x);
   drawHorizontalGuidewire(y);
   context.restore();
}
5、绘制曲线事件
//------------------------5、绘制曲线事件
//鼠标按下事件
canvas.onmousedown = function (e) {
    //坐标转换
   var loc = windowToCanvas(e.clientX, e.clientY);
   e.preventDefault(); 
   //可编辑,默认
   if (!editing) {
      //保存画布
      saveDrawingSurface();
      mousedown.x = loc.x;
      mousedown.y = loc.y;
      //更新橡皮圈
      updateRubberbandRectangle(loc);
      //改变可拖拽状态
      dragging = true;
   }
   else {
    console.log("----------------"+editing+draggingPoint)
      //获取控制点光标位置
      draggingPoint = cursorInControlPoint(loc);
      //如果光标不在控制点上,则获取光标是否在结束点上
      if (!draggingPoint) {
        //获取结束点--光标位置
         draggingPoint = cursorInEndPoint(loc);
      }
   }
};
//鼠标移动
canvas.onmousemove = function (e) {
   var loc = windowToCanvas(e.clientX, e.clientY);
    //如果可以拖拽
   if (dragging || draggingPoint) {
    console.log("&&&&&"+draggingPoint)
      e.preventDefault(); 
      //恢复画布
      restoreDrawingSurface();
     //如果启用了参考线,则绘制参考线
      if(guidewires) {
         drawGuidewires(loc.x, loc.y);
      }
   }
   //如果拖拽为空
   if (dragging) {
     //更新绘制
      updateRubberband(loc);
      drawControlAndEndPoints();
   }
   else if (draggingPoint) {
      //f进行贝塞尔曲线绘制
      updateDraggingPoint(loc);
      drawControlAndEndPoints();
      drawBezierCurve();
   }
};
/**
 * 释放鼠标
 * @param {Object} e
 */
canvas.onmouseup = function (e) {
    //坐标转换
   loc = windowToCanvas(e.clientX, e.clientY);
    //恢复画布
   restoreDrawingSurface();
    //如果可编辑为false ,默认
   if (!editing) {
      //进行贝塞尔曲线绘制
      updateRubberband(loc);
      //绘制结束点与控制点
      drawControlAndEndPoints();
      dragging = false;
      //更改编辑状态
      editing = true;
      //显示提示信息
      if (showInstructions) {
         instructions.style.display = 'inline';
      }
   }
   else {

      //如果光标在结束点与控制点上,继续绘制 ,否则将可编辑设置为false,结束绘制
      if (draggingPoint) drawControlAndEndPoints();
      else               editing = false;
      //绘制曲线
      drawBezierCurve();
      //结束绘制,让所有条件不成立
      draggingPoint = undefined;
   }
};
6、控制事件
//--------------------6、控制事件
//擦 除所有事件
eraseAllButton.onclick = function (e) {
    //清空画布
   context.clearRect(0, 0, canvas.width, canvas.height);
   //重绘网格
   drawGrid(GRID_STROKE_STYLE, GRID_SPACING, GRID_SPACING);
    //保存画两点
   saveDrawingSurface(); 
   //改变所有状态为默认
   editing = false;
   dragging = false;
   draggingPoint = undefined;
};
//--------------------------------
//改变线条事件
strokeStyleSelect.onchange = function (e) {
   context.strokeStyle = strokeStyleSelect.value;
};
//参考线事件
guidewireCheckbox.onchange = function (e) {
   guidewires = guidewireCheckbox.checked;
};
7、信息提示
//-----------------------------7、提示信息事件
//提示信息确定事件
instructionsOkayButton.onclick = function (e) {
   instructions.style.display = 'none';
};
//提示信息不南显示事件
instructionsNoMoreButton.onclick = function (e) {
   instructions.style.display = 'none';
   showInstructions = false;
};

显示效果:
image

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值