I'm working on a project that has some draggable content in it. All of the images that are draggable have portion that are transparent and overlap other content.
I set up an example on JSFiddle: Draggable Example
<body>
<p>The background is transparent, but if you grab ANYWHERE in the border you can drag the image around.</p>
<img src="http://upload.wikimedia.org/wikipedia/commons/thumb/e/e1/Jupiter_(transparent).png/484px-Jupiter_(transparent).png"></img>
</body>
img{
border: solid black 1px;
}
In the example you can grab the image by holding down the left mouse button anywhere within the borders of the image, even if they are transparent. In this example my goal would be to only be able to drag the image if you grabbed a visible portion of the planet Jupiter.
Is this possible in html?
Based on your clarification in comments above, it might be easiest to draw the images in a canvas element. You can add draggability to the canvas as explained in this SO post: Make image drawn on canvas draggable with JavaScript. And you can modify that to trigger the drag flag only if a non-transparent pixel is at the clicked position.
Related
I'm not requiring a full answer to this question, just an idea on how to approach it.
Let's say that a user on my site wants to cut out the background from this image:
Normally this would be a job for some magic outline tool, but this site already carries something that would provide a perfect cutout pattern, namely this:
As you can see this car will fit perfectly over the top one.
If the user could somehow fit the bottom picture over the top one and cut out everything outside that, it would be a perfect background removal.
How do I go about building something like this? Or are there already software out that does something similar?
The bottom picture could be anything, for examle a completely black model for easier recognition, but I'd think that it would be smarter if it used the outline of the transparent .png image and cut out everything outside it.
(The picture itself doesn't need to be used either if there is some way to extract the important bits of it needed for the cutout, of course).
Here's how to do your knockout with html5 canvas
If you have an exact image that defines the desired cut and you also know the position where the cut is to be made, then you can use compositing to do you cut-out. With destination-in compositing, new drawings will keep existing pixels only where new & old pixels are non-transparent.
Here's a few notes, example code and a Demo:
Notes:
Your car on your car-only image is not exactly the size of the car on the car+background image -- the car-only is a bit wider. This causes the cut-out to have some extra pixels. But if you had exact sizing the cutout would be perfect.
Your car on your car-only image has semi-transparent shadowing. This causes the cutout to have some extra semi-transparent pixels where the shadow was on the car-only image.
Example & demo using a different exactly sized cutout with no shadow:
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var bk=new Image();
bk.onload=start;
bk.src='https://dl.dropboxusercontent.com/u/139992952/multple/model-t-car.png';
var cut=new Image();
cut.crossOrigin='anonymous';
cut.onload=start;
cut.src="https://dl.dropboxusercontent.com/u/139992952/multple/model-t-cutout.png";
var imgcount=2;
function start(){
if(--imgcount>0){return;}
canvas.width=bk.width;
canvas.height=bk.height;
ctx.drawImage(bk,0,0);
ctx.globalCompositeOperation='destination-in';
ctx.drawImage(cut,125,40);
// always clean up -- reset the default compositing mode
ctx.globalCompositeOperation='source-over';
}
body{ background-color: ivory; }
canvas{border:1px solid red; margin:0 auto; }
<h4>Original with background</h4>
<img src='https://dl.dropboxusercontent.com/u/139992952/multple/model-t-car.png'>
<h4>Exactly sized cutout</h4>
<img src='https://dl.dropboxusercontent.com/u/139992952/multple/model-t-cutout.png'>
<br>
<h4>With background removed</h4>
<canvas id="canvas" width=300 height=300></canvas>
There's no easy plug-and-play way. I can think of 2 methods:
(1) SVGs. Plot the different points on the outline of the car yourself (very time-consuming), or import the car into Illustrator (or similar), export it as an SVG, and use the points it calculated for you with clip-path.
(2) PNG (or GIF).
Create a rectangle of solid color in Illustrator/Photoshop.
Paste the car image on top of it as a new layer.
Select the outline of the car.
Delete the selection from the rectangle of color. This will leave a rectangle with a transparent car-shaped hole in it.
Save the rectangle as a PNG or GIF or other format supporting transparent backgrounds.
Use CSS to overlay that PNG on various images of cars.
This is useful if, for instance, you have 5 photos of cars in different colors, all with the same dimensions and taken from the same angle, and want to display the 5 cars with the same background. No need to copy the same background 5 times in Photoshop; just re-use the PNG 5 times in CSS.
Now if you want to change the "background" (which is actually an overlay and not really a background) you need only change it in one place.
Keep in mind: The image you provided is not a perfect outline because it has a shadow.
Is it possible to make a mouse event not fire on transparent color of an image?
I have a big background image and several small images which are shaped in different shapes (for example the shape of a ball). I want to catch mouse events on these small images. The problem is that events fire on the whole rect of an image. I can use image map on the background image but this is not a good idea because the small images will be changing under mouse (sprites).
You can check a number of things, either the fill of an svg shape, path or rect or also the opacity property depending on how you have made the element transparent.
For instance:
$('svg rect').mouseenter(function(){
if($(this).attr('opacity') != 0){
$('body').append('hovered element with colour');
}
});
Here is an example:
http://codepen.io/EightArmsHQ/pen/zxLbXO
Edit
With more complex images like
http://mobilite.mobi/wp-content/uploads/white-rabbit-wallpapers-9.
You have two options. The (to me, a graphic designer turned web designer) the simpler way would be to create an SVG hit map)
But a solution that would be far more thorough would be to use HTML5 / JavaScript canvas element which can have all of this stuff included, but will be more complex to initially code.
If you use the words canvas alpha hit detection I'm sure you'll be able to google some great results, such as
Image map by alpha channel
what you can do is add classes for those small small shapes. for example
<div class="big_back" id="big_back">
<div class="small_shapes" id="shape1">
</div>
<div class="small_shapes" id="shape2">
</div>
<div class="small_shapes" id="shape3">
</div>
</div>
and in jquery you can call the method as follow
$(document).ready(function() {
$(".small_shapes").mouseenter(function() {
alert("I enteres shapes");
});
});
If this is not what you are looking let me know.
I'd like to know if there is some way in Kinetic to have an image merged with another image on a lower layer, creating a kind of crop effect based on the shape of the "cropping" image.
The image must have a transparent background as a result, which is the main source of difficulty for me. I would otherwise just have used a mask with dragging turned off... I've made a diagram to explain what I want a bit better. Any suggestions welcome.
diagram
I've also made a quick jsfiddle, where I would like the contents of the image to be displayed inside the box. I feel like one layer is the way to go on this one.
You can use an offscreen Canvas element plus compositing to create your clipped image for use by your Kinetic.Image. Note that the offscreen canvas can be used as an image source for your Kinetic.Image.
Example code and a Demo: http://jsfiddle.net/m1erickson/ks1xxqfL/
var canvas=document.createElement('canvas');
var ctx=canvas.getContext('2d');
canvas.width=background.width;
canvas.height=background.height;
ctx.drawImage(mask,0,0,mask.width*2.25,mask.height*2.25);
ctx.globalCompositeOperation='source-in';
ctx.drawImage(background,0,0);
var support=new Kinetic.Image({
draggable:true,
image:canvas,
});
layer.add(support);
layer.draw();
Illustrations
Left: the background image,
Center: the image to be used as a clipping mask
Right: the background clipped by the mask (mask was scaled by 2.25X)
I am using ImageMapster to resize an image and change the "image map" coordinates to the new size. The image i am resizing is used as the background image, and is therefor centered in the middle of the screen:
CSS:
#block_content
{
text-align:center;
}
block_content is the container div of the image.
I am using code from this example: http://jsfiddle.net/JpgYm/8/
The problem is, that when im using text-align: center, the coordinates are not mapped correctly to the image. They are horizontally on the same line as the image, but a little off to the left.
Is there a way to fix this?
This was a bug. It should be fixed in the current build.
https://github.com/jamietre/ImageMapster
For example:
<div style="background-color:black;width:20px;height:20px;" > </div>
<div style="background-color:red;width:20px;height:20px; margin:50px;" > </div>
http://jsfiddle.net/TLLup/
Here is two bars red and black.
I want to stick black bar to red and black bar must follow to red if it changes coordinates and it doesn't matter what we are doing changes DOM or just using jquery function $(element).position().
Try adding float: left; to the black box, either by modifying the style="" attribute or via jQuery.
The easiest way to do this is using html5 canvas for any custom drawing.
Here is an example that shows you how to draw lines.
http://www.html5canvastutorials.com/advanced/html5-canvas-drag-and-drop-tutorial/
As long as the dots are on the canvas you should be able to listen for their mouse events and draw a line with the canvas.