Copy user selection from one canvas to another - javascript

I'm trying to implement a simple, select area on canvasA and then copy area to canvasB, I've got the selection part working but the drawing of the copied area doesn't want to work. The idea is that the user will select an area and then that selection will appear on another canvas when they finish the selection, i.e. say mousedown, drag rectangular area, mouseup (copy appears)
I confess I'm not much of a front end developer so fear I'm missing something obvious about how this stuff works as I'm just trying to knock something together to prove a concept and understand the basics at the moment.
JSFiddle is here - http://jsfiddle.net/bw4gw83a/2
HTML
<canvas id="original" width=300 height=300></canvas>
<canvas id="copybit" width=300 height=300></canvas>
Javascript
var original = document.getElementById("original");
var CTXoriginal = original.getContext("2d");
var copybit = document.getElementById("copybit");
var CTXcopybit = copybit.getContext("2d");
var background = new Image();
background.src = "https://i.imgur.com/F1pJYM1.jpg";
background.onload = function(){
CTXoriginal.drawImage(background, 0, 0)
}
var imageData = CTXoriginal.getImageData(10, 10, 100, 100);
CTXcopybit.putImageData(imageData,0,0);
Any pointers appreciated.
Si

The following guide might be helpful.
http://www.i-programmer.info/programming/graphics-and-imaging/2078-canvas-bitmap-operations-bitblt-in-javascript.html
It mentions you can draw a section of the image using
drawImage(image,sx,sy,sw,sh,dx,dy,dw,dh)
Where s is source, and d is destination.
From there you just have to determine the position of the click and drag to work out the co-ordinates and width/heights.
I've updated your fiddle just to demonstrate. It's very crude, so just click once somewhere in the top left of the image, then click again somewhere in the bottom right.
http://jsfiddle.net/treerock/1zpc8fz0/

Related

createjs removed all existing info on canvas?

I am trying to verify that this happens no matter what, and there's no way to bypass it. It seems pretty silly to me that createjs uses this architecture. But I noticed that creating a stage from an existing canvas element removes all shapes, writings, etc from the canvas? Code is below:
html:
<canvas id="canvas" width="800" height="400"></canvas>
js:
var canv = document.getElementById("canvas");
var stage = new createjs.Stage(canv);
var ctx = canv.getContext('2d');
ctx.beginPath();
ctx.arc(50,50,10,0,2*Math.PI);
ctx.stroke();
createjs.Ticker.addEventListener("tick", tick);//circle created is overwritten here!!!?! Why createjs!?
//stage.update();
createjs.MotionGuidePlugin.install();
var shape1 = new createjs.Shape();
shape1.graphics.f("#000000").dc(0,0,10);
var path1 = new createjs.Shape();
path1.graphics.beginStroke("#ff0000").mt(0,0).qt(50,100,100,0);
stage.addChild(path1, shape1);
createjs.Tween.get(shape1).to({guide:{ path:[0,0, 50,100, 100,0] }},2000, createjs.Ease.cubicInOut);
function tick(event) {
stage.update();
}
Is this something that cannot be bypassed? It seems silly to me that createjs wouldn't just actually use the existing element unerased. If not, what is the point in passing in an element in the first place, why doesn't it just create a canvas element, and give you the ID? Anyways, if this is how it's going to be, unfortunately, I am going to have to go somewhere else. Sad, because createjs seemed pretty useful.
CreateJS uses a retained graphics mode, that is, it stores the state and redraws it each time. This is because the canvas is basically a big Bitmap with drawing commands – clearing the stage is the only way to remove the previous state.
But good news! There are lots of ways to get around these limitations if you want to blend CreateJS content with other content, or even make additive drawing effects.
The first is easy, which is setting autoClear. This will prevent the clear, and just draw the new contents over the old one.
stage.autoClear = false;
The second is a bit tougher, but great for instances where you want to mix CreateJS content with other libraries or effects. You can basically use the other canvas as the source to a Bitmap you include in CreateJS:
// Create a child for CreateJS referencing the other canvas
var bmp = new createjs.Bitmap(otherCanvas);
// Add it at the bottom (or top or wherever) in your new CreateJS canvas
stage.addChildAt(bmp, 0);
This is a great approach because it lets you put your content wherever you want, edit it separately, etc.
If you have a different case this doesn't cover, let me know and I can try to make a recommendation!
Cheers.

