Weird Streaks in HTML5 Canvas Drawing? - javascript

I'm trying to draw a square of procedurally generated colors using an HTML5 canvas. It should show black at the origin, white at the corner furthest from the origin, and yellow and purple opposite each other in the remaining corners, with various reds in the middle.
Here's a low resolution version I did by hand. In my system, the Y axis is opposite that of canvas's, but that's not important to me, only the generated colors are important. Also in my system, color channels are floats between 0 and 1, not 0 and 255, while the coordinates range from 0 to 1, not 0 to 255.
Here's the code - dividing by 255 is to account for the fact x and y go from 0 to 255 rather than 0 to 1, dividing by 65025 is just 255^2, to account for the fact x and y are both involved, and multiplying by 255 is because the color channels go from 0 to 255, rather than 0 to 1.
<canvas id = "mainCanvas" width="256" height="256"><p>Your browser doesn't support canvas.</p></canvas>
<script>
function drawPix(x, y, r, g, b) {
if (r > 255) {
r = 255;
}
if (g < 0) {
g = 0;
}
if (b < 0) {
b = 0;
}
var c = document.getElementById("mainCanvas").getContext("2d");
c.beginPath();
c.moveTo(x, y);
c.lineTo(x + 1, y + 1);
c.closePath();
var style = "rgb(" + r + ", " + g + ", " + b + ")";
c.strokeStyle = style;
c.stroke();
}
for (var x = 0; x <= 255; x++) {
for (var y = 0; y <= 255; y++) {
drawPix(x, y, x + y, ((2*x/255.0) - (x*y/65025.0) + (y/255.0) - 1) * 255, ((2*y/255.0) - (x*y/65025.0) + (x/255.0) - 1) * 255);
}
}
</script>
I checked this with Chrome, Firefox, and Safari on OS X, plus with Chrome on Windows 7, and all of them output this image with weird streaks of purple on the right side, and the bottom left corner doesn't have a field of purple like it should.
I tried checking the logs, but got lost in a sea of information printing every color at every coordinate, so then I made it only output 1/225th as much as below. The weird streaks of purple towards the right still appear in the canvas produced by the below code, but there's no indication of the blue channel being so hight with such a low y value in the console.
<canvas id = "mainCanvas" width="256" height="256"><p>Your browser doesn't support canvas.</p></canvas>
<script>
function drawPix(x, y, r, g, b) {
if (r > 255) {
r = 255;
}
if (g < 0) {
g = 0;
}
if (b < 0) {
b = 0;
}
if (x % 15 == 0 && y % 15 == 0) {
var c = document.getElementById("mainCanvas").getContext("2d");
c.beginPath();
c.moveTo(x, y);
c.lineTo(x + 15, y + 15);
c.closePath();
var style = "rgb(" + r + ", " + g + ", " + b + ")";
console.log("X: " + x + " Y: " + y + ", " + style);
c.strokeStyle = style;
c.stroke();
}
}
for (var x = 0; x <= 255; x++) {
for (var y = 0; y <= 255; y++) {
drawPix(x, y, x + y, ((2*x/255.0) - (x*y/65025.0) + (y/255.0) - 1) * 255, ((2*y/255.0) - (x*y/65025.0) + (x/255.0) - 1) * 255);
}
}
</script>
Here's a JSFiddle of my code, if that helps you help me:
http://jsfiddle.net/ArtOfWarfare/wjzhnhy8/

rgb() does not seem to accept decimals.
Use this instead:
var style = "rgb(" + r.toFixed(0) + ", " + g.toFixed(0) + ", " + b.toFixed(0) + ")";

Related

Implementing smooth coloring of Mandelbrot set

