Created
November 9, 2018 10:13
-
-
Save Akiyamka/ef4786f62e23a3b3f8ea6724debaa6fe to your computer and use it in GitHub Desktop.
blend-mode-polyfill
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* @author Boggddan <github.com/boggddan> | |
* Запускается в браузерах которые не поддерживают свойство background-blend-mode. | |
* Полифил применяется к тегам помеченым атрибутом `data-background-blend-mode` в свойтвах которого нужно передать режим смешивания. | |
* Поддерживается: normal, multiply, lighten, screen, darken. (протестировано в IE 11) | |
* @example: <div data-background-blend-mode="multiply"></div> | |
*/ | |
/* Element.prepend polyfill for IE 11 */ | |
function prependPolyfill() { | |
const docFrag = document.createDocumentFragment(); | |
Array.prototype.slice.call(arguments).forEach(function(argItem) { | |
docFrag.appendChild( | |
argItem instanceof Node | |
? argItem | |
: document.createTextNode(String(argItem)) | |
); | |
}); | |
this.insertBefore(docFrag, this.firstChild); | |
} | |
[ | |
Element.prototype, | |
Document.prototype, | |
DocumentFragment.prototype | |
].forEach(proto => { | |
if (proto.prepend) return; | |
proto.prepend = prependPolyfill; | |
}); | |
/* window.NodeList polyfill for IE 11 */ | |
if (window.NodeList && !NodeList.prototype.forEach) { | |
NodeList.prototype.forEach = Array.prototype.forEach; | |
} | |
/* blend-mode polyfill */ | |
(() => { | |
const currentBlendMode = window.getComputedStyle(document.body).backgroundBlendMode; | |
const isBlendModeNotSupport = currentBlendMode === undefined; | |
function createSVGFilter({ backgroundImage, backgroundColor, backgroundBlendMode }) { | |
const uniqueId = new Date().getUTCMilliseconds(); | |
const filterId = `background-filter-${uniqueId}`; | |
const namespaceURI = 'http://www.w3.org/2000/svg'; | |
const svg = document.createElementNS(namespaceURI, 'svg'); | |
svg.setAttribute('height', '100%'); | |
svg.setAttribute('width', '100%'); | |
svg.style.position = 'absolute'; | |
svg.style.top = '0'; | |
svg.style.left = '0'; | |
svg.style.bottom = '0'; | |
svg.style.right = '0'; | |
svg.style.overflow = 'hidden'; | |
const defs = svg.appendChild(document.createElementNS(namespaceURI, 'defs')); | |
const filter = defs.appendChild(document.createElementNS(namespaceURI, 'filter')); | |
filter.setAttribute('id', filterId); | |
const feImage = filter.appendChild(document.createElementNS(namespaceURI, 'feImage')); | |
feImage.setAttribute('preserveAspectRatio', 'xMinYMin slice'); | |
feImage.setAttribute('x', '0'); | |
feImage.setAttribute('y', '0'); | |
feImage.setAttribute('height', '100%'); | |
feImage.setAttribute('width', '100%'); | |
feImage.setAttribute('result', 'slide2'); | |
feImage.setAttributeNS('http://www.w3.org/1999/xlink', 'href', backgroundImage); | |
const feBlend = filter.appendChild(document.createElementNS(namespaceURI, 'feBlend')); | |
feBlend.setAttribute('preserveAspectRatio', 'xMinYMin slice'); | |
feBlend.setAttribute('in', 'slide2'); | |
feBlend.setAttribute('in2', 'SourceGraphic'); | |
feBlend.setAttribute('mode', backgroundBlendMode); | |
const shapeBackground = svg.appendChild(document.createElementNS(namespaceURI, 'rect')); | |
shapeBackground.style.position = 'absolute'; | |
shapeBackground.setAttribute('x', '0'); | |
shapeBackground.setAttribute('y', '0'); | |
shapeBackground.setAttribute('width', '100%'); | |
shapeBackground.setAttribute('height', '100%'); | |
shapeBackground.setAttribute('filter', `url(#${filterId})`); | |
shapeBackground.setAttribute('fill', backgroundColor); | |
return svg; | |
}; | |
function mountSVGtoDom(el) { | |
const { | |
borderTopWidth, | |
position, | |
borderWidth, | |
backgroundImage: backgroundImageUrl, backgroundColor | |
} = window.getComputedStyle(el); | |
const backgroundImage = backgroundImageUrl && backgroundImageUrl.replace(/"/g,'').slice(4, -1); | |
const backgroundBlendMode = el.dataset.backgroundBlendMode; | |
if (backgroundImage && backgroundColor && backgroundBlendMode) { | |
if (position === 'static') el.style.position = 'relative'; | |
if (borderTopWidth) { | |
el.style.borderTopWidth = '0.01px'; | |
el.style.borderTopColor = 'transparent'; | |
el.style.borderTopStyle = 'solid'; | |
} | |
const svg = createSVGFilter({ backgroundImage, backgroundColor, backgroundBlendMode }); | |
el.prepend(svg); | |
// Если фон для Body, нужно по вешать обработчик события на измнения размеров окна | |
// потому что размер body может быть меньша размера документа, когда часть контента | |
// выпадает | |
if (el.tagName.toLowerCase() === 'body') { | |
let running = false; | |
let windowHeight = 0; | |
const update = () => { | |
if (windowHeight !== window.innerHeight) { | |
windowHeight = window.innerHeight; | |
svg.style.height = 'auto'; | |
svg.style.height = `${document.documentElement.scrollHeight}px`; | |
} | |
running = false; | |
} | |
const requestTick = () => { | |
if (!running) requestAnimationFrame(update); | |
running = true; | |
} | |
window.addEventListener('resize', requestTick); | |
} | |
} | |
} | |
function applyFilter() { | |
const elements = document.querySelectorAll(`[data-background-blend-mode]`); | |
if (elements) { | |
elements.forEach(el => mountSVGtoDom(el)); | |
} | |
}; | |
window.addEventListener('load', applyFilter); | |
})(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict';function prependPolyfill(){var a=document.createDocumentFragment();Array.prototype.slice.call(arguments).forEach(function(b){a.appendChild(b instanceof Node?b:document.createTextNode(b+''))}),this.insertBefore(a,this.firstChild)}[Element.prototype,Document.prototype,DocumentFragment.prototype].forEach(function(a){a.prepend||(a.prepend=prependPolyfill)}),window.NodeList&&!NodeList.prototype.forEach&&(NodeList.prototype.forEach=Array.prototype.forEach),function(){function a(_ref){var f=_ref.backgroundImage,g=_ref.backgroundColor,h=_ref.backgroundBlendMode,i=new Date().getUTCMilliseconds(),j='background-filter-'+i,k='http://www.w3.org/2000/svg',l=document.createElementNS(k,'svg');l.setAttribute('height','100%'),l.setAttribute('width','100%'),l.style.position='absolute',l.style.top='0',l.style.left='0',l.style.bottom='0',l.style.right='0',l.style.overflow='hidden';var m=l.appendChild(document.createElementNS(k,'defs')),n=m.appendChild(document.createElementNS(k,'filter'));n.setAttribute('id',j);var o=n.appendChild(document.createElementNS(k,'feImage'));o.setAttribute('preserveAspectRatio','xMinYMin slice'),o.setAttribute('x','0'),o.setAttribute('y','0'),o.setAttribute('height','100%'),o.setAttribute('width','100%'),o.setAttribute('result','slide2'),o.setAttributeNS('http://www.w3.org/1999/xlink','href',f);var p=n.appendChild(document.createElementNS(k,'feBlend'));p.setAttribute('preserveAspectRatio','xMinYMin slice'),p.setAttribute('in','slide2'),p.setAttribute('in2','SourceGraphic'),p.setAttribute('mode',h);var q=l.appendChild(document.createElementNS(k,'rect'));return q.style.position='absolute',q.setAttribute('x','0'),q.setAttribute('y','0'),q.setAttribute('width','100%'),q.setAttribute('height','100%'),q.setAttribute('filter','url(#'+j+')'),q.setAttribute('fill',g),l}function b(f){var _window$getComputedSt=window.getComputedStyle(f),g=_window$getComputedSt.borderTopWidth,h=_window$getComputedSt.position,i=_window$getComputedSt.borderWidth,j=_window$getComputedSt.backgroundImage,k=_window$getComputedSt.backgroundColor,l=j&&j.replace(/"/g,'').slice(4,-1),m=f.dataset.backgroundBlendMode;if(l&&k&&m){'static'===h&&(f.style.position='relative'),g&&(f.style.borderTopWidth='0.01px',f.style.borderTopColor='transparent',f.style.borderTopStyle='solid');var n=a({backgroundImage:l,backgroundColor:k,backgroundBlendMode:m});if(f.prepend(n),'body'===f.tagName.toLowerCase()){var o=!1,p=0,q=function(){p!==window.innerHeight&&(p=window.innerHeight,n.style.height='auto',n.style.height=document.documentElement.scrollHeight+'px'),o=!1};window.addEventListener('resize',function r(){o||requestAnimationFrame(q),o=!0})}}}var d=window.getComputedStyle(document.body).backgroundBlendMode;window.addEventListener('load',function(){var f=document.querySelectorAll('[data-background-blend-mode]');f&&f.forEach(function(g){return b(g)})})}(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment