【问题标题】:Scaling SVG (Raphael.js) like an SWF像 SWF 一样缩放 SVG (Raphael.js)
【发布时间】:2010-12-01 09:00:40
【问题描述】:

几天前我开始使用 Raphael.js,我真的很喜欢它。我唯一不知道的是如何让“paper”或 svg/vml 标签像 swf 一样填充浏览器窗口。 See this example.

注意上面的例子随着浏览器窗口调整大小的方式

我能够让“纸张”通过浏览器窗口调整大小,但没有运气让所有矢量图形都调整它们的大小。任何反馈将不胜感激。

编辑

我用这个尝试了很多不同的路线。 viewBox 效果很好,但只有 SVG。我只是想出了如何使用 Raphael 集和 window.onresize 事件上的一些代码来做到这一点。我将在今晚或明天晚些时候发布我的发现。如果有的话,我仍然很想看看这个问题的其他解决方案。

【问题讨论】:

    标签: javascript flash svg raphael vml


    【解决方案1】:

    我花了一段时间,但我终于想出了解决这个问题的方法。我已经将解决​​方案封装在一个可以与 Raphael 一起使用的小 js 文件中。您可以获取 js 文件以及一些简单的文档hereSee it in action.

    工作原理:

    1. 为 svg 使用 viewBox
    2. 将所有 vml 节点包装在一个组节点中
    3. 包装 Raphael 构造函数,以便将 vml 组节点传递给 Raphael 构造函数
    4. 在调整纸张大小时更改一些 css 属性以处理居中、剪裁和保持正确的纵横比。

    任何反馈都将不胜感激。

    【讨论】:

    • 你只能有一个ScaleRaphael实例吗? ...我将 .svg 文件放入缩略图中 ...原始 .svg 大约为 400x400,但拇指为 75x75 ...我一直在为每个拇指使用 Raphael( container_id ) 的唯一实例。 ...但似乎当我切换到new ScaleRaphael( container_id , 75, 75) 时,所有的拇指都集中在一个视觉元素中。
    【解决方案2】:

    你好,泽万,

    我找到了一个很好的答案,由一个叫 Zevan 的人提出。但是,我发现我喜欢的代码过于复杂(必需的 jquery,做了一些奇怪的东西,比如“$(this)”等)。

    所以我简化了它。它现在足够短,可以放入 stackoverflow ;):

    var paper;
    
    window.ScaleRaphael = function(container, width, height) {
        var wrapper = document.getElementById(container);
        wrapper.style.width = width + "px";
        wrapper.style.height = height + "px";
        wrapper.style.overflow = "hidden";
    
        wrapper.innerHTML = "<div id='svggroup'><\/div>";
        var nestedWrapper = document.getElementById("svggroup");
    
        paper = new Raphael(nestedWrapper, width, height);
        paper.w = width;
        paper.h = height;
        paper.canvas.setAttribute("viewBox", "0 0 "+width+" "+height);
        paper.changeSize = function() {
            var w = window.innerWidth
            var h = window.innerHeight
            var ratioW = w / width;
            var ratioH = h / height;
            var scale = ratioW < ratioH ? ratioW : ratioH;
    
            var newHeight = Math.floor(height * scale);
            var newWidth = Math.floor(width * scale);
    
            wrapper.style.width = newWidth + "px";
            wrapper.style.height = newHeight + "px";
            paper.setSize(newWidth, newHeight);
        }
        window.onresize = function() {
            paper.changeSize();
        }
    
        paper.changeSize();
    
        return paper;
    }
    

    您的版本唯一的缺点是它需要 SVG,它不支持 VML。这是个问题吗?

    我将它与您的演示页面的简化版本一起使用:

    <!DOCTYPE html> 
    <html lang="en"> 
    <head>
    <title>ScaleRaphaël Demo 1</title>
    <meta charset="utf-8"> 
    
    <script type="text/javascript" src="raphael.js"></script>
    <script type="text/javascript" src="scale.raphael.js"></script>
    <script type="text/javascript">
    
        window.onload = function() {
            var paper = new ScaleRaphael("wrap", 600, 400);
    
            // draw some random vectors:
            var path = "M " + paper.w / 2 + " " + paper.h / 2;
            for (var i = 0; i < 100; i++){
                var x = Math.random() * paper.w;
                var y = Math.random() * paper.h;
                paper.circle(x, y,
                    Math.random() * 60 + 2).
                    attr("fill", "rgb("+Math.random() * 255+",0,0)").
                    attr("opacity", 0.5);
                path += "L " + x + " " + y + " ";
            }
    
            paper.path(path).attr("stroke","#ffffff").attr("stroke-opacity", 0.2);
    
            paper.text(200,100,"Resize the window").attr("font","30px Arial").attr("fill","#ffffff");
        }
    
          </script>
    <style type="text/css">
        body, html {
            margin: 0;
            padding: 0;
            overflow: hidden;
        }
    
        #wrap{
            background-color: orange;
        }
    </style>
    
    </head>
    <body>
    

    【讨论】:

    • 我知道你没有做 vml 支持,这就是为什么你的调整大小功能没有为 IE 设置?对我来说,Raphael 的很大一部分是对 VML 的支持......所以窗口调整大小方法需要在 IE 中工作
    • 精湛的答案和代码。这只是为我节省了大量的试验和错误。谢谢!
    【解决方案3】:

    调整大小后,您可以根据纸张的新比例循环遍历所有路径并缩放()它们。

    【讨论】:

    • 事实证明如果使用集合并执行 myset.scale(2,2,0,0) 则无需循环
    • @Zeven 有趣!当我使用 raphaël 时,我没有研究场景。
    • 我很快就和我谈过了。不幸的是,如果您缩放一组对象,则不会保留坐标系,这可能会真正搞乱可能正在进行的任何动画。意思是 cx 和 cy 随比例变化。我很确定如果 Raphael 使用的是 transform() SVG 东西,这可以避免。不知道为什么缩放是手动完成的,而不是使用内置的 SVG 功能。也许这与使代码易于与 VML 兼容有关。我会继续调查的。最坏的情况我会写一些插件。
    【解决方案4】:

    您可以在 svg 根元素上添加 'viewBox' 属性来定义坐标系,然后形状将缩放到容器的大小。不确定如何处理 VML 方面的事情。我建议为它报告一个问题,https://github.com/DmitryBaranovskiy/raphael/issues

    【讨论】:

    • 酷,我会试一试 - 我会研究 VML 方面的事情。
    • 这真的很棒。 VML 中的等价物似乎是将所有对象包装在一个组节点中。我这样做了,实际上效果很好。唯一的问题是 Raphael 无法再填充或设置对象样式了。我猜是因为 VML 结构的变化。
    • 我猜在 IE 中,纸张的宽度和高度可以设置为计算父元素尺寸的表达式。
    【解决方案5】:

    这可能只是线程太老了,但 Raphael 2.0 至少有一个 setViewBox 方法 -- http://raphaeljs.com/reference.html#Paper.setViewBox

    您仍然需要将实际画布大小设置为 100%,以便 容器 缩放到窗口,但在 window.resize 回调中使用适当的 w/h 调用 setViewBox 应该做这个伎俩。

    【讨论】:

    • 这是一个同样古老的随机示例,使用 setViewBox 在鼠标滚轮上“缩放” - jsfiddle.net/9zu4U/2
    猜你喜欢
    • 2011-01-21
    • 2012-02-07
    • 2014-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-15
    • 2023-04-07
    相关资源
    最近更新 更多