Canvas is new to me - so I need help.
I have a function that draws data retrieved using getImageData () - on an existing canvas or newly created.
I need to make it possible for a newly created canvas to give it a unique id. However, when I try the following - the canvas is created but the id is undefined.
function drawImageData(img, t1, t2, cc, scale, targetCanvas, userId) {
var canvas = targetCanvas || document.createElement('canvas');
if(!targetCanvas){
canvas.setAttribute('id', userId);
// the rest of the code
}
How to properly assign userId - to "id" canvas?
Your code seems to be working fine.
jsfiddle.net/qsekzt9x/
#gurvinder372 is right about the if condition in his answer below
Related
I want to get part of a canvas in the base 64 data url format which will be sent to my api
for this is I am using the ctx.getImageData() method which is returning a clamped uint 8 array
here is the code:
const data = ctx.getImageData(mousex, mousey, mousex1, mousey1);
const clamped = data.data
}
I have tried many btoa methods but the either return a broken array full of A or a broken array with a lot of /
You can use canvas.toDataURL(type, encoderOptions) for this purpose.
First extract the part of your source image. You don't need getImageData() for that. Instead create a second canvas with part_canvas = document.createElement("canvas"), this canvas doesnt have to be visible on the page.
Assign it its size .width and .height of the part you want to extract
part_ctx = part_canvas.getContext("2d") on the canvas
Then part_ctx.drawImage(source_image, part_x, part_x, part_width, parth_height, 0, 0, part_width, parth_height); This will take a rectangualr area of the source image and put it in the invisble canvas.
Finally you can do part_canvas.toDataURL() and you have the data URL
Didn't test. But I think this should work.
I am writing a simple game in JS using EaselJS. I try to keep everything object-oriented to keep in sync state of game, state of EaselJS objects and what is displayed on my canvas. I would like to have possibility to change stroke color of shapes that are displayed on canvas by changing their attributes. I've found in docs append() here, but I can't get it working.
Here's what I've achieved so far:
Shape definition:
var bLetter = new createjs.Shape();
bLetter.graphics.append({exec: setPoweredState});
bLetter.graphics.moveTo(0, 0)
.lineTo(0, segSize * 2)
.arc(circSize, segSize * 2, circSize, Math.PI, Math.PI + 0.0001, true);
setPoweredState function - When i set bLetter.powered = true, the line color should change:
setPoweredState = function(ctx, shape) {
if(shape.powered) {
shape.color = consts.COLOR_LINE_ACTIVE;
} else {
shape.color = consts.COLOR_LINE_INACTIVE;
}
shape.graphics.beginStroke(shape.color).setStrokeStyle(consts.STROKE_SIZE, 'round', 'round');
}
When I set bLetter.powered = true and I check bLetter.color it seems that the function is executed - the bLetter.color property changes. However, the bLetter object on canvas is not updated. What's more, it's not drawn at all - probably I am using append() in incorrect way. What am I missing?
BTW: I omit the code with initializing createjs.Stage on canvas and adding bLetter as it's child, I don't think it's an issue, the shape is drawn correctly, only color won't change.
The issue is that you are continually appending new stroke / strokestyle commands to the end of the graphics queue, so they have no effect on the preceding paths.
The easiest approach in my opinion would be to save off the command as Lanny suggested, and modify its style in your setPoweredState method.
Here's an example of the above, implement with minimal modifications to your approach:
https://jsfiddle.net/u4o4hahw/
Instead of using append, consider just storing off commands to modify.
Here is another question that I answered outlining how it works: Injecting a new stroke color into a shape, and here is a blog post: http://blog.createjs.com/new-command-approach-to-easeljs-graphics/
Basically, you can store any command, then change its properties later:
var cmd = shape.graphics.beginFill("red").command;
shape.graphics.otherInstructionsHere();
// Later
cmd.style = "blue";
Here is a link to the docs on the Fill command used in the sample code: http://createjs.com/docs/easeljs/classes/Graphics.Fill.html
I'm new to javascript and web development in general, and I'm trying to write a renderer that can draw each slice in a CT scan as a 2D image.
I have a long thin (512x49664) image made from 512x97 slices, each of which is just a 512x512 image. I've already ascertained that this will upset webgl, so I was planning to grab individual slices from the image by drawing it on a canvas and copying the image data into a texture.
My question is: if I have a function in which I do something like:
// Create a small canvas to contain a single slice.
function getSlice(sliceNumber){
var sliceCanvas = document.createElement("canvas");
sliceCanvas.width = 512;
sliceCanvas.height = 512;
var sliceContext = sliceCanvas.getContext('2d');
sliceContext.drawImage(image, 0, 512*sliceNumber, 512, 512, 0, 0, 512, 512);
}
What happens to the canvas I created when the function exits?
It hasn't been:
Added to the DOM
Stored in a variable or property that is still in scope
Returned anywhere
… there are no references remaining to it, so it will be marked for garbage collection.
When you create a DOM element via javascript DOM API, you should attach this element to the page document.
Otherwise this element will never shown in your page.
So you have to add a line like this in your code:
document.body.appendChild(sliceCanvas);
If you call your function multiple times, you should check the canvas creation:
var sliceCanvas = document.getElementsByTagName('canvas')[0];
or
var sliceCanvas = document.getElementById('myCanvasId');
Then check:
if (!sliceCanvas) {
sliceCanvas = document.createElement('canvas');
sliceCanvas.id = 'myCanvasId'; // optional
document.body.appendChild(sliceCanvas);
}
// here your code...
UPDATE:
Consider to change the document.body with the proper DOM element where you want to place your canvas.
I am working on a project that requires creating multiple canvas elements (separate bars each representing one distinct gradient). I would like to do this dynamically with fabric.js, eg:
function add_gradient(color_stops){
// Add a new rectangular canvas with fill representing specified gradient
var grad_box = document.getElementById("divWithCanvases");
var newCanvas = document.createElement("canvas");
grad_box.appendChild(newCanvas);
var gradCanvas = fabric.Canvas(newCanvas, {width: 500, height:50});
var ctx = gradCanvas.getContext('2d');
// Do stuff to canvas...
}
However, the call to fabric.Canvas fails with an error "this.initialize is undefined". (fabric.js line 1627, version 1.4.13)
How can I either:
Generate a new fabric canvas based on an HTML element (instead of the string id), or,
Append an auto-generated new canvas element to the DOM? (the form fabric.Canvas() without arguments will make... something... but it can't be used with appendChild)
According to the fabric.js documentation, the fabric.Canvas constructor accepts either an HTMLElement, or a string element id. I can only make it work with the string.
The function fabric.Canvas is a constructor, you have to call it with the new operator:
var gradCanvas = new fabric.Canvas(newCanvas, {width: 500, height:50});
I was getting the above error because of <div id="canvas"> </div>
Make sure your html element should be canvas
<canvas id="canvas"> </canvas>
When we want to add canvas dynamically and want to call canvas fabric API then we need to give a different name like this..
var html_canvas = document.createElement('canvas');
html_canvas.id = "CursorLayer";
var canvas = new fabric.Canvas(html_canvas, canvasConfigOptions);
// canvasConfigOptions is optional
Now we can perform all fabric operations on this canvas
I hope you can help. I'm having some trouble programmatically resizing a Group of Fabric JS objects. I add the objects to the canvas using canvas.add(object) and then add them to the group. However when trying to resize the objects as a group, the usual setHeight(), scale() and scaleToWidth/Height() methods seem to have no effect.
My code is in several places, but the essence is:
var obj = ........ // I Get my obj from an SVG path
var objectGroup = new fabric.Group();
canvas.clipTo = function(ctx) {
obj.render(ctx);
}
objectGroup.add(obj);
I also tried objectGroup.addWithUpdate(obj);
Then, after adding more objects to the group; in my resize event, I work out the scale I need and do:
objectGroup.scaleToWidth(newX);
objectGroup.scaleToHeight(newY);
objectGroup.setCoords();
canvas.renderAll();
Am I missing something?? Do I have to add my obj to the canvas as well as rendering it inside the clipTo function?
Thanks in advance :)