HTML5 / Canvas "Glass" Circle - html

I need to render a simple chart and I want the points to be glassy looking circles/orbs in the chart area. I can find tons of examples of drawing these with Photoshop, but I don't want to use stock images; I'd prefer to draw them in my HTML5 canvas. I am no artist, though!
There are many HTML5 canvas questions, but I don't see anything that leads me to this solution.
A point in the right direction would be most appreciated.

All you have to do is create one or more radial gradients to fit the properties of the glassy object that you want. It's easy to do!
Just one gradient:
// Create some gradient
var gradient = ctx.createRadialGradient(105, 105, 20, 120, 120, 50);
gradient.addColorStop(0, 'rgba(250,250,255,0)');
gradient.addColorStop(0.75, 'rgba(230,250,255,1.0)');
gradient.addColorStop(1, 'rgba(0,0,255,0)');
// draw the gradient (note that we dont bother drawing a circle, this is more efficient and less work!)
// but make sure it covers the entire gradient
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, 300, 300);​
Can make this:
Live example:
http://jsfiddle.net/GTbjk/
Maybe you want to reign in that fuzzy edge:
gradient.addColorStop(0.8, 'rgba(0,0,255,0)');
gradient.addColorStop(1, 'rgba(0,0,255,0)');
http://jsfiddle.net/GTbjk/1/
I'm not going to make one to your specification, since you didn't provide one and thats not what we're here for anyway. Making these will almost exclusively be the work of well-placed radial gradients, so go experiment!
As j08691 points out this is a really inefficent way of making these unless you want them to be dynamic or scalable, you are better off just making images and use ctx.drawImage

Related

html canvas transform ? is it only: first do the transform, and then you draw into the canvas? Not, stick an image or etc on canvas, and transform it?

