css |vue

Making Miniature Book with CSS

hashrock

hashrock

Posted on July 4, 2020

Making Miniature Book with CSS

Alt Text

As a front-end exercise, I've made a habit of making UI components every Friday.

You can see some of the components I've made in the past in the tag #้‡‘ๆ›œGUI.

I like small, cute things like miniatures, and yesterday I made a Miniature Book component with CSS and Vue.js.

1. Place some divs at absolute

Alt Text

2. Adding a three-dimensional page with perspective properties

Alt Text

To rotate the div in 3D, use the perspective and transform-style properties.

wrapper:

  perspective: 300px;
  transform-style: preserve-3d;

item:

  transform-origin: left center;
  transform: rotateY(30deg);

You can use transform-origin and position: absolute to adjust the position.

Alt Text

3. Curve the edges of the page

Alt Text

CSS can be used to create joint animations. I learned this from s14garnet.

Alt Text

Transformations are affected by the parent element. they can be concatenated using preserve-3d.

4. Add dragging interactions to continuously turn pages

Alt Text

The implementation of drag interaction is straightforward: just keep track of the difference in offsetX and reflect it in the rotation angle.

You can use modulo to loop the book, but note that JavaScript modulo can return a negative value.

HTML:

<div id="app"
       @pointerdown="down"
       @pointermove="move"
       @pointerup="up">
  ...
</div>

JavaScript:

Number.prototype.mod = function (n) {
  return ((this % n) + n) % n;
};
new Vue({
  el: "#app",
  data: {
    rotateRaw: 40,
    rotateOld: 0,
    offset: null
  },
  methods: {
    down(ev) {
      this.$el.setPointerCapture(ev.pointerId);
      this.offset = ev.offsetX;
      this.rotateOld = this.rotate;
    },
    up(ev) {
      this.offset = null;
    },
    move(ev) {
      if (this.offset) {
        this.rotateRaw = this.rotateOld - (ev.offsetX - this.offset);
      }
    }
  },
  computed: {
    rotate() {
      return this.rotateRaw.mod(180);
    }
  }
});

Note that the pointerdown, pointermove and pointerup events require a polyfill in iOS Safari.

To prevent the div element in the wrapper from being selected by dragging, use pointer-events: none to make the Pointer events transparent.

.wrapper {
  ...
  pointer-events: none;
  user-select: none;
}

Here's DEMO:

https://codepen.io/hashrock/pen/RwrxeKe

Vue.js and input type="range" are your friends

I like to adjust the look and feel of the UI with input type="range". It's a one off UI editor. It's similar to building scaffolding to build a house.

Alt Text

Alt Text

Alt Text

input type="range" is useful, but don't forget to write v-model.number to convert its value to a number.

<input type="range" min=0 max=180 step=1 v-model.number="rotate">
๐Ÿ’– ๐Ÿ’ช ๐Ÿ™… ๐Ÿšฉ
hashrock
hashrock

Posted on July 4, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

ยฉ TheLazy.dev

About