Recreating the way I color my Mandelbrot set I'm having a hard time implementing it in JavaScript. I currently use the common "escape time" algorithm:
for(px = 0; px < a; px+=scale){
for(py = 0; py < b; py+=scale){
x0 = panX + px/zm;
y0 = panY + py/zm;
var x = 0;
var y = 0;
var i = 0;
var xtemp;
var xSquare = x*x;
var ySquare = y*y;
while (x*x + y*y <= 4 && i < maxI) {
xtemp = x*x - y*y + x0
y = 2*x*y + y0
x = xtemp
i += 1;
}
//coloring
var shade = pallete.colourAt(i);
c.fillStyle = "#"+shade;
c.fillRect(px,py,scale, scale);
}
}
Here's the full code. I want to implement the part above to this pseudo code found at Wikipedia.
For each pixel (Px, Py) on the screen, do: { x0 = scaled x coordinate
of pixel (scaled to lie in the Mandelbrot X scale (-2.5, 1)) y0 =
scaled y coordinate of pixel (scaled to lie in the Mandelbrot Y scale
(-1, 1)) x = 0.0 y = 0.0 iteration = 0 max_iteration = 1000 // Here
N=2^8 is chosen as a reasonable bailout radius. while ( xx + yy <=
(1 << 16) AND iteration < max_iteration ) { xtemp = xx - yy + x0 y =
2*xy + y0 x = xtemp iteration = iteration + 1 } // Used to avoid
floating point issues with points inside the set. if ( iteration <
max_iteration ) { // sqrt of inner term removed using log
simplification rules. log_zn = log( xx + y*y ) / 2 nu = log( log_zn /
log(2) ) / log(2) // Rearranging the potential function. // Dividing
log_zn by log(2) instead of log(N = 1<<8) // because we want the
entire palette to range from the // center to radius 2, NOT our
bailout radius. iteration = iteration + 1 - nu } color1 =
palette[floor(iteration)] color2 = palette[floor(iteration) + 1] //
iteration % 1 = fractional part of iteration. color =
linear_interpolate(color1, color2, iteration % 1) plot(Px, Py, color)
}
To this:
for(px = 0; px < a; px+=scale){
for(py = 0; py < b; py+=scale){
//zoom factors
x0 = panX + px/zm;
y0 = panY + py/zm;
var x = 0;
var y = 0;
var i = 0;
var xtemp;
var xSquare = x*x;
var ySquare = y*y;
while (x*x + y*y <= 4 && i < maxI) {
/*ticks++
xtemp = x*x - y*y + x0
y = 2*x*y + y0
x = xtemp
i = i + 1*/
y = x*y;
y += y;
y += y0;
x = xSquare - ySquare + x0;
xSquare = Math.pow(x,2);
ySquare = Math.pow(y,2);
i += 1;
}
if ( i < maxI ) {
log_zn = Math.log( x*x + y*y ) / 2
nu = Math.log( log_zn / Math.log(2) ) / Math.log(2)
i += 1 - nu
}
color1 = palette.colourAt(Math.floor(i))
color2 = palette.colourAt(Math.floor(i) + 1)
/*****************
I dont know how to implement this.....
color = linear_interpolate(color1, color2, iteration % 1)
*****************/
c.fillStyle = color
c.fillRect(px,py,scale, scale);
}
}
But I don't know how to implement this part of pseudo-code:
color1 = palette[floor(iteration)]
color2 = palette[floor(iteration) + 1]
// iteration % 1 = fractional part of iteration.
color = linear_interpolate(color1, color2, iteration % 1)
plot(Px, Py, color)
Can someone help me understand and give a way to implement this?
The linear_interpolate function is supposed to calculate a color between two colors, based on the linear function y = mx + b.
To apply the linear function to colors, y is the output color, m is the difference between the two colors, b is the start color and x is a value between 0 and 1.
When x is 0, this function outputs the start color. When x is 1, this function outputs the end color.
To do this calculation we need the color in the form of three numbers. If you need to use hex strings, you'll have to split them and parse each two characters as a 16 bit number. I'm going to use a palette that is already in number form, because it is easier.
Here's my three color palette. I'm not recommending that you use these colors, it's just for demonstration:
let palette = [{r:255,g:0,b:0},{r:0,g:255,b:0},{r:0,g:0,b:0}]
This first function takes in iteration, which is probably not a whole number and may be larger than 1. It takes the floor of iteration, turning it into a whole number which an array index must be. Then it takes the remainder of iteration divided by 1 to get a number between 0 and 1.
function interpolation(iteration) {
let color1 = palette[Math.floor(iteration)];
let color2 = palette[Math.floor(iteration) + 1];
return linear_interpolate(color1, color2, iteration % 1);
}
Now we need to create the linear interpolation function, which must apply the linear function to each color channel and use floor to turn them into a whole number. I have it returning a css color in rgb(), but you could convert it into hex instead.
function linear_interpolate(color1, color2, ratio) {
let r = Math.floor((color2.r - color1.r) * ratio + color1.r);
let g = Math.floor((color2.g - color1.g) * ratio + color1.g);
let b = Math.floor((color2.b - color1.b) * ratio + color1.b);
return 'rgb(' + r + ',' + g + ',' + b + ')';
}
Here is the code shading rectangles: https://jsfiddle.net/q7kLszud/

