javascript 像 SWF 一样缩放 SVG (Raphael.js)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4322660/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-25 11:01:18  来源:igfitidea点击:

Scaling SVG (Raphael.js) like an SWF

javascriptflashsvgraphaelvml

提问by Zevan

I started using Raphael.js a few days ago and I'm really enjoying it. The only thing I haven't been able to figure out is how to get the "paper" or svg/vml tag to fill the browser window like an swf. See this example.

几天前我开始使用 Raphael.js,我真的很喜欢它。我唯一无法弄清楚的是如何让“paper”或 svg/vml 标签像 swf 一样填充浏览器窗口。请参阅此示例。

Note the way the above example resizes with the browser window

请注意上述示例随浏览器窗口调整大小的方式

I was able to get the "paper" to resize with the browser window, but no luck getting all the vector graphics to adjust their size. Any feedback would be greatly appreciated.

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

EDIT

编辑

I tried a bunch of different routes with this. viewBox worked great but its SVG only. I just figured out how to do it using Raphael sets and a little code on the window.onresize event. I'll post my findings later tonight or tomorrow. I'd still really like to see other solutions to the question if there are any.

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

回答by Zevan

It took me awhile but I finally came up with a solution to this problem. I've wrapped the solution in a small js file that can be used with Raphael. You can get the js file along with some simple documentation here. See it in action.

我花了一段时间,但我终于想出了解决这个问题的办法。我已经将解决​​方案包装在一个可以与 Raphael 一起使用的小 js 文件中。您可以在此处获取 js 文件以及一些简单的文档。看到它在行动

How it works:

怎么运行的:

  1. use viewBox for svg
  2. wrap all vml nodes in a group node
  3. wrap the Raphael constructor up so that the vml group node is passed to the Raphael constructor
  4. alter a few css properties when the paper is resized to deal with centering, clipping and maintaining the correct aspect ratio.
  1. 将 viewBox 用于 svg
  2. 将所有 vml 节点包装在一个组节点中
  3. 将 Raphael 构造函数包装起来,以便将 vml 组节点传递给 Raphael 构造函数
  4. 调整纸张大小时更改一些 css 属性以处理居中、剪切和保持正确的纵横比。

Any feedback would be greatly appreciated.

任何反馈将不胜感激。

回答by Zevan

Well hello Zévan,

好吧,你好泽万,

I found a nice answer, made by a guy called Zevan. However, I found the code overcomplicated for my liking (Required jquery, did wierd stuff like "$(this)" etc).

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

So I simplified it. It's now short enough to fit into stackoverflow ;):

所以我简化了它。它现在足够短以适合 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;
}

The only drawback from your version is that it requires SVG, it doesn't do VML. Is this a problem?

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

I'm using it with a simplified version of your demo page:

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

<!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>

回答by drzaus

This might just be too old of a thread, but Raphael 2.0 at least has a setViewBoxmethod -- http://raphaeljs.com/reference.html#Paper.setViewBox

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

You'll still need to set the actual canvas size to 100%, so the containerscales to the window, but calling setViewBoxwith appropriate w/h in your window.resize callback should do the trick.

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

回答by Gipsy King

You could loop over all paths and scale() them acording to the new scale of the paper after resizing it.

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

回答by Erik Dahlstr?m

You could add a 'viewBox'attribute on the svg root element to define the coordinate system, the shapes will then scale to whatever the size of the container is. Not sure how to deal with the VML side of things though. I'd suggest reporting an issue for it, https://github.com/DmitryBaranovskiy/raphael/issues.

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