RaphaelJS - 标准化svg路径形状大小

时间:2014-02-10 15:56:00

标签: javascript jquery svg raphael

我正在使用非常简单的usmap jquery plugin使用Raphael构建一个拥有美国svg地图的网站。如果您单击某个州,我会触发一个点击事件。

在那个场合,我转到同一个美国州的对象来渲染一个州。问题是列表中每个状态的路径在整个美国州地图中呈现的相对于彼此。

但我的要求是,当我查看单个状态时,我需要渲染每个状态大小相同的状态。

我知道我可以在路径参数上加倍,整体状态会增加/减少,但我正在寻找一种方法来动态确定这个乘数。

我也试过使用setViewBox,希望它能增加/减少< path>填补该地区。但据我所知,它没有用。

所以,要么我需要制作< path>填充空格或我需要找出一个乘数来应用于缩放< path>

// state coords pulled from All states svg file
var statePolygon = "M 93.573239,6.3617734 L 97.938071,7.8167177 L 107.6377,10.564946 L 116.2057,12.504871 L 136.2516,18.162988 L 159.20739,23.821104 L 174.36801,27.215777 L 173.36373,31.099829 L 169.27051,44.909503 L 164.81238,65.714155 L 161.63584,81.854036 L 161.28429,91.232806 L 148.10315,87.33877 L 132.53264,83.955591 L 118.86585,84.551329 L 117.28528,83.01913 L 111.95881,84.916253 L 107.9821,84.665645 L 105.2606,82.904814 L 103.68223,83.430208 L 99.476903,83.201576 L 97.601755,81.829846 L 92.824862,80.093194 L 91.382778,79.886558 L 86.397035,78.560984 L 84.614222,80.069004 L 78.922841,79.726077 L 74.101997,75.931831 L 74.30643,75.131651 L 74.374575,67.197996 L 72.248826,63.31142 L 68.133618,62.57938 L 67.768708,60.225014 L 65.2543,59.597968 L 62.372763,59.063086 L 60.594498,60.033049 L 58.331251,57.123161 L 58.654572,54.213272 L 61.4028,53.889951 L 63.019405,49.84844 L 60.432837,48.716816 L 60.594498,44.998625 L 64.959331,44.351984 L 62.211103,41.603756 L 60.756158,34.490695 L 61.4028,31.580807 L 61.4028,23.659444 L 59.624535,20.426234 L 61.887782,11.049927 L 63.989368,11.534908 L 66.414275,14.444797 L 69.162503,17.031364 L 72.395712,18.97129 L 76.922205,21.072876 L 79.993756,21.719518 L 82.903645,23.174462 L 86.298518,24.144425 L 88.561764,23.982765 L 88.561764,21.557857 L 89.855048,20.426234 L 91.956634,19.13295 L 92.279955,20.264574 L 92.603276,22.042839 L 90.340029,22.52782 L 90.016708,24.629406 L 91.794974,26.084351 L 92.926597,28.509258 L 93.573239,30.449183 L 95.028183,30.287523 L 95.189843,28.994239 L 94.219881,27.700955 L 93.734899,24.467746 L 94.543201,22.689481 L 93.89656,21.234537 L 93.89656,18.97129 L 95.674825,15.41476 L 94.543201,12.828192 L 92.118294,7.9783781 L 92.441615,7.1700758 z M 84.116548,12.340738 L 86.137312,12.179078 L 86.622294,13.553197 L 88.158073,11.936582 L 90.502155,11.936582 L 91.310458,13.472361 L 89.774678,15.169801 L 90.42133,15.978114 L 89.693853,17.998875 L 88.319734,18.403021 C 88.319734,18.403021 87.430596,18.483857 87.430596,18.160536 C 87.430596,17.837215 88.885551,15.573958 88.885551,15.573958 L 87.188111,15.008141 L 86.86479,16.463095 L 86.137312,17.109737 L 84.60153,14.84648 z";
var width = 175, 
    height = 125,
    paper = Raphael(document.getElementById("statemap"), 350, 250);

paper.setViewBox(0, 0, width, height, true);
//  paper.canvas.setAttribute('preserveAspectRatio', true);
paper.path(statePolygon);

有人有什么想法吗?

更新

所以,我想通过(谢谢,乔丹)你可以通过捕捉所有X坐标之间的差异得到一个“大小”维度(如果你愿意,可以用y完成。)通过计算差异在最低X和最高X之间你可以得到一个尺寸。

如果你然后弄清楚“正常”大小是什么,那么你可以确定一个乘数应用于每个状态,作为状态相对于“正常”状态的一小部分。

在我的例子中,堪萨斯州的差异为128. CT为29,因此CT需要4.41的乘数才能达到堪萨斯州的相对大小。 TX为242,所以它需要一个0.53的乘数来降低它。

这会规范状态的大小。如果您使用Raphael,则需要增加/减少此值,您可以使用转换函数:

p = paper.path(statePolygonNew);
var scale = 1.5;
p.transform("t" + scale*52 + "," + scale*32 + " s" + scale + "");

谢谢, 斯科特

1 个答案:

答案 0 :(得分:1)

有许多不同的方法可以解决这个问题。这是其中两个。

将视图框与现有路径匹配

当您第一次寻求解决方案时,您使用的方法不正确。视图框本质上是一种机制,用于动态缩放SVG中的坐标转换为屏幕坐标的方式。通过将视图框设置为屏幕坐标中svg的尺寸,您实际上是在告诉它什么也不做 - 这是默认情况下的作用。

相反,请尝试将视图框设置为目标路径的边界框:

var statePathString = "...";  // your path here
var statePath = paper.path( statePathString ).attr( { /* your attributes */ } );
var bbox = statePath.getBBox();
paper.setViewBox( bbox.x, bbox.y, bbox.width, bbox.height, true );

这会实例化状态的路径,计算其尺寸,并缩放视图框以查看只是 SVG坐标系的范围。您可能需要添加其他逻辑来保留纵横比并添加边距,但这绝对是最简单的方法。

转换路径以适合您现有的视窗

如果您选择避免使用视图框操作 - 有一些正当理由 - 那么您可以使用一些Raphael的内置实用程序功能调整路径以匹配默认的查看矩形。这是我使用的方法,因为现有变量widthheight反映了论文的维度:

var bbox = Raphael.pathBBox( statePathString );  // Handy function to retrieve a bounding box without instantiating a path

//  Calculate larger of the two dimensional quotients
var scale = Math.max( bbox.width / width, bbox.height / height );

//  Finally, transform the path such that it is translated to have its origin at 0,0 and scaled in such a way that it will fill the SVG
var transformedPathString = Raphael.transformPath( statePathString,
                                                   [ "T", 0 - bbox.x, 0 - bbox.y,   /* Shift up and left so upper-left extent corresponds to 0,0 */
                                                     "S", 1.0 / scale, 1.0 / scale, 0, 0 ] );

此时你可以做任何你想做的转换路径 - 可能会把它传递给paper.path并设置它。