How to GET fill color of HTML5 canvas element?

There is grid of 10,000 squares, when the cursor hovers over any one of the squares its colour should change and the color of the squares should revert back to its original color once the mouse cursor is no longer over the aforementioned square.
So to revert those squares back to their original color I need their fill color/style.
Although the canvas has a pattern in practice the colors may be random on the grid.
EDIT: The functionality has still not been achieved using getImageData(),code has been written with the function.
Here is the code:
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
ctx.fillStyle = "#FF0000";
var x = 0,
i = 0;
var y = 0,
j = 0;
slotSize = 10;
for (x = 0, i = 0; i < 100; x += slotSize, i++) {
for (y = 0, j = 0; j < 100; y += slotSize, j++) {
if ((Math.floor(i / 10)) % 2 == 0 && (Math.floor(j / 10)) % 2 == 0) //required for creating the pattern
{
ctx.fillStyle = "red"
} else {
ctx.fillStyle = "yellow";
}
ctx.strokeRect(x, y, slotSize, slotSize);
ctx.fillRect(x, y, slotSize, slotSize);
}
}
function getCursorPosition(canvas, event) {
var rect = canvas.getBoundingClientRect();
var x = event.clientX - rect.left;
var y = event.clientY - rect.top;
return {
x: x,
y: y
}
}
var basex = 20,
basey = 20;
function occupy(style, row, col) {
console.log("occupy called with" + style)
ctx.fillStyle = style;
cx = slotSize * row;
cy = slotSize * col;
ctx.fillRect(cx, cy, slotSize, slotSize);
ctx.strokeRect(cx, cy, slotSize, slotSize);
}
var row = 0,
col = 0;
function highlight(event) //
{
var coords = getCursorPosition(canvas, event);
var x = coords.x;
var y = coords.y;
if (row != Math.floor(x / slotSize) || col != Math.floor(y / slotSize)) {
var color = getColor(row, col); //working errantly
occupy(color, row, col); //<--- problem line used to get the orginal color of boxes back
row = Math.floor(x / slotSize); //to truncate to int since all number are float by default
col = Math.floor(y / slotSize);
document.getElementById("info").innerHTML = x + "," + y + " " + row + "," + col;
occupy("#ffffff", row, col); // highlighting color
}
}
function getColor(row, col) {
var x = slotSize * row;
var y = slotSize * col;
var dat = ctx.getImageData(x, y, 1, 1);
console.log(dat.data[0] + " " + dat.data[1] + " " + dat.data[2]);
var color = "#" + rgbToHex(dat.data[0], dat.data[1], dat.data[2]);
return color;
}
function rgbToHex(r, g, b) {
if (r <= 255 && g <= 255 && b <= 255) {
rh = r.toString(16);
gh = g.toString(16);
bh = b.toString(16);
while (rh.length < 2) {
rh = "0" + rh;
}
while (gh.length < 2) {
gh = "0" + gh;
}
while (bh.length < 2) {
bh = "0" + bh;
}
color = rh + gh + bh;
console.log(color + " " + rh + " " + gh + " " + bh);
return color;
} else
console.log("invalid color values" + r + " " + g + " " + b);
}
function clear(event) {
var coords = relMouseCoords(event);
row = (coords.x / slotSize);
col = (coords.y / slotSize);
occupy("#ffffff", row, col);
}
document.getElementById("b").setAttribute("onClick", "occupy('red',1,2)");
document.getElementById("canvas").setAttribute("onmousemove", "highlight(event)");
document.getElementById("canvas").setAttribute("onmouseout", "clear(event)");
<table>
<tr>
<td>
<canvas id="canvas" width="1000" height="1000" style="border:1px solid #c3c3c3;">
Your browser does not support the canvas element.
</canvas>
</td>
<td>
<button id="b">fill</button>
<p id="info"></p>
</td>
</tr>
</table>
Every time you highlight a square, you first save its original color. Then, when you un-highlight it, simply apply the color back.
And if you don't have a color value store somewhere (for example, if you're randomly building the board on a pixel level), you can always read the hovering pixel color.

