HTML5 : Uknown error when trying to copy a canvas into another one - html

I can't figure how to make drawImage work... It just does nothing (except that it throws an exception with an undefined description) :
layerCtx.globalAlpha = 0,2; // same thing with this line commented
layerCtx.drawImage(cvs, 0 , 0);
I have 2 canvas, one is a layer and the other is for drawing using the mouse. I want to save what the user has drawn on the first canvas to the layer and apply opacity...
I won't give you all the code but you have to know that the following code works :
layerCtx.putImageData(ctx.getImageData(0, 0, 800, 500), 0, 0);
but I can't use opacity with the previous, so as it is advised in other stackoverflow.com related questions, I'd like to use drawImage with a canvas element.
ctx is the context for my canvas cvs,
layerCtx is the context fort my canvas layer

You're gonna hate this: You wrote 0,2 instead of 0.2. That's why it isn't working.
I know a comma is used as a decimal in a lot of European countries, but 0.2 is what its gotta be for this.
Working example to check your code by:
http://jsfiddle.net/zC4Wh/

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.

Can I insert a smiley animation dependent on value on an HTML page?

Is there a way to insert a smiley animation on an HTML page, which's smile depends on a value? I have some values between -1 and 1 from a Naive Bayes classifier, which correspond to negative and positive sentiment respectively. Is it possible to visualise this sentiment on a smiley face, meaning if the value is close to -1 the face will be sad :( or if it's close to 1 the face will be happy :) ..?
Thank you.
Assuming that you don't want to do any server-side work, the only option I can think of to do this client-side is using the HTML5 canvas. If you don't know what that is, you first need to read a bit about it and how to draw things on it using JavaScript.
First step is to draw the static part of the emoticon (i.e., the borders of the face and the eyes, etc..). You probably place it as in image on the canvas. Example on how to do that:
var ctx = document.getElementById('canvas').getContext('2d');
var img = new Image();
img.src = 'images/face.png';
img.onload = function() {
ctx.drawImage(img, 0, 0); //draws img where its left-upper corner is at 0, 0
};
Then, to draw the smile-curve, you need to use Bezier Curves. You just move the control point depending on your value properly. Here's a tutorial on how to draw Bezier Curves on a canvas: Link
Hope that helped in any manner!

Flash, AS3: Drawn objects are not the same

I'm playing with Open Flash Chart. Take a look at this chart:
http://teethgrinder.co.uk/open-flash-chart-2/line-solid-dot.php
As you can see, the rounded dot points look ugly. Some of them are more rounded, some of them less, they don't look the same, as they should. I don't know AS3 and have no idea what is the case. I checked the source code:
this.graphics.lineStyle( 0, 0, 0 );
this.graphics.beginFill( colour, 1 );
this.graphics.drawCircle( 0, 0, style.get('dot-size') );
this.graphics.endFill();
I tried to change the size or draw rectangles instead, but they still don't look the same. I guess the problem is somewhere else...
EDIT: I also noticed, that other elements also looks a little bit different (and they shouldn't) - for example axis ticks. My guess is that it is the quality problem. But when I right-click on the flash object, there is an option "quality" and the "high" is set (there is also a "medium" and a "low" to choose). Can I increase the quality level somewhere else?
From hollow dots, I came to realize there is something around each dot which separated each dot from the connecting lines & also produced blurry hollow dots.
Setting the attribute "halo_size" to 0 helped in this case.
I noticed the same gap in your sold dots examples as well. Maybe that's the problem.
To set stage quality, simply use:
stage.quality = "low";
stage.quality = "medium";
stage.quality = "high";
You may set it in the main class itself which happens to be the document class for this project.
I noticed that if the chart size is 400 x 400 these inconsistencies cease to exist. So the problem we see is a scaling problem & not at the place we think.
Besides, Setting line style allows a proper border around the circle. This will at least appear better.
this.graphics.lineStyle(1, colour, 1);
this.graphics.beginFill( colour, 1 );
this.graphics.drawCircle( 0, 0, style.get('dot-size') );
this.graphics.endFill();

AS3 change lineStyle of existing line

im drawing a line from 0,0 to 100,100
im using this to modify the linestyle:
draw_line.graphics.lineStyle(1, 0xFF0000);
That line is now of 1 thickness.
Is there anyway i can change the thickness of the line to say 10, but without redrawing the line?
No, it is not possible with the way the flash player works, you must redraw the line. Or use some kind of library that automatically redraws it for you (for example a Line object in the Flex 4 Framework)
try this:
draw_line.scaleX = 10;
Not exactly the same, but could possibly work under certain circumstances.