#javascript #html #css #contextmenu
Вопрос:
У меня есть контекстное меню, которое обрезается, когда я щелкаю правой кнопкой мыши в правой части страницы, как показано здесь:
Меню обрезается по краю страницы, поэтому я хочу, чтобы меню переместилось на другую сторону курсора, как это делается в Chrome или других популярных приложениях. Я попытался посетить другие страницы в StackOverflow и попробовать некоторые демо-версии, но все они говорят об одном и том же, как показано выше. Я также попытался прокомментировать некоторые другие сообщения, посмотрев, ответят ли они, но все равно ничего.
Обновить
Код:
var menu = document.querySelector('.menu');
function showMenu(x, y) {
menu.style.left = x 'px';
menu.style.top = y 'px';
menu.classList.add('menu-show');
}
function hideMenu() {
menu.classList.remove('menu-show');
}
function onContextMenu(e) {
e.preventDefault();
showMenu(e.pageX, e.pageY);
document.addEventListener('mousedown', onMouseDown, false);
}
function onMouseDown(e) {
hideMenu();
document.removeEventListener('mousedown', onMouseDown);
}
document.addEventListener('contextmenu', onContextMenu, false);
/* Page */
html {
width: 100%;
height: 100%;
background: radial-gradient(circle, #fff 0%, #a6b9c1 100%) no-repeat;
}
.container {
position: absolute;
top: 20%;
left: 0;
width: 100%;
margin: auto;
text-align: center;
}
h1,
h2 {
color: #555;
}
/* Menu */
.menu {
position: absolute;
width: 200px;
padding: 2px;
margin: 0;
border: 1px solid #bbb;
background: #eee;
background: linear-gradient(to bottom, #fff 0%, #e5e5e5 100px, #e5e5e5 100%);
z-index: 100;
border-radius: 3px;
box-shadow: 1px 1px 4px rgba(0, 0, 0, .2);
opacity: 0;
transform: translate(0, 15px) scale(.95);
transition: transform 0.1s ease-out, opacity 0.1s ease-out;
pointer-events: none;
}
.menu-item {
display: block;
position: relative;
margin: 0;
padding: 0;
white-space: nowrap;
}
.menu-btn {
display: block;
color: #444;
font-family: 'Roboto', sans-serif;
font-size: 13px;
cursor: pointer;
border: 1px solid transparent;
white-space: nowrap;
padding: 6px 8px;
border-radius: 3px;
}
button.menu-btn {
background: none;
line-height: normal;
overflow: visible;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
width: 100%;
text-align: left;
}
a.menu-btn {
outline: 0 none;
text-decoration: none;
}
.menu-text {
margin-left: 25px;
}
.menu-btn .fa {
position: absolute;
left: 8px;
top: 50%;
transform: translateY(-50%);
}
.menu-item:hover>.menu-btn {
color: #fff;
outline: none;
background-color: #2E3940;
background: linear-gradient(to bottom, #5D6D79, #2E3940);
border: 1px solid #2E3940;
}
.menu-item-disabled {
opacity: .5;
pointer-events: none;
}
.menu-item-disabled .menu-btn {
cursor: defau<
}
.menu-separator {
display: block;
margin: 7px 5px;
height: 1px;
border-bottom: 1px solid #fff;
background-color: #aaa;
}
.menu-item-submenu::after {
content: "";
position: absolute;
right: 6px;
top: 50%;
transform: translateY(-50%);
border: 5px solid transparent;
border-left-color: #808080;
}
.menu-item-submenu:hover::after {
border-left-color: #fff;
}
.menu .menu {
top: 4px;
left: 99%;
}
.menu-show,
.menu-item:hover>.menu {
opacity: 1;
transform: translate(0, 0) scale(1);
pointer-events: auto;
}
.menu-item:hover>.menu {
transition-delay: 300ms;
}
<ul class="menu">
<li class="menu-item">
<a href="#" class="menu-btn">
<i class="fa fa-folder-open"></i>
<span class="menu-text">Open</span>
</a>
</li>
<li class="menu-item menu-item-disabled">
<button type="button" class="menu-btn">
<span class="menu-text">Open in New Window</span>
</button>
</li>
<li class="menu-separator"></li>
<li class="menu-item">
<button type="button" class="menu-btn">
<i class="fa fa-reply"></i>
<span class="menu-text">Reply</span>
</button>
</li>
<li class="menu-item">
<button type="button" class="menu-btn">
<i class="fa fa-star"></i>
<span class="menu-text">Favorite</span>
</button>
</li>
<li class="menu-item menu-item-submenu">
<button type="button" class="menu-btn">
<i class="fa fa-users"></i>
<span class="menu-text">Social</span>
</button>
<ul class="menu">
<li class="menu-item">
<button type="button" class="menu-btn">
<i class="fa fa-comment"></i>
<span class="menu-text">Comment</span>
</button>
</li>
<li class="menu-item menu-item-submenu">
<button type="button" class="menu-btn">
<i class="fa fa-share"></i>
<span class="menu-text">Share</span>
</button>
<ul class="menu">
<li class="menu-item">
<button type="button" class="menu-btn">
<i class="fa fa-twitter"></i>
<span class="menu-text">Twitter</span>
</button>
</li>
<li class="menu-item">
<button type="button" class="menu-btn">
<i class="fa fa-facebook-official"></i>
<span class="menu-text">Facebook</span>
</button>
</li>
<li class="menu-item">
<button type="button" class="menu-btn">
<i class="fa fa-google-plus"></i>
<span class="menu-text">Google Plus</span>
</button>
</li>
<li class="menu-item">
<button type="button" class="menu-btn">
<i class="fa fa-envelope"></i>
<span class="menu-text">Email</span>
</button>
</li>
</ul>
</li>
</ul>
</li>
<li class="menu-separator"></li>
<li class="menu-item">
<button type="button" class="menu-btn">
<i class="fa fa-download"></i>
<span class="menu-text">Save</span>
</button>
</li>
<li class="menu-item">
<button type="button" class="menu-btn">
<i class="fa fa-edit"></i>
<span class="menu-text">Rename</span>
</button>
</li>
<li class="menu-item">
<button type="button" class="menu-btn">
<i class="fa fa-trash"></i>
<span class="menu-text">Delete</span>
</button>
</li>
</ul>
<div class="container">
<h1>Context Menu</h1>
<h2>(right-click anywhere)</h2>
</div>
Комментарии:
1. Что вы пробовали? Мы ожидаем, что вы проведете некоторое исследование по своей проблеме и попытаетесь сделать это перед публикацией.
2. рассчитайте размер lefting yClient и размер xClient, прежде чем пытаться отобразить контекстное меню. это поможет вам узнать, можете ли вы безопасно визуализировать его, не получая пореза. И чтобы иметь возможность сделать это, вам нужно будет знать точную высоту и ширину вашего пользовательского контекстного меню
3. Нам также нужно будет увидеть ваш код, чтобы иметь возможность помочь вам.
4. Не могли бы вы, пожалуйста, показать нам свой код?
5. Я добавил код и дополнительную информацию.
Ответ №1:
Это должно быть возможно при простом сравнении. Там, где вы задаете положение контекстного меню ( menu.style.left = e.pageX "px";
), вы можете вместо этого проверить, подойдет ли оно:
var contextMenuWidth = 250;
var contextSubMenuWidth = 250;
var leftPos = ''
if (e.pageX < window.innerWidth - contextMenuWidth) {
leftPos = `${e.pageX}px`;
} else {
leftPos = `${e.pageX - contextMenuWidth}px`;
}
if (e.pageX < window.innerWidth - contextMenuWidth - contextSubMenuWidth) {
menu.classList.remove("sub-left");
} else {
menu.classList.add("sub-left");
}
menu.style.left = leftPos;
Это проверка того, находится ли положение курсора ( e.pageX
) на расстоянии ширины контекстного меню contextMenuWidth
() от правой части экрана ( window.innerWidth
). Если это так, мы устанавливаем левую позицию в текущее положение курсора за вычетом ширины.
Мы также используем эту инструкцию if для добавления класса в меню на основе его положения, чтобы изменить положение подменю.
.sub-left .menu-sub-list {
left: -100%;
right: 0;
}
Это также использует шаблонные литералы для ваших строк CSS, эффективно заменяя numberVariable "px"
их:
`${numberVariable}px`
поскольку
по возможности лучше избегать использования оператора для объединения строк.
Это применяется в данном примере с жестко заданной шириной контекстного меню, я бы предложил использовать переменную и сохранить ее в соответствующем месте:
document.onclick = hideMenu;
document.oncontextmenu = rightClick;
function hideMenu() {
document.getElementById("contextMenu").style.display = "none";
}
function rightClick(e) {
e.preventDefault();
var contextMenuWidth = 250;
var contextSubMenuWidth = 250;
var menu = document.getElementById("contextMenu")
menu.style.display = 'block';
var leftPos = ''
if (e.pageX < window.innerWidth - contextMenuWidth) {
leftPos = `${e.pageX}px`;
} else {
leftPos = `${e.pageX - contextMenuWidth}px`;
}
if (e.pageX < window.innerWidth - contextMenuWidth - contextSubMenuWidth) {
menu.classList.remove("sub-left");
} else {
menu.classList.add("sub-left");
}
menu.style.left = leftPos;
menu.style.top = e.pageY "px";
}
feather.replace()
*,
*:after,
*:before {
box-sizing: border-box;
}
:root {
--color-bg-primary: #d0d6df;
--color-bg-primary-offset: #f1f3f7;
--color-bg-secondary: #fff;
--color-text-primary: #3a3c42;
--color-text-primary-offset: #898c94;
--color-orange: #dc9960;
--color-green: #1eb8b1;
--color-purple: #657cc4;
--color-black: var(--color-text-primary);
--color-red: #d92027;
}
body {
font-family: "Inter", sans-serif;
background-color: var(--color-bg-primary);
color: var(--color-text-primary);
}
.menu {
background-color: var(--color-bg-secondary);
border-radius: 10px;
box-shadow: 0 10px 20px #40404015;
}
.menu-list {
margin: 0;
display: block;
width: 100%;
padding: 8px;
}
.menu-list .menu-list {
border-top: 1px solid #ddd;
}
.menu-sub-list:hover {
display: flex;
}
.menu-sub-list {
display: none;
padding: 8px;
background-color: var(--color-bg-secondary);
border-radius: 10px;
box-shadow: 0 10px 20px rgba(#404040, 0.15);
position: absolute;
left: 100%;
right: 0;
z-index: 100;
width: 100%;
top: 0;
flex-direction: column;
}
.sub-left .menu-sub-list {
left: -100%;
right: 0;
}
.menu-item {
position: relative;
}
.menu-button:hover {
background-color: var(--color-bg-primary-offset);
}
.menu-button:hover .menu-sub-list {
display: flex;
}
.menu-button:hover svg {
stroke: var(--color-text-primary);
}
.menu-button {
font: inherit;
border: 0;
padding: 8px 8px;
padding-right: 36px;
width: 100%;
border-radius: 8px;
display: flex;
align-items: center;
position: relative;
background-color: var(--color-bg-secondary);
}
.menu-button--delete:hover {
color: var(--color-red);
}
svg:first-of-type {
stroke: var(--color-red);
}
.menu-button--orange svg:first-of-type {
stroke: var(--color-orange);
}
.menu-button--green svg:first-of-type {
stroke: var(--color-green);
}
.menu-button--purple svg:first-of-type {
stroke: var(--color-purple);
}
.menu-button--blacksvg:first-of-type {
stroke: var(--color-black);
}
.menu-button--checked svg:nth-of-type(2) {
stroke: var(--color-purple);
}
.menu-button svg {
width: 20px;
height: 20px;
margin-right: 10px;
stroke: var(--color-text-primary-offset);
}
.menu-button:nth-of-type(2) {
margin-right: 0;
position: absolute;
right: 8px;
}
.container {
position: absolute;
width: 250px;
display: flex;
align-items: center;
justify-content: center;
}
ul {
list-style: none;
}
<div class="context-menu">
<div class="container" id="contextMenu" style="display:none">
<!-- code here -->
<div class="menu">
<ul class="menu-list">
<li class="menu-item"><button class="menu-button"><i
data-feather="corner-up-right"></i>Share</button></li>
<li class="menu-item"><button class="menu-button"><i data-feather="edit-2"></i>Rename</button></li>
</ul>
<ul class="menu-list">
<li class="menu-item"><button class="menu-button menu-button--black"><i data-feather="circle"></i>No
status<i data-feather="chevron-right"></i></button>
<ul class="menu-sub-list">
<li class="menu-item"><button class="menu-button menu-button--orange"><i
data-feather="square"></i>Needs review</button></li>
<li class="menu-item"><button class="menu-button menu-button--purple"><i
data-feather="octagon"></i>In progress</button></li>
<li class="menu-item"><button class="menu-button menu-button--green"><i
data-feather="triangle"></i>Approved</button></li>
<li class="menu-item"><button class="menu-button menu-button--black menu-button--checked"><i
data-feather="circle"></i>No status<i data-feather="check"></i></button></li>
</ul>
</li>
<li class="menu-item"><button class="menu-button"><i data-feather="link"></i>Copy Link
Address</button></li>
<li class="menu-item"><button class="menu-button"><i data-feather="folder-plus"></i>Move to</button>
</li>
<li class="menu-item"><button class="menu-button"><i data-feather="copy"></i>Copy to</button></li>
<li class="menu-item"><button class="menu-button"><i data-feather="lock"></i>Make Private</button>
</li>
<li class="menu-item"><button class="menu-button"><i data-feather="download"></i>Download</button>
</li>
</ul>
<ul class="menu-list">
<li class="menu-item"><button class="menu-button menu-button--delete"><i
data-feather="trash-2"></i>Delete</button></li>
</ul>
</div>
</div>
</div>
<script src="https://unpkg.com/feather-icons"></script>