js实现可调参数的太阳光通过窗户照射房间动画效果代码

代码语言:html

所属分类:动画

代码描述:js实现可调参数的太阳光通过窗户照射房间动画效果代码

代码标签: js 可调 参数 太阳光 通过 窗户 照射 房间 动画

下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开


<!DOCTYPE html>
<html lang="en" >

<head>

  <meta charset="UTF-8">

  <meta name="viewport" content="width=device-width, initial-scale=1">

<style>
@import "//repo.bfw.wiki/bfwrepo/css/open-props.css";

* {
  margin: 0;
  padding: 0;
}
body {
  width: 960px;
  margin: 0 auto;
  background: var(--gray-0);
  font-family: var(--font-sans);
/*   visibility: hidden; */
}
a {
  text-decoration: none;
}

.container {
  position: relative;
  overflow: hidden;
  box-shadow: var(--shadow-4);
}
.photo img {
  width: 100%;
  height: auto;
  vertical-align: top;
  filter: brightness(0.8) contrast(80%);
}

.sun {
  width: 5.2%; /* 50/960 */
/*   aspect-ratio: 1 / 1; */
  border-radius: 50%;
  box-shadow: 100px 0px 20px rgb(255, 254, 246);
  position: absolute;
  top: 19%;
  left: 31%;
  mix-blend-mode: plus-lighter;
}
.sun::before { /* for old browsers */
  display: block;
  content: '';
  width: 100%;
  height: 0;
  padding-top: 100%;
}
.sunrays {
  width: 50%;
  height: 100%;
  perspective: 5px;
  perspective-origin: 50% 0%;
  transform-style: preserve-3d;
  display: flex;
  align-items: flex-start;
  position: absolute;
  top: 0%;
  left: 0%;
}
.sunrays.r1 {
  top: 13%;
  left: 37%;
  opacity: 0.8;
  transform: rotate(-33deg);
}
.sunrays.r2 {
  top: 21%;
  left: 11%;
  opacity: 0.8;
  transform: rotate(13deg);
}
.outline .sunrays,
.outline .sun {
    outline: 1px solid cyan;
}
.sunrays > * {
  flex: 0 0 15%;
}
.light:nth-child(4n + 1) {
  flex: 3 1 auto;
}
.light:nth-child(4n + 2) {
  box-shadow: none;
}
.light:nth-child(4n + 3) {
  flex: 1 1 auto;
}
.light:nth-child(4n) {
  box-shadow: none;
}
.light {
  height: 80%;
  box-shadow: 200px -15px 30px rgb(255, 254, 246);
  transform-origin: 0% 100% 0px;
  transform: rotateZ(0deg) rotateY(0deg) rotateX(90deg) translateZ(0);
}
.outline .light {
  box-sizing: border-box;
  border-left: 1px solid lime;
}

.r1 .light {
  height: 55%;
}
.r2 .light {
  height: 80%;
}

.mask {
  width: 100%;
  height: 33%;
/*   mix-blend-mode: overlay; */
  background-image: linear-gradient(to top, rgba(0,0,0,0.6), rgba(0,0,0,0));
  position: absolute;
  bottom: 0;
  left: 0;
}

.attribution {
  margin-top: 10px;
  text-align: right;
  font-size: 0.9rem;
}

.buttons {
  display: flex;
  gap: 10px;
  margin-top: 20px;
}
.panel {
  margin-top: 10px;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
}
.rows {
  display: grid;
}
.rows + .rows {
  margin-top: 20px;
}
.cb-list {
  display: flex;
  gap: 8px;
}

.btn {
  color: var(--indigo-8);
  font-size: var(--font-size-1);
  padding: 8px 16px;
  border: var(--border-size-1) solid var(--indigo-8);
  border-radius: var(--radius-2);
  box-shadow: var(--shadow-2);
  background: white;
  cursor: pointer;
}
.btn:hover {
  color: white;
  text-shadow: 0 1px 0 var(--indigo-7);
  background: var(--indigo-8);
}
.btn.active {
  color: #fff;
  background: var(--indigo-8);
  text-shadow: 0 1px 0 var(--indigo-6);
}
.btn.active:hover {
  background: var(--indigo-6);
}

