html 5 canvas shadow just one border - html

i am trying to apply a blur shadow to a circle, but the thing is i just want the outer edge to have this blur/shadow affect, how can i do that? currently, the shadow is applied to all the borders
oh by the way, i am trying to animate...so the endingAngle below is supposed to keep changing to go from 0% circle to full circle..anyway that question is how i can specify just one side of the circle to have blur applied to...thanks
context.shadowBlur = 20;
context.shadowColor = "rgb(0, 255 , 0)";
context.beginPath();
context.arc(295, 295, 175, 1.5 * Math.PI, endingAngle, false);
context.lineWidth = 20;
context.strokeStyle = 'red';
context.stroke();
context.restore();

This isn't usually something you'd use a shadow for. You're better off with a radial gradient.
For example:
http://jsfiddle.net/NEntS/
The code:
var rg = context.createRadialGradient(295, 295, 175, 295, 295, 175+20);
rg.addColorStop(0, 'rgba(0,255,0,1)');
rg.addColorStop(0.8, 'rgba(0,255,0,.2)');
rg.addColorStop(1, 'rgba(255,255,255,0)');
// draw gradient behind
context.strokeStyle = rg;
context.beginPath();
context.arc(295, 295, 185, 1.5 * Math.PI, 2, false);
context.lineWidth = 25;
context.stroke();
context.restore();
// now stroke the red
context.beginPath();
context.arc(295, 295, 175, 1.5 * Math.PI, 2, false);
context.lineWidth = 20;
context.strokeStyle = 'red';
context.stroke();
context.restore();​
I'm drawing an arc with a larger radius and line width that has a green-to-transparent gradient (from center to outer). That gives the same effect you want but only on the outside.

Have you tried
ctx.shadowOffsetX
ctx.shadowOffsetY
to position your shadow?
Reference MDN

Related

In Chrome, Canvas Arcs are distorted when scaled up

