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)
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?
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...
Can you give link of this code displayed in GIF?