.css-code {
  box-sizing: border-box;
  margin-top: 10px;
  width: 100%;
  padding: 10px;
  background-color: #fff;
  border: var(--border-size-1) solid var(--gray-5);
  display: none;
}
.css-code.active {
  display: block;
}
.css-code code {
  font-family: var(--font-mono);
  font-size: var(--font-size-1);
}

@media (max-width: 960px) {
  body {
    width: 100%;
  }
}
</style>


</head>

<body >
  <div class="container">
  <div class="photo">
    <img src="//repo.bfw.wiki/bfwrepo/image/628061ea61ca8.png" width="960" height="640" alt="">
  </div>
  <div class="sunrays r1">
    <div class="light"></div>
    <div class="light"></div>
    <div class="light"></div>
    <div class="light"></div>
    <div class="light"></div>
    <div class="light"></div>
  </div>
  <div class="sunrays r2">
    <div class="light"></div>
    <div class="light"></div>
    <div class="light"></div>
    <div class="light"></div>
    <div class="light"></div>
    <div class="light"></div>
  </div>
  <div class="sun"></div>

  <div class="mask"></div>
</div>



<div class="buttons">
  <button type="button" id="reset-btn" class="btn">Reset</button>
  <button type="button" id="css-btn" class="btn">CSS</button>
  <button type="button" id="play-btn" class="btn">Play</button>
</div>
<div class="css-code"></div>
<div class="panel">
  <div class="column">
    <div class="rows">
      <p>Sun rays: </p>
      <div id="var-sunrays" class="cb-list"></div>
      <label for="cb-ol"><input type="checkbox" id="cb-ol"> outlines</label>
    </div>
    <div class="rows" id="var-position">
      <p>position:</p>
    </div>
    <div class="rows" id="var-angle">
      <p>angle:</p>
    </div>
    <div class="rows" id="var-perspective">
      <p>perspective:</p>
    </div>
    <div class="rows" id="var-opacity">
      <p>opacity:</p>
    </div>
  </div>
  <div class="column">
    <div class="rows" id="var-sun">
      <p>sun:</p>
    </div>
    <div class="rows" id="var-sun-shadow">
      <p>sun shadow:</p>
      <label for="sun-color">color: <input type="color" id="sun-color" value="#ffffff"></label>
    </div>
    <div class="rows" id="var-light-height">
      <p>light height:</p>
    </div>
    <div class="rows" id="var-light-shadow">
      <p>light shadow:</p>
    </div>
  </div>
  <div class="column">
    <div class="rows" id="var-light-origin">
      <p>transform-origin:</p>
    </div>
    <div class="rows" id="var-light-transform">
      <p>transform:</p>
    </div>
    <div class="rows" id="var-filter">
      <p>filter:</p>
    </div>
    <div class="rows" id="var-mask">
      <p>mask:</p>
    </div>
  </div>
</div>

  
      <script  >
const sunrays = document.querySelectorAll('.sunrays');
const initializer = [];
const saved_css = [
  ['.photo img', 'filter'],
  ['.sun', 'width' ],
  ['.sun', 'box-shadow' ],
  ['.sun', 'top' ],
  ['.sun', 'left' ],
  ['.sunrays', 'perspective-origin'],
  ['.sunrays', 'perspective'],
  ['.light', 'box-shadow'],
  ['.light', 'height'],
  ['.light', 'transform-origin'],
  ['.light', 'transform'],
  ['.mask', 'height'],
];

let use_vw_unit = false;

(function(rays) {
  for (const rn of rays) {
    ['top', 'left', 'opacity', 'transform'].forEach(p => {
      saved_css.push([`.sunrays.${rn}`, p]);
    });
    saved_css.push([`.${rn} .light`, 'height'])
  }
})(getSunraysArray());

for (const prop of saved_css) {
  const pval = getCSSValue(prop[0], prop[1]);
  prop.push(pval);
}

function getSunraysArray(prefix) {
  const list = [];
  if (!prefix) {
    prefix = '';
  }
  for (let i = 0; i < sunrays.length; i++) {
    const rn = `r${i + 1}`;
    list.push(`${prefix}${rn}`);
  }
  return list;
}

