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
2. Adding a three-dimensional page with perspective properties
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.
3. Curve the edges of the page
CSS can be used to create joint animations. I learned this from s14garnet.
Transformations are affected by the parent element. they can be concatenated using preserve-3d
.
4. Add dragging interactions to continuously turn pages
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.
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">
Top comments (1)
Cute components! I'm impressed how relatively little code and is required to implement and even customize it