CANVAS 贝塞尔曲线

时间:2021-09-08 05:47:53
12345678910111213141516171819202122232425262728 <!DOCTYPE
html>
<html>    <head>        <title>rect        </title>        <style>          body{            background: #eeeeee;          }              #canvas{                background: #000000;             }        </style>    </head>    <body>         <canvas id="canvas" width="1000" height="800">            Canvas not supported        </canvas>           <script src="chapetal2.js"></script>    </body></html>


12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273 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}    ]; //Functions................................................................. function drawPointer(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 ? 'white' 'blue',        strokeStyle = i % 2 === 0 ? 'blue' 'white';        drawPointer(points[i].x, points[i].y,                  strokeStyle, fillStyle);    }} function drawArrow(){    context.strokeStyle = 'white';    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();} //Initialization.......................................................... context.clearRect(0,
0, canvas.width,canvas.height);
drawArrow();drawBezierPoints();

CANVAS  贝塞尔曲线CANVAS  贝塞尔曲线


三次方贝赛尔曲线:(可以变换两个方向)

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051 var canvas = document.getElementById("canvas"),    context = canvas.getContext("2d"),    endPoints = [{x: 130, y : 70}, { x: 430, y : 270},],    controlPoints = [{ x: 130, y : 250}, { x: 450, y: 70}, ]; //Functions.................................................................. function drawGrid(color, stepx, stepy){ } function drawBezierCurve(){    context.strokeStyle = 'blue';     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 = 'red';     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 = 'blue';     controlPoints.forEach(function (point){        context.beginPath();        context.arc(point.x, point.y, 5, 0, Math.PI*2, false);        context.stroke();        context.fill();    });} drawGrid('lightgray', 10, 10); drawControlPoints();drawEndPoints();drawBezierCurve();


可拖动:

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384 <!DOCTYPE
html>
<html>    <head>        <title>rect        </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;            -moz-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: 20px;            top:25px;          }           #canvas {            background: #ffffff;            cursor: pointer;            margin-left: 10px;            margin-top: 10px;            -webkit-box-shadow: 4px 4px 8px rgba(0,0,0,0.5);            -moz-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 not supported        </canvas>        <div id "controls">          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" selected>navy</option>            <option value="purple" >purple</option>        </select>      Guidewires:      <input id="guidewireCheckbox" type="checkbox" checked />      <input id="eraseAllButton" type="button" value="Erase All" />       </div>        <div id="instructions" class="floatingControls">          <p>Drag the curve end- and control points to            change the shape of the curve.</p>           <p>When you are done dragging end- and control points,              click outside of the points to finalize the curve.</p>           <input id "instructionsOkayButton" type="button"                value "Okay" autofocus/>          <input id "instructionsNoMoreButton" type="button"                value "Do not show these instructions again"/>       </div>         <script src="drawBezier.js"></script>    </body></html>


123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347 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,     AXIS_MARGIN = 40,    HORIZONTAL_TICK_SPACING = 10,    VERTICAL_TICK_SPACING = 10,    TICK_SIZE = 10,     AXIS_ORIGIN = { x: AXIS_MARGIN, y: canvas.height-AXIS_MARGIN },    AXIS_TOP = AXIS_MARGIN,     AXIS_RIGHT = canvas.width - AXIS_MARGIN,    AXIS_WIDTH = AXIS_RIGHT - AXIS_ORIGIN.x,    AXIS_HEIGHT = AXIS_ORIGIN.y - AXIS_TOP,     NUM_VERTICAL_TICKS = AXIS_HEIGHT / VERTICAL_TICK_SPACING,    NUM_HORIZONTAL_TICKS = AXIS_WIDTH / HORIZONTAL_TICK_SPACING,     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(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, // Image data stored on mouse down events    mousedown = {},     //Cursor location for last mouse down events    rubberbandRect = {}, //Constantly update for mouse move events     dragging = false,   //If true, user is dragging the Cursor    draggingPoint = false//End- or control point user is dragging    endPoints = [ {} , {}], //Endpoint locations (x,y)    controlPoints = [ {} , {} ], //Controle point locations (x ,y)    editing = false,            // If true, user is editing the curve     guidewires = guidewireCheckbox.checked; //Functions
...........................................................
 function drawGrid(color, stepx, stepy) {    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();    }} 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)            };} //Save
and restore drawing surface.....................................
 function saveDrawingSurface() {    drawingImageData = context.getImageData(0, 0,                                        canvas.width,canvas.height);} function restoreDrawingSurface(){    context.putImageData(drawingImageData, 0, 0);} //Rubber
bands..........................................................
 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);} //Guidewires................................................... 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();} //Endpoints
and control points......................................
 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(ioc) {    var pt;     controlPoints.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 updateDraggingPoint(loc) {    draggingPoint.x = loc.x;    draggingPoint.y = loc.y;} //Canvas
event handlers.............................................
 canvas.onmousedown
function (e) {
    var loc = windowToCanvas(e.clientX, e.clientY);     e.preventDefault(); //Prevent cursor change     if(!editing) {        saveDrawingSurface();        mousedown.x = loc.x;        mousedown.y = loc.y;        updateRubberbandRectangle(loc);        dragging = true;    }    else {        draggingPoint = cursorInControlPoint(loc);         if(!draggingPoint) {            draggingPoint = cursorInEndPoint(loc);        }    }}; canvas.onmousemove
function (e) {
    var loc = windowToCanvas(e.clientX, e.clientY);     if (dragging || draggingPoint) {        e.preventDefault();        restoreDrawingSurface();         if(guidewires) {            drawGuidewires(loc.x, loc.y);        }    }     if(dragging) {        updateRubberband(loc);        drawControlAndEndPoints();    }    else if (draggingPoint) {        updateDraggingPoint(loc);        drawControlAndEndPoints();        drawBezierCurve();    }}; canvas.onmouseup
function (e) {
    loc = windowToCanvas(e.clientX, e.clientY);     restoreDrawingSurface();     if(!editing) {        updateRubberband(loc);        drawControlAndEndPoints();        dragging = false;        editing = true;        if(showInstructions) {            instructions.style.display = 'inline';        }    }    else {        if (draggingPoint) drawControlAndEndPoints();        else                editing = false;         drawBezierCurve();        draggingPoint = undefined;    }}; //Control
event handlers........................................
 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;}; //Instructions
event handlers....................................
 instructionsOkayButton.onclick
function (e) {
    instructions.style.display = 'none';}; instructionsNoMoreButton.onclick
function (e) {
    instructions.style.display = 'none';    showInstructions = false;}; //Initialization..................................................... context.strokeStyle
= strokeStyleSelect.value;
drawGrid(GRID_STROKE_STYLE,
GRID_SPACING,GRID_SPACING);