function createCheckbox(id, text, checked, value) {
  const label = document.createElement('label');
  label.setAttribute('for', id);
  const item = document.createElement('input');
  item.id = id;
  item.setAttribute('type', 'checkbox');
  if (value) {
    item.value = value;
  }
  item.checked = checked;
  label.appendChild(item);
  
  const el = document.createTextNode(` ${text}`);
  label.appendChild(el);
  return label;
}

function createRangeSlider(id, text, min, max, step) {
  const label = document.createElement('label');
  label.setAttribute('for', id);
  label.textContent = `${text}: `;
  const item = document.createElement('input');
  item.id = id;
  item.setAttribute('type', 'range');
  item.setAttribute('min', min);
  item.setAttribute('max', max);
  if (step) {
    item.setAttribute('step', step);
  }
  label.appendChild(item);
  return label;
}

function setRangeSlider(sel, val, unit) {
  const el = document.getElementById(sel);
  el.value =  updateRangeValue(el, val, unit);
}

(function() {
  let target = document.getElementById('var-perspective');
  let el = createRangeSlider('pers-length', 'length', 1, 100);
  target.appendChild(el);
  el = createRangeSlider('pers-origin-x', 'origin-x', -100, 100);
  target.appendChild(el);
  el = createRangeSlider('pers-origin-y', 'origin-y', -100, 100);
  target.appendChild(el);
  
  target = document.getElementById('var-sun');
  el = createRangeSlider('sun-width', 'size', 1, 15);
  target.appendChild(el);
  el = createRangeSlider('sun-top', 'top', -30, 100);
  target.appendChild(el);
  el = createRangeSlider('sun-left', 'left', -50, 100);
  target.appendChild(el);
  
  target = document.getElementById('var-sun-shadow');
  el = createRangeSlider('sun-shadow-x', 'offset-x', 0, 300);
  target.appendChild(el);
  el = createRangeSlider('sun-shadow-y', 'offset-y', 0, 300);
  target.appendChild(el);
  el = createRangeSlider('sun-shadow-blur', 'blur', 0, 50);
  target.appendChild(el);
  
  target = document.getElementById('var-light-shadow');
  el = createRangeSlider('light-shadow-x', 'offset-x', 0, 300);
  target.appendChild(el);
  el = createRangeSlider('light-shadow-y', 'offset-y', -100, 300);
  target.appendChild(el);
  el = createRangeSlider('light-shadow-blur', 'blur', 0, 50);
  target.appendChild(el);
  
  target = document.getElementById('var-light-origin');
  el = createRangeSlider('light-origin-x', 'x', -50, 150);
  target.appendChild(el);
  el = createRangeSlider('light-origin-y', 'y', -50, 150);
  target.appendChild(el);
  el = createRangeSlider('light-origin-z', 'z', 0, 200);
  target.appendChild(el);
  
  target = document.getElementById('var-light-transform');
  el = createRangeSlider('light-translateZ', 'translateZ', 0, 300);
  target.appendChild(el);
  el = createRangeSlider('light-rotateX', 'rotateX', -360, 360);
  target.appendChild(el);
  el = createRangeSlider('light-rotateY', 'rotateY', -360, 360);
  target.appendChild(el);
  el = createRangeSlider('light-rotateZ', 'rotateZ', -360, 360);
  target.appendChild(el);
  
  target = document.getElementById('var-filter');
  el = createRangeSlider('filter-brightness', 'brightness', 0, 1, 0.1);
  target.appendChild(el);
  el = createRangeSlider('filter-contrast', 'contrast', 0, 100);
  target.appendChild(el);
  
  target = document.getElementById('var-mask');
  el = createRangeSlider('mask-height', 'height', 0, 100);
  target.appendChild(el);
})();

