mirror of
https://github.com/anatolykopyl/vue-three-d-mockup.git
synced 2026-03-26 21:05:10 +00:00
Added video option
This commit is contained in:
17
README.md
17
README.md
@@ -13,7 +13,6 @@ $ npm install github:anatolykopyl/vue-three-d-mockup
|
|||||||
```html
|
```html
|
||||||
<Mockup
|
<Mockup
|
||||||
screenImg="screen.png"
|
screenImg="screen.png"
|
||||||
lightClr="hsl(0, 100%, 100%)"
|
|
||||||
/>
|
/>
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -44,6 +43,20 @@ export default {
|
|||||||
```
|
```
|
||||||
|
|
||||||
### props:
|
### props:
|
||||||
|
|
||||||
- `screenImg`: path to image that will be displayed on the phones screen
|
- `screenImg`: path to image that will be displayed on the phones screen
|
||||||
- `lightClr`: color of the light in the environment
|
- `video`: the video element displayed on the phones screen. When using this option there are caveats, watch below
|
||||||
|
- `lightClr`: color of the light
|
||||||
- `phoneClr`: color of the phone
|
- `phoneClr`: color of the phone
|
||||||
|
- `rotation`: object with x, y and z rotation values
|
||||||
|
|
||||||
|
### Caveats:
|
||||||
|
|
||||||
|
- The `video` prop is unreactive, so when using it it's important to
|
||||||
|
only render the `Mockup` element when the video is loaded. Check out
|
||||||
|
[Demo.vue](src/Demo.vue) to see an example of how to do this.
|
||||||
|
- The video on the model will not be shown if the original `<video>`
|
||||||
|
element is hidden with `display: none`, so use `visibility: hidden`
|
||||||
|
instead.
|
||||||
|
- The video may not be autoplaying if the original `<video>` element
|
||||||
|
is scrolled off screen.
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
BIN
public/screen.mp4
Normal file
BIN
public/screen.mp4
Normal file
Binary file not shown.
50
src/Demo.vue
50
src/Demo.vue
@@ -1,8 +1,33 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<Mockup
|
<h1>
|
||||||
class="mockup"
|
vue-three-d-mockup
|
||||||
screenImg="screen.png"
|
</h1>
|
||||||
|
<div class="showcase">
|
||||||
|
<Mockup
|
||||||
|
v-if="vidReady"
|
||||||
|
class="mockup"
|
||||||
|
:video="$refs.video"
|
||||||
|
/>
|
||||||
|
<Mockup
|
||||||
|
class="mockup"
|
||||||
|
screenImg="screen.png"
|
||||||
|
:rotation="{
|
||||||
|
x: -0.2,
|
||||||
|
y: -0.3,
|
||||||
|
z: -0.06,
|
||||||
|
}"
|
||||||
|
phoneClr="black"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<video
|
||||||
|
src="screen.mp4"
|
||||||
|
ref="video"
|
||||||
|
@canplay="vidReady = true"
|
||||||
|
muted
|
||||||
|
autoplay
|
||||||
|
loop
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -11,6 +36,11 @@
|
|||||||
import { defineAsyncComponent } from 'vue';
|
import { defineAsyncComponent } from 'vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
vidReady: false,
|
||||||
|
};
|
||||||
|
},
|
||||||
components: {
|
components: {
|
||||||
Mockup: defineAsyncComponent(() => import('./Mockup.vue')),
|
Mockup: defineAsyncComponent(() => import('./Mockup.vue')),
|
||||||
},
|
},
|
||||||
@@ -23,10 +53,24 @@ html, body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
|
font-family: sans-serif;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
video {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.showcase {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-evenly;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mockup {
|
.mockup {
|
||||||
|
|||||||
@@ -21,7 +21,9 @@ export default {
|
|||||||
props: {
|
props: {
|
||||||
screenImg: {
|
screenImg: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true,
|
},
|
||||||
|
video: {
|
||||||
|
type: null,
|
||||||
},
|
},
|
||||||
lightClr: {
|
lightClr: {
|
||||||
type: String,
|
type: String,
|
||||||
@@ -31,6 +33,14 @@ export default {
|
|||||||
type: String,
|
type: String,
|
||||||
default: 'white',
|
default: 'white',
|
||||||
},
|
},
|
||||||
|
rotation: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({
|
||||||
|
x: -0.2,
|
||||||
|
y: 0.3,
|
||||||
|
z: 0.06,
|
||||||
|
}),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
setup(props) {
|
setup(props) {
|
||||||
const container = ref(null);
|
const container = ref(null);
|
||||||
@@ -64,8 +74,15 @@ export default {
|
|||||||
// const geometry = new THREE.PlaneGeometry(width, height);
|
// const geometry = new THREE.PlaneGeometry(width, height);
|
||||||
const geometry = roundedPlane(width, height, radius);
|
const geometry = roundedPlane(width, height, radius);
|
||||||
|
|
||||||
const loader = new THREE.TextureLoader();
|
let texture;
|
||||||
const texture = loader.load(props.screenImg);
|
|
||||||
|
if (props.screenImg) {
|
||||||
|
const loader = new THREE.TextureLoader();
|
||||||
|
texture = loader.load(props.screenImg);
|
||||||
|
} else {
|
||||||
|
texture = new THREE.VideoTexture(props.video);
|
||||||
|
}
|
||||||
|
|
||||||
texture.anisotropy = renderer.capabilities.getMaxAnisotropy();
|
texture.anisotropy = renderer.capabilities.getMaxAnisotropy();
|
||||||
|
|
||||||
const material = new THREE.MeshLambertMaterial({ map: texture });
|
const material = new THREE.MeshLambertMaterial({ map: texture });
|
||||||
@@ -119,11 +136,7 @@ export default {
|
|||||||
y: 0,
|
y: 0,
|
||||||
z: 0,
|
z: 0,
|
||||||
},
|
},
|
||||||
rotation: {
|
rotation: props.rotation,
|
||||||
x: -0.2,
|
|
||||||
y: 0.3,
|
|
||||||
z: 0.06,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
phone.startFloat();
|
phone.startFloat();
|
||||||
scene.add(phone);
|
scene.add(phone);
|
||||||
|
|||||||
Reference in New Issue
Block a user