Skip to content

Instantly share code, notes, and snippets.

@Akiyamka
Created November 9, 2018 10:13
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Akiyamka/ef4786f62e23a3b3f8ea6724debaa6fe to your computer and use it in GitHub Desktop.
Save Akiyamka/ef4786f62e23a3b3f8ea6724debaa6fe to your computer and use it in GitHub Desktop.
blend-mode-polyfill
/**
* @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);
})();
'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