Hi I'm facing a problem with canvas.
I try to make a circle that can be reshape like this. In the demo the circle can be reshape
the problem is to drag and drop the circle point to reshape it.
I know how to drag and drop point in the javascript canvas but how to reshape the cirle line to follow the point.
const DEBUG = true;
const WIDTH = window.innerWidth;
const HEIGHT = window.innerHeight;
const MIN_DIMENSION = WIDTH < HEIGHT ? WIDTH : HEIGHT;
const DEFAULT_RADIUS = MIN_DIMENSION * 0.45;
let canvas, ctx;
let cos = Math.cos;
let sin = Math.sin;
let pi = Math.PI;
let pi2 = pi * 2;
class Point {
constructor(x,y) {
this.x = x;
this.y = y;
}
}
function block(c, cb) {
c.save();
c.beginPath();
cb(c);
c.closePath();
c.restore();
}
function circle(c,r) {
c.arc(0, 0, r, 0, pi2);
}
function debugPoints(c, points) {
points.forEach((p,i) => {
if(i % 2 === 0) {
c.fillStyle = 'red';
} else {
c.fillStyle = 'black';
}
c.beginPath();
c.arc(p.x, p.y, 2, 0, pi2);
c.fill();
c.closePath();
})
}
function bezierCirclePoints(r, n) {
let a = pi2/(2*n);
let R = r/cos(a);
let points = new Array(2 * n);
console.log('n:', n);
console.log('a:', a);
console.log('r:', r);
console.log('R:', R);
// calculate even bezier points
for(let i = 0; i < n; i++) {
let i2 = 2*i;
let x = r * sin(i2 * a);
let y = -r * cos(i2 * a);
points[i2] = new Point(x, y);
}
// calculate odd bezier points
for(let i = 0; i < n; i++) {
let i2 = 2*i + 1;
let x = R * sin(i2 * a);
let y = -R * cos(i2 * a);
points[i2] = new Point(x, y);
}
points.push(points[0]);
return points;
}
function bezierCircle(c, r = DEFAULT_RADIUS, n = 7) {
let points = bezierCirclePoints(r,n);
c.translate(WIDTH * 0.5,HEIGHT * 0.5);
if(DEBUG) {
debugPoints(c, points);
}
c.fillStyle = 'red';
c.strokeStyle = 'red';
// draw circle
c.beginPath();
let p = points[0];
c.moveTo(p.x, p.y);
for(let i = 1; i < points.length; i+=2){
let p1 = points[i];
let i2 = i + 1;
if(i2 >= points.length) {
i2 = 0;
}
let p2 = points[i2];
c.quadraticCurveTo(p1.x, p1.y, p2.x, p2.y);
}
c.stroke();
c.closePath();
}
function redCircle(c) {
c.fillStyle = 'red';
c.translate(200,200);
circle(c, 100);
c.fill();
}
canvas = document.getElementById('circle');
canvas.width = WIDTH;
canvas.height = HEIGHT;
ctx = canvas.getContext('2d');
block(ctx, bezierCircle)
<canvas id="circle"></canvas>