SVG - 沿路径复制图像

时间:2018-05-27 18:48:10

标签: javascript html html5 image svg

我目前正在尝试通过SVG和javascript创建自行车链。

我尝试创建的结果将如下所示: bicycle chain

我遇到的问题是如何沿着链条的路径重复单个链接图像。我希望能够使用chainlink图像(例如:chainlink 然后沿着我定义的路径重复这个。

我知道通过SVG沿着路径重复文本是微不足道的,但是可以对图像做同样的事情吗?复杂性来自链环必须作为一条连续线出现的事实。

这是我到目前为止所做的:

public class SquareImageView extends AppCompatImageView {
public SquareImageView(Context context) {
    super(context);
}

public SquareImageView(Context context, AttributeSet attrs) {
    super(context, attrs);
}

public SquareImageView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, widthMeasureSpec);//replace heightMeasureSpec with widthMeasureSpec in this line 
}
}

非常感谢任何帮助。 感谢

3 个答案:

答案 0 :(得分:1)

在 SVG 中,我定义了一个链节并根据需要创建尽可能多的副本(参考点位于链节的中心):

<use class="chain chainlink1" xlink:href="#chainlink" />
<use class="chain chainlink2" xlink:href="#chainlink" />
<use class="chain chainlink3" xlink:href="#chainlink" />
<use class="chain chainlink4" xlink:href="#chainlink" />
....

在css中,我定义了要遵循的路径

.chain {
   offset-path: path("m 50,150 c -2,-19 12,-36 24,-44 13,-8 176,-54 226,-56 
                      60,0 100,49.17776 100,100 0,51 -42,99 -100,99 C 262,250 
                      95,206 72,191 58,182 50,166 50,150 Z");
   animation: cycle 20s linear infinite;
}

@keyframes cycle {
  0% { 
    offset-distance: 0%;
  }
  100% { 
     offset-distance: 100%;
  }
}

以及每个chainlink的延迟

.chainlink2 {
  animation-delay: 1s;
}
.chainlink3 {
  animation-delay: 2s;
}
...

持续时间和延迟取决于链节的长度、路径...和所需速度

答案 1 :(得分:0)

以下是一种解决方案:只要您愿意进行数学运算以确保多边形点之间的距离,就可以使<polyline><polygon>元素生成<marker>元素精确匹配链元素的轴到轴距离(即,它不是元素的总长度,而是重复的放置距离)。它需要使用a^2 + b^2 = c^2,其中c是此音高距离(常数),ab分别是前一点的水平和垂直距离。换句话说,你需要计算链轴中心的x,y坐标(*)(如果你这样做,那么你也可以一个接一个地放置它们,但是你会有很多DOM元素)

您需要orient="auto"将链元素与多边形对齐,并使用属性viewBoxrefXrefYmarkerWidthmarkerHeight使得链元素的一个轴与多边形点完美对齐(然后,通过使用上述毕达哥拉斯定理,另一个链元素中心将对应于下一个多边形点)。

以下是<marker>的一些示例:

当我看到你的链条(普通自行车链条)时,最好将两个几乎相同的多边形彼此叠加在一起,两者之间有半间距偏移:

  • 在后台,部分遮挡的链元素
  • 在前景中,8字形,完全可见的链板

因此,只要您的积分位于正确的位置,您的连锁店就会无缝连接。你甚至可以设置一个动画链的相邻元素之间的过渡循环:-)(它足以仅与链间距过渡,因为链间距平移会让你回到难以区分的视图)

(*)当ccprog指出below时,为了使各个链元素更好地对齐,它不是轴中心,而是必须位于多边形上的链中心。如果出现急转弯,这可能会使数学运算变得冗长乏味,但在这种特殊情况下(自行车链条),圆半径似乎足够大,不会导致链元素明显分离。

答案 2 :(得分:0)

我试图实际实施Robert Monfera的答案,并发现了一些额外的故障。我开始计算多边形坐姿的点,如他所描述的那样,在各个链节的轴/连接销处,并且它们之间的距离完全相同。

如果你看一下就会立刻发出一件事,那就是链条不是一条平滑的线条。对于人眼来说,它可能看起来像一个,但描述围绕齿轮运行的链条是一个圆弧是一个不好的近似。

看看问题中的图片。右齿轮有15个齿。这意味着相邻链节之间的角度是24°,并且弧与点之间的长度差异从点到点(链节的构造长度)是大约。 0.8%。这听起来不是很多,但对于你用50px的屏幕尺寸绘制的链接,它几乎是半个像素。这是可以看到的差异。

下一个建议是使用<marker>元素作为单个链接链接,两个引脚之间的中心位于原点。由于上面定义的多边形的点位于引脚的位置,因此需要连接所有多边形线段的中间的第二个。

实现时,生成的链看起来像这样(我在顶部画了多边形来说明):

enter image description here

当链条的“直线”部分变形为“弯曲”部分时,链节严重错位。原因是标记方向将顶点处的入射和出射切线一分为二。对于直线部分和跟随齿轮弧线的情况,这都是正确的,但是两者都相遇,显然不会。

要使标记的方向正确,点处的切线必须与原始多边形的方向匹配。罗伯特建议在两点之间画一条弧线。这个概率可行,但计算正确的弧半径和位置很复杂。

我想出了一种方法,可以产生一条看起来有点弯曲的平滑路径,但是这条线最终不会显示出来,而且它的计算非常简单 - 我实际上是用Excel工作表做的。

假设我们有一个标记销位置的点列表:

a    b    c    d    e    f    g ...

有两种链接(正面和背面),因此标记两点的每隔一个中间位置:

a    b    c    d    e    f    g ...
  ab        cd        ef

a, ab, c在一条直线上,与c, cd, d相同,依此类推。现在,如果您使用以下命令绘制路径

<path d="M a L ab C b c cd d e ef f g ..." marker-mid="url(#link1)" />

a将不会保留标记,因为它不在中间。定位标记的下一个顶点是ab, cd, ef, ...,而b, c, d, e, ...是三次贝塞尔曲线的控制点。这意味着:顶点ab中的路径切线是ab的直线,cdcd的直线等等。

以下是来自Inkscape的截图:

enter image description here

其他链接可以相应地描述为

<path d="M b L bc C c d de e f fg g ..." marker-mid="url(#link2)" />

如果想要变得有意思,甚至可以用S命令缩短一点,该命令在顶点之前取控制点并且隐含地将其反射添加为之后的下一个控制点(points {{ 1}}计算):

e, g, ...

对于大结局,这是完成的绘图。只是为了它,我用相同的标记技术绘制了齿轮齿。

<path d="M b L bc C c d de S f fg h hj ..." marker-mid="url(#link2)" />