Paper.js Subraster Added Behind Rectangle Instead of in Front - javascript

In this Paper.js Sketch, selecting an area of the Mona Lisa raster makes a whiteout Rectangle of the area in place, as well as a generating a subraster of the area. The whiteout rectangle is added first, and the subraster second. However, as you witness in the sketch, the whiteout rectangle remains on top. Test this by commenting out the whiteout rectangle chunk and uncommenting the last line to see that the subraster does indeed get generated.
This can be remedied in this scenario with a call to bringToFront(), but that still doesn't explain why the subraster ends up behind the white rectangle, despite the fact that it was added last. What is the cause of this behavior? What is the logic going on here? Thanks in advance.

If you look at the getSubRaster() function, you can see that it inserts the returned raster directly above the raster object it was created from.
function() {
var rect = Rectangle.read(arguments),
raster = new Raster(Item.NO_INSERT);
raster.setImage(this.getSubCanvas(rect));
raster.translate(rect.getCenter().subtract(this.getSize().divide(2)));
raster._matrix.preConcatenate(this._matrix);
raster.insertAbove(this);
return raster;
}

Related

Why is this.stop() changing the z-index I set with setChildIndex() in Adobe Animate?

I've been having difficulty getting the expected results with setChildIndex().
In this example I have 2 MovieClip instances named redDot and yellowDot, and a black square Shape. I would expect it to place yellowDot on bottom, then square, then redDot.
//make black rectangle shape
var square = new createjs.Shape(new createjs.Graphics().f("#000000").dr(100,100,100,100));
this.addChild(square);
this.setChildIndex(this.yellowDot, 0); //set z-index towards background
this.setChildIndex(square,1);
this.setChildIndex(this.redDot, 2);//towards foreground
Instead I get redDot, yellowDot, then square. Adding this.stop() to the end seems to change it back to the expected order. It's not clear to me what is causing this discrepancy. Looping is disabled in the publish settings. Am I misunderstanding how this function and the Animate timeline work?
I wonder if the stage is not being updated? What happens if you use stage.update() at the end of your code. (or however you update the stage in an animate script).
I believe calling this.stop() is re-rendering the initial state of the clip, which uses the original z-index definition. Probably makes sense to call it before you change the contents programmatically.

HTML5 Canvas Context.drawImage not showing up

I am trying to make a drawing program with HTML canvas. You can see a version of it here: https://naclcaleb.github.io/Draw
My architecture works somewhat like this:
I have a master Canvas object, which contains a list of layers that it draws.
Each layer has a list of "Strokes". Each stroke contains a list of actions required to draw it.
I've had a few problems with lag. First, it was taking too long to draw all the strokes in the list.
I solved this by "rendering" the layer every time a stroke is added, so it's just an image.
That worked fine, except that I still had to draw every stroke when the user pressed Ctrl+Z, so I could reset the render.
So every time they tried to undo, it would take a while to compute - usable, but not ideal.
To fix this, I tried the same approach with each stroke - when it's done being created, "render" it by drawing it on a different hidden canvas, then turning it into an image with a DataURL.
(NOTE: I did try using getImageData and putImageData instead, but then it would replace the previous strokes with empty pixels)
And now I'm getting a pretty big problem:
Whenever I make a stroke, it immediately disappears. But once I press Ctrl+Z, all the previous strokes suddenly become visible.
I've been trying to figure this out for a while now.
Here's basically what happens:
The mouse is released, which triggers this event listener (found in the layer class):
this.el.addEventListener("mouseup", function(e){
//You can ignore this line...
if (active){
//...and this if statement. It just handles the erasers, and has been tested to work
if (that.erasing){
CURRENT_TOOL.currentStroke.actions.push({
func: ctx.setGlobalCompositeOperation,
params: ["source-over"]
});
}
//Have the current stroke create its render - I have used console.log to ensure that this does get run, and that the dataURL produced shows the correct image.
CURRENT_TOOL.currentStroke.createRender();
//The endStroke method returns the currentStroke, which I grab here
var newStroke = CURRENT_TOOL.endStroke(ctx);
//"that" is just a reference to the layer instance
//Add it to the strokes list
that.strokes.push(newStroke);
//Update the render
that.updateRender();
}
});
As you saw in the event listener, it calls an updateRender method. Here is that method (also in the layer class):
//Clear the canvas
this.ctx.clearRect(0, 0, this.el.width, this.el.height);
//Put the LAYER's render onto the screen
this.ctx.putImageData(this.render, 0, 0);
//Draw the stroke - I'll give you the draw function, but I've confirmed it does get run
this.strokes[this.strokes.length-1].draw();
//Now get the image data and update the render
this.render = this.ctx.getImageData(0,0, this.el.width, this.el.height);
As you saw in that function, it calls the stroke's draw function (found in the stroke class):
draw(){
//Ignore this if
if (this.render === undefined){
for (var i = 0;i<this.actions.length;i++){
this.actions[i].func.apply(this.ctx, this.actions[i].params);
}
}
else {
//I've used console.log to confirm that this runs.
//Draw the render
this.ctx.drawImage(this.render, 0, 0);
//I've also console.logged the dataurl of the layer before and after drawing the image, and neither have the render drawn on them.
}
}
This seems to say that the this.ctx.drawImage is not being run? Or that it's being run in the wrong way?
Anyways, that's that, and though I apologize for the longevity of this question, I'm hoping someone can help me. This is really my last resort.
One more thing: I got it to work in the link I gave earlier by rendering the layer using the same method I render the strokes - using an image with a dataURL instead of getImageData and putImageData. I'm not really sure what to think about that...

