Theese days I have been working on my personal website, i have decided to build an tiny terminal for quering my info. My personal info is also avaiable on the website but a developer's personal website needs to be a bit nerd :D. Website is build with vuejs and bootstrap.
I'm a guy that doesn't like design so my website will not be prettiest in the world but at least, i´m trying to make it functional. Site will be an index of my projects (python libraries especially), usefull links that i been storing during this working years. And of course a CV, but it will be last part.
Component implementation
First, you need implement the component, i choose a component that delegates movement of container on header, you can move function 'drag MouseDown' to modify the behaviour.
Template
Really simple, template with 3 slots for easy custom our component
Script
We will need 3 methods:
- onclick to start dragging. This method will register two functions to handle movement: onmousemove and mouseup. Also, it will register the first position of the container.
- onmousemove: Will update position of our container.
- mouseup: Will delete function handlers for functions onmousemove and itself.
CSS
Only need position absolute and a z-index higher than the other page components
Draggable div component
<template>
<div ref="draggableContainer" id="draggable-container">
<div id="draggable-header" @mousedown="dragMouseDown">
<slot name="header"></slot>
</div>
<slot name="main"></slot>
<slot name="footer"></slot>
</div>
</template>
<script>
export default {
name: 'DraggableDiv',
data: function () {
return {
positions: {
clientX: undefined,
clientY: undefined,
movementX: 0,
movementY: 0
}
}
},
methods: {
dragMouseDown: function (event) {
event.preventDefault()
// get the mouse cursor position at startup:
this.positions.clientX = event.clientX
this.positions.clientY = event.clientY
document.onmousemove = this.elementDrag
document.onmouseup = this.closeDragElement
},
elementDrag: function (event) {
event.preventDefault()
this.positions.movementX = this.positions.clientX - event.clientX
this.positions.movementY = this.positions.clientY - event.clientY
this.positions.clientX = event.clientX
this.positions.clientY = event.clientY
// set the element's new position:
this.$refs.draggableContainer.style.top = (this.$refs.draggableContainer.offsetTop - this.positions.movementY) + 'px'
this.$refs.draggableContainer.style.left = (this.$refs.draggableContainer.offsetLeft - this.positions.movementX) + 'px'
},
closeDragElement () {
document.onmouseup = null
document.onmousemove = null
}
}
}
</script>
<style>
#draggable-container {
position: absolute;
z-index: 9;
}
#draggable-header {
z-index: 10;
}
</style>
Component use example
Components with slots are really easy to use on vue you only need to create a tag template with attribute slot, slot value will be target component
Temmplate
<template>
<DraggableDiv class="col-11">
<template slot="header">
[[[ SOME CONTENT HERE]]]
</template>
<template slot="main" >
[[[ SOME CONTENT HERE]]]
</template>
<template slot="footer">
[[[ SOME CONTENT HERE]]]
</template>
</DraggableDiv>
</template>
Script
<script>
import DraggableDiv from './DraggableDiv'
export default {
components: {
DraggableDiv
}
}
</script>
Thats all
I used this component to implement a draggable terminal for my personal website, the result looks like this.
If any of you wants a post of my terminal implementation on javascript leave a comment below :D
Top comments (7)
Hi, great tutorial, can you tell me how to create this to work on mobile with touch but also with mouse, like now as is?
I think that hammerjs.github.io/ can resolve your problems :). Did you try it? for me its a must in hybrid apps. If you consider it useful i would consider updating the post
I didn't know for hammerjs but I think that's it. That would help me a lot. I will see now what I can do with hammerjs.
thanks for this useful article. Can you please tell how I can initiallize the position of the element in the page. Imagin, we have couple of draggable elements in the page , I like to know how I can set the initial position , so I make sure all of the elements are separated initially
You can pass initial positions via props :
vuejs.org/v2/guide/components-prop...
I used your code to create a draggable popup box. Inside the popup box are forms for register and login. The draggable functionality disables the forms and I cannot enter any info. Any idea why that is?
Can you give link of this code displayed in GIF?