mufuuuu

[Bookmarklet] video要素にフィルターを適用

Apr 15th, 2021 (edited)
693
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. javascript: void((() => {
  2.     /* Video Filter Bookmarklet 2021-04-18 by むふー@4chouyou */
  3.     const SLIDER_STEP = 0.05;
  4.     const PROPERTIES = [
  5.         {
  6.             name: 'brightness',
  7.             min: 0,
  8.             max: 2,
  9.             value: 1,
  10.             step: SLIDER_STEP,
  11.             unit: ''
  12.         },
  13.         {
  14.             name: 'contrast',
  15.             min: 0,
  16.             max: 2,
  17.             value: 1,
  18.             step: SLIDER_STEP,
  19.             unit: ''
  20.         },
  21.         {
  22.             name: 'saturate',
  23.             min: 0,
  24.             max: 2,
  25.             value: 1,
  26.             step: SLIDER_STEP,
  27.             unit: ''
  28.         },
  29.         {
  30.             name: 'hue-rotate',
  31.             min: -180,
  32.             max: 180,
  33.             value: 0,
  34.             step: SLIDER_STEP * 100,
  35.             unit: 'deg'
  36.         },
  37.         {
  38.             name: 'invert',
  39.             min: 0,
  40.             max: 1,
  41.             value: 0,
  42.             step: SLIDER_STEP,
  43.             unit: ''
  44.         },
  45.         {
  46.             name: 'grayscale',
  47.             min: 0,
  48.             max: 1,
  49.             value: 0,
  50.             step: SLIDER_STEP,
  51.             unit: ''
  52.         },
  53.         {
  54.             name: 'sepia',
  55.             min: 0,
  56.             max: 1,
  57.             value: 0,
  58.             step: SLIDER_STEP,
  59.             unit: ''
  60.         }
  61.     ];
  62.  
  63.     let defaultValue = {};
  64.     PROPERTIES.forEach(property => {
  65.         defaultValue[property.name] = property.value;
  66.     });
  67.     let panel = document.querySelector('#bml-videofilter-panel');
  68.     if(panel) panel.remove();
  69.     panel = document.createElement('div');
  70.     panel.id = 'bml-videofilter-panel';
  71.     panel.style.right = '10px';
  72.     panel.style.top = '10px';
  73.     panel.innerHTML = `
  74. <div class="panel-buttons flex">
  75.     <div id="bml-videofilter-drag-handle" class="drag-handle flex-item"></div>
  76.     <button class="panel-button" command="close" title="Close">[ x ]</button>
  77. </div>
  78. <div class="panel-content">
  79.     <div class="slider-container"></div>
  80. </div>
  81. `;
  82.     document.body.appendChild(panel);
  83.     let sliderContainer = document.querySelector('#bml-videofilter-panel .slider-container');
  84.     PROPERTIES.forEach(property => {
  85.         let div = document.createElement('div');
  86.         div.innerHTML = `<label for="${property.name}">${property.name}</label><input class="slider" type="range" id="${property.name}" name="${property.name}" min="${property.min}" max="${property.max}" value="${property.value}" step="${property.step}">`;
  87.         sliderContainer.appendChild(div);
  88.     });
  89.     let style = document.querySelector('#bml-videofilter-style');
  90.     if(!style) {
  91.         style = document.createElement('style');
  92.         style.id = 'bml-videofilter-style';
  93.         style.type = 'text/css';
  94.         document.head.appendChild(style);
  95.  
  96.         var isDrag = false;
  97.         var targetPanel, startX, startY, panelRight, panelTop, panelWidth, panelHeight, parentWidth, parentHeight;
  98.         document.addEventListener('mousedown', e => {
  99.             if(e.target.classList.contains('drag-handle')) {
  100.                 e.preventDefault();
  101.                 let panel = document.querySelector('#bml-videofilter-panel');
  102.                 targetPanel = e.target.id;
  103.                 isDrag = true;
  104.                 startX = e.clientX;
  105.                 startY = e.clientY;
  106.                 panelRight = parseInt(panel.style.right);
  107.                 panelTop = parseInt(panel.style.top);
  108.                 panelWidth = panel.clientWidth;
  109.                 panelHeight = panel.clientHeight;
  110.                 if(panel.getAttribute('embedded') == 'true') {
  111.                     parentWidth = panel.parentNode.clientWidth;
  112.                     parentHeight = panel.parentNode.clientHeight;
  113.                 }else {
  114.                     parentWidth = document.documentElement.clientWidth;
  115.                     parentHeight = document.documentElement.clientHeight;
  116.                 }
  117.             };
  118.         });
  119.         document.addEventListener('mouseup', e => {
  120.             isDrag = false;
  121.         });
  122.         document.addEventListener('mousemove', e => {
  123.             if(isDrag && targetPanel == 'bml-videofilter-drag-handle') {
  124.                 e.preventDefault();
  125.                 let panel = document.querySelector('#bml-videofilter-panel');
  126.                 panel.style.right = Math.min(parentWidth - panelWidth, Math.max(0, panelRight - (e.clientX - startX))) + 'px';
  127.                 panel.style.top = Math.min(parentHeight - panelHeight, Math.max(0, panelTop + (e.clientY - startY))) + 'px';
  128.             }
  129.         });
  130.     }
  131.     style.innerHTML = `
  132. @import url('https://fonts.googleapis.com/css2?family=Roboto:wght@400&display=swap');
  133. #bml-videofilter-panel * {
  134.     appearance: auto;
  135.     width: initial;
  136.     height: initial;
  137.     line-height: initial;
  138.     margin: 0;
  139.     padding: 0;
  140. }
  141. #bml-videofilter-panel {
  142.     position: fixed;
  143.     z-index: 2147483647;
  144.     background-color: rgba(28, 28, 28, 0.5);
  145.     border-radius: 4px;
  146.     backdrop-filter: blur(3px);
  147. }
  148. #bml-videofilter-panel .flex {
  149.     display: flex;
  150. }
  151. #bml-videofilter-panel .flex-item {
  152.     flex-grow: 1;
  153. }
  154. #bml-videofilter-panel .panel-buttons {
  155.     box-sizing: border-box;
  156.     width: 100%;
  157.     padding: 4px;
  158.     float: right;
  159. }
  160. #bml-videofilter-panel .drag-handle {
  161.     border-radius: 4px;
  162.     background-color: rgba(255, 255, 255, .1);
  163.     cursor: move;
  164. }
  165. #bml-videofilter-panel .panel-button {
  166.     margin-left: 5px;
  167.     padding: 0;
  168.     border: none;
  169.     background-color: transparent;
  170.     color: white;
  171.     font-family: Roboto;
  172.     font-size: 11px;
  173.     font-weight: 400;
  174.     cursor: pointer;
  175. }
  176. #bml-videofilter-panel .panel-content {
  177.     padding: 5px;
  178. }
  179. #bml-videofilter-panel .slider-container > div {
  180.     padding: 4px 0;
  181. }
  182. #bml-videofilter-panel .slider-container label {
  183.     display: inline-block;
  184.     width: 100px;
  185.     color: white;
  186.     font-family: Roboto;
  187.     font-size: 16px;
  188.     font-weight: 400;
  189.     cursor: pointer;
  190. }
  191. #bml-videofilter-panel .slider-container .slider {
  192.     width: 200px;
  193. }`;
  194.     let buttons = document.querySelectorAll('#bml-videofilter-panel button');
  195.     buttons.forEach(button => {
  196.         button.addEventListener('click', e => {
  197.             let command = button.getAttribute('command');
  198.             switch(command) {
  199.                 case 'close': {
  200.                     panel.remove();
  201.                     break;
  202.                 }
  203.                 default: {
  204.                     break;
  205.                 }
  206.             }
  207.         });
  208.     });
  209.     let labels = document.querySelectorAll('#bml-videofilter-panel label');
  210.     labels.forEach(label => {
  211.         label.addEventListener('click', e => {
  212.             e.target.nextElementSibling.value = defaultValue[e.target.textContent];
  213.             setFilterStyle();
  214.         });
  215.     });
  216.     let sliders = document.querySelectorAll('#bml-videofilter-panel .slider');
  217.     sliders.forEach(slider => {
  218.         slider.addEventListener('input', setFilterStyle);
  219.     });
  220.  
  221.     function setFilterStyle() {
  222.         let filterValue = '';
  223.         PROPERTIES.forEach(property => {
  224.             let slider = document.querySelector(`#bml-videofilter-panel .slider[name="${property.name}"]`);
  225.             let value = slider.value;
  226.             if(value != property.value) {
  227.                 filterValue += ` ${property.name}(${value}${property.unit})`;
  228.             }
  229.         });
  230.         let style = document.querySelector('#bml-videofilter-style-filter');
  231.         if(!style) {
  232.             style = document.createElement('style');
  233.             style.id = 'bml-videofilter-style-filter';
  234.             style.type = 'text/css';
  235.             document.head.appendChild(style);
  236.         }
  237.         style.innerHTML = `video {filter: ${filterValue} !important;}`;
  238.     }
  239. })());
Add Comment
Please, Sign In to add comment