Drawn line - picking up random point on it

I am using JavaScript to draw on HTML Canvas.
I have a polygon represented as array of [x,y] coordinates. In my situation (game focused on expanding player's area) I want periodically expand the area represented by the polygon. I have two random possibilities - expand one of existing vertexes, or split one of the line.
My method works kinda good, but I have problem with splitting the lines. I can pick random line (or to be more precise two random neighboring polygons) and I can insert new polygon into my array of polygons. That works fine.
To find where the new polygon shall be, I tried to use midpoint formula. In my code it goes like this:
var x_mid = Math.round((globalMap[v1][0] + globalMap[v2][0]) / 2);
var y_mid = Math.round((globalMap[v1][1] + globalMap[v2][1]) / 2);
But I found it is not always picking up the correct spot on the line. Sometimes it ends up inside my polygon, which is a problem, because for expansion, my script is looking for free (not colored) pixels around and it finds none here.
I blame the round() function, but can't figure out how to make sure, I end up on the line that is actually drawn on canvas?
It doesn't have to be exact middle of the line, if someone knows other technique, it just needs to be somewhere on the edge, so it can expand later without flaws. Thanks a lot!

Masked element in Snap SVG doesn't come into view when translated

I have a group of elements that are masked by a rect in SnapSVG and I want to translate the elements, bringing new ones into view (and hiding ones that are currently in view). The code is really simple - here's a codepen: http://codepen.io/austinclemens/pen/ZbpVmX
As you can see from the pen, box1, which starts outside the mask element (clip) should cross through it when animated, but it never appears. Moreover, box2, which should move out of the clipping area, remains visible.
This example seems to do a similar thing and has no problems: http://svg.dabbles.info/snaptut-masks2
Here's the code from codepen:
var t = Snap('#target')
var clip=t.rect(200,200,200,200).attr({fill:'#fff'})
var box1=t.rect(300,100,50,50).attr({fill:'#000'})
var box2=t.rect(300,300,50,50).attr({fill:'#000'})
var boxgroup=t.group(box1,box2)
boxgroup.attr({mask:clip})
boxgroup.animate({transform:'t100,300'},2000)
I notice that the svg.dabbles examples translates the clip region by 0,0 at one point, but adding something like that doesn't seem to get me anywhere.
Ok, I figured this out thanks in part to this really great article about SVG transforms: http://sarasoueidan.com/blog/svg-transformations/
The upshot is that when I translate the box group, it takes the mask with it. This is a little confusing to me still - I guess the mask attribute is causing this somehow? Anyways, the solution is to apply an opposite translation to the mask to keep it in place. Check the pen to see it in action but basically I just had to add:
clip.animate({transform:'t-100,-300'},2000)
The tricky part of this is that you now need to synchronize the movement of the mask and the movement of the box group.
edit - I now demonstrate how synchronization can be achieved using snap's set.animate method on the codepen.

Javascript & Canvas: Draw and delete lines to create a "breathing" circle

I would like to create an element, that shows a red circle. Once the user clicks on it, she can record her voice. In order to show the LIVE mode, I'd like to make the circle "breath" according to the incoming frequencies.
I'm experimenting with a <canvas> element. That means it creates a circle that gets bigger and smaller, depending on the variable arcrad. However, the lines are being drawn correctly, but they do not disappear afterwards. I tried to apply .clip() but can't get it to work...
if (arcrad <= 10) arcrad = 10;
analyserContext.beginPath();
analyserContext.arc(100,120,arcrad,0,2*Math.PI);
analyserContext.closePath();
analyserContext.lineWidth = 2;
analyserContext.strokeStyle = 'red';
analyserContext.stroke();
Any ideas - or completely different strategies for this use case?
Canvas will overdraw by default. For your animation you’ll need to clean the canvas at the start of each frame. Use something the following at the start of your drawing function:
analyserContext.clearRect(0,0,200,200);
assuming your canvas is 200 pixels wide and high. It’s worth pointing out that sometimes you don’t want to completely clear the animation field every frame. For example, if you were to draw a semi transparent rectangle over the frame at the beginning (instead of clearing it) then you’d end up with a basic ‘bullet time’ style effect.
It's a normal behavior. Once something it's drawn on the canvas, it's there forever. You have to think like if you were painting something: what has been done cannot be undone.
Luckily, you still have solutions:
1) redraw another circle on top of the first one with the background color. It's really not the recommend way, but it still can be useful
2) use clearRect method (see How to clear the canvas for redrawing)
There are numerous ways to clear a canvas pre drawing to create animation:
How to clear the canvas for redrawing
simplest in my mind:
canvas.width=canvas.width;
though can equally use clearRect (which is actually quicker and won't reset the entire canvas if that is an issue regarding transforms etc!) over the region or whole canvas.
Get the likes of:
http://jsfiddle.net/dw17jxee/

Categories

Resources