DEMOs

导航页
front
front
back
top
bottom
left
right
#showpart {
  @include flexbox(row, nowrap, center, center);

  width: 90vw;
  height: 90vw;
  max-width: torem(500px);
  max-height: torem(500px);
  border: 1px solid color(black);

  .box {
    color: color(white);
    font-size: torem(20px);

    &.box--2d {
      --transform-translate-x: 0;
      --transform-translate-y: 0;
      --transform-rotate: 0deg;
      --transform-scale: 1;
      --transform-skew-x: 0deg;
      --transform-skew-y: 0deg;

      display: none;
      background-color: color(blue);
      transform:
        translateX(var(--transform-translate-x))
        translateY(var(--transform-translate-y))
        rotate(var(--transform-rotate))
        scale(var(--transform-scale), var(--transform-scale))
        skewX(var(--transform-skew-x))
        skewY(var(--transform-skew-y));

      &.box--active {
        @include flexbox(row, nowrap, center, center);

        width: 32vw;
        height: 32vw;
        max-width: torem(180px);
        max-height: torem(180px);
      }
    }

    &.box--3d {
      --transform-perspective: 1000px;
      --transform-perspective-origin-x: 150%;
      --transform-perspective-origin-y: 150%;
      --transform-transform-style: preserve-3d;
      --transform-transform-origin-x: 50%;
      --transform-transform-origin-y: 50%;
      --transform-backface-visibility: visible;

      display: none;
      perspective: var(--transform-perspective);
      perspective-origin:
        var(--transform-perspective-origin-x)
        var(--transform-perspective-origin-y);

      &.box--active {
        @include flexbox(row, nowrap, center, center);

        width: 100%;
        height: 100%;
      }

      .cube {
        --transform-width: #{torem(160px)};
        --transform-half-width: #{torem(80px)};

        position: relative;
        width: var(--transform-width);
        height: var(--transform-width);
        transform-style: var(--transform-transform-style);

        .face {
          @include flexbox(row, nowrap, center, center);

          position: absolute;
          top: 0;
          left: 0;
          width: 100%;
          height: 100%;
          transform-origin:
            var(--transform-transform-origin-x)
            var(--transform-transform-origin-y);
          backface-visibility: var(--transform-backface-visibility);
        }

        .front {
          background-color: rgba(142, 53, 87, 0.7);
          transform: translateZ(var(--transform-half-width));
        }

        .back {
          background-color: rgba(51, 204, 204, 0.7);
          transform: rotateY(180deg) translateZ(var(--transform-half-width));
        }

        .top {
          background-color: rgba(255, 204, 0, 0.7);
          transform: rotateX(90deg) translateZ(var(--transform-half-width));
        }

        .bottom {
          background-color: rgba(0, 153, 51, 0.7);
          transform: rotateX(-90deg) translateZ(var(--transform-half-width));
        }

        .left {
          background-color: rgba(221, 17, 68, 0.7);
          transform: rotateY(-90deg) translateZ(var(--transform-half-width));
        }

        .right {
          background-color: rgba(255, 51, 0, 0.7);
          transform: rotateY(90deg) translateZ(var(--transform-half-width));
        }
      }
    }
  }
}

.transform {
  .form {
    display: none;

    &.form--active {
      @include flexbox(column);
    }

    .inputArea {
      @include flexbox(row, nowrap, flex-start, center);

      flex: 0 0 torem(32px);

      .label {
        flex: 0 0 auto;
        min-width: torem(150px);

        // 2d
        &.label--translateX {
          &::after {
            content: 'translateX(' attr(data-value) 'px)';
          }
        }

        &.label--translateY {
          &::after {
            content: 'translateY(' attr(data-value) 'px)';
          }
        }

        &.label--rotate {
          &::after {
            content: 'rotate(' attr(data-value) 'deg)';
          }
        }

        &.label--scale {
          &::after {
            content: 'scale(' attr(data-value) ')';
          }
        }

        &.label--skewX {
          &::after {
            content: 'skewX(' attr(data-value) 'deg)';
          }
        }

        &.label--skewY {
          &::after {
            content: 'skewY(' attr(data-value) 'deg)';
          }
        }

        // 3d
        &.label--perspective {
          &::after {
            content: 'perspective: ' attr(data-value);
          }
        }

        &.label--perspective-origin {
          &::after {
            content: 'perspective-origin: ' attr(data-value-x) '% ' attr(data-value-y) '%';
          }
        }

        &.label--transform-style {
          &::after {
            content: 'transform-style: ' attr(data-value);
          }
        }

        &.label--transform-origin {
          &::after {
            content: 'transform-origin: ' attr(data-value-x) '% ' attr(data-value-y) '%';
          }
        }

        &.label--backface-visibility {
          &::after {
            content: 'backface-visibility: ' attr(data-value);
          }
        }
      }
    }
  }
}
import { Group } from 'zp-ui';

