cui*_*ing 12 javascript firefox svg
SVG 1.1规范:5.11.2接口SVGSVGElement
由于Firefox不支持getIntersectionList,getEnclosureList,checkIntersection,checkEnclosure方法,是否有polyfill?或者如何在javascript中为4种方法编写polyfill?
不幸的是,我认为目前 Firefox 中还没有针对这些功能的官方 polyfill。
我尝试了一下,看看是否有一种方法可以使用可用的 API 轻松填充这些函数。
我故意分配了第二个函数,以便我们可以将原始支持的函数(当使用原生支持它的浏览器(例如 Chrome)时)与 polyfill 进行比较。
所以,我们在这里getIntersectionList:
const getIntersectionListPolyfill = function(rect, referenceElement) {
var intersectionList = [];
var root = this.ownerSVGElement || this;
// Get all elements that intersect with rect
var elements = root.querySelectorAll('*');
for (var i = 0; i < elements.length; i++) {
var element = elements[i];
if (element !== this && element instanceof SVGGraphicsElement) {
var bbox = element.getBBox();
if (rect.width && rect.height && bbox.width && bbox.height) {
if (bbox.x + bbox.width > rect.x &&
bbox.y + bbox.height > rect.y &&
bbox.x < rect.x + rect.width &&
bbox.y < rect.y + rect.height) {
intersectionList.push(element);
}
}
}
}
// Sort elements in document order
intersectionList.sort(function(a, b) {
return (a.compareDocumentPosition(b) & 2) ? 1 : -1;
});
// Filter elements by referenceElement
if (referenceElement) {
intersectionList = intersectionList.filter(function(element) {
return element === referenceElement || element.contains(referenceElement);
});
}
return intersectionList;
}
if (!SVGElement.prototype.getIntersectionList) {
SVGElement.prototype.getIntersectionList = getIntersectionListPolyfill;
}
// The code below is for the snippet only
SVGElement.prototype.getIntersectionList2 = getIntersectionListPolyfill;
const mySVG = document.getElementById('mySVG');
const myRect = mySVG.createSVGRect();
myRect.width = myRect.height = 1;
myRect.x = myRect.y = 20;
console.log('Original', mySVG.getIntersectionList(myRect, null).length);
console.log('Polyfill', mySVG.getIntersectionList2(myRect, null).length);Run Code Online (Sandbox Code Playgroud)
svg {
display: block;
border: 1px solid #000;
margin: 20px 0;
visibility: visible;
}
rect, circle {
fill: rgba(255, 0, 0, 0.2);
visibility: visiblePainted;
}Run Code Online (Sandbox Code Playgroud)
<svg id="mySVG" width="500" height="400">
<rect x="10" y="10" width="200" height="100"></rect>
<rect x="20" y="20" width="200" height="100"></rect>
<circle cx="70" cy="70" r="50"></circle>
</svg>Run Code Online (Sandbox Code Playgroud)
这个polyfillSVGElement使用模仿getIntersectionList本机实现的函数扩展了原型。它用于querySelectorAll获取 SVG 的每个元素并检查它们是否与给定的矩形相交。然后,它按文档顺序对元素进行排序,并按参考元素(如果提供)过滤它们。
getEnclosureList非常相似:
const getEnclosureListPolyfill = function(rect, referenceElement) {
var enclosureList = [];
var root = this.ownerSVGElement || this;
// Get all elements that are completely enclosed by rect
var elements = root.querySelectorAll('*');
for (var i = 0; i < elements.length; i++) {
var element = elements[i];
if (element !== this && element instanceof SVGGraphicsElement) {
var bbox = element.getBBox();
if (rect.width && rect.height && bbox.width && bbox.height) {
if (bbox.x >= rect.x &&
bbox.y >= rect.y &&
bbox.x + bbox.width <= rect.x + rect.width &&
bbox.y + bbox.height <= rect.y + rect.height) {
enclosureList.push(element);
}
}
}
}
// Sort elements in document order
enclosureList.sort(function(a, b) {
return (a.compareDocumentPosition(b) & 2) ? 1 : -1;
});
// Filter elements by referenceElement
if (referenceElement) {
enclosureList = enclosureList.filter(function(element) {
return element === referenceElement || element.contains(referenceElement);
});
}
return enclosureList;
};
if (!SVGElement.prototype.getEnclosureList) {
SVGElement.prototype.getEnclosureList = getEnclosureListPolyfill;
}
// The code below is for the snippet only
SVGElement.prototype.getEnclosureList2 = getEnclosureListPolyfill;
const mySVG = document.getElementById('mySVG');
const myRect = mySVG.createSVGRect();
myRect.width = myRect.height = 210;
myRect.x = myRect.y = 0;
console.log('Original', mySVG.getEnclosureList(myRect, null).length);
console.log('Polyfill', mySVG.getEnclosureList2(myRect, null).length);Run Code Online (Sandbox Code Playgroud)
svg {
display: block;
border: 1px solid #000;
margin: 20px 0;
visibility: visible;
}
rect, circle {
fill: rgba(255, 0, 0, 0.2);
visibility: visiblePainted;
}Run Code Online (Sandbox Code Playgroud)
<svg id="mySVG" width="500" height="400">
<rect x="10" y="10" width="200" height="100"></rect>
<rect x="20" y="20" width="200" height="100"></rect>
<circle cx="70" cy="70" r="50"></circle>
</svg>Run Code Online (Sandbox Code Playgroud)
这个polyfillSVGElement使用模仿getEnclosureList本机实现的函数扩展了原型。它用于querySelectorAll获取 SVG 的每个元素并检查它们是否完全被给定的矩形包围。然后,它按文档顺序对元素进行排序,并按参考元素(如果提供)过滤它们。
checkIntersection现在:
const checkIntersectionPolyfill = function(element, rect) {
var root = this.ownerSVGElement || this;
// Get the bounding boxes of the two elements
var bbox1 = element.getBBox();
var bbox2 = rect;
// Check if the two bounding boxes intersect
if (bbox1.x + bbox1.width > bbox2.x &&
bbox1.y + bbox1.height > bbox2.y &&
bbox2.x + bbox2.width > bbox1.x &&
bbox2.y + bbox2.height > bbox1.y) {
// Check if the two elements actually intersect
var intersection = root.createSVGRect();
intersection.x = Math.max(bbox1.x, bbox2.x);
intersection.y = Math.max(bbox1.y, bbox2.y);
intersection.width = Math.min(bbox1.x + bbox1.width, bbox2.x + bbox2.width) - intersection.x;
intersection.height = Math.min(bbox1.y + bbox1.height, bbox2.y + bbox2.height) - intersection.y;
return intersection.width > 0 && intersection.height > 0;
} else {
return false;
}
};
if (!SVGElement.prototype.checkIntersection) {
SVGElement.prototype.checkIntersection = checkIntersectionPolyfill;
}
// The code below is for the snippet only
SVGElement.prototype.checkIntersection2 = checkIntersectionPolyfill;
const mySVG = document.getElementById('mySVG');
const myRect1 = document.getElementById('myRect1');
const myRect2 = mySVG.createSVGRect();
myRect2.width = myRect2.height = 100;
myRect2.x = myRect2.y = 0;
console.log('Original', mySVG.checkIntersection(myRect1, myRect2));
console.log('Polyfill', mySVG.checkIntersection2(myRect1, myRect2));Run Code Online (Sandbox Code Playgroud)
svg {
display: block;
border: 1px solid #000;
margin: 20px 0;
visibility: visible;
}
rect, circle {
fill: rgba(255, 0, 0, 0.2);
visibility: visiblePainted;
}Run Code Online (Sandbox Code Playgroud)
<svg id="mySVG" width="500" height="400">
<rect id="myRect1" x="10" y="10" width="200" height="100"></rect>
</svg>Run Code Online (Sandbox Code Playgroud)
这个polyfillSVGElement使用模仿checkIntersection本机实现的函数扩展了原型。它使用基于矩形交集的简单算法检查两个元素是否相交。如果两个边界框相交,它会创建一个SVGRect表示相交的对象,并检查它是否具有正面积,表明两个元素实际上相交。
checkEnclosure可能是最容易实现的:
const checkEnclosurePolyfill = function(element, rect) {
var root = this.ownerSVGElement || this;
// Get the bounding boxes of the two elements
var bbox1 = rect;
var bbox2 = element.getBBox();
// Check if bbox2 is completely enclosed by bbox1
return bbox1.x <= bbox2.x &&
bbox1.y <= bbox2.y &&
bbox1.x + bbox1.width >= bbox2.x + bbox2.width &&
bbox1.y + bbox1.height >= bbox2.y + bbox2.height;
};
if (!SVGElement.prototype.checkEnclosure) {
SVGElement.prototype.checkEnclosure = checkEnclosurePolyfill;
}
// The code below is for the snippet only
SVGElement.prototype.checkEnclosure2 = checkEnclosurePolyfill;
const mySVG = document.getElementById('mySVG');
const myRect1 = document.getElementById('myRect1');
const myRect2 = mySVG.createSVGRect();
myRect2.width = myRect2.height = 250;
myRect2.x = myRect2.y = 0;
console.log('Original', mySVG.checkEnclosure(myRect1, myRect2));
console.log('Polyfill', mySVG.checkEnclosure2(myRect1, myRect2));Run Code Online (Sandbox Code Playgroud)
svg {
display: block;
border: 1px solid #000;
margin: 20px 0;
visibility: visible;
}
rect, circle {
fill: rgba(255, 0, 0, 0.2);
visibility: visiblePainted;
}Run Code Online (Sandbox Code Playgroud)
<svg id="mySVG" width="500" height="400">
<rect id="myRect1" x="10" y="10" width="200" height="100"></rect>
</svg>Run Code Online (Sandbox Code Playgroud)
这个polyfillSVGElement使用模仿checkEnclosure本机实现的函数扩展了原型。它检查第一个元素是否完全被第二个元素包围。
| 归档时间: |
|
| 查看次数: |
325 次 |
| 最近记录: |