Filling in certain pixels on an HTML canvas

First off, sorry about the bad title, I couldn't think of a better way to describe what I was trying to do. I have an HTML canvas, which, for argument's sake, is x pixels wide and y pixels tall. I have been trying to write a code that takes the location in the array of the canvas' image data of two pixels that are on lines z and z + 1 and fill in all the pixels in the higher row between the two pixels a certain color. I'm afraid I may not have made much sense, so here's a diagram:
Sorry about the poor graphics, but assume each rectangle is a pixel. The program should take in the first value for each of the black pixels (each is stored as r,g,b,a, the program gets the location of the r in the array representing the canvas' image data), and stores the r value for the lower pixel as bottomPixel and the higher one as topPixel. In this case, bottomPixel = 124 and topPixel = 112 It should use this to fill all pixels between the two base pixels a certain color. For example, using the previous pixel locations, the red pixels in the following picture should be colored in, but the blue one should not.
Here is the code I have: (Assume that the canvas has an Id "Canvas" and is 6px wide by 10px tall)
var cnvs = document.getElementById("Canvas");
cnvs.height = 10; //This height and width is here as an example.
cnvs.width = 6;
var cont = cnvs.getContext("2d");
var environment = cont.getImageData(0,0,6,10);
var bottomPixel = 124;//Not neccesarily 124 or 112, just example values
var topPixel = 112;
if ( bottomPixel - topPixel > 6*4 ) //If bottomPixel is to the right of topPixel
{
for ( var i = 0 ; i < ((bottomPixel-6*4)-topPixel)/4 ; i++ )
{
var index = topPixel + i * 4;
environment.data[index] = 0;
environment.data[index + 1 ] = 255;
environment.data[index + 2 ] = 0;
environment.data[index + 3 ] = 255;
}
}
if ( bottomPixel - topPixel > 6*4 ) //If bottomPixel is to the left of topPixel
{
for ( var i = 0 ; i < (topPixel-(bottomPixel-6*4))/4; i++ )
{
var index = topPixel - i * 4;
environment.data[index] = 0;
environment.data[index + 1 ] = 255;
environment.data[index + 2 ] = 0;
environment.data[index + 3 ] = 255;
}
}
I'd like to know why my code isn't doing what I previously described. If anything here needs clarification, please leave a comment. Thanks!
This is a method that works on the point coordinates and uses a the setPixel function to modify imageData. I'm using blue for start and black for end. You'll need to adjust for your exact condition but you can use setPixel to allow for direct x and y edits on the imageData.
update
I've included an alternate line method and your line method. There is also an animation that will help you find errors.
function ptIndex(p, w) {
return ((p.x|0) + ((p.y|0) * w)) * 4;
}
function setPixel(p, w, d, rgba) {
var i = ptIndex(p, w);
d[i] = rgba.r;
d[i + 1] = rgba.g;
d[i + 2] = rgba.b;
d[i + 3] = rgba.a;
}
function yourLine(p1, p2, w, d, rgba) {
var cnvs = document.getElementById("Canvas");
var bottomPixel = ptIndex(p1, w);
var topPixel = ptIndex(p2, w)
if (bottomPixel - topPixel > w * 4) //If bottomPixel is to the right of topPixel
{
for (var i = 0; i < ((bottomPixel - w * 4) - topPixel) / 4; i++) {
var index = topPixel + i * 4;
d[index] = rgba.r;
d[index + 1] = rgba.g;
d[index + 2] = rgba.b;
d[index + 3] = rgba.a
}
}
if (bottomPixel - topPixel > w * 4) //If bottomPixel is to the left of topPixel
{
for (var i = 0; i < (topPixel - (bottomPixel - w * 4)) / 4; i++) {
var index = topPixel - i * 4;
d[index] = rgba.r;
d[index + 1] = rgba.g;
d[index + 2] = rgba.b;
d[index + 3] = rgba.a
}
}
}
function drawRandPoints() {
var cnvs = document.getElementById("Canvas");
var cont = cnvs.getContext("2d");
// ghost last draw
cont.fillStyle = "white";
cont.fillRect(0, 0, cnvs.width, cnvs.height);
// get image data
var environment = cont.getImageData(0, 0, cnvs.width, cnvs.height);
var d = environment.data, w = cnvs.width;
// create colors
var black = {
r: 0,
g: 0,
b: 0,
a: 255
};
var red = {
r: 255,
g: 0,
b: 0,
a: 255
};
var blue = {
r: 0,
g: 0,
b: 255,
a: 255
};
var frames = 0;
var p1 = {x: ((cnvs.width / 2|0)), y: 0, sx: 1, sy:0};
var p2 = {x: cnvs.width, y: ((cnvs.height / 2)|0), sx: -1, sy: 0};
function step(p) {
if (p.x > cnvs.width) {
p.x = cnvs.width;
p.sx = 0;
p.sy = 1;
}
if (p.y > cnvs.height) {
p.y = cnvs.height;
p.sy = 0;
p.sx = -1;
}
if (p.x < 0) {
p.x = 0;
p.sx = 0;
p.sy = -1;
}
if (p.y < 0) {
p.y = 0;
p.sy = 0;
p.sx = 1;
}
}
function ani() {
cont.fillStyle = "white";
cont.fillRect(0, 0, cnvs.width, cnvs.height);
environment = cont.getImageData(0, 0, cnvs.width, cnvs.height);
d = environment.data;
step(p1);
step(p2);
var p3 = {
x: cnvs.width - p1.x,
y: cnvs.height - p2.y
};
var p4 = {
x: cnvs.width - p2.x,
y: cnvs.height - p1.y
};
yourLine(p1, p2, w, d, {r:0,g:255,b:0,a:255});
myDrawLine(p1, p2, w, d, red);
drawLineNoAliasing(p3, p4, w, d, blue);
setPixel(p1, w, d, black);
setPixel(p2, w, d, black);
frames %= 12;
p1.x += p1.sx;
p1.y += p1.sy;
p2.x += p2.sx;
p2.y += p2.sy;
// Put the pixel data on the canvas.
cont.putImageData(environment, 0, 0);
requestAnimationFrame(ani);
}
ani();
}
function myDrawLine(p1, p2, w, d, rgba) {
// Get the max length between x or y
var lenX = Math.abs(p1.x - p2.x);
var lenY = Math.abs(p1.y - p2.y);
var len = Math.sqrt(Math.pow(lenX,2) + Math.pow(lenY,2));
// Calculate the step increment between points
var stepX = lenX / len;
var stepY = lenY / len;
// If the first x or y is greater then make step negetive.
if (p2.x < p1.x) stepX *= -1;
if (p2.y < p1.y) stepY *= -1;
// Start at the first point
var x = p1.x;
var y = p1.y;
for (var i = 0; i < len; i++) {
x += stepX;
y += stepY;
// Make a point from new x and y
var p = {
x: x,
y: y
};
// Draw pixel on data
setPixel(p, w, d, rgba);
// reached goal (removes extra pixel)
if (Math.abs(p.x - p2.x) <= 1 && Math.abs(p.y - p2.y) <= 1) {
break;
}
}
// Draw start and end pixels. (might draw over line start and end)
setPixel(p1, w, d, rgba);
setPixel(p2, w, d, rgba);
}
// alternate from http://stackoverflow.com/questions/4261090/html5-canvas-and-anti-aliasing answer
// some helper functions
// finds the distance between points
function DBP(x1, y1, x2, y2) {
return Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
}
// finds the angle of (x,y) on a plane from the origin
function getAngle(x, y) {
return Math.atan(y / (x == 0 ? 0.01 : x)) + (x < 0 ? Math.PI : 0);
}
// the function
function drawLineNoAliasing(p1, p2, w, d, rgba) {
var dist = DBP(p1.x, p1.y, p2.x, p2.y); // length of line
var ang = getAngle(p2.x - p1.x, p2.y - p1.y); // angle of line
var cos = Math.cos(ang);
var sin = Math.sin(ang);
for (var i = 0; i < dist; i++) {
// for each point along the line
var pt = {
x: p1.x + cos * i,
y: p1.y + sin * i
};
setPixel(pt, w, d, rgba);
}
}
// end alt
drawRandPoints();
#Canvas {
border: 1px solid red image-rendering: optimizeSpeed;
/* Older versions of FF */
image-rendering: -moz-crisp-edges;
/* FF 6.0+ */
image-rendering: -webkit-optimize-contrast;
/* Safari */
image-rendering: -o-crisp-edges;
/* OS X & Windows Opera (12.02+) */
image-rendering: pixelated;
/* Awesome future-browsers */
image-rendering: optimize-contrast;
/* CSS3 Proposed */
-ms-interpolation-mode: nearest-neighbor;
/* IE */
}
<canvas id="Canvas" width="128" height="64" style="width:320px"></canvas>

