254 lines
6.4 KiB
Vue
254 lines
6.4 KiB
Vue
<template>
|
|
<div ref="wrapper" class="relative pointer-events-none" :style="{ width: standardWidth * 0.8 * 1.1 * scale + 'px', height: standardHeight * 1.1 * scale + 'px', marginBottom: 20 + 'px', marginTop: 15 + 'px' }">
|
|
<div ref="card" class="wrap absolute origin-center transform duration-200" :style="{ transform: `scale(${scale * scaleMultiplier}) translateY(${hover2 ? '-40%' : '-50%'})` }">
|
|
<div class="perspective">
|
|
<div class="book-wrap transform duration-100 pointer-events-auto" :class="hover2 ? 'z-80' : 'rotate'" @mouseover="hover = true" @mouseout="hover = false">
|
|
<div class="book book-1 box-shadow-book3d" ref="front"></div>
|
|
<div class="title book-1 pointer-events-none" ref="left"></div>
|
|
<div class="bottom book-1 pointer-events-none" ref="bottom"></div>
|
|
<div class="book-back book-1 pointer-events-none">
|
|
<div class="text pointer-events-none">
|
|
<h3 class="mb-4">Book Back</h3>
|
|
<p>
|
|
<span>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Sunt earum doloremque aliquam culpa dolor nostrum consequatur quas dicta? Molestias repellendus minima pariatur libero vel, reiciendis optio magnam rerum, labore corporis.</span>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
export default {
|
|
props: {
|
|
src: String,
|
|
width: {
|
|
type: Number,
|
|
default: 200
|
|
}
|
|
},
|
|
data() {
|
|
return {
|
|
hover: false,
|
|
hover2: false,
|
|
standardWidth: 200,
|
|
standardHeight: 320,
|
|
isAttached: true,
|
|
pageX: 0,
|
|
pageY: 0
|
|
}
|
|
},
|
|
watch: {
|
|
src(newVal) {
|
|
this.setCover()
|
|
},
|
|
width(newVal) {
|
|
this.init()
|
|
},
|
|
hover(newVal) {
|
|
if (newVal) {
|
|
this.unattach()
|
|
} else {
|
|
this.attach()
|
|
}
|
|
setTimeout(() => {
|
|
this.hover2 = newVal
|
|
}, 100)
|
|
}
|
|
},
|
|
computed: {
|
|
scaleMultiplier() {
|
|
return this.hover2 ? 1.25 : 1
|
|
},
|
|
scale() {
|
|
var scale = this.width / this.standardWidth
|
|
return scale
|
|
}
|
|
},
|
|
methods: {
|
|
unattach() {
|
|
if (this.$refs.card && this.isAttached) {
|
|
var bookshelf = document.getElementById('bookshelf')
|
|
if (bookshelf) {
|
|
var pos = this.$refs.wrapper.getBoundingClientRect()
|
|
|
|
this.pageX = pos.x
|
|
this.pageY = pos.y
|
|
document.body.appendChild(this.$refs.card)
|
|
this.$refs.card.style.left = this.pageX + 'px'
|
|
this.$refs.card.style.top = this.pageY + 'px'
|
|
this.$refs.card.style.zIndex = 50
|
|
this.isAttached = false
|
|
} else if (bookshelf) {
|
|
console.log(this.pageX, this.pageY)
|
|
this.isAttached = false
|
|
}
|
|
}
|
|
},
|
|
attach() {
|
|
if (this.$refs.card && !this.isAttached) {
|
|
if (this.$refs.wrapper) {
|
|
this.isAttached = true
|
|
|
|
this.$refs.wrapper.appendChild(this.$refs.card)
|
|
this.$refs.card.style.left = '0px'
|
|
this.$refs.card.style.top = '0px'
|
|
}
|
|
} else {
|
|
console.log('Is attached already', this.isAttached)
|
|
}
|
|
},
|
|
init() {
|
|
var standardWidth = this.standardWidth
|
|
document.documentElement.style.setProperty('--book-w', standardWidth + 'px')
|
|
document.documentElement.style.setProperty('--book-wx', standardWidth + 1 + 'px')
|
|
document.documentElement.style.setProperty('--book-h', standardWidth * 1.6 + 'px')
|
|
document.documentElement.style.setProperty('--book-d', 40 + 'px')
|
|
},
|
|
setElBg(el) {
|
|
el.style.backgroundImage = `url("${this.src}")`
|
|
el.style.backgroundSize = 'cover'
|
|
el.style.backgroundPosition = 'center center'
|
|
el.style.backgroundRepeat = 'no-repeat'
|
|
},
|
|
setCover() {
|
|
if (this.$refs.front) {
|
|
this.setElBg(this.$refs.front)
|
|
}
|
|
if (this.$refs.bottom) {
|
|
this.setElBg(this.$refs.bottom)
|
|
this.$refs.bottom.style.backgroundSize = '2000%'
|
|
this.$refs.bottom.style.filter = 'blur(1px)'
|
|
}
|
|
if (this.$refs.left) {
|
|
this.setElBg(this.$refs.left)
|
|
this.$refs.left.style.backgroundSize = '2000%'
|
|
this.$refs.left.style.filter = 'blur(1px)'
|
|
}
|
|
}
|
|
},
|
|
mounted() {
|
|
this.setCover()
|
|
this.init()
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style>
|
|
/* :root {
|
|
--book-w: 200px;
|
|
--book-h: 320px;
|
|
--book-d: 30px;
|
|
--book-wx: 201px;
|
|
} */
|
|
/*
|
|
.wrap {
|
|
width: calc(1.1 * var(--book-w));
|
|
height: calc(1.1 * var(--book-h));
|
|
margin: 0 auto;
|
|
}
|
|
.perspective {
|
|
position: relative;
|
|
width: 100%;
|
|
height: 100%;
|
|
|
|
perspective: 600px;
|
|
transform-style: preserve-3d;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.book-wrap {
|
|
height: 100%;
|
|
width: 100%;
|
|
transform-style: preserve-3d;
|
|
transition: 'all ease-out 0.6s';
|
|
}
|
|
|
|
.book {
|
|
width: var(--book-w);
|
|
height: var(--book-h);
|
|
background: url(https://covers.openlibrary.org/b/id/8303020-L.jpg) no-repeat center center;
|
|
background-size: cover;
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
margin: auto;
|
|
cursor: pointer;
|
|
}
|
|
.title {
|
|
content: '';
|
|
height: var(--book-h);
|
|
width: var(--book-d);
|
|
position: absolute;
|
|
right: 0;
|
|
left: calc(var(--book-wx) * -1);
|
|
top: 0;
|
|
bottom: 0;
|
|
margin: auto;
|
|
background: #444;
|
|
transform: rotateY(-80deg) translateX(-14px);
|
|
|
|
background: url(https://covers.openlibrary.org/b/id/8303020-L.jpg) no-repeat center center;
|
|
background-size: 5000%;
|
|
filter: blur(1px);
|
|
}
|
|
|
|
.bottom {
|
|
content: '';
|
|
height: var(--book-d);
|
|
width: var(--book-w);
|
|
position: absolute;
|
|
right: 0;
|
|
bottom: var(--book-h);
|
|
top: 0;
|
|
left: 0;
|
|
margin: auto;
|
|
background: #444;
|
|
transform: rotateY(0deg) rotateX(90deg) translateY(-15px) translateX(-2.5px) skewX(10deg);
|
|
|
|
background: url(https://covers.openlibrary.org/b/id/8303020-L.jpg) no-repeat center center;
|
|
background-size: 5000%;
|
|
filter: blur(1px);
|
|
}
|
|
|
|
.book-back {
|
|
width: var(--book-w);
|
|
height: var(--book-h);
|
|
background-color: #444;
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
margin: auto;
|
|
cursor: pointer;
|
|
transform: rotate(180deg) translateZ(-30px) translateX(5px);
|
|
}
|
|
.book-back .text {
|
|
transform: rotateX(180deg);
|
|
position: absolute;
|
|
bottom: 0px;
|
|
padding: 20px;
|
|
text-align: left;
|
|
font-size: 12px;
|
|
}
|
|
.book-back .text h3 {
|
|
color: #fff;
|
|
}
|
|
.book-back .text span {
|
|
display: block;
|
|
margin-bottom: 20px;
|
|
color: #fff;
|
|
}
|
|
|
|
.book-wrap.rotate {
|
|
transform: rotateY(30deg) rotateX(0deg);
|
|
}
|
|
.book-wrap.flip {
|
|
transform: rotateY(180deg);
|
|
} */
|
|
</style> |