Как добавить стрелку в конец каждой строки, где она встречается с краем области просмотра/указывает на край области просмотра, т. е. сверху, справа, снизу, слева? Мне бы хотелось, чтобы наконечники стрел были около 3 бэров (~50 пикселей), а линия действовала как стержень стрелы. Я бы хотел, чтобы стрелка не была заполнена, т. е. рисовалась линиями, имеющими те же реквизиты, что и текущие линии (1 пиксель, сплошной темно-розовый цвет). Вот макет:
Вот мой текущий код:
body {
margin: 0;
padding: 0;
}
.horver {
width: 100vw;
height: 100vh;
display: grid;
place-content: center;
position: relative;
}
.horver::before {
content: "";
position: absolute;
top: 50%;
left: 0;
width: 100%;
height: 1px;
background: deeppink;
background-image: linear-gradient(to right, transparent 49%, deeppink 49%, deeppink 51%, transparent 51%);
background-size: 100% 1px;
background-position: center;
}
.horver::after {
content: "";
position: absolute;
top: 0;
left: 50%;
width: 1px;
height: 100%;
background: #ff1493;
background-image: linear-gradient(to bottom, transparent 49%, deeppink 49%, deeppink 51%, transparent 51%);
background-size: 1px 100%;
background-position: center;
}
h1 {
font-family: monospace;
background-color: white;
border: 1px solid deeppink;
border-radius: 0.25rem;
color: midnightblue;
padding: 0.25em 0.5em;
z-index: 100;
}<body class = "horver">
<h1>width∶height</h1>
</body>Я готов к реструктуризации CSS и HTML по мере необходимости.
Идея состоит в том, чтобы затем написать функцию, которая будет возвращать ширину и высоту области просмотра динамически/по мере ее изменения.
Спасибо!