window.$ = document.querySelector.bind(document);
window.$$ = document.querySelectorAll.bind(document);

const MAP = {
  translateX: {
    unit: 'px',
    prop: '--transform-translate-x',
  },
  translateY: {
    unit: 'px',
    prop: '--transform-translate-y',
  },
  rotate: {
    unit: 'deg',
    prop: '--transform-rotate',
  },
  scale: {
    unit: '',
    prop: '--transform-scale',
  },
  skewX: {
    unit: 'deg',
    prop: '--transform-skew-x',
  },
  skewY: {
    unit: 'deg',
    prop: '--transform-skew-y',
  },
  perspective: {
    unit: 'px',
    prop: '--transform-perspective',
  },
  'perspective-origin': {
    unit: '%',
    prop: '--transform-perspective-origin',
  },
  'transform-style': {
    unit: '',
    prop: '--transform-transform-style',
  },
  'transform-origin': {
    unit: '%',
    prop: '--transform-transform-origin',
  },
  'backface-visibility': {
    unit: '',
    prop: '--transform-backface-visibility',
  },
};

const selectObserver = () => {
  const boxActive = 'box--active';
  const formActive = 'form--active';

  return {
    /**
     * 模式更改的样式设定
     */
    update({ mode }) {
      const box2d = $('.box--2d');
      const form2d = $('.form--2d');
      const box3d = $('.box--3d');
      const form3d = $('.form--3d');

      if (mode === '3d') {
        box2d.classList.remove(boxActive);
        form2d.classList.remove(formActive);

        box3d.classList.add(boxActive);
        form3d.classList.add(formActive);
      } else {
        box2d.classList.add(boxActive);
        form2d.classList.add(formActive);

        box3d.classList.remove(boxActive);
        form3d.classList.remove(formActive);
      }
    },
  };
};

const form2dObserver = () => ({
  update({ label, value }) {
    const result = value + MAP[label].unit;

    // 修改
    $('.box--2d').style.setProperty(MAP[label].prop, result);
    $(`.form--2d .label--${label}`).dataset.value = value;
  },
});

const form3dObserver = () => ({
  update({ label: tmpLabel, group, value }) {
    let suffix = '';
    let label = tmpLabel;

    if (group && group === 'double') {
      suffix = label.slice(-2);
      label = label.slice(0, -2);
    }

    const result = value + MAP[label].unit;

    // 修改
    $('.box--3d').style.setProperty(MAP[label].prop + suffix, result);
    $(`.form--3d .label--${label}`).dataset[`value${suffix.slice(-1).toUpperCase()}`] = value;
  },
});

const createHandler = ({ select, form2d, form3d }) => ({
  /**
   * 模式切换
   */
  switchMode: ({ target }) => {
    const { value } = target;

    select.setState({ mode: value });
  },

  /**
   * 2d表单
   */
  setValue2D: ({ target }) => {
    const { value } = target;

    form2d.setState({
      label: target.getAttribute('id'),
      value,
    });
  },

  /**
   * 3d表单
   */
  setValue3D: ({ target }) => {
    const {
      value,
      dataset: { group },
    } = target;

    form3d.setState({
      label: target.getAttribute('id'),
      group,
      value,
    });
  },
});

document.addEventListener('DOMContentLoaded', () => {
  const select = new Group('select');
  select.attach(selectObserver());

  const form2d = new Group('form2d');
  form2d.attach(form2dObserver());

  const form3d = new Group('form3d');
  form3d.attach(form3dObserver());

  const handler = createHandler({ select, form2d, form3d });
  $('#select').addEventListener('change', handler.switchMode, false);
  $('.form--2d').addEventListener('change', handler.setValue2D, false);
  $('.form--3d').addEventListener('change', handler.setValue3D, false);

  // init
  select.setState({ mode: '2d' });
}, false);