【问题标题】:How to create a chromatic aberration for a web page?如何为网页创建色差?
【发布时间】:2018-03-20 01:03:49
【问题描述】:

我目前正在开发一个网络用户界面

最近我添加了一个功能,通过一些范围滑块来改变整体效果,这些滑块通过改变一些滤镜 css 来实现,比如色调旋转、灰度、反转和模糊

现在:

做一些截图我随机做了这个!而且很酷!!!

我只是想通过降低一个的不透明度来使这两个在 Photoshop 中适合

以前我想通过使用 open gl shader 语言来实现这样的效果(我一直想这样做,因为你可以实现更好的效果和更多的动态)但是现在,正如我所说,在 Photoshop 中这样做,我想到了解决色差问题的小方法

所有的css都加载完毕后,

$( window ).load(function() {
  //chroma aberration
});

通过一个事件(或另一个范围滑块),我可以克隆所有 html,降低前面那个的不透明度,然后移动后面那个

这样我就可以达到这样的效果

你有什么想法吗? 你觉得有可能吗?? 你觉得我说的对吗??还是您认为有更好的解决方案?

这里我觉得有些问题:

  • 克隆的副本不应是可点击的

  • 当有悬停、过渡、动画时,克隆副本的行为应该与原始副本一样......

  • 克隆的副本不应扩大页面的框大小,自行移动(可能使用 position:absolute 和 overflow:hidden)

我试过这种方法,但它不起作用

$( window ).load(function() {
  //Chromatic Aberration
  //clone all the body
  $('body')
    .children()
    .wrap( "<div class='original'></div>" )
    .clone()
    .insertAfter('.original')
    .addClass('cloned')
    .css('-webkit-filter',
         'hue-rotate(180deg)',
         'blur(3px)',
         'grayscale(50%)',
         'invert(5%)')
    .css('position','absolute')
    .css('left','10%')
    .css('z-index','-500');
  //(hue180,blur3,grayscale25,invert5)
  //lower opacity of the original
  $('body.original').css('opacity','0.5');
});

【问题讨论】:

  • 你试过模糊滤镜了吗?
  • 网页已经有4个过滤范围滑块(也有模糊是的)

标签: javascript jquery html css user-interface


【解决方案1】:

这是可能的,但这是一项困难且需要大量 javascript 的任务。我会首先让你的 css 依赖于 javascript 控制的属性而不是原生 css 属性:

代替:

.button:hover {
    /* fancy hover effects */
}
.button:active {
    /* fancy activation effects */
}

切换到

.button.hover {  /* Note: no longer using the :hover pseudo-class */
    /* fancy hover effects */
}
.button.active {
    /* fancy activation effects */
}

这是一个开始。它将让您通过自定义逻辑而不是原生 CSS 对 DOM 操作做出反应。这是必要的,因为无法在您的模糊层上激活原生 CSS 效果。

现在您需要手动添加和删除这些自定义.hover.active 类:

var buttons = document.getElementsByTagName('button');
for (var i = 0; i < buttons.length; i++) {
    // Add `.hover` class on hover start
    buttons[i].onmouseover = function(button) {
        this.classList.add('hover');
    }.bind(buttons[i]);

    // Remove `.hover` class on hover end
    buttons[i].onmouseout = function(button) {
        this.classList.remove('hover');
    }.bind(buttons[i]);

    // Add `.active` class on mouse down
    buttons[i].onmousedown = function(button) {
        this.classList.add('active');
    }.bind(buttons[i]);

    // Remove `.active` class on mouse up
    buttons[i].onmouseup = function() {
        this.classList.remove('active');
    }.bind(buttons[i]);
}

好的,这足以使您的原始图层通过自定义事件进行控制。但是现在我们需要添加模糊层。我们可以实现一些自定义的深度克隆。我们希望这是自定义的,因为在克隆时,我们希望能够执行自定义操作(添加事件)。

var customCloneNode = function(node) {

    var cloned = node.cloneNode(false); /* DON'T clone children; we'll do it manually */

    // In a moment we'll do some custom logic with `cloned`

    var childNodes = node.childNodes;
    for (var i = 0; i < childNodes.length; i++)
        cloned.appendChild(customCloneNode(childNodes[i]));

    return cloned;

};

所以我们知道如何模拟 css 事件,并克隆 html 节点。现在我们需要将两者结合起来,以便克隆的子元素在原始相应元素获得/丢失时获得和丢失自定义 css 类:

var cloneNodeWithLinkedEvents = function(node) {

    var cloned = node.cloneNode(false); /* DON'T clone children */

    // Here's the custom logic:
    node.onmouseover = function(parallelNode) {
        // Add a "hover" class to the original node AND the cloned one!
        this.classList.add('hover');
        parallelNode.classList.add('hover');
    }.bind(node, cloned);

    node.onmouseout = function(parallelNode) {
        this.classList.remove('hover');
        parallelNode.classList.remove('hover');
    }.bind(node, cloned);

    // Note: For brevity I've only added the hover event here.
    // It will be important to add the active event, as well as
    // any value changes in input elements, etc.

    var childNodes = node.childNodes;
    for (var i = 0; i < childNodes.length; i++)
        cloned.appendChild(cloneNodeWithLinkedEvents(childNodes[i]));

    return cloned;

};

