#codevember 8 - BezierCurves

In this example below you will see how to do a #codevember 8 - BezierCurves with some HTML / CSS and Javascript

An implementation of a Bezier Curve class

Thumbnail
This awesome code was written by phcacique, you can see more from this user in the personal repository.
You can find the original code on Codepen.io
Copyright phcacique ©
  • HTML
  • CSS
  • JavaScript
<!DOCTYPE html>
<html lang="en" >

<head>
  <meta charset="UTF-8">
  <title>#codevember 8 - BezierCurves</title>
  
  
  
      <link rel="stylesheet" href="css/style.css">

  
</head>

<body>

  <canvas id="canvas"></canvas>

<footer>
  <div>Made by <a href="http://www.pedrocacique.com">Cacique</a></div><div> <a href="http://codevember.xyz/about">#codevember</a> <a href="http://codevember.xyz/day/8">#day8</a>
  </div>
    </footer>
  
  

    <script  src="js/index.js"></script>




</body>

</html>

/*Downloaded from https://www.codeseek.co/phcacique/codevember-8-beziercurves-xRGaEN */
body{
  margin:0;
  font-family: Helvetica, Arial;
  font-weight: 100;
}
canvas {
  background-color: #101010;
}

footer{
  position: fixed;
  bottom:0;
  height: 20px;
  width: 100%;
  display: flex;
  justify-content: space-around;
  align-items: center;
  background-color: #202020;
  color: #fff;
  font-size: 0.7em;
}

footer a{
  color: #f0f0f0;
}

header{
  color: #fff;
  padding: 10px;
  position: fixed;
}

/*Downloaded from https://www.codeseek.co/phcacique/codevember-8-beziercurves-xRGaEN */
//---------- MAIN FUNCTION ----------
function init() {
    curves.push(new BezierCurve(new Point(300, 100),
        new Point(300, 150),
        new Point(380, 300),
        new Point(400, 100)));
  
    curves.push(new BezierCurve());
    //curves.push(new BezierCurve(null,null,null,null, {showPoints:false, showLines:false}));
}

//-----------------------------------
var canvas, ctx, cw, ch;
var curves = [];
var draggingCurve, draggingPoint;
const FPS = 60;

var requestAnimationFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.msRequestAnimationFrame || function (callback) {
    return setTimeout(callback, FPS);
};

window.onload = initAll;
window.onresize = initAll;

function initAll() {
    initCanvas();
    init();
    animate();
}

function animate(){
    ctx.clearRect(0,0,cw,ch);
    for (var i = 0; i < curves.length; i++) {
        curves[i].draw(ctx);
    }
    requestAnimationFrame(animate);
}

function initCanvas() {
    canvas = document.getElementById('canvas');
    ctx = canvas.getContext('2d');
    cw = window.innerWidth;
    ch = window.innerHeight;
    canvas.width = cw;
    canvas.height = ch;
    canvas.addEventListener("mousedown", onMouseDown);
    canvas.addEventListener("mouseup", onMouseUp);
}

function onMouseDown(evt) {
    var p = getMousePos(canvas, evt);
    var points = ["startPoint", "endPoint", "controlPoint1", "controlPoint2"];

    draggingCurve = -1;
    for (var i = 0; i < curves.length; i++) {
        for (var j = 0; j < points.length; j++) {
            if (p.near(curves[i][points[j]], curves[i][points[j]].size)) {
                draggingCurve = i;
                draggingPoint = points[j];
            }
        }
    }
    if (draggingCurve != -1)
        canvas.addEventListener("mousemove", onMouseMove);
}

function onMouseUp(evt) {
    canvas.removeEventListener("mousemove", onMouseMove);
}

function onMouseMove(evt) {
    var p = getMousePos(canvas, evt);
    curves[draggingCurve][draggingPoint].x = p.x;
    curves[draggingCurve][draggingPoint].y = p.y;
}

function getMousePos(canvas, evt) {
    var rect = canvas.getBoundingClientRect();
    return new Point(
        evt.clientX - rect.left,
        evt.clientY - rect.top,
        0
    );
}