My goal is to bring in an image on to part of the canvas, then scale it, move/translate it, and optionally skew it, also rotate and make alpha changes, kind of the primary "2d image manipulations", in an animated form, which is: do little changes over time from the starting state to the target end state.
Well, I figured to be efficient, I should use the canvas/2d context transform, https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/transform -- as it does the first 3: scale, move/translate, and skew, "all in one." I did half that code, and now I'm looking at examples and seeking to debug it. All the examples I see, are do 1) some transform, away from the "unity transform":
{ a:1, b:0, c: 0, d:1, e:0, f:0 }; // this basic transform does nothing
and then 2) draw into that. But that's the opposite order from what I want: which is draw on the canvas (the image), and then do an animation over time using the above primary changes (scale, translate, skew, rotate, and alpha). My question is: does it only "work this way", meaning I must setup the (single) transformation on the page first, and then "draw into that?"
I hope not ... that won't give me what I want, and I have to "ditch it", and go to 5 individual "transformations." Comments?
Yes that only works this way, canvas transforms and compositing mode and filters and lineWidth and fillStyle etc. properties are only applied to the next drawing operations.
The canvas itself only holds pixels information, it has no concept of drawn object. Your js code has to do this part.
So for what you wish, you can simply redraw everything every time:
reset the transform so we can clear ctx.setTransform(1,0,0,1,0,0);
Clear the canvas ctx.clearRect(0,0,ctx.canvas.width,ctx.canvas.height)
Set the transform to your new matrix ctx.translate(x,y); ctx.scale(s)...
Draw your transformed graphics ctx.fill(); ctx.drawImage(...
Wait next frame to do it again requestAnimationFrame(update)

Draw stroke on HTML canvas with different levels of opacity

The problem
I'm trying to create a brush tool with opacity jitter (like in Photoshop). The specific problem is:
Draw a stroke on an HTML canvas with different levels of opacity. Pixels with higher opacity should replace pixels with lower opacity; otherwise, pixels are left unchanged.
Transparency should not be lost in the process. The stroke is drawn on a separate canvas and merged with a background canvas afterwards.
The result should look like this. All code and the corresponding output can be found here (JSFiddle).
Because you can't stroke a single path with different levels of opacity (please correct me if I'm wrong) my code creates a path for each segment with different opacity.
Non-solution 1, Using the 'darken' blend mode
The darken blend mode yields the desired result when using opaque pixels but doesn't seem to work with transparency. Loosing transparency is a dealbreaker.
With opaque pixels:
With transparent pixels:
Non-solution 2, Using the 'destination-out' compositing operator
Before drawing a new stroke segment, subtract its opacity from subjacent pixels by using the 'destination-out' compositing operator. Then add the new stroke segment with 'source-over'. This works almost but it's a little bit off.
Looking for a solution
I want to avoid manipulating each pixel by hand (which I have done in the past). Am I missing something obvious? Is there a simple solution to this problem?
"Links to jsfiddle.net must be accompanied by code."
Because you can't stroke a single path with different levels of opacity (please correct me if I'm wrong)
You're wrong =)
When you use globalCompositeOperation = 'destination-out' (which you are in lineDestinationOut) you need to set the strokeStyle opacity to 1 to remove everything.
However, simply changing that in your fiddle doesn't have the required effect due to the order of your path build. Build the 10% transparent one first, the whole length, then delete and draw the two 40% transparent bits.
Here's a jsfiddle of the code below
var canvas = document.getElementById('canvas');
var cx = canvas.getContext('2d');
cx.lineCap = 'round';
cx.lineJoin = 'round';
cx.lineWidth = 40;
// Create the first line, 10% transparency, the whole length of the shape.
cx.strokeStyle = 'rgba(0,0,255,0.1)';
cx.beginPath();
cx.moveTo(20,20);
cx.lineTo(260,20);
cx.lineTo(220,60);
cx.stroke();
cx.closePath();
// Create the first part of the second line, first by clearing the first
// line, then 40% transparency.
cx.strokeStyle = 'black';
cx.globalCompositeOperation = 'destination-out';
cx.beginPath();
cx.moveTo(20,20);
cx.lineTo(100,20);
cx.stroke();
cx.strokeStyle = 'rgba(0,0,255,0.4)';
cx.globalCompositeOperation = 'source-over';
cx.stroke();
cx.closePath();
// Create the second part of the second line, same as above.
cx.strokeStyle = 'black';
cx.globalCompositeOperation = 'destination-out';
cx.beginPath();
cx.moveTo(180,20);
cx.lineTo(260,20);
cx.stroke();
cx.strokeStyle = 'rgba(0,0,255,0.4)';
cx.globalCompositeOperation = 'source-over';
cx.stroke();
cx.closePath();
Use two layers to draw to:
First calculate the top layer opacity 40% - 10% and set this as alpha on top layer
Set bottom layer to 10%
Set top layer with dashed lines (lineDash) (calculate the dash-pattern size based on size requirements)
Draw lines to both layers and the bottom layer will be a single long line, the top layer will draw a dashed line on top when stroked.
Copy both layers to main canvas when done.
#HenryBlyth's answer is probably the best you're going to get; there's no native API to do what you're being asked to do (which, in my opinion, is kinda weird anyways... opacity isn't really supposed to replace pixels).
To spell out the solution in one paragraph: Split up your "stroke" into individual paths with different opacities. Draw the lowest opacity paths as normal. Then, draw the higher opacities with "desitination-out" to remove the low-opacity paths that overlap. Then, draw the high opacity paths as usual, with "source-over", to create the effect desired.
As suggested in the comments to that answer, #markE's comment about making each path an object that is pre-sorted before drawing is a great suggestion. Since you want to perform manual drawing logic that the native API can't do, turning each path into an object and dealing with them that way will be far easier than manually manipulating each pixel (though that solution would work, it could also drive you mad.)
You mention that each stroke is being done on another canvas, which is great, because you can record the mouseevents that fire as that line is being drawn, create an object to represent that path, and then use that object and others in your "merged" canvas without having to worry about pixel manipulation or anything else. I highly recommend switching to an object-oriented approach like #markE suggested, if possible.

The intersection part of CSS Canvas paths seem to have incorrect color.

