multicolors in canvas LineTo - html

function TrackGraphic(model, canvas) {
//TrackModel
this._model = model;
this.draw = function(context) {
var dx = Math.cos(this._model.startAngle + Math.PI / 2);
var dy = Math.sin(this._model.startAngle + Math.PI / 2);
context.beginPath();
context.lineWidth = 10;
context.moveTo(this._model.offsetX, this._model.offsetY);
//CurvePoint
var p;
for (var d = 0; d < this._model.length; d += 1) {
if (d > 1000) {
console.log('2F2F2F');
context.strokeStyle = "#2F2F2F" //"rgb(255,165,0)"; //0x2F2F2F
} else {
context.strokeStyle = "#FFF" //"rgb(255,165,0)"; //0x2F2F2F;
console.log('FFFFFF');
}
p = this._model.getTrackPoint(d);
context.lineTo(this._model.offsetX + p.x, this._model.offsetY + p.y)
}
context.stroke();
}
}​
The above code produces the lines in the canvas. The line is one color, I want to at the beginning or in any municipal color was different. My code does not work: (why?. How to fix it?

Changing the color while you are constructing the path doesn't do anything. The color is applied only once, when stroke() is called, so the last strokeStyle you set will be the color of the entire line.
beginPath(), moveTo(), lineTo(), etc only create a path and that path itself has no color. Stroking or filling that path only ever apply a single color.
If you want a path that is multiple colors you will have to do one of two things:
Begin a path, do some number of lines, stroke it one color, and then begin another path that will be stroked with a different color. In other words:
// make a red line segment
ctx.beginPath();
ctx.moveTo(x, y);
ctx.lineTo(x, y);
ctx.strokeStyle = 'red';
ctx.stroke();
// Begin a new path and make this line segment green
ctx.beginPath();
ctx.moveTo(x, y);
ctx.lineTo(x, y);
ctx.strokeStyle = 'green';
ctx.stroke();
//etc
Or, depending on what you're doing you could also use a linearGradient

Related

HTML5 canvas how to split circle to X parts

I need split circle to X parts without white center
I have already this code: http://jsfiddle.net/U2tPJ/78/
I get this result:
I need finish result like this (without white center):
Since what you want is to fill a part of the circle, use fill(), not stroke().
• The shape you want to draw (a pie) starts in the circle center :
ctx.moveTo(x,y);
Then follow the arc :
context.arc(x, y, radius, i*pieAngle, (i+1)*pieAngle, false);
Then fill().
• Notice that the segmentDepth you were using was in fact an angle in degree. To clarify i used :
// size of a pie : it is an angle in radians
var pieAngle = 2 * Math.PI / hours;
• Lastly i used hsl colors to easily get a bunch of colors different for each hour :
var hueValue = i * 15;
context.fillStyle = 'hsl(' + hueValue + ',70%, 60%)';
result look this way :
draw code
function drawSegments(radius) {
for (var i = 0; i < hours; i++) {
context.beginPath();
context.moveTo(x, y);
context.arc(x, y, radius, i*pieAngle, (i+1)*pieAngle, false);
context.lineWidth = segmentDepth;
var hueValue = i * 15;
context.fillStyle = 'hsl(' + hueValue + ',70%, 60%)';
// '#'+(Math.random()*0xFFFFFF<<0).toString(16);
context.fill();
context.lineWidth = 2;
context.strokeStyle = '#444';
context.stroke();
}
}
fiddle : http://jsfiddle.net/gamealchemist/U2tPJ/79/
The width of the ring is controlled by the line context.lineWidth = segmentDepth;. It seems like you forgot that the line width goes into both directions. To make the ring go to the center, change it to segmentDepth * 2. However, this will also make the whole graphic twice as big, so you might want to compensate by reducing the segmentDepth.

How can I fill in the outside of a path?

I am able to draw these letters using a path. But what I want to do is use that path and fill in what the red image shows instead of filling in the letters.
Here is the code I am using:
function mattes_draw_letter(x, y, width, height, letter, position)
{
var canvas = document.createElement('canvas');
canvas.style.position = "absolute";
canvas.style.top = y + "px";
canvas.id = "canvas_opening_" + position;
canvas.style.zIndex = 5;
canvas.width = width;
canvas.height = height;
canvas.style.left = x + "px";
var ctx = canvas.getContext("2d");
ctx.lineWidth = 1;
ctx.fillStyle = '#bfbfbf';
ctx.strokeStyle = '#000000';
ctx.beginPath();
ctx.moveTo(letter[0] * width, letter[1] * height);
for (i = 0; i < letter.length; i+=2)
{
if (typeof letter[i+3] !== 'undefined')
{
ctx.lineTo(letter[i+2] * width, letter[i+3] * height);
}
}
ctx.fill();
ctx.stroke();
ctx.closePath();
$("#mattes").append(canvas);
canvas.addEventListener("drop", function(event) {drop(event, this);}, false);
canvas.addEventListener("dragover", function(event) {allowDrop(event);}, false);
canvas.addEventListener("click", function() {photos_add_selected_fid(this);}, false);
}
This is what I currently have:
This is what I would like:
Just fill the boxes with red color before drawing the letters in gray.
I was able to do this by adding two lines of code in your code.
ctx.fillStyle = "#F00";
ctx.fillRect(0, 0, width, height);
Put these two lines between the lines:
ctx.lineWidth = 1;
and
ctx.fillStyle = '#bfbfbf';
I assume you're starting the existing letters otherwise (as #Chirag64 says), you can just draw the red rectangles first and then draw the letters on top).
You can use canvas compositing to "draw behind" existing content.
A Demo: http://jsfiddle.net/m1erickson/695dY/
In particular the destination-over compositing mode will draw new content behind existing content (new content is only drawn where the existing content is transparent).
context.globalCompositeOperation="destination-over";
Assuming the HOPE characters are drawn over a transparent background you can add red rectangles behind the HOPE characters like this:
// draw red rectangles **behind** the letters using compositing
ctx.fillStyle="red";
ctx.globalCompositeOperation="destination-over";
for(var i=0;i<4;i++){
ctx.fillRect(i*62+16,13,50,88); // your x,y,width,height depend on your artwork
}

HTM5 draw a shape from multiple objects and then fill it and set opacity

For example lets say I am drawing some circle with arrow, transformatting it and rotating (code and jsfiddle below)... In given code, arrow is red... but when I make it gradient, the gradient is being rotaded during creation of whole object... so I need to apply gradient after everything is drawn... how do I do that?
Second thing... when applying global alpha opacity to context before drawing, arrow on circle is darker, because there are 2 layers in same place... how do I apply opacity to whole shape?
JSFiddle here
var x1 = 10;
var y1 = 10;
var x2 = 50;
var y2 = 50;
var dx = x2 - x1;
var dy = y2 - y1;
var radians = Math.atan2(dy, dx);
var length = Math.sqrt(dx * dx + dy * dy);
ctx.save();
ctx.translate(x1, y1);
ctx.rotate(radians);
ctx.beginPath();
ctx.arc(0, 0, 8, 0, Math.PI * 2);
ctx.closePath();
ctx.fillStyle = "red";
ctx.fill();
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(length, 0);
ctx.lineTo(length - 7, -4);
ctx.lineTo(length - 7, 4);
ctx.lineTo(length, 0);
ctx.closePath();
ctx.fillStyle = "red";
ctx.fill();
ctx.strokeStyle = "red";
ctx.stroke();
ctx.restore();
Gradient rotation
When you createLinearGradient you specify the starting and ending xy's
(basically you specify the line along which the gradient will follow).
Therefore, you can adjust the angle of that line such that the gradient fits your design needs even after it's rotated.
Opacity of the combined circle+arrow
As you've discovered, if you overlap drawings then the resulting opacity will be darker on the overlap.
You have 2 solutions to the darkened opacity:
start drawing the arrow at on the circumference of the circle rather than staring the arrow at the circle's center. This way you have small or no overlap.
combine the arc and arrow into 1 single path.

Canvas draws lines too thick

I want to draw lines on my canvas element at every 48px high. Here's my code (a little jquery selector included since I also use jQuery).
var $canvas = $('canvas')
, maxY = $canvas.outerHeight()
, maxX = $canvas.outerWidth()
, X = 0
, Y = 0
, ctx = $canvas.get(0).getContext('2d');
ctx.strokeStyle = "rgb(100,0,0)";
ctx.lineWidth = 1.0;
ctx.lineCap = "round";
while (Y < maxY) {
ctx.beginPath();
ctx.moveTo(X, Y);
ctx.lineTo(maxX, Y);
//ctx.closePath();
ctx.stroke();
Y += 48;
};
Y = 0;
What I experience is that my first line is crisp and 1px high. All my other lines are higher. Here's the result:
(source: ghentgators.be)
Change your initial Y to +0.5 (or -0.5) and you'll get nice lines.

Finding points on curves in HTML 5 2d Canvas context

Given lines drawn by 2d canvas context functions bezierCurveTo, quadraticCurveTo or arcTo, how can I find points along those lines?
My intent is to draw an object at the midpoint of a curve. Using the SVG DOM, I can do this with methods getPointAtLength & getTotalLength, but I can't see an equivalent in HTML canvas.
You find them the hard way :(
There isn't an equivalent in HTML canvas. You have to find the midpoints yourself with plain old math.
I did an example of how to find midpoint of bezier curves for you. See it live at jsFiddle here. A copy of the javascript is pasted below.
Real curve is red, midpoint is the tiny green rectangle. Everything else is just a visual aid.
var ctx = $("#test")[0].getContext("2d")
function mid(a,b) {
return (a+b) / 2;
}
var cp1x = 100;
var cp1y = 150;
var cp2x = 175;
var cp2y = 175;
var x = 200;
var y = 0;
ctx.lineWidth = 4;
ctx.strokeStyle = "red";
ctx.fillStyle = "rgba(0,0,0,0.6)";
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y);
ctx.stroke();
//line goes from start to control point 1
ctx.strokeStyle = "rgba(0,0,200,0.4)";
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(cp1x , cp1y);
ctx.stroke();
//line goes from end to control point 2
ctx.beginPath();
ctx.moveTo(x, y);
ctx.lineTo(cp2x , cp2y);
ctx.stroke();
//line goes from control point to control point
ctx.strokeStyle = "rgba(200,0,200,0.4)";
ctx.beginPath();
ctx.moveTo(cp1x, cp1y);
ctx.lineTo(cp2x , cp2y);
ctx.stroke();
// now find the midpoint of each of those 3 lines
var ax = mid(cp1x,0);
var bx = mid(cp2x,x)
var cx = mid(cp1x,cp2x)
var ay = mid(cp1y,0)
var by = mid(cp2y,y)
var cy = mid(cp1y,cp2y)
// draw midpoints for visual aid
// not gonna look exact 'cause square
// will be drawn from top-right instead of center
ctx.fillRect(ax, ay, 4, 4);
ctx.fillRect(bx, by, 4, 4);
ctx.fillRect(cx, cy, 4, 4);
//now draw lines between those three points. These are green
ctx.strokeStyle = "rgba(0,200,0,0.4)";
ctx.beginPath();
ctx.moveTo(ax, ay);
ctx.lineTo(cx , cy);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(bx, by);
ctx.lineTo(cx , cy);
ctx.stroke();
//now the midpoint of the green lines:
// so g1 and g2 are the green line midpoints
var g1x = mid(ax,cx);
var g2x = mid(bx,cx);
var g1y = mid(ay,cy);
var g2y = mid(by,cy);
//draw them to make sure:
ctx.fillRect(g1x , g1y, 4, 4);
ctx.fillRect(g2x , g2y, 4, 4);
//now one final line, in gray
ctx.strokeStyle = "rgba(20,20,20,0.4)";
ctx.beginPath();
ctx.moveTo(g1x , g1y);
ctx.lineTo(g2x , g2y);
ctx.stroke();
//whew! We made it!
var FinallyTheMidpointx = mid(g1x,g2x);
var FinallyTheMidpointy = mid(g1y,g2y);
//draw something at the midpoint to celebrate
ctx.fillStyle = "rgba(0,255,0,1)";
ctx.fillRect(FinallyTheMidpointx, FinallyTheMidpointy, 4, 4);
​
A Bezier Curve is calculated Mathematically with this formula
Where P0 is the startpoint, P1 and P2 are the control points and P3 is the end point.
To calculate the halfwaypoint you can just use t = 0.5.
Similar for the Quadratic Curve:
Source and further Information
Check out http://pomax.github.io/bezierjs/
There's a bunch of handy functions there, the one you want to use is .get(t) where t=0.5