HTML5 Canvas - Grouping / Attaching an image TO a canvas - javascript

Using this JS Fiddle I am able to press a button to add new canvases to the screen...
var next = 4
function addCanvas() {
// create a new canvas element
var newCanvas = document.createElement("canvas");
newCanvas.id = "addedcanvases" + next; //added this to give each new canvas a unique id
next++;
newCanvas.width = canvasWidth;
newCanvas.height = canvasHeight;
// add a context for the new canvas to the contexts[] array
contexts.push(newCanvas.getContext("2d"));
// link the new canvas to its context in the contexts[] array
newCanvas.contextIndex = contexts.length;
// wire up the click handler
newCanvas.onclick = function (e) {
handleClick(e, this.contextIndex);
};
// wire up the mousemove handler
newCanvas.onmousemove = function (e) {
handleMousemove(e, this.contextIndex);
};
// add the new canvas to the page
document.body.appendChild(newCanvas);
}
The problem:
What is the best way to go about grouping / attaching a static image to the top of a canvas (as shown in the image below) so that whenever a new canvas is created in JS Fiddle an image is automatically created with it that is grouped / attached to the top of the new canvas.
This is so that where-ever a new canvas is dynamically created on the page an image is put above that canvas?
There may be an obvious way to do this that I am overlooking? but googling has not thrown up much as all 'image' and 'canvas' searches inevitably relate to actually adding an image to the canvas - which is not what I want to do in this instance.

Here's taking #KaliedaRik's answer and creating your groups using javascript:
http://jsfiddle.net/m1erickson/3EUnc/
The code to create a new group could be something like this:
function newGroup(){
// create a new wrapper div
var div=document.createElement("div");
div.className="wrapper";
// create an img and a canvas element
var img=document.createElement("img");
var br=document.createElement("br");
img.style.width="50px";
img.src="houseicon.png";
var canvas=document.createElement("canvas");
canvas.width=300;
canvas.height=55;
// add the img and canvas elements to the wrapper div
div.appendChild(img);
div.appendChild(br);
div.appendChild(canvas);
// add the wrapper div with its contained img + canvas to the page
document.body.appendChild(div);
}

One possible solution: when you create the canvas element, create a new div at the same time and put the canvas and img tags inside it. By making the div position style relative and the contained canvas and img position styles absolute, you'll be able to place the image wherever it needs to go.
<div style="position: relative">
<canvas style="position: absolute; top: 0px; left: 0px;"></canvas>
<img src="whatever" alt="whatever" style="position: absolute; top: -20px; left: 0px" />
</div>

Related

CreateJs Canvas resize Bitmap

