Grid with clicable irregular shapes - javascript

I'm having a bit of trouble here to develop this functionality since it must work on IE9+ so css clip-path is not an option ( http://caniuse.com/#feat=css-clip-path ).
The issue:
I need to create a grid composed of 6 elements.
Each element is an image.
The images can be different according to user answers before getting to the grid page.
Eeach element / image must be clicable and will acquire a "selected" class that will overlay div with text and background image.
image:
What is the best way to achieve this?

One way to do this could be to save out each combination of the six images you require into one big image. Then, depending on the user's answer combination, you insert the corresponding image as a background-image of a div. You then overlay click-able hotspots within the same div that roughly correlate to the dividing edges.
This may however not be the most practical solution and largely depends on how many answers/images you are dealing with.
Alternatively you could draw SVG shapes and set their fills to the images you require.
I can recommend Raphael.js as a starting point. You should be able to find what you need in the documentation
Another option would be to use HTML5 canvas:
http://jsfiddle.net/julienbidoret/GKP7X/1/
(credit goes to julienbidoret for the jsfiddle)
Javascript:
var canvas = document.getElementById('c');
var ctx = canvas.getContext('2d');
var img = document.createElement('IMG');
img.onload = function () {
ctx.save();
ctx.beginPath();
ctx.moveTo(20, 0);
ctx.lineTo(240, 0);
ctx.lineTo(220, 240);
ctx.lineTo(0, 240);
ctx.closePath();
ctx.clip();
ctx.drawImage(img, 0, 0);
ctx.restore();
}
img.src = "http://upload.wikimedia.org/wikipedia/commons/2/2b/Clouds.JPG";
HTML:
<canvas id="c" width="300" height="300" ></canvas>
Both SVG and canvas are supported in IE9.

Related

Clipping multiple images in HTML5 canvas

I am working on HTML5 canvas with image manipulation. In my canvas I have number of images. When I want to clip the images individually. But when I clip one image by creating a shape and use clip() function, it is working fine. But the problem arise when I try to clip another image using the same method. As the canvas stored the previous shape it will concatenate with the new one and clip the second image accordingly. I want destroy the previous shape. Please note that I can't use the clearRect() to clear the canvas as my previous clipped image is there.
Please ref the link :
Demo Problem
In the link drag the image into canvas predefined layer and drag the image around. You can clearly see that the image got clipped properly if it try to go out of the border.
Now drag another image into the canvas in a different box. Now you can see the clipping is not functioning properly.
Here what I have done in the script :
JS Script
Here the JSFiddle Link
JSFiddle Link
Can you help me to fix this issue?
It will be helpful if you find another way to clear the previous shape.
Thanks in advance.
I have fix the issue by own. The canvas doesn't provide the multiple image clip option. So if you want to clip multiple image in your canvas you have to use your own clip function. Just clear the area by clearRect() of the canvas outside your selection. Iterate this process for each image and you are done !
Solution Link :
Solution Demo
JS Script Link :
JS Script
Thanks.
The best solution I could find is to use a hidden canvas, and draw to that, then use the putImageData method onto your main canvas.
var c = document.getElementById("myCanvas");
var ctemp = document.getElementById("myCanvasTemp");
var ctx = c.getContext("2d");
var ctxTemp = ctemp.getContext("2d");
ctxTemp.fillStyle = "red";
ctxTemp.fillRect(10, 10, 50, 50);
ctxTemp.fillStyle = "blue";
ctxTemp.fillRect(20, 20, 50, 50);
function copy() {
var imgData = ctxTemp.getImageData(10, 20, 50, 10);
ctx.putImageData(imgData, 10, 10);
}
<canvas id="myCanvas" width="300" height="150" style="border:1px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.</canvas>
<canvas id="myCanvasTemp" width="300" height="150" style="display:none;">
Your browser does not support the HTML5 canvas tag.</canvas>
<br /><br />
<br />
<button onclick="copy()">Copy</button>

How to delete an instance of an image in Javascript

In my program I am drawing an image the canvas multiple times. My code looks something lik this:
<img id="image1" src="image1.png" width="200" height="100" hidden ="hidden">
<script type ="text/javascript">
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext('2d');
ctx.drawImage(image1, 50, 50, 200, 100);
ctx.drawImage(image1, 100, 100, 200, 100);
<script/>
My questions is, is it possible to delete just one instance of this image? For instance just delete the image drawn at 100,100 and leave the one at 50,50?
The moment you draw something to a canvas it stops being an independent object and becomes a bunch of pixels on a canvas. The information that these pixels together form a larger object is lost. You could remove it by using context.clearRect, but that will also erase anything else which is drawn on the same area, so it won't do what you want when the image overlaps with other content.
I would recommend you to clear the whole canvas and draw the whole scene again without the image.
Another option is to use multiple canvas'es as layers by placing them on top of each other using CSS positioning. That way any transparent pixels on the top canvas will show the content of the canvas below. This allows you to erase parts of one canvas without affecting the content of the canvas above or below it.

Canvas shows the text blurred