The canvas context.arc() method draws distorted arcs when the context is scaled up. It looks like the arcs are (poorly) approximated with a Bézier curve. Works correctly in Firefox. Untested in IE.
I observed this problem some time ago, but recently it seems to have become much worse (I'm not sure when).
I found a number of canvas issues on StackOverflow, but not this one. If you know it to be a manifestation of an already-reported issue, please forward a link. I've already reported it via Chrome's Help/Report Issue mechanism.
Before I write my own, does anyone have a workaround? ...perhaps an overloaded or alternative 'arc' method?
The following demo is viewable here: http://keveney.com/chrome_arc_bug.html
paint_canvas();
// simulate circle with line segments
//
function regular_polygon(ctx, segments, cx, cy, r) {
var i, a;
ctx.moveTo(cx + r, cy);
for (i = 0; i < segments; i++) {
a = (Math.PI * 2) * i / segments;
ctx.lineTo(cx + r * Math.cos(a), cy + r * Math.sin(a));
}
ctx.closePath();
ctx.stroke();
}
function paint_canvas() {
var ctx;
// draw unscaled circle using canvas 'arc' method
//
ctx = document.getElementById('canv').getContext('2d');
ctx.beginPath();
ctx.strokeStyle = "#000";
ctx.lineWidth = 1.25;
ctx.arc(250, 250, 200, 0, 2 * Math.PI, false);
ctx.stroke();
// draw enclosing polygons
//
ctx.beginPath();
ctx.strokeStyle = "#c00";
regular_polygon(ctx, 36, 250, 250, 215);
regular_polygon(ctx, 36, 250, 250, 185);
// the same but scaled up from smaller units
//
ctx = document.getElementById('canv2').getContext('2d');
ctx.beginPath();
ctx.strokeStyle = "#000";
ctx.scale(100, 100);
ctx.lineWidth = 1.25 / 100;
ctx.arc(2.5, 2.5, 2, 0, 2 * Math.PI, false);
ctx.stroke();
ctx.beginPath();
ctx.strokeStyle = "#c00";
regular_polygon(ctx, 36, 2.5, 2.5, 2.15);
regular_polygon(ctx, 36, 2.5, 2.5, 1.85);
}
body {
background-color: #F4F4F4;
width: 800px;
margin-left: auto;
margin-right: auto;
}
canvas {
background-color: #FFFFFF;
}
<p>Chrome arc scaling bug</p>
<canvas id="canv" height=500 width=500></canvas>
<canvas id="canv2" height=500 width=500></canvas>
<p>expected: Both images should be identical.</p>
<p>actual: Arc in second image is badly distorted.</p>
<p>Issue reported 6/17/2015.</p>
<p>tested with 43.0.2357.124 (64-bit)</p>
<p>This issue was observed some time ago, but has gotten worse in recent releases of Chrome. Not tested on Internet Explorer. If you find a convenient solution,
please notify Matt Keveney, matt#keveney.com</p>
This effect stems from an approximation of a circle with a small radius, it looks more like a square than a circle.
If you knowingly will make this kind of circles, I'd recommend making a function that draws a circle with a radius which will generate a good approximation of a circle that will scale well (I chose a radius of 10 in my example below), then adjust the parameters to achieve the wanted circle.
function drawSmallArc(x,y,r,scale) {
var adjust = 10/r;
ctx.save();
ctx.beginPath();
ctx.strokeStyle = "#00f";
ctx.scale(scale/adjust, scale/adjust);
ctx.lineWidth = 1.25 / scale * adjust;
ctx.arc(x*adjust, y*adjust,r*adjust,0,2 * Math.PI, false);
ctx.stroke();
ctx.restore();
}
In action below
var c = document.getElementById("canvas");
var ctx = c.getContext("2d");
//Two referense circles.
ctx.beginPath();
ctx.strokeStyle = "#0f0"; //green
ctx.lineWidth = 1.25;
ctx.arc(250, 250, 180, 0, 2 * Math.PI, false);
ctx.stroke();
ctx.beginPath();
ctx.strokeStyle = "#0f0"; //green
ctx.lineWidth = 1.25;
ctx.arc(250, 250, 220, 0, 2 * Math.PI, false);
ctx.stroke();
//Red circle using OP's original circle
ctx.save();
ctx.beginPath();
ctx.strokeStyle = "#f00"; //Red
ctx.lineWidth = 1.25 / 100;
ctx.scale(100,100);
ctx.arc(2.5, 2.5, 2, 0, 2 * Math.PI, false);
ctx.stroke();
ctx.restore();
//blue circle with better approximation of circle.
drawSmallArc(2.5,2.5,2,100);
function drawSmallArc(x,y,r,scale) {
var adjust = 10/r;
ctx.save();
ctx.beginPath();
ctx.strokeStyle = "#00f";
ctx.scale(scale/adjust, scale/adjust);
ctx.lineWidth = 1.25 / scale * adjust;
ctx.arc(x*adjust, y*adjust,r*adjust,0,2 * Math.PI, false);
ctx.stroke();
ctx.restore();
}
<canvas id="canvas" height=500 width=500></canvas>
I have worked around the problem for now, using a high-count polygon. Mine is not a fully-compatible drop-in replacement for arc, so it will not be repeated here. It is much like the function used in the above sample code to render the red reference polygons.
I remain interested in a better solution, or a Chrome update that fixes the problem, in case anyone finds it.

In canvas, how to draw 2 semi-transparent overlapping circles

I want to draw two circles on the gray rectangle in HTML canvas.
I attempted the following steps:
Fill rectangle gray
Change globalComposition lighter to mix two colors.
I want to mix only blue and red, not gray and gray rectangle.
You can easily achieve this property by fill style of the circles in rgba, where the last parameter will be alpha or opacity. The syntax will be something like this
circle.fillStyle = "rgba(255, 255, 255, 0.5)";
//can be used to fill as red object with opacity of 0.5
The complete code to achieve the desired effect will be something like this.
// JavaScript Code
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var centerleftX = canvas.width / 4;
var centerRightX = 3 * canvas.width / 4;
var centerY = canvas.height / 2;
var radius = 70;
context.beginPath();
context.rect(0, 0, 400, 200);
context.fillStyle = 'rgb(200,200,200)';
context.fill();
context.lineWidth = 7;
context.strokeStyle = 'black';
context.stroke();
context.beginPath();
context.arc(centerleftX + 50, centerY, radius, 0, 2 * Math.PI, false);
context.fillStyle = "rgba(0, 0,255,0.7)";
context.fill();
context.beginPath();
context.arc(centerRightX - 50, centerY, radius, 0, 2 * Math.PI, false);
context.fillStyle = "rgba(255, 0,0,0.7)";
context.fill();
<!-- HTML Code -->
<canvas id="myCanvas" width="400" height="200">

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.

Draw HTML5 Canvas with different background color than text?

I am looking to draw a canvas circle with text, however I want the canvas background color to be different from the color of the text in the circle. my code below uses the same color for both background and text ..
<canvas id="circlecanvas" width="50" height="50"></canvas>
<script>
var canvas = document.getElementById("circlecanvas");
var context = canvas.getContext("2d");
var centerX = canvas.width / 2;
var centerY = canvas.height / 2;
context.arc(centerX, centerY, 25, 0, Math.PI * 2, false);
context.fillStyle ="#dbbd7a";
context.fill()
context.font = 'bold 20pt Calibri';
context.textAlign = 'center';
context.fillText('34', centerX, centerY);
</script>
Try this:
context.arc(centerX, centerY, 25, 0, Math.PI * 2, false);
context.fillStyle ="#dbbd7a";
context.fill()
context.font = 'bold 20pt Calibri';
context.textAlign = 'center';
context.fillStyle ="#ff0000"; // <-- Text colour here
context.fillText('34', centerX, centerY);
So, basically, set the context.fillStyle for the text.
as you asked in the comments, the solution for centering the text vertically
is adding this
context.textBaseline = 'middle';
to Cerbrus's answer

filling a canvas shape with text

i am trying to figure out how to add a text to a canvas shape
for example here is my Code:
var text ="5"; // text to display over the circle
context.fillStyle = "red";
context.beginPath();
context.arc(50,70, 10, 0, Math.PI * 2);
context.closePath();
context.fill();
i would very much appriciate it if someone would help me adding the text to the shape
thanks in advance.
EDIT
i figure out that i need to write again on the canvas so this is what i got so far ... but
the text doesnt allign to the center of the circle :
context.fillStyle = "red";
context.beginPath();
var radius = 10; // for example
context.arc(200, 200, radius, 0, Math.PI * 2);
context.closePath();
context.fill();
context.fillStyle = "black"; // font color to write the text with
var font = "bold " + radius +"px serif";
context.font = font;
context.textBaseline = "top";
context.fillText(text, 200-radius/4 ,200-radius/2);
As you can see here:
http://jsfiddle.net/DKcpS/
The text is getting drawn starting in the center of the circle, and starting with the top of the text since you put the textBaseline to top.
This is the same text centered roughly using the width and height of the text:
http://jsfiddle.net/DKcpS/1/
As you can see we have a context.measureText(theTextToMeasure) function that returns a textMetrics object that has a width property. For now it does not have a height one, so we have to sort of guess that.