How do you get code like this to run in JsFiddle.net?

I'm looking at sample code on how to draw shapes using only JavaScript.
I'm trying to test this sample code in JSFiddle.net, and while hitting 'Run' doesn't produce any errors, the result is completely blank.
Does anyone know how to make something actually appear on the screen in JsFiddle.net?
draw = function() {
//sky
background(172, 238, 247);
//ground
fill(95, 156, 83);
rect(0, 350, 400, 50);
};
draw();
Link to non-working Fiddle:
https://jsfiddle.net/skdopL1b/
So the way javascript works with HTML to draw things is through the Canvas API. First you have to contextualization and establish interactions between JS code and <canvas> element. This is done with built in function and then a little bit of code to make it short-hand.
<html>
<canvas id="canvas" width="500" height="400"></canvas>
<script>
const c = document.getElementById("canvas"); //Grab canvas element to use as object
const ctx = c.getContext('2d'); //Function that enable the 2d functions of Canvas API
ctx.fillRect(0,0,10,10) //Example of ctx function
<script>
</html>
From the JS Fiddle you gave us, It looks like you probably copied functions from a video that pre-established these function as they are not normal canvas function but custom functions. I can show you example of how to write one of these custom functions
function background(red,green,blue) {
ctx.fillStyle = 'rgb('+red+','+green+','+blue+')';;
ctx.fillRect(0,0,c.width,c.height); //Makes a rectangle the size of the canvas
}
background(172,238,247); //Creates a canvas sized rectangle with rgb(172,238,247)
You will have to either find his function declarations or write your own (or just use the raw canvas functions) to work with the javascript this way. You also need to define a canvas element with an ID. Lucky for you Im working on making a JSFiddle that works for you since you seem fairly new to this whole HTML5/JS thing.
-------EDIT-------
Heres your fiddle link friend, I included comments to help you understand everything https://jsfiddle.net/xwqg1cez/2/

Dynamic canvas, "moving line" Css and/or SVG

I'm making a UI in Angular6 where I have a list that occupies the left third of the screen with selectable entries that upon selection reveal additional data of that entry.
the additional data does not move but the the selected line in the entries can because the list is scrollable and also selecting it will change which line is highlighted obviously.
I want to make it visually clear to the user that the additional data he is seeing corresponds to the entry selected in the list.
here's what I have now :
as you can see I've already helped out the user visually by highlighting the entry in the list and the whole additional data view in the same light blue
and here's my attempt at sealing the deal in terms of the view's clarity :
<!DOCTYPE html>
<html>
<body>
<canvas id="myCanvas" width="400" height="180">
Your browser does not support the HTML5 canvas tag.</canvas>
<script>
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.beginPath();
ctx.moveTo(0, 20);
ctx.lineTo(400, 180);
ctx.lineTo(400, 40);
ctx.lineTo(0, 0);
ctx.fillStyle = '#9ec7e2';
ctx.fill();
</script>
<p><strong>Note:</strong> The canvas tag is not supported in Internet Explorer 8 and earlier versions.</p>
</body>
</html>
But I'm facing here a challenge I've never faced before : I need it to be dynamic and fluid.
I know I could JQuery-watch both select and scroll and also JQuery get X-Y coordinates of top and bottom corners of relevant divs, then redraw the canvas on every scroll and select call but that sounds extra poor performance-wise, and with a high probability of flashing (re-draws) while I scroll.
not to mention this all sounds extra clunky and poor execution,
Plus I'm fairly certain any resizing of the window or any other easy test would break the illusion.
Isn't there a new more "CSS3-SASS-SVG-Angular6" approach?

Canvas clipping object without drawing path [duplicate]