I'm trying to draw a path using HTML Canvas. It consists of several Bezier curves linked together. For some reason, I cannot draw the whole path and then stroke. Instead, I need to stroke for each Bezier curve. I'm using a light purple color as the stroke color, but at the intersection of the curves, I seem to get something like white instead of the light purple I expect. Like this (sorry I can't post an image since I'm new on Stack Overflow):
I'm using stroke style with opacity 1, so I believe it's not a transparency issue. So what might be causing this problem?
FYI, I'm drawing each Bezier curve with code like this, where a is the drawing context of the canvas, and this.bloom.c is something like "rgba(xxx,xxx,xxx,1)":
a.strokeStyle = this.bloom.c;
a.beginPath();
a.moveTo(e.x, e.y);
a.bezierCurveTo(c.x, c.y, b.x, b.y, d.x, d.y);
a.stroke();
Thanks very much!
Use the appropriate "blend modes" natively supported by HTML5 Canvas context for Composite Operations. In your case you may use 'source-over'
For example:
var context = document.getElementById('myCanvas').getContext('2d');
context.globalCompositeOperation = 'source-over';
See Compositing and Blending 1.0
source-atop
source-in
source-out
source-over
destination-atop
destination-in
destination-out
destination-over
lighter
xor
copy

Custom Line stroke in HTML5 canvas

When drawing lines with the HTML5 canvas element, is it possible to define the stroke style of the lines? Basically in Photoshop and other similar programs, you can define a stroke style for lines that looks like it is "hand drawn". Is is possible to do anything like that in HTML5 canvas or am I shooting for the moon here?
Thanks
-Jesse
It is possible but not by default. See ShadowCloud's post for what you can do by default (very little).
Depending on what you want, it shouldn't be too hard.
If by "hand drawn" you mean you want jitter, you'd have to break up every drawn line/curve into smaller parts and add some noise to each of the points.
If you want a brush you'd have to break up every drawn line/curve into smaller parts and call drawImage every few pixels to emulate a photoshop brush.
Almost all of them rely on breaking up your lines and curves into smaller bits, so you should figure that out foremost.
If you decide to implement these and are having trouble breaking up bezier curves and want help, let me know and I'll give you my code for that.
There is no standard API in HTML5 Canvas to manage such thing.
You can just set the color or the width of the stroke, for example:
context.strokeStyle = '#f00'; // red color
context.lineWidth = 4; // 4px wide
// Draw some rectangles.
context.fillRect (0, 0, 100, 100);
context.strokeRect(0, 0, 100, 100);
You can try to get more control using a library (Processing.js or Fabric.js)

as3: draw circle with a hole in it using only actionscript

Okay so basically I want to draw a circle in as3 that has a 'hole' in it (like a donut). Something like this, but without the outlines:
http://www.steel.ie/DugganSteel/Pictures/Hollow-circle.gif
This doesn't work:
SPRITE.graphics.beginFill(0xFFFFFF);
SPRITE.graphics.drawCircle(0,0,10);
SPRITE.graphics.endFill();
SPRITE.graphics.drawCircle(0,0,5);
I mean this seems like it'd be simple but I can't find any information on it. I should also mention that I'm trying to only draw 3/4 of the circle, like 3/4 of donut. So I was planning on drawing a transparent circle and square over the original circle, I know this seems kinda of weird since you'd expect something transparent to show whats underneath it.
Its actually really simple. See the following code:
var p:Point = new Point(100, 100);
graphics.beginFill(0xFF0000);
graphics.drawCircle(p.x, p.y, 100);
graphics.drawCircle(p.x, p.y, 50);
Intersections cancel each other out until you call endFill
Goodluck!
You can just make the line thickness the desired donut width and avoid using beginFill
set graphics.lineStyle
To make it only go 3/4 of the way around you could use curveTo to draw the 3 quarters.
The above method by Tyler works, however if an easier way to do it is to simply begin drawing the inner circle first. Basically Flash doesn't actually fill in the color until you call endFill() (again as mentioned by Tyler), so you start drawing on the inner circle, then the outer circle then on endFill() Flash fills in the gap.
SPRITE.graphics.beginFill(0xFFFFFF);
SPRITE.graphics.drawCircle(0,0,5);
SPRITE.graphics.drawCircle(0,0,10);
SPRITE.graphics.endFill();
Hope this clears things up for you.
Introduction to Flash drawing API, will help you understand a bit more :
http://www.senocular.com/flash/tutorials/flash10drawingapi/