如何为Raphael元素提供随元素移动而移动的填充,例如background-image
HTML元素的CSS position: absolute;
如何在移动时保持相对于其位置的相同位置?
这是一个示例演示:如何将Raphael元素(三角形路径)的背景图像模式拖动为HTML元素(方形div)时的行为相同?
这个问题基本上与偏振眼镜模拟器的 How to make a pattern “fixed” in Raphael.js / IE? 相反 - 我想在所有浏览器(包括所有浏览器)中尝试避免一致的IE特定行为IE8)。
正如其他问题所详述的那样,仅在IE8(VML)中,Raphael元素就像我想要的那样;但即使这是不稳定的:诸如在setSize
元素上调用paper
或重新定义填充(基本上是强制重绘的任何东西)等各种事情会导致它切换到其他行为。
有一个question similar to this for pure SVG,但在撰写本文时没有任何好的答案,当然也没有一个适用于拉斐尔。
编辑2 :观察SVG模式中发生的情况,似乎每个Raphael变换也会自动对svg <pattern>
元素进行相同的矩阵变换。我认为这是导致我试图避免的行为的原因 - 我认为patternContentUnits
和patternUnits
是无关的。这里似乎有一个未解决的问题(在行this.pattern && updatePosition(this);
旁边突出显示与clip-rect相同的问题) - https://github.com/DmitryBaranovskiy/raphael/issues/638
因此,一种可能是to define a custom attribute可以将变换应用于元素而不将其应用于模式。听起来很难 - 可能需要黑客拉斐尔或复制大量拉斐尔变换代码。希望还有其他一些方法。并且god help us making this work in VML ...
编辑3:一些可能相关的信息,不仅仅是有这个问题的路径填充。使用image
创建的Raphael paper.image()
元素在SVG模式下没有这个问题,但是在IE8 VML模式下有一个非常类似的问题。 Here's a demo 有几种方法可以让图像元素移动,这里有一个并排比较,显示它们在非IE中完美运行并且在IE中都失败了:
答案 0 :(得分:3)
我最近偶然发现了类似的问题。我无法在任何地方找到合适的解决方案,所以我想出了自己的解决方案。我使用@ user568458的答案作为起点。首先,我更改了updatePosition函数:
updatePosition = function (o) {
if(!o.data("relativeFill")) { //data is a custom store for user's properties
var bbox = o.getBBox(1);
$(o.pattern, {patternTransform: o.matrix.invert() + " translate(" + bbox.x + "," + bbox.y + ")"});
}
},
我还改变了fill
setFillAndStroke
函数的情况,如下所示:
var relativeFill = o.data("relativeFill"),
isURL = Str(value).match(R._ISURL);
if (isURL) {
el = $("pattern");
var ig = $("image");
el.id = R.createUUID();
$(el, {x: 0, y: 0, patternUnits: relativeFill ? "objectBoundingBox" : "userSpaceOnUse", height: 1, width: 1});
$(ig, {x: 0, y: 0, "xlink:href": isURL[1]});
el.appendChild(ig);
(function (el) {
R._preload(isURL[1], function () {
var w = this.offsetWidth,
h = this.offsetHeight,
bbox = o.getBBox();
$(el, {width: 1, height: 1});
$(ig, {width: relativeFill ? bbox.width : w, height: relativeFill ? bbox.height : h});
o.paper.safari();
});
})(el);
o.paper.defs.appendChild(el);
$(node, {fill: "url(#" + el.id + ")"});
o.pattern = el;
o.pattern && updatePosition(o);
break;
}
然后,只要您想使用它,就必须设置yourElement.data({ relativeFill: true })
以下是相对和重复填充的工作示例:https://codepen.io/mmazur/pen/Gmebrj?editors=0010
我同意@ user568458,这个解决方案非常难看,可能会停止使用未来的Raphael更新。然而,拉斐尔最近没有改变太多,所以我很好地承担了这个风险。
编辑:修正了此处描述的错误:Image blurry when using url fill pattern for svg circle
答案 1 :(得分:1)
修改:
有一个粗略的解决方法,不需要黑客Raphael核心代码,但确实依赖于一个不完全稳定的IE错误,描述https://github.com/DmitryBaranovskiy/raphael/issues/177
它通过在Raphael对象中重命名来隐藏Raphael中的SVG模式对象,导致updatePosition()
不被调用。这会阻止Raphael在SVG模式下移动背景图像。在VML模式下,IE8有一个错误,即使代码移动<fill>
元素,在重新强制重绘之前,屏幕上不会更新。
path.patternTmp = path.pattern;
delete path.pattern;
这与下面的建议有相同的另一个缺点,即在VML模式下它依赖于IE错误。但它适用于简单的情况。我没有完全测试,看看这个修复是否有其他副作用,但不应该 - 看看Raphael的源代码,看起来updatePosition()
是唯一使用{{1}的Raphael函数}}
请注意,每次应用图片填充时都必须重命名element.pattern
- 因此,如果您因任何原因重新应用填充,则需要重新执行此修复 - 并重新应用填充将“修复”我们依赖的IE错误导致图像与对象失去同步。
原始回答:这是一种修复方法。它在两个方面很难看:
但是你可以获得相对位置,只要你的代码不会触发IE重绘(例如通过重新设置元素的填充)。
理想情况下,有一种方法可以在IE VML中稳健地运行,而不是依赖于错误。
你可以通过以某种方式关闭Raphael函数path.pattern
来解决这个问题。上述行为不是SVG默认值,它是updatePosition()
函数中定义的Raphael特性,似乎旨在使Raphael SVG元素的行为与VML元素 行为的行为相匹配Internet Explorer不是一堆bug和错误。请注意,updatePosition()
函数仅在 中以SVG模式调用 - 默认情况下,假定 以此方式运行(但由于重绘而无法可靠地执行此操作)上述链接问题中描述的错误......)。
我(丑陋)这样做的方法是将updatePosition()
功能代码修改为:
updatePosition()
...然后,对于要进行相对填充的每个元素,设置updatePosition = function (o) {
if(!o.relativeFill) { // <<< added this condition
var bbox = o.getBBox(1);
$(o.pattern, {patternTransform: o.matrix.invert() + " translate(" + bbox.x + "," + bbox.y + ")"});
}
},
请注意这不是一种好的做法 - 例如未来的Raphael更新可能会将relativeFill命名空间用于其他内容。这只是一个粘性石膏修复的例子(几乎可以)。
<强>重。 VML模式:理论上,您可以通过在VML模式Raphael函数someElement.relativeFill = true;
和/或{{1}中向该位置添加类似条件,使此修复变得健壮且不依赖于bug将setFillAndStroke
设置为动态计算。这些似乎是setCoords
的VML等价物。理论上,VML应该默认设置相对于形状的填充,只要alignshape = true
for the fill element, which in theory should be true by default。
但是,它似乎在实践中并没有像那样工作。从我的测试来看,依赖于上面的IE错误实际上似乎更多强大,而不是试图让IE VML按照记录的方式工作。在我的测试中,让IE8重绘填充是非常困难的:只重置填充似乎就可以了。