Mouse-Driven Marquee Effect in Vue.js
Foreword
As a Vue.js developer, I often find myself experimenting with innovative UI components to enhance user experience. In this article, I’ll delve into the creation of a simple mouse-driven marquee effect, which allows users to select a group of elements by dragging a rectangular box over them. This effect is particularly useful for selecting multiple items in a list or grid.
Achieving the Marquee Effect
The marquee effect relies on positioning mode, which is best applied to the parent element of the marquee. This ensures that the marquee area is consistent with the mouse events. To achieve this effect, we need to get the mouse events, depending on the position of the mouse, and create a dynamic follow-the-mouse div.
The process can be broken down into two steps:
- Press and hold the left mouse button, move the mouse to create a rectangular box.
- Release the left mouse button, and the DOM elements within the rectangular box will be selected.
Creating the Marquee Node
To create the marquee node, we use the following code:
// Create a marquee node
this.selectBoxDashed = document.createElement('div');
this.selectBoxDashed.className = 'haorooms-select-box';
document.body.appendChild(this.selectBoxDashed);
this.scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
this.scrollY = document.documentElement.scrollTop || document.body.scrollTop;
// Set the initial position of the box
this.startX = e.x + this.scrollX || e.clientX + this.scrollX;
this.startY = e.y + this.scrollY || e.clientY + this.scrollY;
this.selectBoxDashed.style.cssText = `left: ${this.startX}px; top: ${this.startY}px`;
Mouse Move and Selecting Elements
When the mouse is moved, we get a list of the selected elements and add a temporary class to them. We also set the position of the marquee box based on the mouse movement.
// The position of the mouse movement, the box set, the width and height
this.initx = this.scrollX || e.clientX;
this.inity = e.y + this.scrollY || e.clientY;
// Temporary storage location and width and height of the box for the select-item selected
this.left = Math.min(this.initx, this.startX);
this.top = Math.min(this.inity, this.startY);
this.width = Math.abs(this.initx - this.startX);
this.height = Math.abs(this.inity - this.startY);
this.selectBoxDashed.style.left = `${this.left}px`;
this.selectBoxDashed.style.top = `${this.top}px`;
this.selectBoxDashed.style.width = `${this.width}px`;
this.selectBoxDashed.style.height = `${this.height}px`;
let fileDivs = document.getElementsByClassName('list');
for (let i = 0; i < fileDivs.length; i++) {
let itemX_pos = fileDivs[i].offsetWidth + fileDivs[i].offsetLeft;
let itemY_pos = fileDivs[i].offsetHeight + fileDivs[i].offsetTop;
let condition1 = itemX_pos > this.left;
let condition2 = itemY_pos > this.top;
let condition3 = fileDivs[i].offsetLeft < (this.left + this.width);
let condition4 = fileDivs[i].offsetTop < (this.top + this.height);
if (condition1 && condition2 && condition3 && condition4) {
// Within the scope of the marquee
fileDivs[i].classList.add('temp-selected');
} else {
fileDivs[i].classList.remove('temp-selected');
}
}
Lifting the Mouse and Selecting Elements
When the mouse is lifted, we select the elements that have the temporary class and remove the temporary class from other elements.
// Lift the mouse, select the class increase
let selectDom = document.getElementsByClassName('temp-selected');
[].slice.call(selectDom).forEach((item) => {
if (item.classList.contains('selected')) {
item.classList.remove('selected');
} else {
item.classList.add('selected');
}
item.classList.remove('temp-selected');
});
if (this.selectBoxDashed) {
try {
this.selectBoxDashed.parentNode.removeChild(this.selectBoxDashed);
} catch (err) {
// console.log(err);
}
}
let fileDivs = document.getElementsByClassName('list');
for (let i = 0; i < fileDivs.length; i++) {
if (fileDivs[i].classList.contains('selected')) {
this.timeList[i] = '1';
} else {
this.timeList[i] = '0';
}
}
Publishing the Component to npm
The component, including the mobile Vue I wrote before the end of the pull-down load the next page of data components, are released to the npm. The npm address is: https://www.npmjs.com/package/timedivselect.
npm install timedivselect -S
import timeDivSelect from 'timedivselect';
Encountered a Small Problem with npm Publish
Before I npm also released some on how to publish npm package, although there is no written before I blog, but many online. The first time with the generally:
npm adduser
// Enter your user name, password, etc. [npm site wants to register in advance, npm site's user name and password]
Not the first time:
npm login
Publish, delete, etc.
npm publish // release
npm unpublish package name // undelete
Back to the topic, the problem I encountered today is npm: no_perms Private mode enable, only admin can publish this module. Before publishing are good, why suddenly this conference have this error message? The original is because I’ve specified npm Taobao mirror. Currently recommended NRM:
sudo npm install -g nrm
View source list
nrm ls
Use a source
nrm use npm
Such a re-release either.