I am trying to draw a sharp thin rectangle using canvas control.I want the canvas background to get loaded with an image and in foreground with some text .
Though i am able to set the color and text they are somehow appearing blurred.Is there a way to fix this issue ?
And i want to apply an image as background image for each canvas rectangle i will draw.These rectangels will appear a in a div control.So wherever there is a canvas rectangle i want its background image to be filled with the image i choose.entire div will not be filled with canvas rectangles but only half of it.Is there a way whether we can have one image for all the canvas rectangles i will draw or do ineed to draw it for every rectangle ?
html:
<div id="divBoard" >
<canvas id="canvasBoard" />
</div>
javascript:
canvas = document.getElementById("canvasBoard");
if (canvas.getContext) {
var context = canvas.getContext("2d");
}
context.fillStyle = "green";
context.fillRect(x, y, width,height);
context.font = "5px tahoma";
context.fillStyle = "black";
context.fillText("cell"+i, x, y + width);
this is the image displayed after executing my code
I have experienced the same issue with fonts not rendering as sharply on a canvas. In my project I did a workaround by placing the font in a separate DIV and overlaying it on the canvas using an appropriate z-index. This approach worked very well for me.
Have you tried adding 0.5 to x and y? The html5 canvas uses antialiasing so if you want "crisp" lines, you need to draw "in between" the pixels.
You will find a good explanation on how this works in mozilla developer reference page for lineWidth
PS. also see this question

Canvas images and Click event

I have currently two circles in a <canvas> tag with HTML5 & JavaScript.
Now I'm trying to add an image (done) that changes based on mouse-over and click.
It's basically an implementation of a play / pause button with an extra color change when the user mouse-overs the button.
I can't seem to figure out how events work on shapes in HTML5 since they are not objects ... Here is my code at the moment :
window.onload = function() {
var canvas = document.getElementsByTagName('canvas')[0];
var context = canvas.getContext('2d');
var centerX = canvas.width / 2;
var centerY = canvas.height / 2;
//Outer circle
context.beginPath();
context.arc(centerX, centerY, 150, 0, Math.PI * 2, false);
context.fillStyle = "#000";
context.fill();
context.stroke();
//Inner cicle
context.beginPath();
context.arc(centerX, centerY, 75, 0, Math.PI * 2, false);
context.fillStyle = "#fff";
context.fill();
context.stroke();
//Play / Pause button
var imagePlay = new Image();
var imageHeight = 48/2;
imagePlay.onload = function() {
context.drawImage(imagePlay, centerX - imageHeight, centerY - imageHeight);
};
imagePlay.src = "images/play.gif";
}
How to handle events on shapes created with <canvas>?
How to clean-up / remove images on the <canvas> when replacing it with another one?
There is technically no way to register mouse events on canvas-drawn shapes. However, if you use a library, like Raphael (http://raphaeljs.com/), it can keep track of shape positions and thus figure out what shape is receiving the mouse event. here's an example:
var circle = r.circle(50, 50, 40);
circle.attr({fill: "red"});
circle.mouseover(function (event) {
this.attr({fill: "red"});
});
As you can see, it's very simple this way. For modifying shapes, this library will also come in handy. Without it you would need to remember how to redraw everything each time you make a change
Well The simple answer is you can't. You either will have to find the coordinates of the click event and calculate whether you want to perform an option or not or you can use area and map tags and overlay the canvas element with it. To change a canvas use the clearRect function to draw paint a rectangle over everything and then redraw what you want.
There is no "built-in" way of keeping track of shapes drawn on the canvas. They are not treated as objects, but rather just pixels in an area. If you want to handle events on shapes drawn on the canvas, you would need to keep track of the area each shape covers, and then determine which shape you're triggering the event for based on the mouse position.
You can just draw over other shapes if you want to replace it with something. You might want to take a look at globalCompositeOperation.
If you want to treat your drawings as objects, I would recommend using SVG instead of canvas.
Another option is to use buttons, and then style them using CSS.
Basically, what you're doing now really wasn't the intended purpose or use of the canvas. It's like using a pencil to hammer in nails - you're using the wrong tool for the job.
While it's true that you cannot create click events for objects drawn on the canvas there is a workaround: Wrap the canvas in a DIV tag and then add the images within the DIV tag above the CANVAS tag.
<div id="wrapper">
<img src="img1.jpg" id="img1"></img>
<canvas id="thecanvas"></canvas>
</div>
Then use CSS to make the images position:absolute and use left:*px and top:*px attributes to place the image over the canvas where you would have normally drawn it.
#img1{
position:absolute;
left: 10px;
top: 10px;
}
You can then add click events to the image which is placed over the canvas giving the impression that you are clicking on the canvas(the below example uses the jQuery click() function)
$( "#img1" ).click(function(){
alert("Thanks for clicking me");
});
You can cast a ray into the canvas and manually test your images for intersection with the ray. You should look at it like you press, and send a ray into the screen. You should write a
objectsUnderPoint( x, y );
function that returns an array of all the images that intersect with the ray at x, y.
This is the only real right answer, and this is how it is usually done in 3D engines as well.

possible to render canvas drawing into div?

I am trying to draw a shape on an HTML5 canvas but have the shape appear in a div (that can be manipulated by javascript). How can i do this? I would post code but i dont even know where to start with this. Please help.
To clarify: i want the shapes rendered on the canvas to be placed in divs. Sorry for any confusion.
Mozilla Drawing: https://developer.mozilla.org/en/Canvas_tutorial/Drawing_shapes
<div>
<canvas id="my_canvas"></canvas>
</div>
<script>
var canvas = document.getElementById('my_canvas');
// Set width height. You should probably use the width/height of the div.
canvas.width = 300;
canvas.height = 300;
var ctx = canvas.getContext('2d');
// Draw something with ctx.....
// ....
</script>
You could use the library Canvas2Image. It will allow you to convert what's on the Canvas into an image. There are some quirks on a per browser basis, but it is the closest thing to what you want to do without having to put many canvas elements on your page that you update in tandem.

Categories

Resources