Cylinder partially visible WebGL

I am designing a cylinder in WebGL 1.0 (which is based on OpenGL ES 2.0).
It started off as a n-sided polygon (n slices) with m stacks. Its normals are specified as follows:
Even though the polygon/cylinder is being drawn correctly, its faces aren't visible from every angle. They can only be seen from the inside as the following images show:
My goal is to have a fully visible cylinder like the following one (no top/bottom faces required):
Does anyone have any idea on how to fix this? Code below:
//End if stacks = 0
if (this.stacks <= 0) return;
this.vertices = [];
this.indices = [];
this.normals = [];
//--- Vertices & Normals ---
var angle;
var alpha = 360 / this.slices;
var zCoord = 0;
// (N) stacks -> (N + 1) faces -> (faces * this.slices) vertex
for ( var stackIndex = 0; stackIndex < this.stacks + 1; stackIndex++) {
//Reset angle for each face of the stack
angle = 0;
for ( var sliceIndex = 0; sliceIndex < this.slices; sliceIndex++) {
this.vertices.push(Math.cos(angle * degToRad)); //X
this.vertices.push(Math.sin(angle * degToRad)); //Y
this.vertices.push(zCoord); //Z
this.normals.push(Math.cos(angle * degToRad)); //X
this.normals.push(Math.sin(angle * degToRad)); //Y
this.normals.push(zCoord); //Z
//Updating angle
angle = angle + alpha;
}
//Updating z coordinate
zCoord = zCoord + (1 / this.stacks);
}
//--- Indices ---
var stackInc; stackIndex = 0; sliceIndex = 0;
for (stackIndex = 0; stackIndex < this.stacks; stackIndex++) {
stackInc = stackIndex * this.slices;
for (sliceIndex = 0; sliceIndex < this.slices; sliceIndex++) {
if (sliceIndex != this.slices - 1) {
//T1
this.indices.push(sliceIndex + stackInc);
this.indices.push(sliceIndex + stackInc + this.slices);
this.indices.push(sliceIndex + stackInc + this.slices + 1);
//T2
this.indices.push(sliceIndex + stackInc + this.slices + 1); //this.slices
this.indices.push(sliceIndex + stackInc + 1); //0
this.indices.push(sliceIndex + stackInc); //int4
}
//Handling last face which uses repeated vertices
else {
this.indices.push(sliceIndex + stackInc);
this.indices.push(sliceIndex + stackInc + this.slices);
this.indices.push(stackInc + this.slices);
this.indices.push(stackInc + this.slices);
this.indices.push(stackInc);
this.indices.push(sliceIndex + stackInc); //int4
}
}
}
Regardless of face normals, WebGL defines the front- and back-face based on the order in which you define the triangle.
Having this triangle:
A-------B
\ /
\ /
\ /
C
If you add the vertices to the index in order A, B, C (clock wise), and you don't see them, you need to switch the order in A, C, B (counter clock wise).
This is because of this: https://www.opengl.org/wiki/Face_Culling