//----------- Prototypes -------------
//----------- POINT -----------
function Point(x, y, properties) {
    this.x = (x == null) ? 0 : x;
    this.y = (y == null) ? 0 : y;
    this.lineColor = "#fff";
    this.fillColor = null;
    this.shape = "square";
    this.size = 5;
    this.lineWidth = 1;
    if (properties != null) this.setProperties(properties);
}
Point.prototype.distance = function (p2) {
    //Euclidean Disctance
    return Math.sqrt(Math.pow(this.x - p2.x, 2) + Math.pow(this.y - p2.y, 2) + Math.pow(this.z - p2.z, 2));
}
Point.prototype.manhatan = function (p2) {
    return (p2.x - p1.x) + (p2.y - p1.y) + (p2.z - p1.z);
}
Point.prototype.setProperties = function (properties) {
    for (var p in properties) {
        this[p] = properties[p];
    }
}
Point.prototype.clone = function () {
    var copy = new Point();
    for (var attr in this) {
        if (this.hasOwnProperty(attr)) copy[attr] = this[attr];
    }
    return copy;
}
Point.prototype.equals = function (p2) {
    return (this.x == p2.x && this.y == p2.y);
}
Point.prototype.near = function (p2, offset) {
    return (this.x > p2.x - offset && this.x < p2.x + offset && this.y > p2.y - offset && this.y < p2.y + offset)
}
Point.prototype.draw = function (ctx) {
    ctx.beginPath();
    if (this.lineColor != null) {
        ctx.strokeStyle = this.lineColor;
        ctx.lineWidth = this.lineWidth;
    }
    if (this.fillColor == null) this.fillColor = "rgba(0,0,0,0)";
    ctx.fillStyle = this.fillColor;
    if (this.shape == "circle") ctx.arc(this.x, this.y, this.size / 2, 0, Math.PI * 2);
    else ctx.rect(this.x - this.size / 2, this.y - this.size / 2, this.size, this.size);
    if (this.lineColor != null) ctx.stroke();
    ctx.fill();
}
Point.prototype.trace = function () {
    console.log(this);
}

//----------- RECT -----------
function Rect(p1, p2, properties) {
    this.p1 = (p1 == null) ? new Point() : p1;
    this.p2 = (p2 == null) ? new Point(10, 0) : p2;
    this.lineColor = "#fff";
    this.lineWidth = 1;
    if (properties != null) this.setProperties(properties);
}
Rect.prototype.setProperties = function (properties) {
    for (var p in properties) {
        this[p] = properties[p];
    }
}
Rect.prototype.clone = function () {
    var copy = new Rect();
    for (var attr in this) {
        if (this.hasOwnProperty(attr)) copy[attr] = this[attr];
    }
    return copy;
}
Rect.prototype.draw = function (ctx) {
    ctx.beginPath();
    ctx.lineWidth = this.lineWidth;
    ctx.strokeStyle = this.lineColor;
    ctx.moveTo(this.p1.x, this.p1.y);
    ctx.lineTo(this.p2.x, this.p2.y);
    ctx.stroke();
}
Rect.prototype.trace = function () {
    console.log(this);
}

//----------- BEZIER CURVE -----------
function BezierCurve(startPoint, controlPoint1, controlPoint2, endPoint, properties) {
    this.startPoint = (startPoint != null) ? startPoint : (new Point(100,200));
    this.endPoint = (endPoint != null) ? endPoint : (new Point(200,100));
    this.controlPoint1 = (controlPoint1 != null) ? controlPoint1 : (new Point(150,200));
    this.controlPoint2 = (controlPoint2 != null) ? controlPoint2 : (new Point(200,150));
    this.color = "#fff";
    this.lineWidth = 1;
    this.showLines = true;
    this.showPoints = true;
    var prop1 = {
        shape: "circle",
        lineColor: "#ffd460",
        fillColor: "#ffd460",
        size: 8
    };
    var prop2 = {
        shape: "square",
        lineColor: "#68ccff",
        fillColor: "#68ccff",
        size: 8
    };
    this.startPoint.setProperties(prop1);
    this.endPoint.setProperties(prop1);
    this.controlPoint1.setProperties(prop2);
    this.controlPoint2.setProperties(prop2);
    if (properties != null) this.setProperties(properties);
}
BezierCurve.prototype.draw = function (ctx) {
    if (this.showLines) {
        this.startPoint.draw(ctx);
        this.endPoint.draw(ctx);
        this.controlPoint1.draw(ctx);
        this.controlPoint2.draw(ctx);
        if (this.showPoints) {
            var r1 = new Rect(this.startPoint, this.controlPoint1, {
                lineColor: this.controlPoint1.lineColor, lineWidth: this.lineWidth/2
            });
            r1.draw(ctx);
            var r2 = new Rect(this.endPoint, this.controlPoint2, {
                lineColor: this.controlPoint2.lineColor, lineWidth: this.lineWidth/2
            });
            r2.draw(ctx);
        }
    }

    ctx.beginPath();
    ctx.strokeStyle = this.color;
    ctx.lineWidth = this.lineWidth;
    ctx.moveTo(this.startPoint.x, this.startPoint.y);
    ctx.bezierCurveTo(this.controlPoint1.x, this.controlPoint1.y, this.controlPoint2.x, this.controlPoint2.y, this.endPoint.x, this.endPoint.y);
    ctx.stroke();
}
BezierCurve.prototype.setProperties = function (properties) {
    for (var p in properties) {
        this[p] = properties[p];
    }
}
BezierCurve.prototype.clone = function () {
    var copy = new BezierCurve();
    for (var attr in this) {
        if (this.hasOwnProperty(attr)) copy[attr] = this[attr];
    }
    return copy;
}
BezierCurve.prototype.trace = function () {
    console.log(this);
}

Comments