<template>
<section id="parentAll">
<div class="minHr" ref="container" @mousedown="startDrag" @mouseup="endDrag" @mousemove="whileDrag">
<slot></slot>
</div>
<canvas ref="myCanvas" v-if="showCanvas" @mouseup="endDrag" @mousemove="whileDrag"></canvas>
</section>
</template>
<script>
export default {
name: "MyDrag",
data() {
return {
dragStatus: false,
childrenArr: [],
startEvent: null,
endEvent: null,
direction: "topBottom",
selectedArr: [],
heightContainer: null,
widthContainer: null,
/* Rectangular area data for drawing during drag */
rect: {
startX: null,
startY: null,
w: null,
h: null
},
startDragData: {
x: null,
y: null
},
whileDragData: {
x: null,
y: null,
CLY: null
},
showCanvas: false
}
},
methods: {
childrenInfo: function () {
const { container } = this.$refs;
const stylesDiv = window.getComputedStyle(container, null);
this.widthContainer = parseFloat( stylesDiv.getPropertyValue("width") );
this.heightContainer = parseFloat( stylesDiv.getPropertyValue("height") );
let children = container.childNodes;
children.forEach((item, index) => {
let childObj = {
offsetTop: item.offsetParent.offsetTop + item.offsetTop,
offsetHeight: item.offsetHeight
}
this.childrenArr.push(childObj);
})
},
startDrag: function (event) {
if(event.button === 0) {
this.dragStatus = true;
this.startEvent = event.pageY;
this.startDragData.x = event.pageX;
this.startDragData.y = event.pageY;
this.showCanvas = false;
}
},
whileDrag: async function (event) {
if (this.dragStatus) {
await this.showMethod();
console.log("dragging");
this.whileDragData.x = event.pageX;
this.whileDragData.y = event.pageY;
this.whileDragData.CLY = event.clientY
await this.canvasMethod();
} else {
this.showCanvas = false;
}
},
endDrag: function (event) {
if(event.button === 0) {
console.log("end drag");
this.dragStatus = false;
this.showCanvas = false;
this.endEvent = event.pageY;
this.calculateDirection();
this.calculateSelected();
}
},
showMethod: function () {
this.showCanvas = true;
},
calculateDirection: function () {
if (this.startEvent <= this.endEvent) {
this.direction = "topBottom";
} else {
this.direction = "bottomTop";
}
},
calculateSelected: function () {
this.selectedArr = [];
let endIndex = null;
let startIndex = null;
this.childrenArr.forEach( (item, index) => {
if ( (item.offsetTop < this.endEvent) && ( (item.offsetTop + item.offsetHeight) > this.endEvent) ) {
endIndex = index;
console.log(endIndex);
}
if ( (item.offsetTop < this.startEvent) && ( (item.offsetTop + item.offsetHeight) > this.startEvent) ) {
startIndex = index;
console.log(startIndex);
}
});
if( endIndex !== null ) {
if (this.direction === "topBottom") {
for (let i = startIndex; i <= endIndex; i++ ) {
this.selectedArr.push(i+1);
}
} else {
for (let i = startIndex; i >= endIndex; i-- ) {
this.selectedArr.push(i+1);
}
}
}
this.$emit("change", this.selectedArr);
},
canvasMethod: function () {
const { myCanvas } = this.$refs;
myCanvas.width = this.widthContainer;
myCanvas.height = this.heightContainer;
const html = document.documentElement;
let ctx = myCanvas.getContext('2d');
this.rect.startX = this.startDragData.x - myCanvas.offsetParent.offsetLeft;
this.rect.startY = this.startDragData.y - myCanvas.offsetParent.offsetTop;
this.rect.w = (this.whileDragData.x - myCanvas.offsetParent.offsetLeft) - this.rect.startX;
this.rect.h = (this.whileDragData.y - myCanvas.offsetParent.offsetTop) - this.rect.startY ;
if ( Math.abs(this.whileDragData.CLY - window.innerHeight) < 12) {
console.log("near");
html.scrollTop += 25;
}
if ( Math.abs(this.whileDragData.CLY) < 12 ) {
html.scrollTop -= 25;
}
if ( (this.whileDragData.y > (myCanvas.offsetParent.offsetTop + myCanvas.offsetHeight) - 25) || (this.whileDragData.y < myCanvas.offsetParent.offsetTop + 25) ) {
ctx.clearRect(0,0,myCanvas.width,myCanvas.height);
}
ctx.clearRect(0,0,myCanvas.width,myCanvas.height);
ctx.setLineDash([6]);
ctx.strokeRect(this.rect.startX, this.rect.startY, this.rect.w, this.rect.h);
},
},
mounted() {
this.childrenInfo();
}
}
</script>
<style scoped>
.minHr {
min-height: 900px;
}
#parentAll {
position: relative;
}
#parentAll canvas {
position: absolute;
top: 0;
left: 0;
}
</style>