how to create bezier curve in JavaScript?

I am trying to create a bezier curve using JavaScript on a HTML5 canvas. Below is the code that I have written us in the drawbeziercurve function. The result is that, I only get the four points, but cant get the bezier curve to appear. Any help guys?
function drawBezierCurve() {
"use strict";
var t, i, x, y, x0, x1, x2, x3;
// for (t = 1; t <= nSteps; t++) {
//t = 1/nSteps
q0 = CalculateBezierPoint(0, x0, x1, x2, x3);
for(i = 0; i <= nSteps; i++)
{
t = i / nSteps;
q1 = CalculateBezierPoint(t, x0, x1, x2, x3);
DrawLine(q0, q1);
q0 = q1;
}
//[x] = (1-t)³x0 + 3(1-t)²tx1+3(1-t)t²x2+t³x3
//[y] = (1-t)³y0 + 3(1-t)²ty1+3(1-t)t²y2+t³y3
procedure draw_bezier(A, v1, v2, D)
B = A + v1
C = D + v2
//loop t from 0 to 1 in steps of .01
for(t=0; t <=1; t+ 0.1){
a = t
b = 1 - t
point = A*b³ + 3*B*b²*a + 3C*b*a2 + D*a³
//drawpixel (point)
drawLine(arrayX[0], arrayY[0], (arrayX[0] + arrayX[1] + arrayX[2] + arrayX[3]) / 4,
(arrayY[0] + arrayY[1] + arrayY[2] + arrayY[3]) / 4, 'blue');
//end of loop
}
end of draw_bezier
/* drawLine(arrayX[0], arrayY[0], (arrayX[0] + arrayX[1] + arrayX[2] + arrayX[3]) / 4,
(arrayY[0] + arrayY[1] + arrayY[2] + arrayY[3]) / 4, 'blue');
drawLine((arrayX[0] + arrayX[1] + arrayX[2] + arrayX[3]) / 4,
(arrayY[0] + arrayY[1] + arrayY[2] + arrayY[3]) / 4, arrayX[3], arrayY[3], 'blue'); */
}
// points array
Do draw a poly-line (a line consisting of many points) on a canvas, do something like this:
var canvas = document.querySelector('canvas'),
ctx = canvas.getContext('2d');
ctx.lineWidth = 1.5;
ctx.strokeStyle = 'red';
ctx.beginPath();
for (var i = 0; i < 100; i++)
{
var x = Math.random() * 100,
y = Math.random() * 100;
ctx.lineTo(x, y);
}
ctx.stroke();
You can use something similar, however instead of choosing random x and y values, use your own logic.
Here's a working example on jsFiddle.

Categories