The title say it all. You can see Fabric.js Mask Filter Demo. This should be pretty simple but I can't find any example of applying mask to Fabric.js.
I am trying to apply mask to my JSFiddle. http://jsfiddle.net/ZxYCP/342/
From my JSFiddle, my goal is to have both logo and pugImg clipped inside this picture (or any picture if you want). Well, I can't even mask one picture anyway, so if this is not bothering you, please update the JSFiddle for better explanation.
In addition, the code from #kangax, creator of Fabric.js <3, in this question should be the solution but I can't manage to work. The result should be like the image below. Any further suggestion is appreciated.
You are not really trying ot mask an image. You are using some compositing effects.
There are a couple of things to understand that are not directly related to fabric.js.
A mask goes over an image.
The demo link you posted will not make you get the effect as in the screenshot.
If this is the case, you should have:
a light blue canvas
a pug.jpg image
a white overlay image with a girl-shaped transparent hole in it
Make a sandwich with those 3.
In this case you are masking the canvas not the image.
If you have a girl-shaped path, you can clip the canvas as seen in:
Fabric.js Clip Canvas (or object group) To Polygon
But you state that you want to use a image instead.
So if you do not have the overlay with girl-shaped hole, you can use another solution to get the same effect:
a transparent canvas
a light blu image with a shape you need and transparent pixels all around
a pug.jpg image
Add the first image on the canvas;
set the globalCompositeOperation of the pug.jpg to 'source-atop'
paint the other image over the other
var canvas = new fabric.Canvas('c');
fabric.Image.fromURL('http://fabricjs.com/assets/2.svg', function(img){
img1 = img;
fabric.Image.fromURL('http://fabricjs.com/assets/pug.jpg', function(img){
img1.scaleToWidth(canvas.getWidth());
img2 = img;
img2.scaleToHeight(300);
img2.left = 50;
img2.top = 50;
img2.globalCompositeOperation = 'source-atop';
canvas.add(img1);
canvas.add(img2);
});
});
<script type ="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.5.0/fabric.min.js"></script>
<canvas id="c" width="400" height="400" style="border:1px solid #ccc"></canvas>

Fabric.js: Image controls behind an overlay image

I'm building a canvas user interface with jquery and fabric.js library and I set an overlay png image with a transparent section using the following code
var bgImgSrc = bgImg.attr('src');
canvas.setOverlayImage(bgImgSrc, function(img){
canvas.renderAll();
});
I also added an image behind the overlay and resized to fit the container using the following code
var photoImg = $('#img-photo');
var photoImgSrc = photoImg.attr('src');
fabric.Image.fromURL(photoImgSrc, function(img) {
var photoImgWidth = photoImg.width();
var photoImgHeight = photoImg.height();
var hRatio = 380/photoImgWidth;
var vRatio = 300/photoImgHeight;
var ratio = Math.min(hRatio, vRatio);
pImg = img.set({left: 380/2, top: 300/2, angle: 0})
img.scale(ratio).setCoords();
canvas.add(pImg);
canvas.sendToBack(pImg);
canvas.renderAll();
});
And it works as expected, however, when I click on the image to scale/resize it, I don't see the controls, except through the transparent space of the overlay image. Controls are behind the overlay image, is there a way to force show the image controls without having to put the entire image in front of the overlay?
Just set the boolean controlsAboveOverlay:
canvas.controlsAboveOverlay = true;
The problem here is that overlay image is rendered on top of objects' controls. This is expected behavior. Take a look at this wiki article, which shows the z-index of various things on fabric canvas and in which order they're rendered.
There are plans to add support for object controls that are always on top, as you can see from this ticket, but I can't tell you when that's going to happen.
You can also try using "after:render" callback and draw image manually onto canvas.
canvas.controlsAboveOverlay = true; //did the job... but:
I don't want to render controls above the overlay image (as overlay means overlay to me). I just want to render the stack exactly as described in Wiki (by default).
I just wonder...as described in the Wiki rendering-stack, the controls should be rendered on top of all objects (always visible by default), but they do not (look at kitchensink demo).
IMHO this behaviour should be set by a flag like canvas.controlsInStack = true.
By the way ... that thing is really beautiful!

Categories