Open FlashTang opened 4 years ago
At first, I tried to use 2 Cubic Bezier Curves, but seems it's not so simple (I have no idea how to adjust that 4 control points, and even I don't know that if this is possible)
At first, I tried to use 2 Cubic Bezier Curves, but seems it's not so simple (I have no idea how to adjust that 4 control points, and even I don't know that if this is possible)
Hi Pomax , actually I found your bezierjs project & readed that 「§39 Curve offsetting」article before I noticed your reply. The "Graduated curve offsetting" is exactly what I want, I think I can grab some relevant codes from bezierjs then convert to swift , or maybe use bezierjs to get "bezier data" on swift directly (use "JavaScriptCore" as bridge) , or use wkwebview for rendering bezier lines singly (some as I using LaTex - MathJax js on swift ) Thanks for your great project and the free book, it's fun to read !
@aab29 @Pomax
Hi ,I tried JavaScriptCore + ios , but slow performance ( I guess only 5 fps animated curves )
So I port it to swift, bezierjs based : https://github.com/FlashTang/BezierSwift
But still slow performance ( I mean the offset function) ,it seems ok if you have only 1 or 2 offset curves , but if you have more offset curves (e.g 4 curves), it's getting slow, very low , let alone 10 or 30 offset curves
p.s I also converted bezier.dart to swift , the same result (a little bit better than the port based on bezierjs)
So, I suspect there are something wrong in my code
then I back to HTML + Canvas + bezierjs , but it acts the same ,slow ,logy
I don't know if this is proleptic (since offset processing is heavy ? ) , thank you
There is the code
index.js
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
function draw(event){
var p = getMousePos(c, event);
ctx.clearRect(0,0,c.width, c.height);
var bezier = new Bezier({x:p.x,y:p.y},{x:50,y:50},{x:200,y:50},{x:200,y:200});
var points = bezier.points;
ctx.beginPath();
var i;
for(i=0;i<4;i++){ // if change to i < 1 , works smoothly
var offsetBeziers = bezier.offset(i * 10);
offsetBeziers.forEach(function(bz){
points = bz.points;
ctx.moveTo(points[0].x, points[0].y);
ctx.bezierCurveTo(points[1].x,points[1].y, points[2].x, points[2].y, points[3].x, points[3].y);
})
}
ctx.stroke();
}
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Bezierjs Test</title>
</head>
<body>
<h1>Bezierjs Test</h1>
<canvas onmousemove="draw(event)" id="myCanvas" width="640" height="480" style="border:1px solid #000000;"></canvas>
<script src="./bezier.js"></script>
<script src="./index.js"></script>
</body>
</html>
Perhaps https://stackoverflow.com/a/18017438 is useful to you?
Perhaps https://stackoverflow.com/a/18017438 is useful to you? Hi Pomax thanks for the link, actually I had the same idea in the pinned answer of this link early, I guess maybe it will perform the same - aka slow , anyway I will give it try Besides, I found a small logical mistake ? in your bezierjs - utils.js - compute function At line 164 dCpts[i].z is always "undefined" ,since dCpts[i] = {x:..,y:...}
// higher order curves: use de Casteljau's computation
var dCpts = JSON.parse(JSON.stringify(points));
while (dCpts.length > 1) {
for (var i = 0; i < dCpts.length - 1; i++) {
dCpts[i] = {
x: dCpts[i].x + (dCpts[i + 1].x - dCpts[i].x) * t,
y: dCpts[i].y + (dCpts[i + 1].y - dCpts[i].y) * t
};
if (typeof dCpts[i].z !== "undefined") {
dCpts[i] = dCpts[i].z + (dCpts[i + 1].z - dCpts[i].z) * t;
}
}
dCpts.splice(dCpts.length - 1, 1);
}
Perhaps https://stackoverflow.com/a/18017438 is useful to you?
Just tested this idea , it's fast , fairly fast even with 100 curves , but unfortunately ,it's not "safe" ,it can get a convolution
BUT fortunately , it works fine if the distance is small ,for my use the distance is small ,and the angle always less than 90
Thanks agian, very appreciated your help
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
function draw(event){
var p = getMousePos(c, event);
ctx.clearRect(0,0,c.width, c.height);
var bezier = new Bezier({x:c.width/2,y:400},{x:50,y:50},{x:200,y:50},{x:p.x,y:p.y});
ctx.beginPath();
var pt, nv, d=50;
var pts_nvs = [],i,j;
for(var t=0; t<=1; t+=0.01) {
var pt = bezier.get(t);
var nv = bezier.normal(t);
pts_nvs.push({pt:pt,nv:nv,t:t});
}
for(i=-3;i<3;i++){
for(j=0;j<pts_nvs.length;j++){
var m = 1 - pts_nvs[j].t
if(j==0){
ctx.moveTo(bezier.points[0].x + pts_nvs[j].nv.x * d * i * m,bezier.points[0].y + pts_nvs[j].nv.y * d * i * m);
}
else{
ctx.lineTo(pts_nvs[j].pt.x + pts_nvs[j].nv.x * d * i * m,pts_nvs[j].pt.y + pts_nvs[j].nv.y * d * i * m);
}
}
}
ctx.stroke();
}
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
Besides, I found a small logical mistake ? in your bezierjs - utils.js - compute function
please file that over on https://github.com/pomax/bezierjs because I'm guaranteed going to forget about it otherwise ^^;
otherwise
^Done,just created an issue https://github.com/Pomax/bezierjs/issues/134
Thank you for writing this awesome library , but I don't know Dart , any chance to convert this library to apple Swift ? I want to realize such line effect : (Draw with Adobe Flash CC Pen Tool , single line but with tapered width effect) At first, I tried to use 2 Cubic Bezier Curves, but seems it's not so simple (I have no idea how to adjust that 4 control points, and even I don't know that if this is possible) so now I'm trying to use single curves , and split it to segments (same length) ,and draw those segments with different width from big to small (maybe bad performance ? since the line(s) will be animated , any suggest ? )