Skip to content

Instantly share code, notes, and snippets.

@medJemmoudi
Created August 12, 2019 14:13
Show Gist options
  • Save medJemmoudi/89fd100d38493e83adcd0c63bb6f6122 to your computer and use it in GitHub Desktop.
Save medJemmoudi/89fd100d38493e83adcd0c63bb6f6122 to your computer and use it in GitHub Desktop.
class ClipPath {
/**
* Checks if css property clip-path supports 'polygon()' attribute
* @return {Boolean} Return TRUE if browser has support
*/
hasSupportToPolygon = (function () {
var testEl = document.createElement('div');
var propValue = 'polygon(0 0, 0 0, 0 0, 0 0)';
testEl.style.clipPath = propValue;
return testEl.style.clipPath === propValue;
})();
/**
* Generate an unique identifier
* @return {String}
*/
getUniqueID = () => {
return 'clip-path-' + Math.random().toString(36).substring(7);
}
/**
* Use SVG polygon
*/
SVGPolyfill = (element, pathPoints, edge) => {
var units = 'px';
var svgUnits = 'userSpaceOnUse';
if(pathPoints.indexOf('%') !== -1){
units = '%';
svgUnits = 'objectBoundingBox';
}
pathPoints = pathPoints.replace(/px|em|%/g, '');
// Remove units from path
if(units !== 'px'){
var finishedPathPoints = '';
var arrayPathPoints = pathPoints.split(', ');
for (var i = 0; i < arrayPathPoints.length; i++)
{
var item = arrayPathPoints[i];
var arrayPathPoint = item.split(' ');
var lN = Number(arrayPathPoint[0]), rN = Number(arrayPathPoint[1]);
if(lN !== 0){
lN = (lN/100);
}
if(rN !== 0){
rN = (rN/100);
}
finishedPathPoints += lN+' '+rN;
if(i < (arrayPathPoints.length - 1)){
finishedPathPoints += ', ';
}
}
pathPoints = finishedPathPoints;
}
var elClipPathId = element.getAttribute('data-clip-path-id');
if(elClipPathId) {
var actualClipPath = document.getElementById(elClipPathId);
actualClipPath.setAttribute('clipPathUnits', svgUnits);
var actualPolygon = document.querySelector('#' + elClipPathId + ' > polygon');
actualPolygon.setAttribute('points', pathPoints);
} else {
var clipPathID = this.getUniqueID();
var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
svg.setAttribute('width', '0');
svg.setAttribute('height', '0');
svg.setAttribute('data-clip-path-id', clipPathID);
svg.setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:xlink', 'http://www.w3.org/1999/xlink');
if(edge){
if(element.getAttribute('class')){
svg.setAttribute('class', element.getAttribute('class'));
}
element.setAttribute('class', '');
element.style.width = "100%";
element.style.height = "100%";
svg.style.width = "100%";
svg.style.height = "100%";
var defs = document.createElementNS('http://www.w3.org/2000/svg', 'defs');
var clipPath = document.createElementNS('http://www.w3.org/2000/svg', 'clipPath');
clipPath.setAttribute('id', clipPathID);
clipPath.setAttribute('clipPathUnits', svgUnits);
var polygon = document.createElementNS('http://www.w3.org/2000/svg', 'polygon');
polygon.setAttribute('points', pathPoints);
var foreignObject = document.createElementNS('http://www.w3.org/2000/svg', 'foreignObject');
foreignObject.setAttribute('clip-path', 'url(#'+clipPathID+')');
foreignObject.setAttribute('width', '100%');
foreignObject.setAttribute('height', '100%');
foreignObject.appendChild(element.cloneNode(true));
svg.appendChild(foreignObject);
clipPath.appendChild(polygon);
defs.appendChild(clipPath);
svg.appendChild(defs);
element.parentNode.replaceChild(svg, element);
}else{
var clipPath = document.createElementNS('http://www.w3.org/2000/svg', 'clipPath');
clipPath.setAttribute('id', clipPathID);
clipPath.setAttribute('clipPathUnits', svgUnits);
var polygon = document.createElementNS('http://www.w3.org/2000/svg', 'polygon');
polygon.setAttribute('points', pathPoints);
clipPath.appendChild(polygon);
svg.appendChild(clipPath);
document.body.appendChild(svg);
element.setAttribute('data-clip-path-id', clipPathID);
setTimeout(function () {
element.style.clipPath = 'url(#' + clipPathID + ')';
}, 0);
}
}
}
/**
* Apply clip path
*/
applyClipPath = (element, pathPoints, _supportPolygon) => {
_supportPolygon = typeof _supportPolygon !== 'undefined' ? _supportPolygon : this.hasSupportToPolygon;
// Chrome / Safari
if(typeof(element.style.webkitClipPath) !== 'undefined'){
element.style.webkitClipPath = 'polygon(' + pathPoints + ')';
// Unprefixed support
} else if(_supportPolygon){
element.style.clipPath = 'polygon(' + pathPoints + ')';
// SVG
} else {
//Edge
if(window.navigator.userAgent.indexOf("Edge") > -1){
this.SVGPolyfill(element, pathPoints, true);
//Other
}else{
this.SVGPolyfill(element, pathPoints);
}
}
}
/**
* Main function
*/
make = (selector, pathPoints, supportPolygon) => {
if(!selector) {
console.error('Missing selector');
return false;
}
var nodeList = document.querySelectorAll(selector || '');
nodeList.forEach((element) => {
var elementPathPoints = element.getAttribute('data-clip') || pathPoints;
if(elementPathPoints) {
this.applyClipPath(element, elementPathPoints, supportPolygon);
} else {
console.error('Missing clip-path parameters. Please check ClipPath() arguments or data-clip attribute.', element);
}
});
}
}
export { ClipPath };
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment