Fill & Stoke width issue in html 5 canvas - html5-canvas

I want to draw a closed shape(Using paths) & my stroke width is 10.
Now,i want to fill that shape,i can fill it using fill() function of context.
But,when i want to change alpha of my shape,then stroke & fill area overlap at border of shape.
I want only fill the area of shape that remains black after my stroke.
I have attached image of explaining my problem.
Click here to show shape with stork & fill bug.
As you can see in jsfiddle,
-- Color of overlapping area are composite color. That i don't want.
I want it to be exactly same as in border(or stroke color with alpha).
-- i am not enable to specify fill area of closed path.(there is no method of contexx.)
-- I can't use "glabalCompositeOperation",because i am drawing more than 1 shapes in 1 canvas in my application.

The effect you are getting seems to be a property of how canvas draws lines round a shape. Half the thickness of the line is drawn inside the shape and half outside the shape. One way round it is to draw the filled shape and the border as seperate paths. The changes to do this for your example are shown below. This will be more difficult with irregular shapes.
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
var topLeftCornerX = 188;
var topLeftCornerY = 50;
var width = 200;
var height = 100;
var linewidth = 10;
context.globalAlpha = 0.5;
context.beginPath();
context.moveTo(topLeftCornerX, topLeftCornerY);
context.lineTo(topLeftCornerX+width,topLeftCornerY);
context.lineTo(topLeftCornerX+width,topLeftCornerY+height);
context.lineTo(topLeftCornerX,topLeftCornerY+height);
context.closePath();
context.fillStyle = "#FF0000";
context.fill();
context.beginPath();
context.moveTo(topLeftCornerX-linewidth/2, topLeftCornerY-linewidth/2);
context.lineTo(topLeftCornerX+width+linewidth/2,topLeftCornerY-linewidth/2);
context.lineTo(topLeftCornerX+width+linewidth/2,topLeftCornerY+height+linewidth/2);
context.lineTo(topLeftCornerX-linewidth/2,topLeftCornerY+height+linewidth/2);
context.closePath();
context.lineWidth = linewidth;
context.strokeStyle = "#00FF00";
context.stroke();

Related

can we show geometries that are out of canvas (3D space) in three.js

