24

How can i rescale all the element inside a Raphael canvas on window change ?

considering the following code / DEMO if i re-size my window only div container scaled since i set its width to 50% of the window width and none of the (rect , circle or path) change

CODE

<div id="container"></div>​
 #container{border : 1px solid black ;
               width : 50% ;
               height:300px}​
var con = $("#container");
var paper = Raphael(con.attr('id'), con.attr('width'), con.attr('height'));
var win = paper.rect(0,0,400,300).attr({stroke: 'black' }) ; 
var path = paper.path("M 200 100 l 100 0 z") ; 
var cir = paper.circle(50, 50, 40);

Mina Gabriel
  • 23,150
  • 26
  • 96
  • 124

4 Answers4

31

If you use Raphaël version 2.0 or later an alternative is to call paper.setViewBox to setup your coordinate system, and then let the browsers handle the resizing automatically.

Update: Ok, turns out Raphaël is a bit less auto-scalable than I thought... anyway, here's an example (raphaël still sets an absolute width/height on the root <svg>, so they need to be removed for normal svg scaling to take place). The size is then decided by CSS, and the svg is just fit into the area given. It's possible to tweak this to deal with overflowing content, which can happen due to the svg viewBox aspect-ratio not matching the CSS box it's placed into. You do this by adding a preserveAspectRatio attribute to the root svg element.

You can read more about the values you can set on the svg preserveAspectRatio attribute here, but the three values that are probably of interest are 'none' (for squeezing/stretching to fit whatever rect is given), 'xMidYMid slice' (to scale up to fill the rect, possibly clipping away some parts if the aspect doesn't match), 'xMidYMid meet' (this is the default, same as not specifying pAR at all, and means the content will be centered and will overflow in one direction if aspect doesn't match).

David Sýkora
  • 574
  • 1
  • 3
  • 16
Erik Dahlström
  • 59,452
  • 12
  • 120
  • 139
  • can you edit this to my [jsfiddle](http://jsfiddle.net/minagabriel/vHXCc/) , i really appreciated , because i don't really know how to do this – Mina Gabriel Jun 25 '12 at 14:21
  • caveat: this may not work fully for the VML backend (IE8 and lower), please test. – Erik Dahlström Jun 25 '12 at 22:40
  • Erik, your fiddle doesn't work (anymore). Removing width and height renders nothing at all. That said, you needn't actually remove anything and instead _resize the canvas_ on window resizing. As a quick test, you can just add `paper.setSize(300, 200);` to your fiddle after creation of the paper to see that it scales instantly. Note, however, that `setViewBox()` only has a Boolean parameter for scaling and thus doesn't expose all SVG scaling options. However, you can easily assign a different option after the fact, e.g.: `paper.canvas.setAttribute('preserveAspectRatio', 'xMidYMid meet');` – mklement0 Dec 15 '12 at 15:43
  • 5
    @mklement it still works (firefox, opera), looks like webkit changed/broke recently then (try http://jsfiddle.net/AUNwC/44/ instead, it sets the svg width/height in CSS too, then you get something in webkit too). You can of course do manual resizing like you suggest, but it shouldn't actually be needed for svg-capable browsers - just give it a viewBox and an area to render in (using CSS) and it will render at that size. – Erik Dahlström Dec 15 '12 at 16:37
  • 5
    Thanks, Erik. Turns out that _your CSS fix obviates the need for removing the `width` and `height` attributes_ - scaling works in a cross-browser fashion just based on that, even with the explicit attributes present. I've forked your fiddle and added more comments here: http://jsfiddle.net/mklement/7rpmH/ For better cross-browser testing, I've also worked around a Raphael bug by explicitly specifying stretching/shrinking without preserving aspect ratio (`preserveAspectRatio='none'`). Scaling then works in current versions of Chrome, Safari, FF, Opera - sadly, to varying extents - see fiddle. – mklement0 Dec 15 '12 at 22:08
21

http://jsfiddle.net/vnTQT/

    var paper = Raphael("wrap");
    paper.setViewBox(0,0,w,h,true);
    paper.setSize('100%', '100%');

Used this (paper.setViewBox) with paper.setSize('100%', '100%') and resize of window with resize of svg content working without using svg functions direcly.

  • but unfortunately height seems to be fit screen, which cover other content in the page :(. anybody has solution for this issue ? **http://jsfiddle.net/vnTQT/22/** – Mo. May 24 '13 at 08:38
  • setting a 'max-height: 300px;' or whatever on the svg or its container worked for me. – r8n5n Nov 27 '13 at 15:41
4

i think i found a solution : the following code will re scale all the element when re size the window , and this is what i was looking for

            var w = $(window).width();
            var h = $(window).height();
            function draw(w, h) {
                var paper = Raphael($('#wrap').attr('id'), w, h);
                paper.setViewBox(0, 0, 1500, 1500, true);
                var rec = paper.rect(0, 0, 200, 200).attr({ stroke: 'black' });
                var cir = paper.circle(100, 100, 50);
            };
            draw(w, h);
            function resize() {
                var xw = $(window).width();
                var xh = $(window).height();
                draw(xw, xh)
            }
            $(window).resize(resize);

reference from @Erik Dahlström : Paper.setViewBox(x, y, w, h, fit) AND ‘viewBox’ attribute

David Sýkora
  • 574
  • 1
  • 3
  • 16
Mina Gabriel
  • 23,150
  • 26
  • 96
  • 124
0

If you have a set of elements to resize, you can use directly in your js code ...

for (var i = 0; i < your_set.length; i++) {
    your_set[i].scale(ratio, ratio, 0,0);
};

... and a function to reload the page on browser resizing:

window.addEventListener('resize', function () { 
    "use strict";
    window.location.reload(); 
});
John Slegers
  • 45,213
  • 22
  • 199
  • 169
mquantin
  • 1,085
  • 8
  • 23