I'm currently working with createJS canvas. I have an image with a predefined size into a Json file and boxes that are link to an eventListener on "mouseout" and "mouseover").
var stage = new createjs.Stage("testCanvas");
createjs.Touch.enable(stage);
stage.enableMouseOver(10);
Bitmap for the image:
var image = new Image();
image.onload = function () {
var img = new createjs.Bitmap(event.target);
stage.addChild(img);
then i draw my boxes (rectangles):
angular.forEach(..., function(value){
var rectGreen = new createjs.Shape();
rectGreen.graphics.beginFill("green")
.drawRect(
value.shapeDimension....,
value.shapeDimension....,
value.shapeDimension....,
value.shapeDimension....
);
rectGreen.alpha = 0.01;
stage.addChild(rectGreen);
my mouse events:
rectGreen.addEventListener("mouseover", function (event) {
var target = event.target;
target.alpha = 0.35;
stage.update();
});
rectGreen.addEventListener("mouseout", function (event) {
var target = event.target;
target.alpha = 0.01;
stage.update();
});
So, it's working but I have some difficulties with the canvas/image size.
If I don't set any width/heigth to the canvas Html, it results in a
300*150 canvas but the image is not resized so it displays only a
slight piece of the real image.
If i set width and height in the canvas html, (real size is 1700*1133), the image appears only 842*561 and the canvas takes place).
I tried different solution with Setting DIV width and height in JavaScript
but nothing enabled me to set my image correctly, and responsive so that the size of my rectangles adpt to the screen size of the image.
In order to dynamically resize the Canvas to the exact size of the image, you can do this:
//to get a variable reference to the canvas
var canvas = document.getElementById("testCanvas");
//supposing the Bitmap is the variable named 'img'
canvas.width = img.image.width;
canvas.height = img.image.height;
If you have more elements on the screen and the total size is bigger than the image itself, you can add everything on the screen in a container, and then scale the container itself to fit the canvas perfectly, like this:
var container = new createjs.Container();
container.addChild(img, [your other rectangle elements here]);
stage.addChild(container);
//will downscale or upscale the container to fit the canvas
container.scaleX = container.scaleY = canvas.width / img.image.width;

Resize canvas elements

I am looking for an easy solution to resize a canvas element (a chart) automatically once the parent div size changes (= browser size changes). At the moment my Canvas element only fits perfectly into the parent div when the page is loaded.
This is what I've done so far and what I've tried:
<div class="panel-body">
<canvas id="userlogins"></canvas>
<script type="text/javascript">
jQuery(document).ready(function($)
{
var ctx = $("#userlogins").get(0).getContext("2d");
var myLineChart = new Chart(ctx).Line(data, options);
});
function fitToContainer(canvas){
// Make it visually fill the positioned parent
canvas.style.width ='100%';
// ...then set the internal size to match
canvas.width = canvas.offsetWidth;
}
var canvas = document.querySelector('canvas');
fitToContainer(canvas);
jQuery( window ).resize(function() {
fitToContainer(canvas);
redraw();
});
</script>
</div>
When I resize my browser the canvas chart disappears. The parent div fit on page load works well.
Edit: The approaches in the given "duplicates" doesn't work for me! Here is what I have tried given from the "duplicate question":
jQuery( window ).resize(function() {
clearTimeout(timerID);
timerID = setTimeout(function() {
var cnvs = $("#userlogins")[0]; // cache canvas element
var rect = cnvs.getBoundingClientRect(); // actual size of canvas el. itself
cnvs.width = rect.width;
cnvs.height = rect.height;
redraw();
});
});
It looks like you're using ChartJS. If yes, it has a property you can set to make the chart responsive to resizing.
Chart.defaults.global.responsive = true;
Changing the canvas element width or height clears the canvas. In fact, it's often used as a way of clearing it on purpose. So this line:
canvas.width = canvas.offsetWidth;
clears your canvas. After that, you can either:
redraw the chart
or remove that line and rely on the CSS transformations, which can ruin the proportions of your canvas

Javascript html2canvas cant get background

Some issues using Javascript library html2canvas. The problem is that html2canvas is getting "div2" with a transparent (sometimes white) background, I want to include the body background (or is behind this div) on "div2".
<div id="div2" style="width: 150px; height: 50px;"></div>
html2canvas(document.getElementById("div2"), {
onrendered: function(canvas) {
var photostring = canvas.toDataURL("image/png");
console.log(photostring);
}
});
Logically the rendering works from the element you select.
So will not get the background, unless you select the "parent element" or "root element".
I have two solutions:
1 - Using Javascript/Jquery you can capture X and Y position from div#target
then you set background-image and background-position in div#target by X/Y position
2 - You capture <body> with html2canvas, then using canvas/javascript api you crop image by X/Y position and Width/Height from div#target, see example: #242 (comment)
Note: set width/height/x/y in these variables (see example):
var targetDiv = $("#target");
var sourceX = targetDiv.position().left;/*X position from div#target*/
var sourceY = targetDiv.position().top;/*Y position from div#target*/
var sourceWidth = targetDiv.width();/*clientWidth/offsetWidth from div#target*/
var sourceHeight = targetDiv.height();/*clientHeight/offsetHeight from div#target*/
Get background-image in parent/root element:
https://github.com/niklasvh/html2canvas/commit/281e6bbedf9f611846eba3af4d256eb97f608aa2
Crop canvas:
https://github.com/niklasvh/html2canvas/issues/242#issuecomment-20875688

Cannot save canvas with draggable object

I'm trying to save my HTML canvas to file which I can successfully do, but it's not saving any objects I've dragged into the canvas.
So, by using the Draggable JQuery I can happily move my object around screen and place it ontop of my canvas. When I save the canvas using the Canvas.ToDataURL() it does not save my dragged objects (and also does something strange to my canvas in the jsFiddle, it appears to change the colour of my canvas?).
To see a "working" example, please visit my jsFiddle http://jsfiddle.net/JVSFS/74/
Please simply drag the green box over the blue box and click the save button. The result will be shown underneath (just an orange box).
HTML
<canvas id="MyCanvas" class="canvas"></canvas>
<div class="popup_click">
<div id="popup_title">Drag</div>
</div>
<asp:HiddenField ID="hideMe" runat="server" />
<asp:Button runat="server" OnClick="ClickMe" Text="Click" OnClientClick="SaveMe()" />
<button onclick="SaveMe()">Try it</button>
<p>Results: </p>
<img id="myImage" />
JavaScript
$(document).ready(function () {
$('.popup_click').show(0).draggable();
});
function SaveMe() {
var canvas = document.getElementById("MyCanvas");
var context = canvas.getContext("2d");
context.fillStyle = "orange";
context.fillRect(0, 0, 100, 100);
var image = canvas.toDataURL("image/png");
document.getElementById("myImage").src = image;
document.getElementById("hideMe").value = image;
}
CSS
.popup_click {
background: #80FF80;
width: 50px; }
.canvas {
width: 100px;
height: 100px;
background-color: #0FC;
}
How can I get the dragged object to save? I assume I have to tell the Canvas that the object is part of it's context but no idea how and my own searches came up with nothing.
From https://developer.mozilla.org/en-US/docs/HTML/Canvas/Drawing_DOM_objects_into_a_canvas
You can't just draw HTML into a canvas. Instead, you need to use an SVG image containing the content you want to render. To draw HTML content, you'd use a element containing the HTML, then draw that SVG image into your canvas.
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var data = "<svg xmlns='http://www.w3.org/2000/svg' width='200' height='200'>" +
"<foreignObject width='100%' height='100%'>" +
"<div xmlns='http://www.w3.org/1999/xhtml' style='font-size:40px'>" +
"<em>I</em> like <span style='color:white; text-shadow:0 0 2px blue;'>cheese</span>" +
"</div>" +
"</foreignObject>" +
"</svg>";
var DOMURL = self.URL || self.webkitURL || self;
var img = new Image();
var svg = new Blob([data], {type: "image/svg+xml;charset=utf-8"});
var url = DOMURL.createObjectURL(svg);
img.onload = function() {
ctx.drawImage(img, 0, 0);
DOMURL.revokeObjectURL(url);
};
img.src = url;
That's because your draggable object isn't in the canves.
They are simple html elements.
It'll save only the objects whose created with canvas methods.
Any way to create html elements on canvas you have to use svg.
Mozilla show nice way to to this but you need to get all the css to inline css before.
mozilla explanation
Anyway with using svg on you canvas you won't be able to use toDataUrl because of security policy.

jQuery and Canvas loading behaviour

After being a long time lurker, this is my first post here! I've been RTFMing and searching everywhere for an answer to this question to no avail. I will try to be as informative as I can, hope you could help me.
This code is for my personal webpage.
I am trying to implement some sort of a modern click-map using HTML5 and jQuery.
In the website you would see the main image and a hidden canvas with the same size at the same coordinates with this picture drawn into it.
When the mouse hovers the main picture, it read the mouse pixel data (array of r,g,b,alpha) from the image drawn onto the canvas. When it sees the pixel color is black (in my case I only check the RED value, which in a black pixel would be 0) it knows the activate the relevant button.
(Originally, I got the idea from this article)
The reason I chose this method, is for the page to be responsive and dynamically change to fit different monitors and mobile devices. To achieve this, I call the DrawCanvas function every time the screen is re-sized, to redraw the canvas with the new dimensions.
Generally, this works OK. The thing is ,there seems to be an inconsistent behavior in Chrome and IE(9). When I initially open the page, I sometimes get no pixel data (0,0,0,0), until i re-size the browser. At first I figured there's some loading issues that are making this happen so I tried to hack it with setTimeout, it still doesn't work. I also tried to trigger the re-size event and call the drawCanvas function at document.ready, still didn't work.
What's bothering me is most, are the inconsistencies. Sometimes it works, sometimes is doesn't. Generally, it is more stable in chrome than in IE(9).
Here is the deprecated code:
<script type="text/javascript">
$(document).ready(function(){setTimeout(function() {
// Get main image object
var mapWrapper = document.getElementById('map_wrapper').getElementsByTagName('img').item(0);
// Create a hidden canvas the same size as the main image and append it to main div
var canvas = document.createElement('canvas');
canvas.height = mapWrapper.clientHeight;
canvas.width = mapWrapper.clientWidth;
canvas.fillStyle = 'rgb(255,255,255)';
canvas.style.display = 'none';
canvas.id = 'hiddencvs';
$('#map_wrapper').append(canvas);
// Draw the buttons image into the canvas
drawCanvas(null);
$("#map_wrapper").mousemove(function(e){
var canvas = document.getElementById('hiddencvs');
var context = canvas.getContext('2d');
var pos = findPos(this);
var x = e.pageX - pos.x;
var y = e.pageY - pos.y;
// Get pixel information array (red, green, blue, alpha)
var pixel = context.getImageData(x,y,1,1).data;
var red = pixel[0];
var main_img = document.getElementById('map_wrapper').getElementsByTagName('img').item(0);
if (red == 0)
{
...
}
else {
...
}
});
},3000);}); // End DOM Ready
function drawCanvas(e)
{
// Get context of hidden convas and set size according to main image
var cvs = document.getElementById('hiddencvs');
var ctx = cvs.getContext('2d');
var mapWrapper = document.getElementById('map_wrapper').getElementsByTagName('img').item(0);
cvs.width = mapWrapper.clientWidth;
cvs.height = mapWrapper.clientHeight;
// Create img element for buttons image
var img = document.createElement("img");
img.src = "img/main-page-buttons.png";
// Draw buttons image inside hidden canvas, strech it to canvas size
ctx.drawImage(img, 0, 0,cvs.width,cvs.height);
}
$(window).resize(function(e){
drawCanvas(e);
}
);
function findPos(obj)
{
...
}
</script>
I'd appreciate any help!
Thanks!
Ron.
You don't wait for the image to be loaded so, depending on the cache, you may draw an image or not in the canvas.
You should do this :
$(function(){
var img = document.createElement("img");
img.onload = function() {
var mapWrapper = document.getElementById('map_wrapper').getElementsByTagName('img').item(0);
...
// your whole code here !
...
}
img.src = "img/main-page-buttons.png";
});

Categories

Resources