Господи, в производстве я просто брал SVG и делал его фоновым изображением элемента, который действовал бы как ось X и Y, но я хотел попробовать этот способ.
Некоторый из моего кода может быть немного перегружен переменными CSS и множеством вычислений, но суть его в том, что вместо использования псевдоэлементов для вашей оси сделайте их определенными элементами, а затем используйте псевдоэлементы для маленьких «стрелок». на концах вашей линии.
Чтобы создать стрелку, я использовал элемент div с контуром обрезки, чтобы разрезать ее пополам. Граница используется для толщины штриха, соответствующей вашей линии.
Во-первых, вы использовали top: 50%, чтобы разместить ось посередине вниз, и это отчасти правильно, однако, если у вас когда-либо будет более толстая ось, это сразу станет очевидным: ваша линия НАЧИНАЕТСЯ на 50% вниз, поэтому она не совсем центрирована.
Чтобы центрировать линию, нам нужно, чтобы она начиналась 50% минус половина толщины вашей линии. Поэтому я использую calc(50% - var(--stroke) / 2 для динамического обновления значения top, таким образом вы можете обновить обводку и получить работающий проект. Кроме того, я считаю, что переменные и вычисления проясняют ситуацию, чем использование «магических чисел».
Вы также можете использовать transform: translate или просто translate, чтобы сместить элемент на 50%, и иногда это более понятно при чтении, однако на этот раз я выбрал расчетный метод.
Я объединил большую часть CSS, поэтому общие стили пишутся один раз, что делает работу немного более СУХОЙ.
Еще одна сложная часть заключалась в том, что после того, как я заставил псевдоэлементы, действующие как стрелки, вращаться, мне нужно было отодвинуть их от края области просмотра, чтобы они действовали как стрелки, поэтому мне пришлось вычислить значение диагонали, вычесть значение ширину, разделите на 2, и это даст мне величину перемещения от края.
JS в этом примере на удивление гораздо легче читать и понимать, чем CSS. Я надеюсь, что демо-версия окажется для вас полезной. Если у вас возникнут вопросы, дайте мне знать!
const w = document.querySelector(".w");
const h = document.querySelector(".h");
const updateSize = () => {
w.innerText = window.innerWidth + "px";
h.innerText = window.innerHeight + "px";
};
window.addEventListener("resize", updateSize);
window.addEventListener("load", updateSize);* {
box-sizing: border-box;
}
body {
margin: 0;
padding: 0;
overflow: hidden;
}
.horver {
width: 100vw;
height: 100vh;
display: grid;
place-content: center;
position: relative;
}
.axis {
position: absolute;
--stroke: 1px;
--bg-colors:
transparent 49%,
deeppink 49%,
deeppink 51%,
transparent 51%;
background-image: linear-gradient(
var(--direction, to right),
var(--bg-colors)
);
background-color: deeppink;
background-position: center;
}
.x.axis {
--direction: to right;
top: calc(50% - var(--stroke) / 2);
left: var(--stroke);
width: calc(100% - 2 * var(--stroke));
height: var(--stroke);
background-size: 100% 1px;
}
.y.axis {
--direction: to bottom;
background-size: 1px 100%;
height: calc(100% - 2 * var(--stroke));
width: var(--stroke);
top: var(--stroke);
left: calc(50% - var(--stroke) / 2);
}
.axis::before,
.axis::after {
content: "";
position: absolute;
--size: 20px;
height: var(--size);
width: var(--size);
border: var(--stroke) solid deeppink;
--edge-offset: calc(
(sqrt(2) * var(--size)) / 2
- var(--size) / 2
- var(--stroke)
);
--axis-offset: calc(
-1 * var(--size) / 2
- var(--stroke) / 2
);
clip-path: polygon(
0 0,
100% 100%,
0 100%
);
}
.x.axis::before {
left: var(--edge-offset);
top: var(--axis-offset);
rotate: 45deg;
}
.y.axis::before {
top: var(--edge-offset);
left: var(--axis-offset);
rotate: 135deg;
}
.x.axis::after {
right: var(--edge-offset);
top: var(--axis-offset);
rotate: -135deg;
}
.y.axis::after {
bottom: var(--edge-offset);
left: var(--axis-offset);
rotate: -45deg;
}
h1 {
font-family: monospace;
background-color: white;
border: 1px solid deeppink;
border-radius: 0.25rem;
color: midnightblue;
padding: 0.25em 0.5em;
z-index: 100;
}<div class = "horver">
<div class = "x axis"></div>
<div class = "y axis"></div>
<h1>
<span class = "w">width</span>∶<span class = "h">height</span>
</h1>
</div>Обновлено: добавление опции SVG в качестве ответа на комментарий.
Это очень похоже, только я использую SVG для стрелок, чтобы было меньше вычислений. Я также избавился от фоновых изображений, потому что не думаю, что они что-то делали.
Мой svg имеет формат data uri, потому что я не хотел ссылаться на файл, но вы могли бы с тем же успехом иметь файл, содержащий содержимое svg, и получить те же результаты. Я просто погуглил «svg стрелка», чтобы найти тот, который соответствует моим потребностям.
const w = document.querySelector(".w");
const h = document.querySelector(".h");
const updateSize = () => {
w.innerText = window.innerWidth + "px";
h.innerText = window.innerHeight + "px";
};
window.addEventListener("resize", updateSize);
window.addEventListener("load", updateSize);* {
box-sizing: border-box;
}
:root {
--stroke: 5px;
}
body {
margin: 0;
padding: 0;
overflow: hidden;
}
.horver {
width: 100dvw;
height: 100dvh;
display: grid;
place-content: center;
position: relative;
}
.axis {
position: absolute;
background-color: deeppink;
background-position: center;
top: 50%; left: 50%;
translate: -50% -50%;
}
.x.axis {
width: calc(100% - 2 * var(--stroke));
height: var(--stroke);
}
.y.axis {
height: calc(100% - 2 * var(--stroke));
width: var(--stroke);
}
.axis::before,
.axis::after {
content: "";
--size: 75px;
width: var(--size);
height: var(--size);
position: absolute;
--axis-offset: calc(-1 * var(--size) / 2 + var(--stroke) / 2);
--edge-offset: calc(-1 * var(--size) / 3);
background-image: url("data:image/svg+xml,%3C%3Fxml version='1.0' encoding='utf-8'%3F%3E%3C!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools --%3E%3Csvg width='800px' height='800px' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M7.82054 20.7313C8.21107 21.1218 8.84423 21.1218 9.23476 20.7313L15.8792 14.0868C17.0505 12.9155 17.0508 11.0167 15.88 9.84497L9.3097 3.26958C8.91918 2.87905 8.28601 2.87905 7.89549 3.26958C7.50497 3.6601 7.50497 4.29327 7.89549 4.68379L14.4675 11.2558C14.8581 11.6464 14.8581 12.2795 14.4675 12.67L7.82054 19.317C7.43002 19.7076 7.43002 20.3407 7.82054 20.7313Z' fill='deeppink'/%3E%3C/svg%3E");
background-position: center;
background-size: cover;
}
.x.axis::before {
top: var(--axis-offset);
left: var(--edge-offset);
rotate: 180deg;
}
.y.axis::before {
left: var(--axis-offset);
top: var(--edge-offset);
rotate: -90deg;
}
.x.axis::after {
top: var(--axis-offset);
right: var(--edge-offset);
}
.y.axis::after {
left: var(--axis-offset);
bottom: var(--edge-offset);
rotate: 90deg;
}
h1 {
font-family: monospace;
background-color: white;
border: var(--stroke) solid deeppink;
border-radius: 0.25rem;
color: midnightblue;
padding: 0.25em 0.5em;
z-index: 100;
}<div class = "horver">
<div class = "x axis"></div>
<div class = "y axis"></div>
<h1>
<span class = "w">width</span>∶<span class = "h">height</span>
</h1>
</div>Причина появления артефактов заключается в том, что это «иллюзия» стрелки, хотя на самом деле это граница, имеющая особые свойства рендеринга, и хотя я предварительно выполнил некоторые расчеты, чтобы сделать позиционирование «достаточно хорошим», оно не совсем идеально из-за способа квадратный край вала образует диагональ. Я также рад показать вам решение SVG примерно через час :)
Спасибо! Мне бы хотелось понять подход SVG, особенно потому, что он может отображаться более точно. 🙏🙏🙏
Большое спасибо! Ваши объяснения действительно ясны! Как дизайнер, я могу понять почти все, что вы здесь сделали. Удивительный. Один вопрос… потребует ли обновление значения --stroke перекодирования URI данных SVG, чтобы он соответствовал новой ширине, например, если я хочу использовать 2 пикселя вместо 5 пикселей?
Лично я бы просто изменил контейнер --size, в котором в качестве фона используется SVG, но тогда в итоге стрелки будут меньшего размера. Если вам нужен другой стиль стрелки, вы можете создать свой собственный SVG или найти другой, который соответствует вашему дизайну. Существует множество бесплатных ресурсов, и это отличное руководство как написать их самостоятельно или лучше понять :)
Спасибо! Я измеряю штрихи стрелок примерно на три пикселя шире, чем оси с помощью XScope, поэтому я поиграю с --size или вытащу новый SVG. Похоже, код URI данных тоже нуждается в небольшой очистке. Спасибо за ссылку на SVG. Я определенно сожру это. СД! 🙌
Боже мой… это почти идеально! Я собирался написать функции, но СПАСИБО 🙏, что взялись за это. И вы правы, в этом случае JS намного проще, чем CSS. Увеличивая масштаб, я вижу некоторые (белые) визуальные артефакты в местах пересечения линий со стрелками. Именно поэтому вы выбрали бы решение SVG, и если да, то как бы вы к нему подошли?