I am creating one geometry at location (0,0,0) but projecting at some other location (for ex. #50,50,50). If the point (0,0,0) is going out of canvas, then geometry is hiding.
Is there any way to always render it on canvas?
How far off the edge does the origin need to be?
You could make the canvas larger than you need, than mask the areas on the edge such that only the center area shows. That way when the origin goes off the side, it will still technically be on the canvas, and the projected geometry will be in the visible area. I expect you will only need a buffer space equal to projection offset.
See here for an example of applying a mask: https://jsfiddle.net/shawnoakley/n1368qr0/2/
Example code:
var context = document.getElementById('canvas').getContext('2d');
// Mask color
context.fillStyle = '#000';
// Image proportions
context.fillRect(0,0,600,400);
var unmaskedImage = function(x, y, radius){
context.save();
context.globalCompositeOperation = 'destination-out';
context.beginPath();
context.arc(x, y, radius, 0, 2 * Math.PI, false);
context.fill();
context.restore();
};
unmaskedImage(300, 300, 300);

How to convert world rotation to screen rotation?

I need to convert the position and rotation on a 3d object to screen position and rotation. I can convert the position easily but not the rotation. I've attempted to convert the rotation of the camera but it does not match up.
Attached is an example plunkr & conversion code.
The white facebook button should line up with the red plane.
https://plnkr.co/edit/0MOKrc1lc2Bqw1MMZnZV?p=preview
function toScreenPosition(position, camera, width, height) {
var p = new THREE.Vector3(position.x, position.y, position.z);
var vector = p.project(camera);
vector.x = (vector.x + 1) / 2 * width;
vector.y = -(vector.y - 1) / 2 * height;
return vector;
}
function updateScreenElements() {
var btn = document.querySelector('#btn-share')
var pos = plane.getWorldPosition();
var vec = toScreenPosition(pos, camera, canvas.width, canvas.height);
var translate = "translate3d("+vec.x+"px,"+vec.y+"px,"+vec.z+"px)";
var euler = camera.getWorldRotation();
var rotate = "rotateX("+euler.x+"rad)"+
" rotateY("+(euler.y)+"rad)"+
" rotateY("+(euler.z)+"rad)";
btn.style.transform= translate+ " "+rotate;
}
... And a screenshot of the issue.
I would highly recommend not trying to match this to the camera space, but instead to apply the image as a texture map to the red plane, and then use a raycast to see whether a click goes over the plane. You'll save yourself headache in translating and rotating and then hiding the symbol when it's behind the cube, etc
check out the THREEjs examples to see how to use the Raycaster. It's a lot more flexible and easier than trying to do rotations and matching. Then whatever the 'btn' onclick function is, you just call when you detect a raycast collision with the plane

Stroke Effect on Arabic Text At Junctions

Briefly, I am having a problem performing a simple stroke operation on arabic text in an html5 2D canvas.
Arabic text has this property of characters changing forms and merging together when they're next to each other. Apparently, how js handles text stroke is by taking every character by itself and operating on them separately. When the characters are then rendered to the screen, the boundaries of characters becomes visible resulting in leaking stroke colors at the joints.
On the left is the result produced by Javascript's stroke function. On the right is a correct result created with Photoshop (different font).
Is there a way around this?
Your problem is probably that you draw the stroked version on top of the filled one.
Do the inverse and everything will look as you wanted :
var ctx = c.getContext('2d');
ctx.font = "200px Al Tharikh, Arial"
var txt = 'مثال';
ctx.textBaseline = 'top';
// change the stroke style
ctx.strokeStyle = 'red';
ctx.lineWidth = 5;
// first draw the stroke
ctx.strokeText(txt , 100, 0);
// then draw the fill
ctx.fillText(txt , 100, 0);
<canvas id="c" height="200" width="500"></canvas>
Ps : if you want to get only the external stroke, then you can use globalCompositeOperations :
var ctx = c.getContext('2d');
ctx.font = "200px Al Tharikh, Arial"
var txt = 'مثال';
ctx.textBaseline = 'top';
// change the stroke style
ctx.strokeStyle = 'red';
ctx.lineWidth = 5;
// first draw a larger stroke
ctx.strokeText(txt , 100, 0);
// then set the gCO
ctx.globalCompositeOperation = 'destination-out';
// then draw the filled version which will act as an "eraser"
ctx.fillText(txt , 100, 0);
// reset the gCO
ctx.globalCompositeOperation = 'source-over';
canvas{background: ivory;}
<canvas id="c" height="200" width="500"></canvas>

Canvas context's stroke() makes transparent border, instead of fully opaque?

I had a quick question regarding the ctx function stroke along with the usage of rect. In my code, I draw a rect and fill it with red. I want to also add a green border around the rect, but when I use stroke it seems to create a transparent border, rather than a fully solid line. Why does it do this by default?
Img of result:
My code:
var ctx = Canvas.ctx;
ctx.beginPath();
ctx.rect(this.x, this.y, this.width, this.height);
/*
* CONTAINER
*/
ctx.fillStyle = this.primaryColor;
ctx.fill();
/*
* CONTAINER BAR
*/
if(this.borderColor){
ctx.strokeStyle = this.borderColor;
ctx.stroke();
}
/*
* INNER BAR
*/
var per = this.percent;
if(per > 0){
//the width of the actual loading bar that appears
//inside the entire box
var innerWidth = Math.floor(this.width*(per/100));
ctx.fillStyle = this.secondaryColor;
ctx.fillRect(this.x+1, this.y+1, innerWidth-2, this.height-2);
}
/*
* TEXT
*/
if(this.text){
ctx.textAlign = this.textAlign;
ctx.font = this.font;
ctx.fillStyle = this.textColor;
ctx.fillText(this.text, this.textX, this.textY);
}
Canvas draws its lines straddling your pixel coordinate. So a lineWidth=1 vertical line at x=20 will be drawn from 19.5 to 20.5.
To help clarify your rectangle follow these 2 hints:
Assign the rect's x,y,width,height as integers
Set translate(0.50,0.50) before drawing the rect(s) and unset translate(-0.50,-0.50) afterwards
You can read more about the "why?" here:
http://diveintohtml5.info/canvas.html
Note that these hints help with vertical & horizontal lines, but don't help angled lines & curves.

How do I get rid of default opacity in HTML5 canvas?

I am trying to draw 2 black lines in HTML5 canvas:
JSFiddle: http://jsfiddle.net/KFNt5/
Javascript:
var canvas = document.createElement('canvas');
canvas.height = 150;
canvas.width = 150;
var canvasContext = canvas.getContext('2d');
canvasContext.beginPath();
// Draw the red line.
canvasContext.strokeStyle = '#000';
canvasContext.moveTo(10, 0);
canvasContext.lineTo(10, 100);
canvasContext.stroke();
// Draw the green line.
canvasContext.moveTo(50, 0);
canvasContext.lineTo(50, 100);
canvasContext.stroke();
document.body.appendChild(canvas);​
However, the line to the right is gray, implying that it is semitransparent. How do I ensure that the default opacity is 100 (not transparent at all)?
The second line is lighter due to anti-aliasing. You can include the following line to ensure that you render each line once and avoid the anti-aliasing effect.
canvasContext.translate(0.5, 0.5);
http://jsfiddle.net/bagWQ/
Your first line is darker because you drew it twice, once for each call to stroke(). The second call to stroke() draws both lines because you didn't start a new path.

Resources