现在我们可以从原始元素中复制一个元素:

var originalElem = document.getElementByClassName('ui')[0];
var parallelElem = cloneNodeWithLinkedEvents(originalElem);

// Add the cloned node to the same parent which is holding `originalElem`
originalElem.parentNode.appendChild(parallelElem);

// Give the parallel node a unique class so we can style it:
parallelElem.classList.add('duplicate');

现在为重复元素设置样式:

.ui.duplicate {
    left: -10px;
    top: -5px;
    opacity: 0.3;
    z-index: 2; /* Or whatever value is necessary to make it appear on top */
}

工作示例:

window.onload = function() {
  var cloneNodeWithLinkedEvents = function(node) {
            
      var cloned = node.cloneNode(false); /* DON'T clone children */
      
      if (node.classList && node.classList.contains('button')) {
        
          // Here's the custom logic for buttons:
          node.onmouseover = function(parallelNode) {
              this.classList.add('hover');
              parallelNode.classList.add('hover');
          }.bind(node, cloned);

          node.onmouseout = function(parallelNode) {
              this.classList.remove('hover');
              parallelNode.classList.remove('hover');
          }.bind(node, cloned);
        
      }
      
      if (node.nodeName === 'INPUT') {
          
          var changeFunc = function(parallelNode) {
              parallelNode.value = this.value;
          }.bind(node, cloned);
          node.addEventListener('input', changeFunc);
          node.addEventListener('keyup', changeFunc);
          node.addEventListener('keydown', changeFunc);
          
      }

      // Note: For brevity I've only added the hover event here.
      // It will be important to add the active event, as well as
      // any value changes in input elements, etc.

      var childNodes = node.childNodes;
      for (var i = 0; i < childNodes .length; i++) {
          cloned.appendChild(cloneNodeWithLinkedEvents(childNodes[i]));
      }
      return cloned;

  };

  var originalElem = document.getElementsByClassName('ui')[0];
  var parallelElem = cloneNodeWithLinkedEvents(originalElem);

  originalElem.parentNode.appendChild(parallelElem);
  parallelElem.classList.add('duplicate');
 
 };
.ui {
    position: absolute;
    left: 0; top: 0;
    width: 100%; height: 100%;
    background-color: rgba(0, 0, 0, 0.5);
    box-shadow: inset 0 0 0 3px #000000;
}
.ui .button {
    position: absolute;
    width: 100px;
    height: 30px; line-height: 30px;
    margin-left: -51px; margin-top: -16px;
    text-align: center;
    background-color: #ffffff;
    font-family: monospace;
    border: 2px dotted #ff0000;
    background-color: #800000;
    color: #ffffff;
    
    transition: background-color 300ms linear;
}
.ui .button.hover {
    background-color: #808080;
}
.ui .button1 { left: 20%; top: 20%; }
.ui .button2 { left: 50%; top: 20%; }
.ui .button3 { left: 80%; top: 20%; }

.ui .decoration {
    position: absolute;
    left: 30%; top: 30%;
    width: 40%; height: 5%;
    background-color: #5050ff;
}
.ui .text {
    position: absolute;
    left: 5%; top: 38%;
    width: 90%;
    color: #6060df;
}
.ui input {
    position: absolute;
    width: 200px; height: 30px; line-height: 30px;
    left: 10%; top: 70%;
    color: #00ff00;
}

.ui {
    opacity: 1;
    z-index: 1;
}
.ui.duplicate {
    left: -10px; top: -5px;
    pointer-events: none !important;
    opacity: 0.7;
    z-index: 2;
    
    filter: hue-rotate(60deg);
}
<div class="ui">
    <div class="button button1">BUTTON1</div>
    <div class="button button2">BUTTON2</div>
    <div class="button button3">BUTTON3</div>
    <div class="decoration"></div>
    <div class="text">
         Some text haha wheeee yayyy<br/>
         Some text haha wheeee yayyy<br/>
         Some text haha wheeee yayyy<br/>
    </div>
    <input type="text"/>
</div>

请注意,将鼠标悬停在复制图层上不会激活任何悬停效果,而将鼠标悬停在原始图层上会同时激活两者的效果!另外,请注意,输入 input 元素会将值更改事件链接到副本。

【讨论】:

  • 非常感谢您的回答,我不是程序员这一切对我来说都非常困难(我想你有)但我会尽力做到这一点,谢谢
  • 当然,很高兴我能帮上忙!请注意,此示例并未考虑许多技术细节;例如如果有任何元素设置了id 属性,则在克隆后这些元素将变得非唯一(因此无效)。另请注意,仍有大量输入操作尚未解决 - 工作示例仅演示悬停事件和输入值更改。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-09
  • 1970-01-01
  • 2011-02-25
  • 1970-01-01
  • 2019-02-13
  • 2014-09-12
相关资源
最近更新 更多