(function(rays) {
  let el;
  let target = document.getElementById('var-sunrays');
  for (const rn of rays) {
    el = createCheckbox(`cb-${rn}`, rn, true, rn);
    target.appendChild(el);
  }
  el = createCheckbox('cb-sun', 'sun', true);
  target.appendChild(el);
  
  target = document.getElementById('var-position');
  for (const rn of rays) {
    el = createRangeSlider(`${rn}-top`, `${rn}.top`, 0, 100);
    target.appendChild(el);
    el = createRangeSlider(`${rn}-left`, `${rn}.left`, -100, 100);
    target.appendChild(el);
  }
  
  target = document.getElementById('var-angle');
  for (const rn of rays) {
    el = createRangeSlider(`${rn}-rotate`, `${rn}`, -180, 180);
    target.appendChild(el);
  }
  
  target = document.getElementById('var-opacity');
  for (const rn of rays) {
    el = createRangeSlider(`opacity-${rn}`, rn, 0, 1, 0.05);
    target.appendChild(el);
  }
  
  target = document.getElementById('var-light-height');
  for (const rn of rays) {
    el = createRangeSlider(`height-${rn}`, `${rn}.height`, 10, 100);
    target.appendChild(el);
  }
})(getSunraysArray());

/*
 * sunrays position, angle
 */
function visible(el, yes) {
  if (yes) {
    el.removeAttribute('style');
  } else {
    el.style.display = 'none';
  }
}

getSunraysArray('cb-').forEach(sel => {
  const el = document.getElementById(sel);
  el.addEventListener('click', function() {
    const target = document.querySelector(`.${this.value}`);
    visible(target, this.checked);
  });
});

document.getElementById('cb-sun').addEventListener('click', function() {
  const target = document.querySelector('.sun');
  visible(target, this.checked);
});

(function(init) {
  init();
  initializer.push(init);
})(function() {
  getSunraysArray().forEach(rn => {
    const o = getPosition(`.sunrays.${rn}`);
    setRangeSlider(`${rn}-top`, o.top, '%');
    setRangeSlider(`${rn}-left`, o.left, '%');
  });
});

function getPosition(sel) {
  const o = {};
  o.top = getCSSValue(sel, 'top');
  o.left = getCSSValue(sel, 'left');
  return o;
}

getSunraysArray().forEach(rn => {
  [`${rn}-top`, `${rn}-left`].forEach(sel => {
    const item = document.getElementById(sel);
    item.addEventListener('input', function() {
      updateRangeValue(this, this.value, '%');
      const prop = /-top$/.test(sel)? 'top': 'left';
      setCSSValue(`.sunrays.${rn}`, prop, `${this.value}%`)
    });
  });
});

function getRayAngle(sel) {
  const o = {};
  const pval = getCSSValue(sel, 'transform');
  const found = pval.match(/rotate\((-?[0-9]+deg)\)/);
  o.angle = found[1];
  return o;
}

(function(init) {
  init();
  initializer.push(init);
})(function() {
  getSunraysArray().forEach(rn => {
    const o = getRayAngle(`.sunrays.${rn}`);
    setRangeSlider(`${rn}-rotate`, o.angle, 'deg');
  })
});

getSunraysArray().forEach(rn => {
  const item = document.getElementById(`${rn}-rotate`);
  item.addEventListener('input', function() {
    updateRangeValue(this, this.value, 'deg');
    const pval = `rotate(${this.value}deg)`;
    setCSSValue(`.sunrays.${rn}`, 'transform', pval);
  });
});

  
document.getElementById('cb-ol').addEventListener('click', function() {
  const el = document.querySelector('.container');
  if (this.checked) {
    el.classList.add('outline');
  } else {
    el.classList.remove('outline');
  }
});

/*
 * perspective, perspective-origin
 */
(function(init) {
  init();
  initializer.push(init);
})(function() {
  const pval = getCSSValue('.sunrays', 'perspective');
  setRangeSlider('pers-length', pval, 'px');
});

document.getElementById('pers-length').addEventListener('input', function() {
  updateRangeValue(this, this.value, 'px');
  setCSSValue(`.sunrays`, 'perspective', `${this.value}px`) 
});

(function(init) {
  init();
  initializer.push(init);
})(function() {
  let pval = getCSSValue('.sunrays', 'perspective-origin');
  let arr = pval.split(' ');
  setRangeSlider('pers-origin-x', arr[0], '%');
  setRangeSlider('pers-origin-y', arr[1].........完整代码请登录后点击上方下载按钮下载查看

网友评论0