I am brand new to Raphael and am really stuck, I would like to rotate a div and its contents, using a button, with Raphael.
Ideally, I would like to have a smooth animation that goes from 0 degrees to -90 degrees when the button is clicked, then when the button is clicked again, the animation would reverse. I think I will change the id or class on mouse click so that I can use the same button for both animations. Would that be wise?
I really would like some help please, my Sandbox is at http://jsbin.com/isijo/ and you can edit it at http://jsbin.com/isijo/edit
Many thanks in advance for any help.
Hello and welcome to Raphael!
I have been looking at Raphael for more than a few months and although the documentation is not very comprehensive the software is brilliant.
I have been mixing Divs with Raphael objects in many ways and have got a "feel" for what works and what does not work.
I am recommending that you do not try rotating divs but (instead) Raphael objects.
First of all you could make a shiney set of Raphael buttons using this "tweakable" code below..
var bcontrols = new Array();
var yheight = 300;
for (var i = 0; i < 3; i++) {
bcontrols[i] = paper.circle(15 + (35 * i), yheight, 15).attr({
fill: "r(.5,.9)#39c-#036",
stroke: "none"
});
bcontrols[i].shine = paper.ellipse(15 + (35 * i), yheight, 14, 14).attr({
fill: "r(.5,.1)#ccc-#ccc",
stroke: "none",
opacity: 0
});
bcontrols[i].index = i;
bcontrols[i].shine.index = i;
bcontrols[i].shine.mouseover(function (e) {
this.insertBefore(bcontrols[this.index]);
});
bcontrols[i].mouseout(function () {
this.insertBefore(bcontrols[this.index].shine);
});
/* Called from Raphael buttons */
bcontrols[i].click(function () {
alert("Hello you just clicked " + this.index);
});
}
Next you need to know more about rotating Sets:
var s = paper.set();
s.push(paper.rect(10, 10, 30, 30, 10).attr({fill:'red'}));
s.push(paper.rect(50, 10, 30, 30, 5).attr({fill:'blue'}));
s.push(paper.rect(90, 10, 30, 30).attr({fill:'orange'}));
s.animate({rotation: "360 65 25"}, 2000);
This shows the degree of rotation and the centre of rotation of the "set" on the last line.
My additional Raphael resources website which aims to supplement documentation (Amongst other things):
http://www.irunmywebsite.com/raphael/raphaelsource.html
Heres where you can run the above 2 code examples without alteration:
http://raphaeljs.com/playground.html
I'm hoping this helped...
To my knowledge, there is no way to convert a div into a Raphael object. Since the Raphael rotate command is only defined for Raphael objects, your best bet is to create the major elements of your div (images, text, buttons and all) in Raphael instead of HTML, put them together in a single set, and, as the set is a Raphael object, rotate the set.
Consult Rotate a div in CSS and in IE filters. This is not the same as SVG, so if you need more layout magic, Raphael shapes are likely the way to go. You should be able to used JQuery in concert with Raphael to manipulate both in your window, but I am brand new to Raphael and have never done so.
Related
I need to implement a plotly.js chart on a page with a very restricted width. As a result, a tooltip is partially cut. Is it possible to cause tooltip not to be limited by plotly.js container size?
My code example at codepen: https://codepen.io/anatoly314/pen/gOavXzZ?editors=1111
//my single trace defined as following but it's better to see example at codepen
const yValue1 = [1000];
const trace1 = {
x: [1],
y: yValue1,
name: `Model 1`,
text: yValue1.map(value => Math.abs(value)),
type: 'bar',
textposition: 'outside'
};
It is, by design, not possible for any part of the chart to overflow its container.
I would say it is wrong to say that by design this is not possible! It is a bit hacky, but when you add the following lines, it shows the label outside of svg:
svg.main-svg,svg.main-svg *
{
overflow:visible !important;
}
The answer given by rokdd works. However the css selector should be more specific, otherwise it's natural that you will introduce subtle bugs (particularly if you need to scroll the content where the plotly chart is contained).
If we look at the DOM tree constructed by Plotly, we find that the tooltips are created inside the <g class="hoverlayer"></g> element (which is a direct child of one of the three <svg class="main-svg"></svg>). So that parent (that svg.main-svg element) is only one that needs to affected.
The ideal css selector in this case would be the :has selector. However it's still not supported (as of 2022): https://css-tricks.com/the-css-has-selector/
So the next simplest thing is to use a little bit of javascript right after we call Plotly.newPlot:
// get the correct svg element
var mainSvgEl = document.querySelector('#positive g.hoverlayer').parentElement;
mainSvgEl.style['overflow'] = 'visible';
Or in a more generic way (works for any chart):
Array.from(document.querySelectorAll('g.hoverlayer')).forEach(hoverEl => {
let mainSvgEl = hoverEl.parentElement;
mainSvgEl.style['overflow'] = 'visible';
});
I am working on a game using EaselJS, and I am still trying the functions provided by this great library.
What I may need is Alphamaskfilter class & Spritesheet class.
Currently, I have a canvas like this:
<canvas id = 'container3' width = 320px; height = 480px;
style = 'outline: 2px solid; margin-right: 10px;float:left;'></canvas>
and in my script, I have draw a rect with blue color:
var ctx3 = document.getElementById('container3').getContext('2d');
ctx3.beginPath();
ctx3.rect(0,0,320,480);
ctx3.fillStyle = 'blue';
ctx3.fill();
So now I have a blue color 320*480 canvas. And now I have a sprite sheet to animate on it,
here is the sprite and code I wrote:
http://i.imgur.com/XumDvic.png
PS: the sprite frame is 200*200 FYI.
stage = new createjs.Stage(document.getElementById('container3'));
var test = new Image();
test.src = 'trans_blackball.png';
test.onload = function(){
var sprite = new createjs.SpriteSheet({
images: [test],
frames: {width: 200, height: 200},
animations: {
born: [0,3,0]
}
});
var animation = new createjs.BitmapAnimation(sprite);
animation.gotoAndPlay("born");
animation.x = 10;
animation.y = 10;
animation.currentFrame = 0;
stage.addChild(animation);
createjs.Ticker.addListener(window);
createjs.Ticker.useRAF = true;
createjs.Ticker.setFPS(10);
}
function tick(){
stage.update();
}
Okay, my question is: I expect an animation of an enlarging black circle on a blue background(rect), but what I got is firstly the canvas is blue, but for a certain mini-second after, the whole canvas became white, and the animation is running on the white background, what is the reason of this and how can I solve it?
Here is two points that may help:
I am working with chrome, and I check with F12 & console, the fillStyle of the canvas is still blue even it appears white after the sprite animation start
If I set the canvas background property to blue instead of drawing a blue rect on it, everything's fine!!
<canvas id = 'container3' width = 320px; height = 480px;
style = 'background: blue; outline: 2px solid; margin-right:
10px;float:left;'></canvas>
but clearly this is not what I want...
The problem can be solved as well by not using native canvas rect but use EaselJS's Shape to draw the rect:
var shape = new createjs.Shape();
shape.graphics.beginFill("#ff0000").drawRect(0, 0, 320, 480);
stage.addChild(shape);
But I still wanna know why the native rect drawing code is not working...
Please bare my bad english and thanks for reading and any attempt to help...I can elaborate more if there is anything unclear in the situation..thanks!
createjs.Stage.update() will clear the canvas-contents by default before rendering the new frame.
The reason for this is one the one hand the technical behaviour of canvas, the canvas is basically just an image of pixels, you cannot have real 'layers' and say "I just want to remove/update this one object" - you just can modify the flattened pixels of the frame or remove everything and redraw it(which is safer, easier to achieve, and actually fast enough performance-whise. And on the other hand, it makes sense to make consistent use of a framework like EaselJS, and not do some parts with the framework and some parts without it, this would result in a big mess at the end.
So, the right solution is to go with 3.
You can set myStage.autoClear = false; to prevent the Stage from autoClearing the canvas on every update() but I don't think this will suit your needs in this case.
I would recommend instead using the EaselJS Shape class to make your blue box. If it part of the EaselJS display list, it will be drawn with the other content.
javascript
var shape = new createjs.Shape();
shape.graphics.beginFill("blue").drawRect(0,0,320,480);
stage.addChild(shape);
Here's a related image:
I want to achieve something like what's pictured on the right side of my image. But I also have a parent container that has a background image of its own, instead of a solid color.
Any advice?
EDIT: Forgot to add, cross-browser compatibility is important. (Or atleast Firefox).
I can only think of one pure CSS solution and it is simply insane.
Let's say your image has a width of 100px. You'll have to create a div that's 100px wide and give it 100 children that are each 1px wide, that each have the same background (positioned accordingly) and that each have an opacity from 0 (the first child) to .99 (the last child).
Personally, I think it's crazy and I'd never use this method.
Rory O'Kane came with a nice and clean solution and I also have another idea which involves JavaScript.
Basically, the idea is that you use a canvas element (support), draw your image on it, loop through its pixels and adjust the alpha for each.
demo
(scroll down to see the result)
Relevant HTML:
<div class='parent'>
<canvas id='c' width='575' height='431'></canvas>
</div>
Relevant CSS (setting the background image on the parent)
.parent {
background: url(parent-background.jpg);
}
JavaScript:
window.onload = function() {
var c = document.getElementById('c'),
ctxt = c.getContext('2d'),
img = new Image();
img.onload = function() {
ctxt.drawImage(img, 0, 0);
var imageData = ctxt.getImageData(0, 0, 575, 431);
for(var i = 0, n = imageData.data.length; i < n; i += 4) {
imageData.data[i + 3] = 255*((i/4)%575)/575;
}
ctxt.putImageData(imageData, 0, 0);
};
/* images drawn onto the canvas must be hosted on the same web server
with the same domain as the code executing it */
/* or they can be encoded like in the demo */
img.src = 'image-drawn-on-canvas.jpg';
};
check these out maybe helpful
DEMO 1
DEMO 2
Ignoring possible CSS-only methods, you can make the image a PNG with the transparent gradient built in to the image’s alpha channel. All browsers support PNG transparency, except for IE 6 and below. Here’s what your sample image would look like as a PNG with a transparent gradient (try putting this image against other backgrounds):
If the images are user-submitted so you can’t add the gradient ahead of time, you could create and store a gradient-added version of each image at the time that the user uploads them.
CSS only method:
https://gist.github.com/3750808
I want to create an SVG animation, yet render it to Canvas. I know about CanVG, but I'm not certain it does what I need: Displaying SVG elements animated using javascript within a Canvas div, rather than a 'native' SVG window. When I look at CanVG example code, it seems to point to an SVG file, rather than utilizing SVG code that is part of the same file, & being manipulated in realtime by javascript. Any help?
I faced this issue me too some time ago and tried every possibilities mentioned above, unfortunately without results. After some research I found a method to inject SVG into Canvas, with a little pain and extra work it's possible. So the solution is to define svg elements then push it to an array then render that SVG as an image.
Here is a short code snippet:
SVG part:
var data = "data:image/svg+xml," +
"<svg xmlns='http://www.w3.org/2000/svg' width='400' height='400'>" +
"<foreignObject width='100%' height='100%'>" +
"<div xmlns='http://www.w3.org/1999/xhtml' style='font: bold 160px Myriad Pro, Arial, Helvetica, Arial, sans-serif'>" +
"<span style='color:rgb(32,124,202); opacity: 0.8; -webkit-text-stroke-color: white; -webkit-text-stroke-width: 2px'>" + letters[pos] + "</span>" +
"</div>" +
"</foreignObject>" +
"</svg>";
characters.push(data);
and JS part:
var letters = [...] // a pool of characters
var images = new Array(letters.length);
for (var i=0; i< letters.length; i++) {
var textPosition = WIDTH/2 - (letters.length * CHAR_DISTANCE)/2;
var txt = new Text(letters[i], textPosition + (i*CHAR_DISTANCE), HEIGHT/2,
(Math.random() * 3) + 5 , (-Math.random() * 10) + 5);
images[i] = new Image();
images[i].src = characters[i];
textArray.push(txt);
}
You may check the whole source code here: https://esimov.com/experiments/javascript/404/
There are several libraries (like CanVG) that merely turn SVG into Canvas drawing commands. They won't help you much with animation.
For animation you're going to have to do it on your own. You could attempt to use CanVG to draw the SVG onto the canvas as it is being animated, using a timer to update the canvas, but this is supremely messy and cannot be done unless the browser also supports SVG (and if it does, why would you want to do it?)
If you want to manipulate the SVG in real time you're going to have to stick with SVG proper. Otherwise you need to roll all your own state and interactivity on the canvas. No shortcuts there[1], sorry.
[1] Well, there are a few libraries for canvas object interaction that allow you to use SVG objects as their objects, such as fabric.js. But depending on what you want this may be nowhere near enough.
I asked a question on SO about compiling an image file from HTML. Michaël Witrant responded and told me about the canvas element and html5.
I'm looked on the net and SO, but i haven't found anything regarding drawing a misc element's contents onto a canvas. Is this possible?
For example, say i have a div with a background image. Is there a way to get this element and it's background image 'onto' the canvas? I ask because i found a script that allows one to save the canvas element as a PNG, but what i really want to do is save a collection of DOM elements as an image.
EDIT
It doesn't matter what language, if it could work, i'm willing to attempt it.
For the record, drawWindow only works in Firefox.
This code will only work locally and not on the internet, using drawWindow with an external element creates a security exception.
You'll have to provide us with a lot more context before we can answer anything else.
http://cutycapt.sourceforge.net/
CutyCapt is a command line utility that uses Webkit to render HTML into PNG, PDF, SVG, etc. You would need to interface with it somehow (such as a shell_exec in PHP), but it is pretty robust. Sites render exactly as they do in Webkit browsers.
I've not used CutyCapt specifically, but it came to me highly recommended. And I have used a similar product called WkHtmlToPdf, which has been awesome in my personal experience.
After many attempts using drawWindow parameters, that were drawing wrong parts or the element, I managed to do it with a two steps processing : first capture the whole page in a canvas, then draw a part of this canvas in another one.
This was done in a XUL extension. drawWindow will not work in other browsers, and may not work in a non-privileged context due to security reasons.
function nodeScreenshot(aSaveLocation, aFileName, aDocument, aCSSSelector) {
var doc = aDocument;
var win = doc.defaultView;
var body = doc.body;
var html = doc.documentElement;
var selection = aCSSSelector
? Array.prototype.slice.call(doc.querySelectorAll(aCSSSelector))
: [];
var coords = {
top: 0,
left: 0,
width: Math.max(body.scrollWidth, body.offsetWidth,
html.clientWidth, html.scrollWidth, html.offsetWidth),
height: Math.max(body.scrollHeight, body.offsetHeight,
html.clientHeight, html.scrollHeight, html.offsetHeight)
var canvas = document.createElement("canvas");
canvas.width = coords.width;
canvas.height = coords.height;
var context = canvas.getContext("2d");
// Draw the whole page
// coords.top and left are 0 here, I tried to pass the result of
// getBoundingClientRect() here but drawWindow was drawing another part,
// maybe because of a margin/padding/position ? Didn't solve it.
context.drawWindow(win, coords.top, coords.left,
coords.width, coords.height, 'rgb(255,255,255)');
if (selection.length) {
var nodeCoords = selection[0].getBoundingClientRect();
var tempCanvas = document.createElement("canvas");
var tempContext = tempCanvas.getContext("2d");
tempCanvas.width = nodeCoords.width;
tempCanvas.height = nodeCoords.height;
// Draw the node part from the whole page canvas into another canvas
// void ctx.drawImage(image, sx, sy, sLargeur, sHauteur,
dx, dy, dLargeur, dHauteur)
tempContext.drawImage(canvas,
nodeCoords.left, nodeCoords.top, nodeCoords.width, nodeCoords.height,
0, 0, nodeCoords.width, nodeCoords.height);
canvas = tempCanvas;
context = tempContext;
}
var dataURL = canvas.toDataURL('image/jpeg', 0.95);
return dataURL;
}