Изменение уровня линейной градации фона на свитке - PullRequest
2 голосов
/ 13 мая 2019

В моем веб-приложении у меня есть этот фон, который состоит из 2-х линейных градиентов. Я хочу изменить «наклон» градиента на основе прокрутки.

У меня нет идеи, каксделать это ...

это текущее состояние: https://prnt.sc/no3las (поэтому я хотел бы анимировать синий фон на свитке :-))

Это CSSфона моего сайта

html {
  font-family: 'Roboto Mono', monospace;
  background: linear-gradient(70deg, #5870cb 20%, rgba(0, 0, 0, 0) 1%), 
              linear-gradient(20deg, white 85%, #5870cb 2%);
  background-position: center;
  background-repeat: no-repeat;
  background-size: cover;
  background-attachment: fixed;
  height: 100vh;
}

Ответы [ 2 ]

3 голосов
/ 14 мая 2019

Чтобы повернуть градиент, вы должны понимать (и деконструировать) linear-gradient (что, на самом деле, background-image). Хорошее краткое изложение можно найти на MDN , а официальная спецификация на CSSWG (W3C).

Первое, что нужно знать об этом, это то, что вы не можете перемещать его центр. Поскольку это фон элемента, центр градиента всегда будет центром элемента.
Примечание. Если для вашего дизайна требуются разные центры вращения, вы всегда можете использовать более 1 элемента и соответственно изменять их размер.

Теперь предположим, что вы хотите повернуть первый градиент с 70deg до 110deg, а второй с 20deg до 155deg.

Быстрый поиск scroll event (надеюсь) откроет вам страницу MDN , в которой есть пример.

В сочетании с вышесказанным вы получаете что-то вроде этого (я поместил логику для поворота backgroundImage внутри функции doSomething примера).

Я также указал, откуда я взял каждый бит, чтобы показать, как шаг за шагом документировать ваш вопрос. Суть здесь в следующем: каждый бит, который вы можете сделать самостоятельно, сделать это и оставить только те биты, которые вы не знаете.

let last_known_scroll_position = 0;
let ticking = false;

// helpers
const body = document.querySelector('body');
const html = document.querySelector('html');

function doSomething(scroll_pos) {

 // from https://stackoverflow.com/a/1147768/1891677 :
 const bodyHeight = Math.max( body.scrollHeight, 
                              body.offsetHeight, 
                              html.clientHeight, 
                              html.scrollHeight, 
                              html.offsetHeight);
 
 // from https://stackoverflow.com/a/8876069/1891677 :
 const viewportHeight = Math.max(document.documentElement.clientHeight,
                                 window.innerHeight || 0);
 
 // set scrollPercentage, if we have available scroll (0 otherwise):
 const availableScroll = bodyHeight - viewportHeight;
 const percentage = availableScroll > 0 ? scroll_pos * 100/availableScroll : 0;
  
 // this is what the question is about:
 const fromPercent = (from,to,current) => ((to - from) * current/100) + from;
 body.style.backgroundImage = `
 linear-gradient(${fromPercent(70, 110, percentage)}deg, #5870cb 20%, rgba(0,0,0,0) 0),
 linear-gradient(${fromPercent(20, 155, percentage)}deg, white 85%, #5870cb 2%)
 `;
}

// rest of example, from MDN:
window.addEventListener('scroll', function(e) {
  last_known_scroll_position = window.scrollY;

  if (!ticking) {
    window.requestAnimationFrame(function() {
      doSomething(last_known_scroll_position);
      ticking = false;
    });

    ticking = true;
  }
});
body {
  font-family: 'Roboto Mono', monospace;
  background-image: linear-gradient(70deg, #5870cb 20%, rgba(0,0,0,0) 1%), 
                    linear-gradient(20deg, white 85%, #5870cb 2%);
  background-position: center;
  background-repeat: no-repeat;
  background-size: cover;
  background-attachment: fixed;
  height: 300vh;
}
1 голос
/ 14 мая 2019

По сути, вам нужна текущая позиция прокрутки (через .scrollTop), а также максимальное расстояние прокрутки (<SCROLLING_ELEMENT>.scrollHeight - window.innerHeight). Если у вас есть эта информация, вы можете легко вычислить угол поворота / угол наклона с помощью JS:

// HTML :: Element
const HTML = document.documentElement;

// getCurrentScroll :: () -> Number
const getCurrentScroll = () => HTML.scrollTop;

// getMaxScroll :: () -> Number
const getMaxScroll = () => HTML.scrollHeight - window.innerHeight;

// calcRotation :: (Number, Number) -> Number
const calcRotation = (pos, max) => pos / max * 360;

// getBG :: Number -> String
const getBG = r => `linear-gradient(${r + 70}deg, #5870cb 20%, rgba(0,0,0,0) 1%), linear-gradient(${r + 20}deg, white 85%, #5870cb 2%)`;



document.addEventListener('scroll', () => {
  const rot = calcRotation(getCurrentScroll(), getMaxScroll());
  HTML.style.backgroundImage = getBG(rot);
});
html {
  font-family: 'Roboto Mono', monospace;
  background: linear-gradient(70deg, #5870cb 20%, rgba(0, 0, 0, 0) 1%), 
  linear-gradient(20deg, white 85%, #5870cb 2%);
  background-position: center;
  background-repeat: no-repeat;
  background-size: cover;
  background-attachment: fixed;
  height: 100vh;
  overflow: auto; /* no scrolling without this line */
}

body { height: 200vh; } /* just to create a scroll bar */
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...