Is it possible to only trigger a div's mouseover when the cursor is over an opaque part of the div's background image? Perhaps via Javascript?
All I can find with Google are old IE PNG fixes.
This looks like a similar question to this one: Hit detection on non-transparent pixel
I suppose this could also be done for background image by getting the attribute with jQuery:
$('#myDiv').css('background-image');
I haven't personally done this, but it seems like a viable solution. This will only work for modern browsers, but you should be able to make it back-compatible with excanvas.
It is possible, just not very easily. You'll have to use a lot of Javascript.
You'd want to attach to your <div>'s onmousemove event, which returns the X,Y coordinates of the cursor. Your event handler function would then test to see if the cursor is in the correct place in order to trigger an alternative onmouseover event.
Implementing the "is the cursor over an opaque pixel or not?" test can be done two ways: the first is to create a simple mathematical expression (say if the opaque parts of the image make neat rectangles, circles or polygons). The more difficult (and less browser-supported) way is to load the background image into a Canvas object and then get the current pixel value's opacity figure and take it from there, like so:
var pixel = canvas.getImageData(x, y, 1, 1).data;
var alpha = pixel[3]; // assuming RGBA
if( alpha > threshold ) onMouseOver(); // raise the event
Another alternative is to create an entirely transparent div (or some other element) positioned and sized so that it only covers the opaque part of the div below, then just test the mouseover of that element's box.
It's a bit of tweaking but why don't you add a class to your opaque div, and use JavaScript to check for it?
In jQuery:
$('div').mouseover(function(){
if ($(this).is('.opaque')) {
//Some actions
}
});
Related
My goal is to bring in an image on to part of the canvas, then scale it, move/translate it, and optionally skew it, also rotate and make alpha changes, kind of the primary "2d image manipulations", in an animated form, which is: do little changes over time from the starting state to the target end state.
Well, I figured to be efficient, I should use the canvas/2d context transform, https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/transform -- as it does the first 3: scale, move/translate, and skew, "all in one." I did half that code, and now I'm looking at examples and seeking to debug it. All the examples I see, are do 1) some transform, away from the "unity transform":
{ a:1, b:0, c: 0, d:1, e:0, f:0 }; // this basic transform does nothing
and then 2) draw into that. But that's the opposite order from what I want: which is draw on the canvas (the image), and then do an animation over time using the above primary changes (scale, translate, skew, rotate, and alpha). My question is: does it only "work this way", meaning I must setup the (single) transformation on the page first, and then "draw into that?"
I hope not ... that won't give me what I want, and I have to "ditch it", and go to 5 individual "transformations." Comments?
Yes that only works this way, canvas transforms and compositing mode and filters and lineWidth and fillStyle etc. properties are only applied to the next drawing operations.
The canvas itself only holds pixels information, it has no concept of drawn object. Your js code has to do this part.
So for what you wish, you can simply redraw everything every time:
reset the transform so we can clear ctx.setTransform(1,0,0,1,0,0);
Clear the canvas ctx.clearRect(0,0,ctx.canvas.width,ctx.canvas.height)
Set the transform to your new matrix ctx.translate(x,y); ctx.scale(s)...
Draw your transformed graphics ctx.fill(); ctx.drawImage(...
Wait next frame to do it again requestAnimationFrame(update)
I am painting on a window simple html using QTextDocument::drawContents(painter)
I want to do the drawing inside some margins in the window but I don't see a direct way to specify the target rectangle of the painting (in the painter/window).
I guess a few ways to do it:
Using the QTextDocuments::setMargin (although this does not allow different values for left/top.
Placing the html into an styled <div>
Applying a translation transform to the painter.
But all this seems a bit too much for what I want to do and I guess if I a missing something straight (as you do with QPainter::drawText where you tell the target rectangle)
Set the textWidth property to the width of the area where the text is supposed to fit. The clipping rectangle you pass to drawContents will cut the text off vertically if there's too much of it to fit; you can't do much about that of course.
So, this would be the missing function you're after:
void drawContents(QPainter * p, QTextDocument & doc, const QRectF & rect) {
p->save();
p->translate(rect.topLeft());
doc.setTextWidth(rect.width());
doc.drawContents(p, rect);
p->restore();
}
Yes, you do need to jump through a few hoops, that's why it needs to be factored out. It's perhaps lamentable that a similar overload of drawContents doesn't exist.
I have a canvas with the following size: 500x200. Inside this canvas i'm drawing some number of blocks (actually - table cells). Information about how much blocks i should draw i'm getting via AJAX, but size for every cell is fixed - 100x50. So, i can display inside my canvas only 5 blocks horizontally and 4 vertically. But what about other blocks? What if script return a table 30x30 cells. How can i side scroll (mouse preferred) my canvas so user can the rest of the cells (no zoom out, only scrolling).
If you need any more information, please, tell me and i will provide it.
Thank you.
The easiest way to accomplish this is to implement mouse-panning.
On the mouse down event, begin panning and save the mouse position
On the mouse move event, translate the context (ctx.translate(x,y)) by the difference between the current mouse position and the original position, then redraw the scene.
On the mouse up event, stop panning.
There are harder ways. You could implement scrollbars inside the canvas, as Mozilla Bespin has done (...which became Mozilla Skywriter which then merged with Ace and dropped all Canvas use). The code that they used was pretty good.
Or you could implement DOM scrollbars for use with your canvas, which isn't exactly easy to get right in all cases. This involves adding several dummy divs in order to give the appearance and function of real scrollbars. I have done this but the code remains unreleased for now. But thats no reason you can't give it a try if thats what you really want.
Check out a great tutorial at: http://www.brighthub.com/hubfolio/matthew-casperson/blog/archive/2009/06/29/game-development-with-javascript-and-the-canvas-element.aspx
It will give you an answer to your question and much much more...
I'm with Simon Sarris on this, but as an alternative, you could clone the canvas, and replace it with a blank canvas, and then render the original canvas as an image. I've some MooTools js that goes like this, which is fine for my use, by ymmv:
var destinationCanvas = this.canvas.clone()l
destinationCanvas.cloneEvents( this.canvas, 'mousemove');
var destCtx = destinationCanvas.getContext('2d');
destCtx.drawImage(
this.canvas,
(this.options.scrollPx)*-1,
0
);
destinationCanvas.replaces( this.canvas );
this.canvas.destroy();
this.canvas = destinationCanvas;
this.ctx = destCtx; // this.canvas.getContext('2d');
Usless Background Info
Hello, all. This is my first post here, but I often come here for help.
I am an amateur web designer and have been in web designing for almost a year now.
The Problem
My question is about CSS3 transforms. I have a small, circular element in the center of my page that transforms successfully when I hover over it. I have a larger circular element that is, by z-index, underneath it. The larger circle also has CSS3 transforms coded in the CSS, but will not transform, or even triggerd when hovered over. Both circles are overlaid, with the smallest on top, to create concentric circles.
My Attempted Solution
One word: Z-index. I have tried putting the larger circle on top, which works fine. The problem with this is that the smaller circle no longer triggers...
The Result I Want
I would like for the circles to remain in their 'concentric' positions and for the larger circle on the outside to transform by :hover. Is it possible to have an 'alternate trigger'? e.g.: in JavaScript, I can trigger an animation by hovering over any element that I specify. Is this possible to do in CSS? Can I hover element (I), and change properties for element (II)? If I cannot do this, how would I go about triggering animations for both circles, by hovering over only one? I am trying to stay with pure CSS/HTML, but I will accept JavaScript answers.
Last Notes
I hope I have provided ample info for a decent answer... Here is a screenshot: http://i.stack.imgur.com/WPj62.png
The circle with the infinity sign is the smaller circle element. The larger circle with the faint border around the screen is the other element.
EDIT:
Something's still not right, please take a look at the full code posted here: http://cssdesk.com/eJ8BH
If I understand your question, it sounds like when you hover over the small circle, you want both the large and small circle to transform, correct?
The easiest way is likely to use javascript for this. If you are using jQuery, it's even easier:
$('.littleCircle')
.hover(function(){
$(this).addClass('myTransformationClass');
$('.biggerCircle').addClass('myTransformationClass');
})
UPDATE: Some further examples based on follow-up feedback.
Here's what I'd do. First, give all 4 related elements a class so you can grab them via jQuery. For the example I use .rolloverSet
// grab all 4 elements and cache them
$rolloverSet = $('.rolloverSet');
// grab the one element that needs to have two classes
$otherElement = $rolloverSet.find('.otherElement');
$rolloverSet
.hover(function(){ // we'll add a hover event to each element in the group
$(this).addClass('myTransformationClass');
$otherElement.addClass('myOtherTransformationClass');
})
.blur(function(){ // remove the classes on mousout
$(this).removeClass('myTransformationClass');
$otherElement.removeClass('myOtherTransformationClass');
})
You do not need jQuery for this. You need to apply :hover on the parent element of the concentric circles and then apply the animation to its immediate children like this: http://jsfiddle.net/nimbu/taqr4/
Things I changed:
Updated to use shorter transitions, animations property
Added moz, o, unprefixed properties
Removed -webkit- from border-radius
Gathered common properties of concentric circles to prevent repetition
Fixed incorrect background-color (#00000000)
The reason for asking this question is because I want to be able to draw an arrow between two svg images. I want to use canvas to create the arrows, so firstly I generate the svgs then place a canvas on top of them to be able to draw the arrows.
I've tried using style=... but haven't had any luck as everytime I add the canvas element it just pushes my svg images to another pl
If there's no easy way to do this I'll just create arrows using SVG, I figured it would be more efficient to use canvas if I had to do lots of arrows in a short amount of time.
You need position:absolute on the CSS for the canvas to take it out of the flow, and then you can layer it as you like using z-index.
However, I instead suggest that you can use one or two tiny canvases to create the arrowheads and use toDataURL() on them to create a url you can use for <image> tags in the SVG. This way all your graphics are in SVG but you can use the canvas for complex raster effects if you need to.
have you tried z-index? it's a useful css trick
#svgcontent
{
z-index:1
}
#html5content
{
z-index:3
}
EDIT: accidentally screwed the #s up. 'scuse me.